1 package org.simantics.graph.db;
\r
3 import java.io.DataOutput;
\r
4 import java.io.DataOutputStream;
\r
5 import java.io.FileNotFoundException;
\r
6 import java.io.FileOutputStream;
\r
7 import java.io.IOException;
\r
8 import java.util.HashSet;
\r
9 import java.util.Map;
\r
10 import java.util.Set;
\r
12 import org.simantics.databoard.Bindings;
\r
13 import org.simantics.databoard.accessor.error.AccessorException;
\r
14 import org.simantics.databoard.adapter.AdaptException;
\r
15 import org.simantics.databoard.binding.mutable.Variant;
\r
16 import org.simantics.db.ReadGraph;
\r
17 import org.simantics.db.Resource;
\r
18 import org.simantics.db.WriteOnlyGraph;
\r
19 import org.simantics.db.common.WriteBindings;
\r
20 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
\r
21 import org.simantics.db.common.uri.UnescapedChildMapOfResource;
\r
22 import org.simantics.db.common.utils.Logger;
\r
23 import org.simantics.db.common.utils.NameUtils;
\r
24 import org.simantics.db.exception.DatabaseException;
\r
25 import org.simantics.db.exception.ResourceNotFoundException;
\r
26 import org.simantics.db.service.ClusterBuilder;
\r
27 import org.simantics.db.service.ClusterBuilder.ResourceHandle;
\r
28 import org.simantics.db.service.SerialisationSupport;
\r
29 import org.simantics.graph.representation.Extensions;
\r
30 import org.simantics.graph.representation.External;
\r
31 import org.simantics.graph.representation.Identity;
\r
32 import org.simantics.graph.representation.IdentityDefinition;
\r
33 import org.simantics.graph.representation.Internal;
\r
34 import org.simantics.graph.representation.Optional;
\r
35 import org.simantics.graph.representation.Root;
\r
36 import org.simantics.graph.representation.TransferableGraph1;
\r
37 import org.simantics.graph.representation.TransferableGraphUtils;
\r
38 import org.simantics.graph.representation.Value;
\r
39 import org.simantics.graph.utils.TGResourceUtil;
\r
40 import org.simantics.graph.utils.TGResourceUtil.LongAdapter;
\r
42 public class TransferableGraphImportProcess implements TransferableGraphImporter {
\r
44 public static String LOG_FILE = "transferableGraphs.log";
\r
45 final static private boolean LOG = false;
\r
47 static DataOutput log;
\r
53 FileOutputStream stream = new FileOutputStream(LOG_FILE);
\r
54 log = new DataOutputStream(stream);
\r
55 } catch (FileNotFoundException e) {
\r
56 e.printStackTrace();
\r
62 private static void log(String line) {
\r
65 log.writeUTF(line + "\n");
\r
66 } catch (IOException e) {
\r
67 e.printStackTrace();
\r
72 TransferableGraph1 tg;
\r
73 IImportAdvisor advisor;
\r
74 TGStatusMonitor monitor;
\r
75 final TGResourceUtil resourceUtil = new TGResourceUtil();
\r
77 Resource[] resources;
\r
78 ResourceHandle[] handles;
\r
80 Set<String> missingExternals = new HashSet<String>();
\r
83 Resource RootLibrary;
\r
87 Resource InstanceOf;
\r
88 Resource ConsistsOf;
\r
93 public TransferableGraphImportProcess(TransferableGraph1 tg, IImportAdvisor advisor, TGStatusMonitor monitor) {
\r
95 this.advisor = advisor;
\r
96 this.monitor = monitor;
\r
99 public TransferableGraphImportProcess(TransferableGraph1 tg, IImportAdvisor advisor) {
\r
100 this(tg, advisor, null);
\r
103 public void findBuiltins(WriteOnlyGraph g) throws DatabaseException {
\r
104 RootLibrary = g.getBuiltin("http:/");
\r
105 String = g.getBuiltin(CoreInitialization.LAYER0 + "String");
\r
106 Library = g.getBuiltin(CoreInitialization.LAYER0 + "Library");
\r
107 InstanceOf = g.getBuiltin(CoreInitialization.LAYER0 + "InstanceOf");
\r
108 ConsistsOf = g.getBuiltin(CoreInitialization.LAYER0 + "ConsistsOf");
\r
109 PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");
\r
110 HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");
\r
111 NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");
\r
114 public void findBuiltins(ReadGraph g) throws DatabaseException {
\r
115 RootLibrary = g.getBuiltin("http:/");
\r
116 String = g.getBuiltin(CoreInitialization.LAYER0 + "String");
\r
117 Library = g.getBuiltin(CoreInitialization.LAYER0 + "Library");
\r
118 InstanceOf = g.getBuiltin(CoreInitialization.LAYER0 + "InstanceOf");
\r
119 ConsistsOf = g.getBuiltin(CoreInitialization.LAYER0 + "ConsistsOf");
\r
120 PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");
\r
121 HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");
\r
122 NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");
\r
125 /* Preparation that is used when the core is empty.
\r
127 void initialPrepare(WriteOnlyGraph graph) throws DatabaseException {
\r
128 findBuiltins(graph);
\r
130 resources = new Resource[tg.resourceCount];
\r
133 int SimanticsDomain = -1;
\r
136 for(Identity identity : tg.identities) {
\r
137 if(identity.definition instanceof Internal) {
\r
138 Internal def = (Internal)identity.definition;
\r
139 Resource res = null;
\r
140 if(def.parent == Layer0) {
\r
142 res = graph.getBuiltin(CoreInitialization.LAYER0 + def.name);
\r
143 } catch(ResourceNotFoundException e) {
\r
146 else if(def.parent == SimanticsDomain) {
\r
147 if(def.name.equals("Layer0-1.1"))
\r
148 Layer0 = identity.resource;
\r
150 else if(def.parent == Root) {
\r
151 if(def.name.equals("www.simantics.org"))
\r
152 SimanticsDomain = identity.resource;
\r
156 res = createChild(graph, resources[def.parent], def.name);
\r
158 createChild(graph, res, resources[def.parent], def.name);
\r
159 resources[identity.resource] = res;
\r
161 else if(identity.definition instanceof Root) {
\r
162 Root = identity.resource;
\r
163 resources[identity.resource] = RootLibrary;
\r
168 void addMissing(String external) {
\r
169 Set<String> removals = new HashSet<String>();
\r
170 for(String ext : missingExternals) if(ext.startsWith(external)) return;
\r
171 for(String ext : missingExternals) if(external.startsWith(ext)) removals.add(ext);
\r
172 missingExternals.removeAll(removals);
\r
173 missingExternals.add(external);
\r
176 void prepare(ReadGraph graph) throws DatabaseException {
\r
177 findBuiltins(graph);
\r
179 Resource[] resources = new Resource[tg.resourceCount];
\r
181 for(Identity identity : tg.identities) {
\r
182 IdentityDefinition definition = identity.definition;
\r
183 if(definition instanceof External) {
\r
184 External def = (External)definition;
\r
185 if(def.parent == -1) {
\r
186 resources[identity.resource] = RootLibrary;
\r
188 if("@inverse".equals(def.name)) {
\r
189 Resource parent = resources[def.parent];
\r
190 Resource child = graph.getInverse(parent);
\r
191 resources[identity.resource] = child;
\r
193 Resource parent = resources[def.parent];
\r
194 // TODO: escape should be removed when names become well-behaving
\r
195 if(parent != null) {
\r
196 Resource child = graph
\r
197 .syncRequest(new UnescapedChildMapOfResource(parent),
\r
198 new TransientCacheAsyncListener<Map<String, Resource>>())
\r
200 if(child == null) {
\r
201 String uri = graph.getPossibleURI(parent);
\r
203 addMissing(NameUtils.getSafeName(graph, parent) + " /" + def.name);
\r
205 addMissing(graph.getURI(parent) + "/" + def.name);
\r
208 resources[identity.resource] = child;
\r
210 addMissing(TransferableGraphUtils.getURI(tg, def.parent) + "/" + def.name);
\r
215 else if(definition instanceof Internal) {
\r
216 // Do not do anything for now
\r
218 else if(definition instanceof Root) {
\r
219 Root root = (Root)definition;
\r
220 if(root.name.equals(""))
\r
221 resources[identity.resource] = RootLibrary;
\r
223 Resource existing = advisor.analyzeRoot(graph, root);
\r
224 if(existing != null)
\r
225 resources[identity.resource] = existing;
\r
228 else if(definition instanceof Optional) {
\r
229 External def = (External)definition;
\r
230 Resource parent = resources[def.parent];
\r
232 resources[identity.resource] =
\r
233 graph.syncRequest(new UnescapedChildMapOfResource(parent)).get(def.name);
\r
237 this.resources = resources;
\r
239 if(!missingExternals.isEmpty()) throw new MissingDependencyException(this);
\r
243 Resource createChild(WriteOnlyGraph graph, Resource parent, String name) throws DatabaseException {
\r
244 Resource child = graph.newResource();
\r
245 //graph.claim(parent, ConsistsOf, PartOf, child);
\r
246 Resource nameResource = graph.newResource();
\r
247 graph.claim(nameResource, InstanceOf, null, String);
\r
248 graph.claimValue(nameResource, name, WriteBindings.STRING);
\r
249 graph.claim(child, HasName, NameOf, nameResource);
\r
254 public Resource createChild(WriteOnlyGraph graph, Resource child, Resource parent, String name) throws DatabaseException {
\r
255 graph.claim(parent, ConsistsOf, PartOf, child);
\r
256 Resource nameResource = graph.newResource();
\r
257 graph.claim(nameResource, InstanceOf, null, String);
\r
258 graph.claimValue(nameResource, name, WriteBindings.STRING);
\r
259 graph.claim(child, HasName, NameOf, nameResource);
\r
263 int[] getClustering() {
\r
264 Variant v = tg.extensions.get(Extensions.CLUSTERING);
\r
265 if(v == null) return null;
\r
267 return (int[])v.getValue(Bindings.INT_ARRAY);
\r
268 } catch (AdaptException e) {
\r
269 Logger.defaultLogError(e);
\r
274 class ResourceAdapter implements LongAdapter {
\r
275 final SerialisationSupport ss;
\r
278 ResourceAdapter(SerialisationSupport ss, Value value) {
\r
280 this.value = value;
\r
283 public long adapt(long in) {
\r
284 if(original == null) original = value.value.clone();
\r
285 Resource res = handles[(int)in].resource(ss);
\r
287 if(res == null) return in;
\r
288 return res.getResourceId();
\r
292 Variant translate(SerialisationSupport ss, Value value, final ResourceHandle[] handles) throws DatabaseException {
\r
295 ResourceAdapter adapter = new ResourceAdapter(ss, value);
\r
296 resourceUtil.adaptValue( value.value.getBinding(), value.value.getValue(), adapter);
\r
297 Variant result = value.value;
\r
298 if(adapter.original != null) value.value = adapter.original;
\r
300 } catch (AccessorException e) {
\r
301 e.printStackTrace();
\r
304 return value.value;
\r
308 class ResourceAdapter2 implements LongAdapter {
\r
311 ResourceAdapter2(Value value) {
\r
312 this.value = value;
\r
315 public long adapt(long in) {
\r
316 if(original == null) original = value.value.clone();
\r
317 Resource res = resources[(int)in];
\r
319 if(res == null) return in;
\r
320 return res.getResourceId();
\r
324 Variant translate2(Value value, final Resource[] resources) throws DatabaseException {
\r
327 ResourceAdapter2 adapter = new ResourceAdapter2(value);
\r
328 resourceUtil.adaptValue( value.value.getBinding(), value.value.getValue(), adapter);
\r
329 Variant result = value.value;
\r
330 if(adapter.original != null) value.value = adapter.original;
\r
332 } catch (AccessorException e) {
\r
333 e.printStackTrace();
\r
336 return value.value;
\r
340 void write(WriteOnlyGraph graph) throws DatabaseException {
\r
342 Resource[] resources = this.resources;
\r
344 this.handles = new ResourceHandle[resources.length];
\r
346 ResourceHandle[] handles = this.handles;
\r
348 int[] clustering = getClustering();
\r
350 // Internal identities
\r
351 for(Identity identity : tg.identities) {
\r
352 IdentityDefinition definition = identity.definition;
\r
353 if(resources[identity.resource] != null)
\r
355 if(definition instanceof External) {
\r
356 // Already done everything
\r
358 else if(definition instanceof Internal) {
\r
359 Internal def = (Internal)definition;
\r
360 resources[identity.resource] =
\r
361 createChild(graph, resources[def.parent], def.name);
\r
363 else if(definition instanceof Root) {
\r
364 Root root = (Root)definition;
\r
365 resources[identity.resource] = advisor.createRoot(graph, root);
\r
367 else if(definition instanceof Optional) {
\r
368 Optional def = (Optional)definition;
\r
369 Resource child = createChild(graph, resources[def.parent], def.name);
\r
370 graph.claim(child, InstanceOf, null, Library); // ???
\r
371 resources[identity.resource] = child;
\r
375 ClusterBuilder builder = graph.getService(ClusterBuilder.class);
\r
376 SerialisationSupport ss = graph.getService(SerialisationSupport.class);
\r
378 if(clustering != null) {
\r
381 for(int c : clustering) {
\r
382 builder.newCluster();
\r
383 for(int r=0;r<c;r++, i++)
\r
384 if(resources[i] == null)
\r
385 handles[i] = builder.newResource();
\r
387 handles[i] = builder.resource(resources[i]);
\r
391 for(;i<resources.length;++i)
\r
392 if(resources[i] == null)
\r
393 handles[i] = builder.newResource();
\r
395 handles[i] = builder.resource(resources[i]);
\r
399 // Create blank resources
\r
400 for(int i=0;i<resources.length;++i)
\r
401 if(resources[i] == null)
\r
402 handles[i] = builder.newResource();
\r
404 handles[i] = builder.resource(resources[i]);
\r
408 // Write statements
\r
409 int[] statements = tg.statements;
\r
411 // int internals = tg.resourceCount - tg.identities.length;
\r
413 for(int i=0;i<statements.length;i+=4) {
\r
415 int sub = statements[i];
\r
416 int pred = statements[i+1];
\r
417 int inv = statements[i+2];
\r
418 int obj = statements[i+3];
\r
420 ResourceHandle subject = handles[sub];
\r
421 ResourceHandle predicate = handles[pred];
\r
422 ResourceHandle object = handles[obj];
\r
424 if(resources[sub] == null) {
\r
425 subject.addStatement(graph, predicate, object);
\r
428 handles[sub].resource(ss),
\r
429 handles[pred].resource(ss),
\r
430 null, handles[obj].resource(ss));
\r
435 if(resources[obj] == null) {
\r
436 ResourceHandle inverse = handles[inv];
\r
437 object.addStatement(graph, inverse, subject);
\r
439 Resource s = handles[obj].resource(ss);
\r
440 if(!graph.isImmutable(s))
\r
443 handles[inv].resource(ss),
\r
444 null, handles[sub].resource(ss));
\r
450 log("[STATEMENT] " + resources[statements[i]].getResourceId() + ", " + resources[statements[i+1]].getResourceId() + ", " + resources[statements[i+3]].getResourceId());
\r
456 for(Value value : tg.values) {
\r
457 Variant variant = translate(ss, value, handles);
\r
458 int file = value.resource & 0x80000000;
\r
459 int resource = value.resource & 0x7FFFFFFF;
\r
461 throw new UnsupportedOperationException();
\r
462 //graph.claimValue(handles[resource].resource(), value.value, Bindings.BYTE_ARRAY);
\r
464 graph.claimValue(handles[resource].resource(ss), variant.getValue(), variant.getBinding());
\r
469 private int updatePercentage(int percentage, int done, int total) {
\r
470 if(monitor != null && (done & 63) == 0) {
\r
471 int current = 100*done / total;
\r
472 if(current > percentage) {
\r
473 percentage = current;
\r
474 monitor.status(percentage);
\r
480 void write2(WriteOnlyGraph graph) throws DatabaseException {
\r
481 Resource[] resources = this.resources;
\r
483 // Internal identities
\r
484 for(Identity identity : tg.identities) {
\r
485 IdentityDefinition definition = identity.definition;
\r
486 if(resources[identity.resource] != null)
\r
488 if(definition instanceof External) {
\r
489 // Already done everything
\r
491 else if(definition instanceof Internal) {
\r
492 Internal def = (Internal)definition;
\r
493 resources[identity.resource] =
\r
494 createChild(graph, resources[def.parent], def.name);
\r
496 else if(definition instanceof Root) {
\r
497 Root root = (Root)definition;
\r
498 resources[identity.resource] = advisor.createRoot(graph, root);
\r
500 else if(definition instanceof Optional) {
\r
501 Optional def = (Optional)definition;
\r
502 Resource child = createChild(graph, resources[def.parent], def.name);
\r
503 graph.claim(child, InstanceOf, null, Library); // ???
\r
504 resources[identity.resource] = child;
\r
508 // Create blank resources
\r
509 for(int i=0;i<resources.length;++i)
\r
510 if(resources[i] == null)
\r
511 resources[i] = graph.newResource();
\r
513 int total = tg.statements.length + tg.values.length;
\r
515 int percentage = 0;
\r
517 // Write statements
\r
518 int[] statements = tg.statements;
\r
520 for(int i=0;i<statements.length;i+=4) {
\r
521 int inv = statements[i+2];
\r
523 resources[statements[i]],
\r
524 resources[statements[i+1]],
\r
525 inv < 0 ? null : resources[inv],
\r
526 resources[statements[i+3]]
\r
529 log("[STATEMENT] " + resources[statements[i]].getResourceId() + ", " + resources[statements[i+1]].getResourceId() + ", " + resources[statements[i+3]].getResourceId());
\r
531 percentage = updatePercentage(percentage, done++, total);
\r
535 for(Value value : tg.values) {
\r
536 Variant variant = translate2(value, resources);
\r
537 int file = value.resource & 0x80000000;
\r
538 int resource = value.resource & 0x7FFFFFFF;
\r
540 throw new UnsupportedOperationException();
\r
541 //graph.claimValue(resources[resource], value.value, Bindings.BYTE_ARRAY);
\r
543 graph.claimValue(resources[resource], variant.getValue(), variant.getBinding());
\r
545 percentage = updatePercentage(percentage, done++, total);
\r
550 public long[] getResourceIds(SerialisationSupport serializer) throws DatabaseException {
\r
551 final int count = resources.length;
\r
552 long[] resourceIds = new long[count];
\r
553 if(handles != null) {
\r
554 for(int i=0;i<count;++i)
\r
555 resourceIds[i] = serializer.getRandomAccessId(handles[i].resource(serializer));
\r
557 for(int i=0;i<count;++i)
\r
558 resourceIds[i] = serializer.getRandomAccessId(resources[i]);
\r
560 return resourceIds;
\r