1 package org.simantics.graph.db;
3 import java.io.DataOutput;
4 import java.io.DataOutputStream;
5 import java.io.FileNotFoundException;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.util.HashSet;
12 import org.simantics.databoard.Bindings;
13 import org.simantics.databoard.accessor.error.AccessorException;
14 import org.simantics.databoard.adapter.AdaptException;
15 import org.simantics.databoard.binding.mutable.Variant;
16 import org.simantics.databoard.util.URIStringUtils;
17 import org.simantics.db.ReadGraph;
18 import org.simantics.db.Resource;
19 import org.simantics.db.WriteOnlyGraph;
20 import org.simantics.db.common.WriteBindings;
21 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
22 import org.simantics.db.common.uri.UnescapedChildMapOfResource;
23 import org.simantics.db.common.utils.Logger;
24 import org.simantics.db.common.utils.NameUtils;
25 import org.simantics.db.exception.DatabaseException;
26 import org.simantics.db.exception.ResourceNotFoundException;
27 import org.simantics.db.service.ClusterBuilder;
28 import org.simantics.db.service.ClusterBuilder.ResourceHandle;
29 import org.simantics.db.service.SerialisationSupport;
30 import org.simantics.graph.representation.Extensions;
31 import org.simantics.graph.representation.External;
32 import org.simantics.graph.representation.Identity;
33 import org.simantics.graph.representation.IdentityDefinition;
34 import org.simantics.graph.representation.Internal;
35 import org.simantics.graph.representation.Optional;
36 import org.simantics.graph.representation.Root;
37 import org.simantics.graph.representation.TransferableGraph1;
38 import org.simantics.graph.representation.TransferableGraphUtils;
39 import org.simantics.graph.representation.Value;
40 import org.simantics.graph.utils.TGResourceUtil;
41 import org.simantics.graph.utils.TGResourceUtil.LongAdapter;
43 public class TransferableGraphImportProcess implements TransferableGraphImporter {
45 public static String LOG_FILE = "transferableGraphs.log";
46 final static private boolean LOG = false;
48 static DataOutput log;
54 FileOutputStream stream = new FileOutputStream(LOG_FILE);
55 log = new DataOutputStream(stream);
56 } catch (FileNotFoundException e) {
63 private static void log(String line) {
66 log.writeUTF(line + "\n");
67 } catch (IOException e) {
73 TransferableGraph1 tg;
74 IImportAdvisor advisor;
75 TGStatusMonitor monitor;
76 final TGResourceUtil resourceUtil = new TGResourceUtil();
79 ResourceHandle[] handles;
81 Set<String> missingExternals = new HashSet<String>();
94 public TransferableGraphImportProcess(TransferableGraph1 tg, IImportAdvisor advisor, TGStatusMonitor monitor) {
96 this.advisor = advisor;
97 this.monitor = monitor;
100 public TransferableGraphImportProcess(TransferableGraph1 tg, IImportAdvisor advisor) {
101 this(tg, advisor, null);
104 public void findBuiltins(WriteOnlyGraph g) throws DatabaseException {
105 RootLibrary = g.getBuiltin("http:/");
106 String = g.getBuiltin(CoreInitialization.LAYER0 + "String");
107 Library = g.getBuiltin(CoreInitialization.LAYER0 + "Library");
108 InstanceOf = g.getBuiltin(CoreInitialization.LAYER0 + "InstanceOf");
109 ConsistsOf = g.getBuiltin(CoreInitialization.LAYER0 + "ConsistsOf");
110 PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");
111 HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");
112 NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");
115 public void findBuiltins(ReadGraph g) throws DatabaseException {
116 RootLibrary = g.getBuiltin("http:/");
117 String = g.getBuiltin(CoreInitialization.LAYER0 + "String");
118 Library = g.getBuiltin(CoreInitialization.LAYER0 + "Library");
119 InstanceOf = g.getBuiltin(CoreInitialization.LAYER0 + "InstanceOf");
120 ConsistsOf = g.getBuiltin(CoreInitialization.LAYER0 + "ConsistsOf");
121 PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");
122 HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");
123 NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");
126 /* Preparation that is used when the core is empty.
128 void initialPrepare(WriteOnlyGraph graph) throws DatabaseException {
131 resources = new Resource[tg.resourceCount];
134 int SimanticsDomain = -1;
137 for(Identity identity : tg.identities) {
138 if(identity.definition instanceof Internal) {
139 Internal def = (Internal)identity.definition;
141 if(def.parent == Layer0) {
143 res = graph.getBuiltin(CoreInitialization.LAYER0 + def.name);
144 } catch(ResourceNotFoundException e) {
147 else if(def.parent == SimanticsDomain) {
148 if(def.name.equals("Layer0-1.1"))
149 Layer0 = identity.resource;
151 else if(def.parent == Root) {
152 if(def.name.equals("www.simantics.org"))
153 SimanticsDomain = identity.resource;
157 res = createChild(graph, resources[def.parent], def.name);
159 createChild(graph, res, resources[def.parent], def.name);
160 resources[identity.resource] = res;
162 else if(identity.definition instanceof Root) {
163 Root = identity.resource;
164 resources[identity.resource] = RootLibrary;
169 void addMissing(String external) {
170 Set<String> removals = new HashSet<String>();
171 for(String ext : missingExternals) if(ext.startsWith(external)) return;
172 for(String ext : missingExternals) if(external.startsWith(ext)) removals.add(ext);
173 missingExternals.removeAll(removals);
174 missingExternals.add(external);
177 void prepare(ReadGraph graph) throws DatabaseException {
180 Resource[] resources = new Resource[tg.resourceCount];
182 for(Identity identity : tg.identities) {
183 IdentityDefinition definition = identity.definition;
184 if(definition instanceof External) {
185 External def = (External)definition;
186 if(def.parent == -1) {
187 resources[identity.resource] = RootLibrary;
189 if("@inverse".equals(def.name)) {
190 Resource parent = resources[def.parent];
191 Resource child = graph.getInverse(parent);
192 resources[identity.resource] = child;
194 Resource parent = resources[def.parent];
195 // TODO: escape should be removed when names become well-behaving
197 Resource child = graph
198 .syncRequest(new UnescapedChildMapOfResource(parent),
199 new TransientCacheAsyncListener<Map<String, Resource>>())
202 String uri = graph.getPossibleURI(parent);
204 addMissing(URIStringUtils.escape(NameUtils.getSafeName(graph, parent)) + " /" + URIStringUtils.escape(def.name));
206 addMissing(graph.getURI(parent) + "/" + URIStringUtils.escape(def.name));
209 resources[identity.resource] = child;
211 addMissing(TransferableGraphUtils.getURI(tg, def.parent) + "/" + URIStringUtils.escape(def.name));
216 else if(definition instanceof Internal) {
217 // Do not do anything for now
219 else if(definition instanceof Root) {
220 Root root = (Root)definition;
221 if(root.name.equals(""))
222 resources[identity.resource] = RootLibrary;
224 Resource existing = advisor.analyzeRoot(graph, root);
226 resources[identity.resource] = existing;
229 else if(definition instanceof Optional) {
230 External def = (External)definition;
231 Resource parent = resources[def.parent];
233 resources[identity.resource] =
234 graph.syncRequest(new UnescapedChildMapOfResource(parent)).get(def.name);
238 this.resources = resources;
240 if(!missingExternals.isEmpty()) throw new MissingDependencyException(this);
244 Resource createChild(WriteOnlyGraph graph, Resource parent, String name) throws DatabaseException {
245 Resource child = graph.newResource();
246 //graph.claim(parent, ConsistsOf, PartOf, child);
247 Resource nameResource = graph.newResource();
248 graph.claim(nameResource, InstanceOf, null, String);
249 graph.claimValue(nameResource, name, WriteBindings.STRING);
250 graph.claim(child, HasName, NameOf, nameResource);
255 public Resource createChild(WriteOnlyGraph graph, Resource child, Resource parent, String name) throws DatabaseException {
256 graph.claim(parent, ConsistsOf, PartOf, child);
257 Resource nameResource = graph.newResource();
258 graph.claim(nameResource, InstanceOf, null, String);
259 graph.claimValue(nameResource, name, WriteBindings.STRING);
260 graph.claim(child, HasName, NameOf, nameResource);
264 int[] getClustering() {
265 Variant v = tg.extensions.get(Extensions.CLUSTERING);
266 if(v == null) return null;
268 return (int[])v.getValue(Bindings.INT_ARRAY);
269 } catch (AdaptException e) {
270 Logger.defaultLogError(e);
275 class ResourceAdapter implements LongAdapter {
276 final SerialisationSupport ss;
279 ResourceAdapter(SerialisationSupport ss, Value value) {
284 public long adapt(long in) {
285 if(original == null) original = value.value.clone();
286 Resource res = handles[(int)in].resource(ss);
288 if(res == null) return in;
289 return res.getResourceId();
293 Variant translate(SerialisationSupport ss, Value value, final ResourceHandle[] handles) throws DatabaseException {
296 ResourceAdapter adapter = new ResourceAdapter(ss, value);
297 resourceUtil.adaptValue( value.value.getBinding(), value.value.getValue(), adapter);
298 Variant result = value.value;
299 if(adapter.original != null) value.value = adapter.original;
301 } catch (AccessorException e) {
309 class ResourceAdapter2 implements LongAdapter {
312 ResourceAdapter2(Value value) {
316 public long adapt(long in) {
317 if(original == null) original = value.value.clone();
318 Resource res = resources[(int)in];
320 if(res == null) return in;
321 return res.getResourceId();
325 Variant translate2(Value value, final Resource[] resources) throws DatabaseException {
328 ResourceAdapter2 adapter = new ResourceAdapter2(value);
329 resourceUtil.adaptValue( value.value.getBinding(), value.value.getValue(), adapter);
330 Variant result = value.value;
331 if(adapter.original != null) value.value = adapter.original;
333 } catch (AccessorException e) {
341 void write(WriteOnlyGraph graph) throws DatabaseException {
343 Resource[] resources = this.resources;
345 this.handles = new ResourceHandle[resources.length];
347 ResourceHandle[] handles = this.handles;
349 int[] clustering = getClustering();
351 // Internal identities
352 for(Identity identity : tg.identities) {
353 IdentityDefinition definition = identity.definition;
354 if(resources[identity.resource] != null)
356 if(definition instanceof External) {
357 // Already done everything
359 else if(definition instanceof Internal) {
360 Internal def = (Internal)definition;
361 resources[identity.resource] =
362 createChild(graph, resources[def.parent], def.name);
364 else if(definition instanceof Root) {
365 Root root = (Root)definition;
366 resources[identity.resource] = advisor.createRoot(graph, root);
368 else if(definition instanceof Optional) {
369 Optional def = (Optional)definition;
370 Resource child = createChild(graph, resources[def.parent], def.name);
371 graph.claim(child, InstanceOf, null, Library); // ???
372 resources[identity.resource] = child;
376 ClusterBuilder builder = graph.getService(ClusterBuilder.class);
377 SerialisationSupport ss = graph.getService(SerialisationSupport.class);
379 if(clustering != null) {
382 for(int c : clustering) {
383 builder.newCluster();
384 for(int r=0;r<c;r++, i++)
385 if(resources[i] == null)
386 handles[i] = builder.newResource();
388 handles[i] = builder.resource(resources[i]);
392 for(;i<resources.length;++i)
393 if(resources[i] == null)
394 handles[i] = builder.newResource();
396 handles[i] = builder.resource(resources[i]);
400 // Create blank resources
401 for(int i=0;i<resources.length;++i)
402 if(resources[i] == null)
403 handles[i] = builder.newResource();
405 handles[i] = builder.resource(resources[i]);
410 int[] statements = tg.statements;
412 // int internals = tg.resourceCount - tg.identities.length;
414 for(int i=0;i<statements.length;i+=4) {
416 int sub = statements[i];
417 int pred = statements[i+1];
418 int inv = statements[i+2];
419 int obj = statements[i+3];
421 ResourceHandle subject = handles[sub];
422 ResourceHandle predicate = handles[pred];
423 ResourceHandle object = handles[obj];
425 if(resources[sub] == null) {
426 subject.addStatement(graph, predicate, object);
429 handles[sub].resource(ss),
430 handles[pred].resource(ss),
431 null, handles[obj].resource(ss));
436 if(resources[obj] == null) {
437 ResourceHandle inverse = handles[inv];
438 object.addStatement(graph, inverse, subject);
440 Resource s = handles[obj].resource(ss);
441 if(!graph.isImmutable(s))
444 handles[inv].resource(ss),
445 null, handles[sub].resource(ss));
451 log("[STATEMENT] " + resources[statements[i]].getResourceId() + ", " + resources[statements[i+1]].getResourceId() + ", " + resources[statements[i+3]].getResourceId());
457 for(Value value : tg.values) {
458 Variant variant = translate(ss, value, handles);
459 int file = value.resource & 0x80000000;
460 int resource = value.resource & 0x7FFFFFFF;
462 throw new UnsupportedOperationException();
463 //graph.claimValue(handles[resource].resource(), value.value, Bindings.BYTE_ARRAY);
465 graph.claimValue(handles[resource].resource(ss), variant.getValue(), variant.getBinding());
470 private int updatePercentage(int percentage, int done, int total) {
471 if(monitor != null && (done & 63) == 0) {
472 int current = 100*done / total;
473 if(current > percentage) {
474 percentage = current;
475 monitor.status(percentage);
481 void write2(WriteOnlyGraph graph) throws DatabaseException {
482 Resource[] resources = this.resources;
484 // Internal identities
485 for(Identity identity : tg.identities) {
486 IdentityDefinition definition = identity.definition;
487 if(resources[identity.resource] != null)
489 if(definition instanceof External) {
490 // Already done everything
492 else if(definition instanceof Internal) {
493 Internal def = (Internal)definition;
494 resources[identity.resource] =
495 createChild(graph, resources[def.parent], def.name);
497 else if(definition instanceof Root) {
498 Root root = (Root)definition;
499 resources[identity.resource] = advisor.createRoot(graph, root);
501 else if(definition instanceof Optional) {
502 Optional def = (Optional)definition;
503 Resource child = createChild(graph, resources[def.parent], def.name);
504 graph.claim(child, InstanceOf, null, Library); // ???
505 resources[identity.resource] = child;
509 // Create blank resources
510 for(int i=0;i<resources.length;++i)
511 if(resources[i] == null)
512 resources[i] = graph.newResource();
514 int total = tg.statements.length + tg.values.length;
519 int[] statements = tg.statements;
521 for(int i=0;i<statements.length;i+=4) {
522 int inv = statements[i+2];
524 resources[statements[i]],
525 resources[statements[i+1]],
526 inv < 0 ? null : resources[inv],
527 resources[statements[i+3]]
530 log("[STATEMENT] " + resources[statements[i]].getResourceId() + ", " + resources[statements[i+1]].getResourceId() + ", " + resources[statements[i+3]].getResourceId());
532 percentage = updatePercentage(percentage, done++, total);
536 for(Value value : tg.values) {
537 Variant variant = translate2(value, resources);
538 int file = value.resource & 0x80000000;
539 int resource = value.resource & 0x7FFFFFFF;
541 throw new UnsupportedOperationException();
542 //graph.claimValue(resources[resource], value.value, Bindings.BYTE_ARRAY);
544 graph.claimValue(resources[resource], variant.getValue(), variant.getBinding());
546 percentage = updatePercentage(percentage, done++, total);
551 public long[] getResourceIds(SerialisationSupport serializer) throws DatabaseException {
552 final int count = resources.length;
553 long[] resourceIds = new long[count];
554 if(handles != null) {
555 for(int i=0;i<count;++i)
556 resourceIds[i] = serializer.getRandomAccessId(handles[i].resource(serializer));
558 for(int i=0;i<count;++i)
559 resourceIds[i] = serializer.getRandomAccessId(resources[i]);