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