From c13c4179bda758e77fe1f2032d3c4268bb9e3120 Mon Sep 17 00:00:00 2001 From: Tuukka Lehtonen Date: Mon, 15 Jan 2018 16:29:39 +0200 Subject: [PATCH] Added migration step implementation for changing InstanceOf statements refs #7717 Change-Id: I0f427b5f222feae9b74d9e2d3d82becb0cda46af --- bundles/org.simantics.db.layer0/adapters.xml | 5 + .../migration/InstanceOfMigrationStep.java | 142 ++++++++++++++++++ .../graph/Layer0Migration.pgraph | 8 + 3 files changed, 155 insertions(+) create mode 100644 bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/InstanceOfMigrationStep.java diff --git a/bundles/org.simantics.db.layer0/adapters.xml b/bundles/org.simantics.db.layer0/adapters.xml index 5586b5fd1..9e85e9a1b 100644 --- a/bundles/org.simantics.db.layer0/adapters.xml +++ b/bundles/org.simantics.db.layer0/adapters.xml @@ -266,6 +266,11 @@ + + + + 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 diff --git a/bundles/org.simantics.layer0/graph/Layer0Migration.pgraph b/bundles/org.simantics.layer0/graph/Layer0Migration.pgraph index a2be43da6..49361d515 100644 --- a/bundles/org.simantics.layer0/graph/Layer0Migration.pgraph +++ b/bundles/org.simantics.layer0/graph/Layer0Migration.pgraph @@ -55,3 +55,11 @@ L0.OrderedSetToListMigrationStep.Change -- L0.OrderedSetToListMigrationStep.orderedSetType --> L0.String -- L0.OrderedSetToListMigrationStep.listRelation --> L0.String -- L0.OrderedSetToListMigrationStep.listType --> L0.String