]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/migration/InstanceOfMigrationStep.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / migration / InstanceOfMigrationStep.java
1 package org.simantics.db.layer0.migration;
2
3 import java.io.PrintWriter;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.List;
7
8 import org.eclipse.core.runtime.IProgressMonitor;
9 import org.simantics.databoard.Bindings;
10 import org.simantics.db.ReadGraph;
11 import org.simantics.db.RequestProcessor;
12 import org.simantics.db.Resource;
13 import org.simantics.db.Session;
14 import org.simantics.db.WriteGraph;
15 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
16 import org.simantics.db.common.request.DelayedWriteRequest;
17 import org.simantics.db.common.utils.ListUtils;
18 import org.simantics.db.common.utils.NameUtils;
19 import org.simantics.db.exception.DatabaseException;
20 import org.simantics.db.layer0.adapter.impl.EntityInstances.QueryIndex;
21 import org.simantics.db.layer0.request.PossibleResource;
22 import org.simantics.layer0.Layer0;
23
24 /**
25  * Changes L0.InstanceOf relations according to descriptions in the migrated
26  * index root.
27  * 
28  * @author Tuukka Lehtonen
29  * @since 1.33.0
30  */
31 public class InstanceOfMigrationStep implements MigrationStep {
32
33     private static class Migration {
34         public final String fromUri;
35         public final String toUri;
36
37         public Migration(String from, String to) {
38             this.fromUri = from;
39             this.toUri = to;
40         }
41
42         @Override
43         public String toString() {
44             return fromUri + " -> " + toUri;
45         }
46     }
47
48     private static class RMigration {
49         public final Migration m;
50         public final Resource from;
51         public final Resource to;
52
53         public RMigration(RequestProcessor processor, Migration m) throws DatabaseException {
54             this.m = m;
55             this.from = processor.syncRequest(new PossibleResource(m.fromUri));
56             this.to = processor.syncRequest(new PossibleResource(m.toUri));
57         }
58
59         public boolean isValid() {
60             return from != null && to != null;
61         }
62     }
63
64     private final Migration[] migrations;
65
66     public InstanceOfMigrationStep(String fromUri, String toUri) {
67         this.migrations = new Migration[] { new Migration(fromUri, toUri) };
68     }
69
70     public InstanceOfMigrationStep(ReadGraph graph, Resource step) throws DatabaseException {
71         List<Migration> ms = new ArrayList<>();
72         List<Resource> uris = ListUtils.toList(graph, step);
73         int size = uris.size() & ~1;
74         for (int i = 0; i < size; i += 2) {
75             String from = graph.getPossibleValue(uris.get(i), Bindings.STRING);
76             String to   = graph.getPossibleValue(uris.get(i+1), Bindings.STRING);
77             if (from != null && to != null)
78                 ms.add(new Migration(from, to));
79         }
80         migrations = ms.toArray(new Migration[ms.size()]);
81     }
82
83     @Override
84     public void applyTo(final IProgressMonitor monitor, Session session, MigrationState state) throws DatabaseException {
85         final Collection<Resource> roots = state.getProperty(MigrationStateKeys.CURRENT_ROOT_RESOURCES);
86         if (roots.isEmpty())
87             return;
88         final PrintWriter log = MigrationUtils.getProperty(state, MigrationStateKeys.MESSAGE_LOG_WRITER, NullWriter.PRINT_INSTANCE);
89
90         session.sync(new DelayedWriteRequest() {
91             @Override
92             public void perform(WriteGraph graph) throws DatabaseException {
93                 migrateInstances(monitor, graph, roots, log);
94             }
95         });
96     }
97
98     private void migrateInstances(IProgressMonitor monitor, WriteGraph graph, Collection<Resource> roots, PrintWriter log) throws DatabaseException {
99         for (Migration m : migrations)
100             migrateInstances(monitor, graph, new RMigration(graph, m), roots, log);
101     }
102
103     private void migrateInstances(IProgressMonitor monitor, WriteGraph graph, RMigration rm, Collection<Resource> roots, PrintWriter log) throws DatabaseException {
104         log.println("## InstanceOf Migration ##");
105         log.println("* From: `" + rm.m.fromUri + "`");
106         log.println("* To: `" + rm.m.toUri + "`");
107         if (rm.isValid()) {
108             for (Resource root : roots)
109                 migrateInstances(monitor, graph, root, rm, log);
110         } else {
111             log.println("\nSkipping migration as invalid.\n");
112         }
113     }
114
115     private static void migrateInstances(IProgressMonitor monitor, WriteGraph graph, Resource root, RMigration migration, PrintWriter log) throws DatabaseException {
116         log.println("### Migrating root `" + NameUtils.getSafeName(graph, root) + "` ###");
117         String rootUri = NameUtils.getURIOrSafeNameInternal(graph, root); 
118         Layer0 L0 = Layer0.getInstance(graph);
119
120         for (Resource instance : instancesOf(graph, root, migration.from)) {
121             if (graph.hasStatement(instance, L0.InstanceOf, migration.from)) {
122                 graph.deny(instance, L0.InstanceOf, null, migration.from);
123                 graph.claim(instance, L0.InstanceOf, null, migration.to);
124                 log.println("* `" + relativeUri(graph, rootUri, instance) + "`");
125             }
126         }
127     }
128
129     private static List<Resource> instancesOf(ReadGraph graph, Resource root, Resource type) throws DatabaseException {
130         return graph.syncRequest(
131                 new QueryIndex(root, type, ""),
132                 TransientCacheListener.<List<Resource>>instance());
133     }
134
135     private static String relativeUri(ReadGraph graph, String rootUri, Resource r) throws DatabaseException {
136         String uri = graph.getPossibleURI(r);
137         return uri != null
138                 ? uri.substring(rootUri.length())
139                 : NameUtils.getURIOrSafeNameInternal(graph, r);
140     }
141
142 }