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