]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/MigrationUtils.java
Fixed MigrationUtils.importTo root activation to use virtual graph
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / migration / MigrationUtils.java
1 /*******************************************************************************
2  * Copyright (c) 2012 Association for Decentralized Information Management in
3  * 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.migration;
13
14 import java.io.DataInputStream;
15 import java.io.File;
16 import java.io.IOException;
17 import java.net.MalformedURLException;
18 import java.net.URL;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashSet;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.core.runtime.NullProgressMonitor;
28 import org.simantics.databoard.Bindings;
29 import org.simantics.databoard.adapter.AdaptException;
30 import org.simantics.databoard.binding.mutable.Variant;
31 import org.simantics.databoard.container.DataContainer;
32 import org.simantics.databoard.container.DataContainers;
33 import org.simantics.db.ReadGraph;
34 import org.simantics.db.Resource;
35 import org.simantics.db.Session;
36 import org.simantics.db.WriteGraph;
37 import org.simantics.db.WriteOnlyGraph;
38 import org.simantics.db.common.CommentMetadata;
39 import org.simantics.db.common.primitiverequest.PossibleResource;
40 import org.simantics.db.common.request.BinaryRead;
41 import org.simantics.db.common.request.FreshEscapedName;
42 import org.simantics.db.common.request.UnaryRead;
43 import org.simantics.db.common.request.WriteRequest;
44 import org.simantics.db.common.utils.VersionMap;
45 import org.simantics.db.common.utils.VersionMapRequest;
46 import org.simantics.db.common.utils.Versions;
47 import org.simantics.db.exception.DatabaseException;
48 import org.simantics.db.layer0.adapter.Instances;
49 import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler;
50 import org.simantics.db.layer0.adapter.impl.SharedOntologyImportAdvisor;
51 import org.simantics.db.layer0.adapter.impl.TrashBinRemover;
52 import org.simantics.db.layer0.internal.SimanticsInternal;
53 import org.simantics.db.layer0.request.ActivateModel;
54 import org.simantics.db.layer0.util.ExternalDownloadBean;
55 import org.simantics.db.layer0.util.Layer0Utils;
56 import org.simantics.db.layer0.util.TGTransferableGraphSource;
57 import org.simantics.db.request.Write;
58 import org.simantics.db.service.XSupport;
59 import org.simantics.graph.db.IImportAdvisor;
60 import org.simantics.graph.db.ImportResult;
61 import org.simantics.graph.db.MissingDependencyException;
62 import org.simantics.graph.db.TransferableGraphException;
63 import org.simantics.graph.representation.Identity;
64 import org.simantics.graph.representation.Root;
65 import org.simantics.graph.representation.TransferableGraph1;
66 import org.simantics.graph.representation.TransferableGraphUtils;
67 import org.simantics.layer0.Layer0;
68 import org.simantics.operation.Layer0X;
69 import org.simantics.simulation.ontology.SimulationResource;
70 import org.simantics.utils.datastructures.Pair;
71 import org.simantics.utils.datastructures.collections.CollectionUtils;
72
73 public class MigrationUtils {
74         
75         public static final boolean DEBUG = false;
76
77     public static MigrationState newState() {
78         return new MigrationStateImpl();
79     }
80
81     public static MigrationStep getStep(Session session, String uri) throws DatabaseException {
82         return session.sync(new UnaryRead<String, MigrationStep>(uri) {
83
84             @Override
85             public MigrationStep perform(ReadGraph graph) throws DatabaseException {
86                 Resource r = graph.getResource(parameter);
87                 return graph.adapt(r, MigrationStep.class);
88             }
89
90         });
91     }
92
93 //    public static TransferableGraph1 getTG(Session session, MigrationState state) {
94 //        return getTG(session, state, true, false);
95 //    }
96     
97     public static void clearTempResource(Session session, Resource resource) {
98         session.asyncRequest((Write) graph -> {
99             graph.deny(resource, Layer0.getInstance(graph).PartOf);
100         });
101     }
102
103     /**
104      * Activate the imported resource, if there are no other active models and the resource is a Model. 
105      */
106     private static void activateIfNoActiveModel(WriteGraph graph, Resource root, Resource parent) throws DatabaseException {
107         Layer0X L0X = Layer0X.getInstance(graph);
108         SimulationResource SIMU = SimulationResource.getInstance(graph);
109         if (!graph.hasStatement(parent, L0X.Activates) && graph.isInstanceOf(root, SIMU.Model)) {
110             new ActivateModel(parent, root).perform(graph);
111         }
112     }
113
114     public static Collection<Resource> importTo(IProgressMonitor monitor, Session session, MigrationState state, final Resource parent, final IImportAdvisor advisor) throws DatabaseException, TransferableGraphException {
115         final Resource resource = getResource(monitor, session, state);
116         final ArrayList<Resource> result = new ArrayList<>();
117         if(resource != null) {
118             session.syncRequest(new WriteRequest() {
119                 
120                 @Override
121                 public void perform(WriteGraph graph) throws DatabaseException {
122                     
123                         Layer0 L0 = Layer0.getInstance(graph);
124                         
125                         for(Resource root : graph.getObjects(resource, L0.ConsistsOf)) {
126                                 
127                                 String baseName = Versions.getBaseName(graph, root);
128                             String version = Versions.getVersion(graph, root);
129                             if(version != null) {
130                                         VersionMap map = graph.syncRequest(new VersionMapRequest(parent));
131                                         if(map.contains(baseName, version)) {
132                                     String newName = graph.syncRequest(new FreshEscapedName(parent, L0.ConsistsOf, baseName));
133                                         graph.claimLiteral(root, L0.HasName, newName + "@1", Bindings.STRING);
134                                         }
135                             } else {
136                             String newName = graph.syncRequest(new FreshEscapedName(parent, L0.ConsistsOf, baseName));
137                             if(!newName.equals(baseName)) {
138                                 graph.claimLiteral(root, L0.HasName, newName, Bindings.STRING);
139                             }
140                             }
141
142                             graph.deny(root, L0.PartOf);
143                             graph.claim(root, L0.PartOf, parent);
144
145                             if (Boolean.TRUE.equals( state.getProperty(MigrationKeys.ACTIVATE_ROOT_IF_NONE_ACTIVE) )) {
146                                 activateIfNoActiveModel(graph, root, parent);
147                             }
148
149                             CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
150                             graph.addMetadata(cm.add("Imported " + graph.getURI(root) + ", resource " + root));
151                             
152                             result.add(root);
153                     
154                         }
155                         
156                         graph.deny(resource, L0.PartOf);
157
158                 }
159             });
160         } else {
161             TransferableGraph1 tg = getTG(session, state);
162             if(tg != null) {
163                 DefaultPasteHandler.defaultExecute(tg, parent, new IImportAdvisor() {
164                     
165                     @Override
166                     public Resource createRoot(WriteOnlyGraph graph, Root root) throws DatabaseException {
167                         Resource r = advisor.createRoot(graph, root);
168                         result.add(r);
169                         return r;
170                     }
171                     
172                     @Override
173                     public Resource analyzeRoot(ReadGraph graph, Root root) throws DatabaseException {
174                         return advisor.analyzeRoot(graph, root);
175                     }
176                 });
177             }
178         }
179         return result;
180     }
181     
182     
183         public static Collection<MigrationStep> getMigrationSteps(DataContainer header) throws DatabaseException {
184         
185         return SimanticsInternal.sync(new BinaryRead<String,Integer,Collection<MigrationStep>>(header.format, header.version) {
186
187                         @Override
188                         public Collection<MigrationStep> perform(ReadGraph graph) throws DatabaseException {
189                                 
190                                 Layer0 L0 = Layer0.getInstance(graph);
191                                 ArrayList<Pair<Double,MigrationStep>> steps = new ArrayList<>();
192                         Instances query = graph.adapt(L0.Migration, Instances.class);
193                         Set<Resource> migrations = new HashSet<>();
194                                 for(Resource ontology : Layer0Utils.listOntologies(graph)) {
195                                         migrations.addAll(Layer0Utils.sortByCluster(graph, query.find(graph, ontology)));
196                                 }
197                                 for(Resource migration : migrations) {
198                                         if(DEBUG)
199                                                 System.err.println("getMigrationSteps: " + graph.getURI(migration));
200                                         String format = graph.getRelatedValue(migration, L0.Migration_format);
201                                         if(DEBUG)
202                                                 System.err.println("-format=" + format);
203                                         if(parameter.equals(format)) {
204                                                 Integer from = graph.getRelatedValue(migration, L0.Migration_from);
205                                                 if(DEBUG)
206                                                         System.err.println("-from=" + from);
207                                                 Resource step = graph.getSingleObject(migration, L0.Migration_step);
208                                                 if(parameter2.equals(from)) {
209                                                         Double priority = graph.getRelatedValue(migration, L0.Migration_priority);
210                                                         steps.add(Pair.make(-priority, graph.adapt(step, MigrationStep.class))); 
211                                                         if(DEBUG)
212                                                                 System.err.println("=> ACCEPT");
213                                                 } else {
214                                                         if(DEBUG)
215                                                                 System.err.println("=> REJECT");
216                                                 }
217                                         }
218                                 }
219                                 /*
220                                 Resource base = graph.getResource(baseURI);
221                         if(DEBUG)
222                                 System.err.println("getMigrationSteps format=" + parameter + ", version=" + parameter2);
223                                 for(Resource migration : graph.sync(new ObjectsWithType(base, L0.ConsistsOf, L0.Migration))) {
224                                 }*/
225                                 return CollectionUtils.sortByFirst(steps);
226                         }
227                 
228         });
229     }
230     
231     public static Resource importMigrated(IProgressMonitor monitor, Session session, File modelFile, MigrationState state, IImportAdvisor advisor, Resource target) throws Exception {
232         Collection<Resource> roots = importMigratedMany(monitor, session, modelFile, state, advisor, target);
233         if(roots.size() == 1) {
234             return roots.iterator().next();
235         } else {
236             return null;
237         }
238     }
239
240     public static Collection<Resource> importMigratedMany(IProgressMonitor monitor, Session session, File modelFile, MigrationState state, IImportAdvisor advisor, Resource target) throws Exception {
241
242         //assert(target != null);
243         assert(advisor != null);
244         
245         if(monitor == null) monitor = new NullProgressMonitor();
246         
247         if(DEBUG)
248                 System.err.println("importMigrated: file=" + (modelFile != null ? modelFile.getAbsolutePath() : null));
249         
250         //String baseURI = state.getProperty(MigrationStateKeys.BASE_URI);
251 //      if(DEBUG)
252 //              System.err.println("importMigrated: baseURI=" + baseURI);
253
254         state.setProperty(MigrationStateKeys.MODEL_FILE, modelFile);
255         state.setProperty(MigrationStateKeys.SESSION, session);
256         state.setProperty(MigrationStateKeys.PROGRESS_MONITOR, monitor);
257         state.setProperty(MigrationStateKeys.IMPORT_ADVISOR, advisor);
258
259         DataContainer dc = state.getProperty(MigrationStateKeys.CURRENT_DATA_CONTAINER);
260         Collection<MigrationStep> migration = getMigrationSteps(dc);
261
262 //        TransferableGraph1 tg = state.getProperty(MigrationStateKeys.CURRENT_TG);
263 //        state.setProperty(MigrationStateKeys.TG_EXTENSIONS, tg.extensions);
264         
265         for(MigrationStep step : migration) {
266             step.applyTo(monitor, session, state);
267             if (monitor.isCanceled())
268                 break;
269         }
270
271         if (monitor.isCanceled()) {
272             // Move possibly created material into TrashBin and quit.
273             final Resource root = state.probeProperty(MigrationStateKeys.CURRENT_RESOURCE);
274             if (root != null) {
275                 session.syncRequest(new WriteRequest() {
276                     @Override
277                     public void perform(WriteGraph graph) throws DatabaseException {
278                         new TrashBinRemover(root).remove(graph);
279                     }
280                 });
281             }
282             return Collections.emptyList();
283         }
284
285         // Absolute path imports end up here
286         if(target == null) {
287                 Collection<Resource> roots = state.getProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES);
288                 return roots;
289         }
290                         
291         // Finally import model into final destination
292         return importTo(monitor, session, state, target, advisor);
293         
294     }
295     
296     public static TransferableGraph1 getTG(Session session, MigrationState state) throws DatabaseException {
297         return state.getProperty(MigrationStateKeys.CURRENT_TG);
298     }
299     
300     public static Resource getResource(IProgressMonitor monitor, Session session, MigrationState state) throws DatabaseException {
301         return state.getProperty(MigrationStateKeys.CURRENT_RESOURCE);
302     }
303
304     public static Collection<Resource> getRootResources(IProgressMonitor monitor, Session session, MigrationState state) throws DatabaseException {
305         return state.getProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES);
306     }
307
308     /**
309      * Get a property from the specified MigrationState and return specified
310      * default value if the property value is <code>null</code>.
311      * 
312      * @param state the state to get the property from
313      * @param key the property to get
314      * @param defaultValue
315      *            the default value to return if the property value is
316      *            <code>null</code>
317      * @return the property value
318      * @throws DatabaseException
319      *             if fetching the property fails for some reason
320      */
321     public static <T> T getProperty(MigrationState state, String key, T defaultValue) throws DatabaseException {
322         T t = state.getProperty(key);
323         return t != null ? t : defaultValue;
324     }
325
326     public static MigratedImportResult importSharedOntology(Session session, TransferableGraph1 tg, boolean published) throws DatabaseException {
327         return importSharedOntology(null, session, tg, published);
328     }
329
330     public static MigratedImportResult importSharedOntology(IProgressMonitor monitor, Session session, TransferableGraph1 tg, boolean published) throws DatabaseException {
331         
332         if(monitor == null) monitor = new NullProgressMonitor();
333         
334         Variant edbVariant = tg.extensions.get(ExternalDownloadBean.EXTENSION_KEY);
335         if(edbVariant != null) {
336                 try {
337                                 ExternalDownloadBean edb = (ExternalDownloadBean)edbVariant.getValue(ExternalDownloadBean.BINDING);
338                                 for(Map.Entry<String, String> entry : edb.downloads.entrySet()) {
339                                         String uri = entry.getKey();
340                                         Resource existing = session.syncRequest(new PossibleResource(uri));
341                                         if(existing == null) {
342                                                 String download = entry.getValue();
343                                                  URL url = new URL(download);
344                                                  DataContainer container = DataContainers.readFile(new DataInputStream(url.openStream()));
345                                                  TransferableGraph1 dependencyTg = (TransferableGraph1) container.content.getValue(TransferableGraph1.BINDING);
346                                                  importSharedOntology(monitor, session, dependencyTg, true);
347                                         }
348                                 }
349                         } catch (AdaptException e) {
350                                 throw new DatabaseException(e);
351                         } catch (MalformedURLException e) {
352                                 throw new DatabaseException(e);
353                         } catch (IOException e) {
354                                 throw new DatabaseException(e);
355                         }
356                 
357         }
358         
359         Collection<Identity> roots = TransferableGraphUtils.getRoots(tg);
360         if(roots.size() == 1) {
361             try {
362                 TGTransferableGraphSource tgSource = new TGTransferableGraphSource(tg);
363                 SharedOntologyImportAdvisor advisor = new SharedOntologyImportAdvisor(published);
364
365                 MigrationState state = newState();
366                 state.setProperty(MigrationStateKeys.UPDATE_DEPENDENCIES, false);
367                 state.setProperty(MigrationStateKeys.CURRENT_TGS, tgSource);
368                 state.setProperty(MigrationStateKeys.SESSION, session);
369                 state.setProperty(MigrationStateKeys.PROGRESS_MONITOR, monitor);
370                 state.setProperty(MigrationStateKeys.CURRENT_DATA_CONTAINER, new DataContainer("sharedLibrary", 1, new Variant(TransferableGraph1.BINDING, tg)));
371
372                 MigrationUtils.importMigrated(monitor, session, null, state, advisor, null);
373
374                 Collection<Resource> resultRoots = state.getProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES);
375                 ImportResult result = state.getProperty(MigrationStateKeys.IMPORT_RESULT);
376                 return new MigratedImportResult(resultRoots, result);
377                         } catch (TransferableGraphException e) {
378                                 throw new DatabaseException(e);
379                         } catch (MissingDependencyException e) {
380                                 throw e;
381                         } catch (DatabaseException e) {
382                                 throw e;
383                         } catch (Exception e) {
384                             throw new DatabaseException(e);
385             } finally {
386                 session.getService(XSupport.class).setServiceMode(false, false);
387             }
388             
389         }
390         
391         return null;
392         
393     }
394     
395 }