+/*******************************************************************************\r
+ * Copyright (c) 2012 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.layer0.migration;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.NullProgressMonitor;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.container.DataContainer;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.WriteOnlyGraph;\r
+import org.simantics.db.common.CommentMetadata;\r
+import org.simantics.db.common.request.BinaryRead;\r
+import org.simantics.db.common.request.FreshEscapedName;\r
+import org.simantics.db.common.request.UnaryRead;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.utils.VersionMap;\r
+import org.simantics.db.common.utils.VersionMapRequest;\r
+import org.simantics.db.common.utils.Versions;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.adapter.Instances;\r
+import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler;\r
+import org.simantics.db.layer0.adapter.impl.SharedOntologyImportAdvisor;\r
+import org.simantics.db.layer0.adapter.impl.TrashBinRemover;\r
+import org.simantics.db.layer0.internal.SimanticsInternal;\r
+import org.simantics.db.layer0.util.Layer0Utils;\r
+import org.simantics.db.layer0.util.TGTransferableGraphSource;\r
+import org.simantics.db.service.XSupport;\r
+import org.simantics.graph.db.IImportAdvisor;\r
+import org.simantics.graph.db.MissingDependencyException;\r
+import org.simantics.graph.db.TransferableGraphException;\r
+import org.simantics.graph.representation.Identity;\r
+import org.simantics.graph.representation.Root;\r
+import org.simantics.graph.representation.TransferableGraph1;\r
+import org.simantics.graph.representation.TransferableGraphUtils;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.utils.datastructures.Pair;\r
+import org.simantics.utils.datastructures.collections.CollectionUtils;\r
+\r
+public class MigrationUtils {\r
+ \r
+ public static final boolean DEBUG = false;\r
+\r
+ public static MigrationState newState() {\r
+ return new MigrationStateImpl();\r
+ }\r
+\r
+ public static MigrationStep getStep(Session session, String uri) throws DatabaseException {\r
+ return session.sync(new UnaryRead<String, MigrationStep>(uri) {\r
+\r
+ @Override\r
+ public MigrationStep perform(ReadGraph graph) throws DatabaseException {\r
+ Resource r = graph.getResource(parameter);\r
+ return graph.adapt(r, MigrationStep.class);\r
+ }\r
+\r
+ });\r
+ }\r
+\r
+// public static TransferableGraph1 getTG(Session session, MigrationState state) {\r
+// return getTG(session, state, true, false);\r
+// }\r
+ \r
+ public static void clearTempResource(Session session, final Resource resource) {\r
+ session.asyncRequest(new WriteRequest() {\r
+\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ graph.deny(resource, Layer0.getInstance(graph).PartOf);\r
+ }\r
+ });\r
+ }\r
+\r
+ public static Collection<Resource> importTo(IProgressMonitor monitor, Session session, MigrationState state, final Resource parent, final IImportAdvisor advisor) throws DatabaseException, TransferableGraphException {\r
+ final Resource resource = getResource(monitor, session, state);\r
+ final ArrayList<Resource> result = new ArrayList<Resource>();\r
+ if(resource != null) {\r
+ session.syncRequest(new WriteRequest() {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ \r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ \r
+ for(Resource root : graph.getObjects(resource, L0.ConsistsOf)) {\r
+ \r
+ String baseName = Versions.getBaseName(graph, root);\r
+ String version = Versions.getVersion(graph, root);\r
+ if(version != null) {\r
+ VersionMap map = graph.syncRequest(new VersionMapRequest(parent));\r
+ if(map.contains(baseName, version)) {\r
+ String newName = graph.syncRequest(new FreshEscapedName(parent, Layer0.getInstance(graph).ConsistsOf, baseName));\r
+ graph.claimLiteral(root, L0.HasName, newName + "@1", Bindings.STRING);\r
+ }\r
+ } else {\r
+ String newName = graph.syncRequest(new FreshEscapedName(parent, Layer0.getInstance(graph).ConsistsOf, baseName));\r
+ if(!newName.equals(baseName)) {\r
+ graph.claimLiteral(root, L0.HasName, newName, Bindings.STRING);\r
+ }\r
+ }\r
+\r
+ graph.deny(root, L0.PartOf);\r
+ graph.claim(root, L0.PartOf, parent);\r
+\r
+ CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
+ graph.addMetadata(cm.add("Imported " + graph.getURI(root) + ", resource " + root));\r
+ \r
+ result.add(root);\r
+ \r
+ }\r
+ \r
+ graph.deny(resource, L0.PartOf);\r
+\r
+ }\r
+ });\r
+ } else {\r
+ TransferableGraph1 tg = getTG(session, state);\r
+ if(tg != null) {\r
+ DefaultPasteHandler.defaultExecute(tg, parent, new IImportAdvisor() {\r
+ \r
+ @Override\r
+ public Resource createRoot(WriteOnlyGraph graph, Root root) throws DatabaseException {\r
+ Resource r = advisor.createRoot(graph, root);\r
+ result.add(r);\r
+ return r;\r
+ }\r
+ \r
+ @Override\r
+ public Resource analyzeRoot(ReadGraph graph, Root root) throws DatabaseException {\r
+ return advisor.analyzeRoot(graph, root);\r
+ }\r
+ });\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ \r
+ @SuppressWarnings("deprecation")\r
+ public static Collection<MigrationStep> getMigrationSteps(DataContainer header) throws DatabaseException {\r
+ \r
+ return SimanticsInternal.sync(new BinaryRead<String,Integer,Collection<MigrationStep>>(header.format, header.version) {\r
+\r
+ @Override\r
+ public Collection<MigrationStep> perform(ReadGraph graph) throws DatabaseException {\r
+ \r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ ArrayList<Pair<Double,MigrationStep>> steps = new ArrayList<Pair<Double,MigrationStep>>();\r
+ Instances query = graph.adapt(L0.Migration, Instances.class);\r
+ Set<Resource> migrations = new HashSet<Resource>();\r
+ for(Resource ontology : Layer0Utils.listOntologies(graph)) {\r
+ migrations.addAll(Layer0Utils.sortByCluster(graph, query.find(graph, ontology)));\r
+ }\r
+ for(Resource migration : migrations) {\r
+ if(DEBUG)\r
+ System.err.println("getMigrationSteps: " + graph.getURI(migration));\r
+ String format = graph.getRelatedValue(migration, L0.Migration_format);\r
+ if(DEBUG)\r
+ System.err.println("-format=" + format);\r
+ if(parameter.equals(format)) {\r
+ Integer from = graph.getRelatedValue(migration, L0.Migration_from);\r
+ if(DEBUG)\r
+ System.err.println("-from=" + from);\r
+ Resource step = graph.getSingleObject(migration, L0.Migration_step);\r
+ if(parameter2.equals(from)) {\r
+ Double priority = graph.getRelatedValue(migration, L0.Migration_priority);\r
+ steps.add(Pair.make(-priority, graph.adapt(step, MigrationStep.class))); \r
+ if(DEBUG)\r
+ System.err.println("=> ACCEPT");\r
+ } else {\r
+ if(DEBUG)\r
+ System.err.println("=> REJECT");\r
+ }\r
+ }\r
+ }\r
+ /*\r
+ Resource base = graph.getResource(baseURI);\r
+ if(DEBUG)\r
+ System.err.println("getMigrationSteps format=" + parameter + ", version=" + parameter2);\r
+ for(Resource migration : graph.sync(new ObjectsWithType(base, L0.ConsistsOf, L0.Migration))) {\r
+ }*/\r
+ return CollectionUtils.sortByFirst(steps);\r
+ }\r
+ \r
+ });\r
+ }\r
+ \r
+ public static Resource importMigrated(IProgressMonitor monitor, Session session, File modelFile, MigrationState state, IImportAdvisor advisor, Resource target) throws Exception {\r
+ Collection<Resource> roots = importMigratedMany(monitor, session, modelFile, state, advisor, target);\r
+ if(roots.size() == 1) {\r
+ return roots.iterator().next();\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public static Collection<Resource> importMigratedMany(IProgressMonitor monitor, Session session, File modelFile, MigrationState state, IImportAdvisor advisor, Resource target) throws Exception {\r
+\r
+ //assert(target != null);\r
+ assert(advisor != null);\r
+ \r
+ if(monitor == null) monitor = new NullProgressMonitor();\r
+ \r
+ if(DEBUG)\r
+ System.err.println("importMigrated: file=" + (modelFile != null ? modelFile.getAbsolutePath() : null));\r
+ \r
+ //String baseURI = state.getProperty(MigrationStateKeys.BASE_URI);\r
+// if(DEBUG)\r
+// System.err.println("importMigrated: baseURI=" + baseURI);\r
+\r
+ state.setProperty(MigrationStateKeys.MODEL_FILE, modelFile);\r
+ state.setProperty(MigrationStateKeys.SESSION, session);\r
+ state.setProperty(MigrationStateKeys.PROGRESS_MONITOR, monitor);\r
+ state.setProperty(MigrationStateKeys.IMPORT_ADVISOR, advisor);\r
+\r
+ DataContainer dc = state.getProperty(MigrationStateKeys.CURRENT_DATA_CONTAINER);\r
+ Collection<MigrationStep> migration = getMigrationSteps(dc);\r
+\r
+// TransferableGraph1 tg = state.getProperty(MigrationStateKeys.CURRENT_TG);\r
+// state.setProperty(MigrationStateKeys.TG_EXTENSIONS, tg.extensions);\r
+ \r
+ for(MigrationStep step : migration) {\r
+ step.applyTo(monitor, session, state);\r
+ if (monitor.isCanceled())\r
+ break;\r
+ }\r
+\r
+ if (monitor.isCanceled()) {\r
+ // Move possibly created material into TrashBin and quit.\r
+ final Resource root = state.probeProperty(MigrationStateKeys.CURRENT_RESOURCE);\r
+ if (root != null) {\r
+ session.syncRequest(new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ new TrashBinRemover(root).remove(graph);\r
+ }\r
+ });\r
+ }\r
+ return Collections.emptyList();\r
+ }\r
+\r
+ // Absolute path imports end up here\r
+ if(target == null) {\r
+ Collection<Resource> roots = state.getProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES);\r
+ return roots;\r
+ }\r
+ \r
+ // Finally import model into final destination\r
+ return importTo(monitor, session, state, target, advisor);\r
+ \r
+ }\r
+ \r
+ public static TransferableGraph1 getTG(Session session, MigrationState state) throws DatabaseException {\r
+ return state.getProperty(MigrationStateKeys.CURRENT_TG);\r
+ }\r
+ \r
+ public static Resource getResource(IProgressMonitor monitor, Session session, MigrationState state) throws DatabaseException {\r
+ return state.getProperty(MigrationStateKeys.CURRENT_RESOURCE);\r
+ }\r
+\r
+ public static Collection<Resource> getRootResources(IProgressMonitor monitor, Session session, MigrationState state) throws DatabaseException {\r
+ return state.getProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES);\r
+ }\r
+\r
+ /**\r
+ * Get a property from the specified MigrationState and return specified\r
+ * default value if the property value is <code>null</code>.\r
+ * \r
+ * @param state the state to get the property from\r
+ * @param key the property to get\r
+ * @param defaultValue\r
+ * the default value to return if the property value is\r
+ * <code>null</code>\r
+ * @return the property value\r
+ * @throws DatabaseException\r
+ * if fetching the property fails for some reason\r
+ */\r
+ public static <T> T getProperty(MigrationState state, String key, T defaultValue) throws DatabaseException {\r
+ T t = state.getProperty(key);\r
+ return t != null ? t : defaultValue;\r
+ }\r
+\r
+ public static Resource importSharedOntology(Session session, TransferableGraph1 tg, boolean published) throws DatabaseException {\r
+ return importSharedOntology(null, session, tg, published);\r
+ }\r
+\r
+ public static Resource importSharedOntology(IProgressMonitor monitor, Session session, TransferableGraph1 tg, boolean published) throws DatabaseException {\r
+ \r
+ if(monitor == null) monitor = new NullProgressMonitor();\r
+ \r
+ Collection<Identity> roots = TransferableGraphUtils.getRoots(tg);\r
+ if(roots.size() == 1) {\r
+// Identity id = roots.iterator().next();\r
+// final Root root = (Root)id.definition;\r
+// Resource rootResource = session.syncRequest(new WriteResultRequest<Resource>() {\r
+// @Override\r
+// public Resource perform(WriteGraph graph) throws DatabaseException {\r
+// Resource type = graph.getResource(root.type);\r
+// Resource existing = graph.getPossibleResource(root.name);\r
+// if(existing != null) throw new DatabaseException("Shared library " + root.name + " exists already.");\r
+// return Layer0Utils.applySCL("Simantics/SharedOntologies", "createSharedOntology", graph, root.name, type);\r
+// }\r
+// });\r
+ try {\r
+ \r
+ TGTransferableGraphSource tgSource = new TGTransferableGraphSource(tg);\r
+ SharedOntologyImportAdvisor advisor = new SharedOntologyImportAdvisor(published);\r
+// TransferableGraphs.importGraph1(session, tgSource, advisor);\r
+ \r
+// if (advisor.getRoots().size() == 1) {\r
+// return advisor.getRoots().iterator().next();\r
+// }\r
+ //TransferableGraphs.importGraph1(session, tg, new SharedOntologyImportAdvisor(), null);\r
+\r
+ MigrationState state = newState();\r
+ //state.setProperty(MigrationStateKeys.BASE_URI, AprosBuiltins.URIs.Migration);\r
+ state.setProperty(MigrationStateKeys.UPDATE_DEPENDENCIES, false);\r
+ state.setProperty(MigrationStateKeys.CURRENT_TGS, tgSource);\r
+ state.setProperty(MigrationStateKeys.SESSION, session);\r
+ state.setProperty(MigrationStateKeys.PROGRESS_MONITOR, monitor);\r
+ state.setProperty(MigrationStateKeys.CURRENT_DATA_CONTAINER, new DataContainer("sharedLibrary", 1, new Variant(TransferableGraph1.BINDING, tg)));\r
+\r
+ return MigrationUtils.importMigrated(monitor, session, null, state, advisor, null);\r
+ \r
+ } catch (TransferableGraphException e) {\r
+ throw new DatabaseException(e);\r
+ } catch (MissingDependencyException e) {\r
+ throw e;\r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ } finally {\r
+ session.getService(XSupport.class).setServiceMode(false, false);\r
+ }\r
+ \r
+ }\r
+ \r
+ return null;\r
+ \r
+ }\r
+ \r
+}\r