X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Fmigration%2FInstanceOfMigrationStep.java;fp=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Fmigration%2FInstanceOfMigrationStep.java;h=26b051a417f17b31dfd165a301b4f87566f01ed5;hp=0000000000000000000000000000000000000000;hb=c13c4179bda758e77fe1f2032d3c4268bb9e3120;hpb=72186a982dc8b076bef48313fbbd22ecc78c08bc diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/InstanceOfMigrationStep.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/InstanceOfMigrationStep.java new file mode 100644 index 000000000..26b051a41 --- /dev/null +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/InstanceOfMigrationStep.java @@ -0,0 +1,142 @@ +package org.simantics.db.layer0.migration; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.common.request.DelayedWriteRequest; +import org.simantics.db.common.utils.ListUtils; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.impl.EntityInstances.QueryIndex; +import org.simantics.db.layer0.request.PossibleResource; +import org.simantics.layer0.Layer0; + +/** + * Changes L0.InstanceOf relations according to descriptions in the migrated + * index root. + * + * @author Tuukka Lehtonen + * @since 1.33.0 + */ +public class InstanceOfMigrationStep implements MigrationStep { + + private static class Migration { + public final String fromUri; + public final String toUri; + + public Migration(String from, String to) { + this.fromUri = from; + this.toUri = to; + } + + @Override + public String toString() { + return fromUri + " -> " + toUri; + } + } + + private static class RMigration { + public final Migration m; + public final Resource from; + public final Resource to; + + public RMigration(RequestProcessor processor, Migration m) throws DatabaseException { + this.m = m; + this.from = processor.syncRequest(new PossibleResource(m.fromUri)); + this.to = processor.syncRequest(new PossibleResource(m.toUri)); + } + + public boolean isValid() { + return from != null && to != null; + } + } + + private final Migration[] migrations; + + public InstanceOfMigrationStep(String fromUri, String toUri) { + this.migrations = new Migration[] { new Migration(fromUri, toUri) }; + } + + public InstanceOfMigrationStep(ReadGraph graph, Resource step) throws DatabaseException { + List ms = new ArrayList<>(); + List uris = ListUtils.toList(graph, step); + int size = uris.size() & ~1; + for (int i = 0; i < size; i += 2) { + String from = graph.getPossibleValue(uris.get(i), Bindings.STRING); + String to = graph.getPossibleValue(uris.get(i+1), Bindings.STRING); + if (from != null && to != null) + ms.add(new Migration(from, to)); + } + migrations = ms.toArray(new Migration[ms.size()]); + } + + @Override + public void applyTo(final IProgressMonitor monitor, Session session, MigrationState state) throws DatabaseException { + final Collection roots = state.getProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES); + if (roots.isEmpty()) + return; + final PrintWriter log = MigrationUtils.getProperty(state, MigrationStateKeys.MESSAGE_LOG_WRITER, NullWriter.PRINT_INSTANCE); + + session.sync(new DelayedWriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + migrateInstances(monitor, graph, roots, log); + } + }); + } + + private void migrateInstances(IProgressMonitor monitor, WriteGraph graph, Collection roots, PrintWriter log) throws DatabaseException { + for (Migration m : migrations) + migrateInstances(monitor, graph, new RMigration(graph, m), roots, log); + } + + private void migrateInstances(IProgressMonitor monitor, WriteGraph graph, RMigration rm, Collection roots, PrintWriter log) throws DatabaseException { + log.println("## InstanceOf Migration ##"); + log.println("* From: `" + rm.m.fromUri + "`"); + log.println("* To: `" + rm.m.toUri + "`"); + if (rm.isValid()) { + for (Resource root : roots) + migrateInstances(monitor, graph, root, rm, log); + } else { + log.println("\nSkipping migration as invalid.\n"); + } + } + + private static void migrateInstances(IProgressMonitor monitor, WriteGraph graph, Resource root, RMigration migration, PrintWriter log) throws DatabaseException { + log.println("### Migrating root `" + NameUtils.getSafeName(graph, root) + "` ###"); + String rootUri = NameUtils.getURIOrSafeNameInternal(graph, root); + Layer0 L0 = Layer0.getInstance(graph); + + for (Resource instance : instancesOf(graph, root, migration.from)) { + if (graph.hasStatement(instance, L0.InstanceOf, migration.from)) { + graph.deny(instance, L0.InstanceOf, null, migration.from); + graph.claim(instance, L0.InstanceOf, null, migration.to); + log.println("* `" + relativeUri(graph, rootUri, instance) + "`"); + } + } + } + + private static List instancesOf(ReadGraph graph, Resource root, Resource type) throws DatabaseException { + return graph.syncRequest( + new QueryIndex(root, type, ""), + TransientCacheListener.>instance()); + } + + private static String relativeUri(ReadGraph graph, String rootUri, Resource r) throws DatabaseException { + String uri = graph.getPossibleURI(r); + return uri != null + ? uri.substring(rootUri.length()) + : NameUtils.getURIOrSafeNameInternal(graph, r); + } + +} \ No newline at end of file