]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/DefaultPasteHandler.java
Check if root allows paste only for non-null target root to prevent NPE
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / adapter / impl / DefaultPasteHandler.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.layer0.adapter.impl;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashSet;
18 import java.util.Map;
19 import java.util.Set;
20
21 import org.simantics.db.ReadGraph;
22 import org.simantics.db.Resource;
23 import org.simantics.db.WriteGraph;
24 import org.simantics.db.common.utils.NameUtils;
25 import org.simantics.db.exception.DatabaseException;
26 import org.simantics.db.layer0.adapter.PasteHandlerAdapter;
27 import org.simantics.db.layer0.internal.SimanticsInternal;
28 import org.simantics.db.layer0.util.ClipboardUtils;
29 import org.simantics.db.layer0.util.ModelTransferableGraphSource;
30 import org.simantics.db.layer0.util.PasteEventHandler;
31 import org.simantics.db.layer0.util.RemoverUtil;
32 import org.simantics.db.layer0.util.SimanticsClipboard;
33 import org.simantics.db.layer0.util.SimanticsClipboard.Representation;
34 import org.simantics.db.layer0.util.SimanticsKeys;
35 import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec;
36 import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec.SeedSpecType;
37 import org.simantics.graph.db.IImportAdvisor;
38 import org.simantics.graph.db.IImportAdvisor2;
39 import org.simantics.graph.db.IImportAdvisor2.RootInfo;
40 import org.simantics.graph.db.TransferableGraphException;
41 import org.simantics.graph.db.TransferableGraphSource;
42 import org.simantics.graph.db.TransferableGraphs;
43 import org.simantics.graph.representation.Identity;
44 import org.simantics.graph.representation.Root;
45 import org.simantics.graph.representation.TransferableGraph1;
46 import org.simantics.graph.representation.TransferableGraphUtils;
47 import org.simantics.layer0.Layer0;
48
49 public class DefaultPasteHandler extends PasteHandlerAdapter {
50
51     protected Resource resource;
52
53     public DefaultPasteHandler(Resource resource) {
54         this.resource = resource;
55     }
56
57     public static void defaultExecute(TransferableGraph1 tg, Resource resource, IImportAdvisor advisor) throws DatabaseException, TransferableGraphException {
58         TransferableGraphs.importGraph1(SimanticsInternal.getSession(), tg, advisor);
59     }
60
61     public static void defaultExecute(WriteGraph graph, TransferableGraph1 tg, Resource resource, IImportAdvisor advisor) throws DatabaseException {
62         TransferableGraphs.importGraph1(graph, tg, advisor);
63     }
64
65     public void execute(WriteGraph graph, TransferableGraph1 tg, Resource resource, IImportAdvisor advisor) throws DatabaseException {
66         defaultExecute(graph, tg, resource, advisor);
67     }
68
69     /**
70      * Override this in your inherited class if post processing is done.
71      */
72     public void onPasteBegin(WriteGraph graph) throws DatabaseException {
73     }
74
75     /**
76      * Override this in your inherited class if post processing is done
77      * advisor.getTarget() returns an object under which data is copied
78      * advisor.getRoot() returns the object which have been pasted.
79      * @param representations TODO
80      */
81     public void onPaste(WriteGraph graph, IImportAdvisor2 advisor, Set<Representation> representations) throws DatabaseException {
82     }
83
84     /**
85      * Override this in your inherited class if post processing is done.
86      */
87     public void onPasteEnd(WriteGraph graph) throws DatabaseException {
88     }
89     
90     public IImportAdvisor2 getAdvisor(ReadGraph graph, TransferableGraph1 tg, Resource target, PasteEventHandler handler) throws DatabaseException {
91         
92         Collection<Identity> roots = TransferableGraphUtils.getRoots(tg);
93         if(roots.size() == 1) {
94                 Root root = (Root)roots.iterator().next().definition;
95                 Resource type = graph.getPossibleResource(root.type);
96                 ImportAdvisorFactory factory = graph.getPossibleAdapter(type, ImportAdvisorFactory.class);
97                 if(factory != null) {
98                         if(handler != null)
99                                 return handler.createAdvisor(graph, factory, target);
100                         else
101                                 return factory.create(graph, target, Collections.<String,Object>emptyMap());
102                 }
103         }
104
105         return new DefaultPasteImportAdvisor(target);
106     }
107
108     public Collection<Resource> pasteObject(WriteGraph graph, Set<Representation> object, PasteEventHandler handler) throws DatabaseException {
109         Collection<Resource> result = new ArrayList<>();
110         TransferableGraphSource tgs = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH_SOURCE);
111         if (tgs != null) {
112                 TransferableGraph1 tg = TransferableGraphs.create(graph, tgs);
113             IImportAdvisor2 advisor = getAdvisor(graph, tg, resource, handler); 
114             execute(graph, tg, resource, advisor);
115             Collection<RootInfo> roots = advisor.getRootInfo();
116             if(handler != null) {
117                 for(RootInfo r : roots) handler.postProcess(graph, r.resource);
118             }
119             onPaste(graph, advisor, object);
120             if(tgs instanceof ModelTransferableGraphSource) {
121                 
122                 ModelTransferableGraphSource mtgs = (ModelTransferableGraphSource)tgs;
123                 
124                 loop: for(SeedSpec spec : mtgs.getConfiguration().seeds) {
125                         if(SeedSpecType.SPECIAL_ROOT.equals(spec.specType)) continue;
126                         for(RootInfo info : roots) {
127                                 if(spec.name.equals(info.root.name)) {
128                                         result.add(info.resource);
129                                         continue loop;
130                                 }
131                         }
132                                 // Fallback
133                                 result.clear();
134                                 result.addAll(advisor.getRoots());
135                                 break;
136                 }
137                 
138             } else {
139                 result.addAll(advisor.getRoots());
140             }
141         }
142         return result;
143     }
144
145     @Override
146     public Collection<Resource> pasteFromClipboard(WriteGraph graph, SimanticsClipboard clipboard, PasteEventHandler handler) throws DatabaseException {
147         
148         Collection<Resource> result = new ArrayList<>();
149         
150         
151         // Check if root resource is allowed for pasting
152         checkIfRootAllowsPaste(graph);
153         
154         Map<String,Object> hints = Collections.singletonMap(ClipboardUtils.HINT_TARGET_RESOURCE, resource);
155         
156         onPasteBegin(graph);
157
158         final Set<Resource> cuts = new HashSet<>();
159         for(Set<Representation> object : clipboard.getContents()) {
160             Collection<Resource> cut = ClipboardUtils.accept(object, SimanticsKeys.KEY_CUT_RESOURCES);
161             TransferableGraphSource tg = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH_SOURCE, hints);
162             if(tg != null) {
163                 result.addAll(pasteObject(graph, object, handler));
164                 if (cut != null)
165                     cuts.addAll(cut);
166             } else {
167                 Layer0 L0 = Layer0.getInstance(graph);
168                 for(Resource r : cut) {
169                         graph.deny(r, L0.PartOf);
170                         graph.claim(resource, L0.ConsistsOf, L0.PartOf, r);
171                         result.add(r);
172                 }
173             }
174         }
175
176         onPasteEnd(graph);
177
178         if(!cuts.isEmpty()) {
179                 for (Resource cut : cuts)
180                         RemoverUtil.remove(graph, cut);
181         }
182         
183         return result;
184         
185     }
186
187     protected void checkIfRootAllowsPaste(ReadGraph graph) throws DatabaseException {
188         if (resource == null)
189             return;
190         Layer0 L0 = Layer0.getInstance(graph);
191         // check if root is published
192         Boolean published = graph.getPossibleRelatedValue(resource, L0.Entity_published);
193         if (published != null && published) {
194             throw new DatabaseException("Target resource " + NameUtils.getSafeName(graph, resource) + " is published and does not allow paste.");
195         }
196     }
197
198     @SuppressWarnings("rawtypes")
199     @Override
200     public Object getAdapter(Class adapter) {
201         if(Resource.class == adapter) return resource;
202         return null;
203     }
204
205 }