]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.graph.db/src/org/simantics/graph/db/TransferableGraphImportProcess.java
TransferableGraph import to VG with different name
[simantics/platform.git] / bundles / org.simantics.graph.db / src / org / simantics / graph / db / TransferableGraphImportProcess.java
index 6df34f95b56b17ce625a3b9de8fc7ddc826302b4..3b3c78bac7039c6c7e31147de6bf06a39c084d94 100644 (file)
-package org.simantics.graph.db;\r
-\r
-import java.io.DataOutput;\r
-import java.io.DataOutputStream;\r
-import java.io.FileNotFoundException;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.util.HashSet;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.accessor.error.AccessorException;\r
-import org.simantics.databoard.adapter.AdaptException;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteOnlyGraph;\r
-import org.simantics.db.common.WriteBindings;\r
-import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
-import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.ResourceNotFoundException;\r
-import org.simantics.db.service.ClusterBuilder;\r
-import org.simantics.db.service.ClusterBuilder.ResourceHandle;\r
-import org.simantics.db.service.SerialisationSupport;\r
-import org.simantics.graph.representation.Extensions;\r
-import org.simantics.graph.representation.External;\r
-import org.simantics.graph.representation.Identity;\r
-import org.simantics.graph.representation.IdentityDefinition;\r
-import org.simantics.graph.representation.Internal;\r
-import org.simantics.graph.representation.Optional;\r
-import org.simantics.graph.representation.Root;\r
-import org.simantics.graph.representation.TransferableGraph1;\r
-import org.simantics.graph.representation.TransferableGraphUtils;\r
-import org.simantics.graph.representation.Value;\r
-import org.simantics.graph.utils.TGResourceUtil;\r
-import org.simantics.graph.utils.TGResourceUtil.LongAdapter;\r
-\r
-public class TransferableGraphImportProcess implements TransferableGraphImporter {\r
-       \r
-       public static String LOG_FILE = "transferableGraphs.log";\r
-       final static private boolean LOG = false;\r
-       \r
-       static DataOutput log;\r
-\r
-       static {\r
-\r
-               if (LOG) {\r
-                       try {\r
-                               FileOutputStream stream = new FileOutputStream(LOG_FILE);\r
-                               log = new DataOutputStream(stream);\r
-                       } catch (FileNotFoundException e) {\r
-                               e.printStackTrace();\r
-                       }\r
-               }\r
-\r
-       }\r
-       \r
-       private static void log(String line) {\r
-               if (LOG) {\r
-                       try {\r
-                               log.writeUTF(line + "\n");\r
-                       } catch (IOException e) {\r
-                               e.printStackTrace();\r
-                       }\r
-               }\r
-       }\r
-       \r
-       TransferableGraph1 tg;\r
-       IImportAdvisor advisor;\r
-       TGStatusMonitor monitor;\r
-       final TGResourceUtil resourceUtil = new TGResourceUtil();\r
-       \r
-       Resource[] resources;\r
-       ResourceHandle[] handles;\r
-       \r
-       Set<String> missingExternals = new HashSet<String>(); \r
-       \r
-       // Builtins\r
-       Resource RootLibrary;\r
-       Resource String;\r
-       Resource Library;\r
-       \r
-       Resource InstanceOf;\r
-       Resource ConsistsOf;\r
-       Resource PartOf;\r
-       Resource HasName;\r
-       Resource NameOf;        \r
-                               \r
-       public TransferableGraphImportProcess(TransferableGraph1 tg, IImportAdvisor advisor, TGStatusMonitor monitor) {\r
-               this.tg = tg;\r
-               this.advisor = advisor;\r
-               this.monitor = monitor;\r
-       }\r
-       \r
-    public TransferableGraphImportProcess(TransferableGraph1 tg, IImportAdvisor advisor) {\r
-        this(tg, advisor, null);\r
-    }\r
-\r
-       public void findBuiltins(WriteOnlyGraph g) throws DatabaseException {\r
-               RootLibrary = g.getBuiltin("http:/");\r
-               String = g.getBuiltin(CoreInitialization.LAYER0 + "String");\r
-               Library = g.getBuiltin(CoreInitialization.LAYER0 + "Library");\r
-               InstanceOf = g.getBuiltin(CoreInitialization.LAYER0 + "InstanceOf");\r
-               ConsistsOf = g.getBuiltin(CoreInitialization.LAYER0 + "ConsistsOf");\r
-               PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");\r
-               HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");\r
-               NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");\r
-       }\r
-       \r
-       public void findBuiltins(ReadGraph g) throws DatabaseException {\r
-               RootLibrary = g.getBuiltin("http:/");\r
-               String = g.getBuiltin(CoreInitialization.LAYER0 + "String");\r
-               Library = g.getBuiltin(CoreInitialization.LAYER0 + "Library");\r
-               InstanceOf = g.getBuiltin(CoreInitialization.LAYER0 + "InstanceOf");\r
-               ConsistsOf = g.getBuiltin(CoreInitialization.LAYER0 + "ConsistsOf");\r
-               PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");\r
-               HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");\r
-               NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");\r
-       }\r
-\r
-       /* Preparation that is used when the core is empty. \r
-        */\r
-       void initialPrepare(WriteOnlyGraph graph) throws DatabaseException {\r
-               findBuiltins(graph);\r
-               \r
-               resources = new Resource[tg.resourceCount];\r
-               \r
-               int Root = -1;\r
-               int SimanticsDomain = -1;\r
-               int Layer0 = -1;\r
-               \r
-               for(Identity identity : tg.identities) {\r
-                       if(identity.definition instanceof Internal) {\r
-                               Internal def = (Internal)identity.definition;\r
-                               Resource res = null;\r
-                               if(def.parent == Layer0) {\r
-                                       try {\r
-                                               res = graph.getBuiltin(CoreInitialization.LAYER0 + def.name);\r
-                                       } catch(ResourceNotFoundException e) {                                                                          \r
-                                       }\r
-                               }\r
-                               else if(def.parent == SimanticsDomain) {\r
-                                       if(def.name.equals("Layer0-1.1"))\r
-                                               Layer0 = identity.resource;\r
-                               }\r
-                               else if(def.parent == Root) {\r
-                                       if(def.name.equals("www.simantics.org"))\r
-                                               SimanticsDomain = identity.resource;\r
-                               }\r
-\r
-                               if(res == null)\r
-                                       res = createChild(graph, resources[def.parent], def.name);\r
-                               else\r
-                                       createChild(graph, res, resources[def.parent], def.name);\r
-                               resources[identity.resource] = res;\r
-                       }\r
-                       else if(identity.definition instanceof Root) {\r
-                               Root = identity.resource;\r
-                               resources[identity.resource] = RootLibrary;                             \r
-                       } \r
-               }\r
-       }\r
-       \r
-       void addMissing(String external) {\r
-               Set<String> removals = new HashSet<String>();\r
-               for(String ext : missingExternals) if(ext.startsWith(external)) return;\r
-               for(String ext : missingExternals) if(external.startsWith(ext)) removals.add(ext);\r
-               missingExternals.removeAll(removals);\r
-               missingExternals.add(external);\r
-       }\r
-       \r
-       void prepare(ReadGraph graph) throws DatabaseException {\r
-               findBuiltins(graph);\r
-               \r
-               Resource[] resources = new Resource[tg.resourceCount];\r
-               \r
-               for(Identity identity : tg.identities) {\r
-                       IdentityDefinition definition = identity.definition;\r
-                       if(definition instanceof External) {\r
-                               External def = (External)definition;\r
-                               if(def.parent == -1) {\r
-                                       resources[identity.resource] = RootLibrary;\r
-                               } else {\r
-                                       if("@inverse".equals(def.name)) {\r
-                                               Resource parent = resources[def.parent];\r
-                                               Resource child = graph.getInverse(parent);\r
-                                               resources[identity.resource] = child;\r
-                                       } else {\r
-                                               Resource parent = resources[def.parent];\r
-                                               // TODO: escape should be removed when names become well-behaving\r
-                                               if(parent != null) {\r
-                                                       Resource child = graph\r
-                                                       .syncRequest(new UnescapedChildMapOfResource(parent),\r
-                                                               new TransientCacheAsyncListener<Map<String, Resource>>())\r
-                                                               .get(def.name);\r
-                                                       if(child == null) {\r
-                                                               String uri = graph.getPossibleURI(parent);\r
-                                                               if(uri == null) {\r
-                                                                       addMissing(NameUtils.getSafeName(graph, parent) + " /" + def.name);\r
-                                                               } else {\r
-                                                                       addMissing(graph.getURI(parent) + "/" + def.name);\r
-                                                               }\r
-                                                       }\r
-                                                       resources[identity.resource] = child;\r
-                                               } else {\r
-                                                   addMissing(TransferableGraphUtils.getURI(tg, def.parent) + "/" + def.name);\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-                       else if(definition instanceof Internal) {\r
-                               // Do not do anything for now\r
-                       }\r
-                       else if(definition instanceof Root) {\r
-                               Root root = (Root)definition;\r
-                               if(root.name.equals(""))\r
-                                       resources[identity.resource] = RootLibrary;\r
-                               else {\r
-                                       Resource existing = advisor.analyzeRoot(graph, root);\r
-                                       if(existing != null)\r
-                                               resources[identity.resource] = existing;\r
-                               }\r
-                       }\r
-                       else if(definition instanceof Optional) {\r
-                               External def = (External)definition;\r
-                               Resource parent = resources[def.parent];\r
-                               if(parent != null)\r
-                                       resources[identity.resource] = \r
-                                               graph.syncRequest(new UnescapedChildMapOfResource(parent)).get(def.name);                               \r
-                       }\r
-               }               \r
-               \r
-               this.resources = resources;\r
-               \r
-               if(!missingExternals.isEmpty()) throw new MissingDependencyException(this);\r
-               \r
-       }\r
-\r
-       Resource createChild(WriteOnlyGraph graph, Resource parent, String name) throws DatabaseException {\r
-               Resource child = graph.newResource();\r
-               //graph.claim(parent, ConsistsOf, PartOf, child);\r
-               Resource nameResource = graph.newResource();\r
-               graph.claim(nameResource, InstanceOf, null, String);\r
-               graph.claimValue(nameResource, name, WriteBindings.STRING);\r
-               graph.claim(child, HasName, NameOf, nameResource);\r
-               return child;\r
-       }\r
-\r
-       @Override\r
-       public Resource createChild(WriteOnlyGraph graph, Resource child, Resource parent, String name) throws DatabaseException {\r
-               graph.claim(parent, ConsistsOf, PartOf, child);\r
-               Resource nameResource = graph.newResource();\r
-               graph.claim(nameResource, InstanceOf, null, String);\r
-               graph.claimValue(nameResource, name, WriteBindings.STRING);\r
-               graph.claim(child, HasName, NameOf, nameResource);\r
-               return child;\r
-       }\r
-       \r
-       int[] getClustering() {\r
-               Variant v = tg.extensions.get(Extensions.CLUSTERING);\r
-               if(v == null) return null;\r
-               try {\r
-                       return (int[])v.getValue(Bindings.INT_ARRAY);\r
-               } catch (AdaptException e) {\r
-                       Logger.defaultLogError(e);\r
-                       return null;\r
-               }\r
-       }\r
-\r
-       class ResourceAdapter implements LongAdapter {\r
-           final SerialisationSupport ss;\r
-           final Value value;\r
-           Variant original;\r
-           ResourceAdapter(SerialisationSupport ss, Value value) {\r
-               this.ss = ss;\r
-               this.value = value;\r
-           }\r
-        @Override\r
-        public long adapt(long in) {\r
-            if(original == null) original = value.value.clone();\r
-            Resource res = handles[(int)in].resource(ss);\r
-            // Maybe throw?\r
-            if(res == null) return in;\r
-            return res.getResourceId();\r
-        }           \r
-       }\r
-       \r
-       Variant translate(SerialisationSupport ss, Value value, final ResourceHandle[] handles) throws DatabaseException {\r
-               \r
-               try {\r
-                   ResourceAdapter adapter = new ResourceAdapter(ss, value);\r
-                       resourceUtil.adaptValue( value.value.getBinding(), value.value.getValue(), adapter);\r
-                       Variant result = value.value;\r
-                       if(adapter.original != null) value.value = adapter.original;\r
-                       return result;\r
-               } catch (AccessorException e) {\r
-                       e.printStackTrace();\r
-               }               \r
-               \r
-               return value.value;\r
-               \r
-       }\r
-       \r
-    class ResourceAdapter2 implements LongAdapter {\r
-        final Value value;\r
-        Variant original;\r
-        ResourceAdapter2(Value value) {\r
-            this.value = value;\r
-        }\r
-        @Override\r
-        public long adapt(long in) {\r
-            if(original == null) original = value.value.clone();\r
-            Resource res = resources[(int)in];\r
-            // Maybe throw?\r
-            if(res == null) return in;\r
-            return res.getResourceId();\r
-        }           \r
-    }\r
-\r
-       Variant translate2(Value value, final Resource[] resources) throws DatabaseException {\r
-               \r
-        try {\r
-            ResourceAdapter2 adapter = new ResourceAdapter2(value);\r
-            resourceUtil.adaptValue( value.value.getBinding(), value.value.getValue(), adapter);\r
-            Variant result = value.value;\r
-            if(adapter.original != null) value.value = adapter.original;\r
-            return result;\r
-        } catch (AccessorException e) {\r
-            e.printStackTrace();\r
-        }       \r
-        \r
-        return value.value;\r
-               \r
-       }\r
-\r
-       void write(WriteOnlyGraph graph) throws DatabaseException {\r
-\r
-               Resource[] resources = this.resources;\r
-\r
-               this.handles = new ResourceHandle[resources.length];\r
-               \r
-               ResourceHandle[] handles = this.handles; \r
-\r
-               int[] clustering = getClustering();\r
-\r
-               // Internal identities          \r
-               for(Identity identity : tg.identities) {\r
-                       IdentityDefinition definition = identity.definition;\r
-                       if(resources[identity.resource] != null)\r
-                               continue;\r
-                       if(definition instanceof External) {\r
-                               // Already done everything\r
-                       }\r
-                       else if(definition instanceof Internal) {\r
-                               Internal def = (Internal)definition;\r
-                               resources[identity.resource] = \r
-                                       createChild(graph, resources[def.parent], def.name);\r
-                       }\r
-                       else if(definition instanceof Root) {\r
-                               Root root = (Root)definition;                           \r
-                               resources[identity.resource] = advisor.createRoot(graph, root);                                 \r
-                       }\r
-                       else if(definition instanceof Optional) {\r
-                               Optional def = (Optional)definition;\r
-                               Resource child = createChild(graph, resources[def.parent], def.name);\r
-                               graph.claim(child, InstanceOf, null, Library); // ???\r
-                               resources[identity.resource] = child;                                   \r
-                       }\r
-               }               \r
-\r
-               ClusterBuilder builder = graph.getService(ClusterBuilder.class);\r
-               SerialisationSupport ss = graph.getService(SerialisationSupport.class);\r
-\r
-               if(clustering != null) {\r
-                       \r
-               int i = 0;\r
-                       for(int c : clustering) {\r
-                               builder.newCluster();\r
-                               for(int r=0;r<c;r++, i++)\r
-                                       if(resources[i] == null)\r
-                                               handles[i] = builder.newResource();\r
-                                       else \r
-                                               handles[i] = builder.resource(resources[i]);\r
-\r
-                       }\r
-\r
-                       for(;i<resources.length;++i)\r
-                               if(resources[i] == null)\r
-                                       handles[i] = builder.newResource();\r
-                               else \r
-                                       handles[i] = builder.resource(resources[i]);\r
-                       \r
-               } else {\r
-               \r
-                       // Create blank resources\r
-                       for(int i=0;i<resources.length;++i)\r
-                               if(resources[i] == null)\r
-                                       handles[i] = builder.newResource();\r
-                               else \r
-                                       handles[i] = builder.resource(resources[i]);\r
-\r
-               }\r
-               \r
-               // Write statements\r
-               int[] statements = tg.statements;\r
-               \r
-//             int internals = tg.resourceCount - tg.identities.length;\r
-               \r
-               for(int i=0;i<statements.length;i+=4) {\r
-\r
-                       int sub = statements[i];\r
-                       int pred = statements[i+1];\r
-                       int inv = statements[i+2];\r
-                       int obj = statements[i+3];\r
-\r
-                       ResourceHandle subject = handles[sub];\r
-                       ResourceHandle predicate = handles[pred];\r
-                       ResourceHandle object = handles[obj];\r
-\r
-                       if(resources[sub] == null) {\r
-                               subject.addStatement(graph, predicate, object); \r
-                       } else {\r
-                               graph.claim(\r
-                                               handles[sub].resource(ss),\r
-                                               handles[pred].resource(ss),\r
-                                               null, handles[obj].resource(ss));\r
-                       }\r
-                       \r
-                       if(inv >= 0) {\r
-                               \r
-                               if(resources[obj] == null) {\r
-                                       ResourceHandle inverse = handles[inv];\r
-                                       object.addStatement(graph, inverse, subject);   \r
-                               } else {\r
-                                   Resource s = handles[obj].resource(ss);\r
-                                   if(!graph.isImmutable(s))\r
-                                       graph.claim(\r
-                                                       s,\r
-                                                       handles[inv].resource(ss),\r
-                                                       null, handles[sub].resource(ss));\r
-                               }\r
-                               \r
-                       }\r
-                       \r
-                       if(LOG) {\r
-                               log("[STATEMENT] " + resources[statements[i]].getResourceId() + ", " + resources[statements[i+1]].getResourceId() + ", " + resources[statements[i+3]].getResourceId());\r
-                       }\r
-                       \r
-               }\r
-                               \r
-               // Write values\r
-               for(Value value : tg.values) {\r
-                       Variant variant = translate(ss, value, handles);\r
-                       int file = value.resource & 0x80000000;\r
-                       int resource = value.resource & 0x7FFFFFFF;\r
-                       if (file != 0) {\r
-                           throw new UnsupportedOperationException();\r
-                               //graph.claimValue(handles[resource].resource(), value.value, Bindings.BYTE_ARRAY);\r
-                       } else {\r
-                               graph.claimValue(handles[resource].resource(ss), variant.getValue(), variant.getBinding());\r
-                       }\r
-               }\r
-       }\r
-\r
-       private int updatePercentage(int percentage, int done, int total) {\r
-           if(monitor != null && (done & 63) == 0) {\r
-               int current = 100*done / total;\r
-               if(current > percentage) {\r
-                   percentage = current;\r
-                   monitor.status(percentage);\r
-               }\r
-           }\r
-        return percentage;\r
-       }\r
-       \r
-       void write2(WriteOnlyGraph graph) throws DatabaseException {\r
-               Resource[] resources = this.resources;\r
-               \r
-               // Internal identities          \r
-               for(Identity identity : tg.identities) {\r
-                       IdentityDefinition definition = identity.definition;\r
-                       if(resources[identity.resource] != null)\r
-                               continue;\r
-                       if(definition instanceof External) {\r
-                               // Already done everything\r
-                       }\r
-                       else if(definition instanceof Internal) {\r
-                               Internal def = (Internal)definition;\r
-                               resources[identity.resource] = \r
-                                       createChild(graph, resources[def.parent], def.name);\r
-                       }\r
-                       else if(definition instanceof Root) {                           \r
-                               Root root = (Root)definition;                           \r
-                               resources[identity.resource] = advisor.createRoot(graph, root);                                 \r
-                       }\r
-                       else if(definition instanceof Optional) {\r
-                               Optional def = (Optional)definition;\r
-                               Resource child = createChild(graph, resources[def.parent], def.name);\r
-                               graph.claim(child, InstanceOf, null, Library); // ???\r
-                               resources[identity.resource] = child;                                   \r
-                       }\r
-               }               \r
-               \r
-               // Create blank resources\r
-               for(int i=0;i<resources.length;++i)\r
-                       if(resources[i] == null)\r
-                               resources[i] = graph.newResource();\r
-               \r
-               int total = tg.statements.length + tg.values.length;\r
-               int done = 0;\r
-               int percentage = 0;\r
-               \r
-               // Write statements\r
-               int[] statements = tg.statements;\r
-               \r
-               for(int i=0;i<statements.length;i+=4) {\r
-                       int inv = statements[i+2];\r
-                       graph.claim(\r
-                                       resources[statements[i]],\r
-                                       resources[statements[i+1]],\r
-                                       inv < 0 ? null : resources[inv],\r
-                                       resources[statements[i+3]]\r
-                                       );\r
-                       if(LOG) {\r
-                               log("[STATEMENT] " + resources[statements[i]].getResourceId() + ", " + resources[statements[i+1]].getResourceId() + ", " + resources[statements[i+3]].getResourceId());\r
-                       }\r
-                       percentage = updatePercentage(percentage, done++, total);\r
-               }\r
-\r
-               // Write values\r
-               for(Value value : tg.values) {\r
-                       Variant variant = translate2(value, resources);\r
-                       int file = value.resource & 0x80000000;\r
-                       int resource = value.resource & 0x7FFFFFFF;\r
-                       if (file != 0) {\r
-                           throw new UnsupportedOperationException();\r
-                               //graph.claimValue(resources[resource], value.value, Bindings.BYTE_ARRAY);\r
-                       } else {\r
-                           graph.claimValue(resources[resource], variant.getValue(), variant.getBinding());\r
-                       }\r
-            percentage = updatePercentage(percentage, done++, total);\r
-               }\r
-               \r
-       }\r
-       \r
-       public long[] getResourceIds(SerialisationSupport serializer) throws DatabaseException {\r
-               final int count = resources.length;\r
-               long[] resourceIds = new long[count];\r
-               if(handles != null) {\r
-                       for(int i=0;i<count;++i)\r
-                               resourceIds[i] = serializer.getRandomAccessId(handles[i].resource(serializer));\r
-               } else {\r
-                       for(int i=0;i<count;++i)\r
-                               resourceIds[i] = serializer.getRandomAccessId(resources[i]);\r
-               }\r
-               return resourceIds;\r
-       }\r
+package org.simantics.graph.db;
+
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.accessor.error.AccessorException;
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.util.URIStringUtils;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteOnlyGraph;
+import org.simantics.db.common.WriteBindings;
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
+import org.simantics.db.common.uri.UnescapedChildMapOfResource;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ResourceNotFoundException;
+import org.simantics.db.service.ClusterBuilder;
+import org.simantics.db.service.ClusterBuilder.ResourceHandle;
+import org.simantics.db.service.SerialisationSupport;
+import org.simantics.graph.representation.Extensions;
+import org.simantics.graph.representation.External;
+import org.simantics.graph.representation.Identity;
+import org.simantics.graph.representation.IdentityDefinition;
+import org.simantics.graph.representation.Internal;
+import org.simantics.graph.representation.Optional;
+import org.simantics.graph.representation.Root;
+import org.simantics.graph.representation.TransferableGraph1;
+import org.simantics.graph.representation.TransferableGraphUtils;
+import org.simantics.graph.representation.Value;
+import org.simantics.graph.utils.TGResourceUtil;
+import org.simantics.graph.utils.TGResourceUtil.LongAdapter;
+
+public class TransferableGraphImportProcess implements TransferableGraphImporter {
+       
+       public static String LOG_FILE = "transferableGraphs.log";
+       final static private boolean LOG = false;
+       
+       static DataOutput log;
+
+       static {
+
+               if (LOG) {
+                       try {
+                               FileOutputStream stream = new FileOutputStream(LOG_FILE);
+                               log = new DataOutputStream(stream);
+                       } catch (FileNotFoundException e) {
+                               e.printStackTrace();
+                       }
+               }
+
+       }
+       
+       private static void log(String line) {
+               if (LOG) {
+                       try {
+                               log.writeUTF(line + "\n");
+                       } catch (IOException e) {
+                               e.printStackTrace();
+                       }
+               }
+       }
+       
+       TransferableGraph1 tg;
+       IImportAdvisor advisor;
+       TGStatusMonitor monitor;
+       final TGResourceUtil resourceUtil = new TGResourceUtil();
+       
+       Resource[] resources;
+       ResourceHandle[] handles;
+       
+       Set<String> missingExternals = new HashSet<String>(); 
+       
+       // Builtins
+       Resource RootLibrary;
+       Resource String;
+       Resource Library;
+       
+       Resource InstanceOf;
+       Resource ConsistsOf;
+       Resource PartOf;
+       Resource HasName;
+       Resource NameOf;        
+                               
+       public TransferableGraphImportProcess(TransferableGraph1 tg, IImportAdvisor advisor, TGStatusMonitor monitor) {
+               this.tg = tg;
+               this.advisor = advisor;
+               this.monitor = monitor;
+       }
+       
+    public TransferableGraphImportProcess(TransferableGraph1 tg, IImportAdvisor advisor) {
+        this(tg, advisor, null);
+    }
+
+       public void findBuiltins(WriteOnlyGraph g) throws DatabaseException {
+               RootLibrary = g.getBuiltin("http:/");
+               String = g.getBuiltin(CoreInitialization.LAYER0 + "String");
+               Library = g.getBuiltin(CoreInitialization.LAYER0 + "Library");
+               InstanceOf = g.getBuiltin(CoreInitialization.LAYER0 + "InstanceOf");
+               ConsistsOf = g.getBuiltin(CoreInitialization.LAYER0 + "ConsistsOf");
+               PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");
+               HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");
+               NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");
+       }
+       
+       public void findBuiltins(ReadGraph g) throws DatabaseException {
+               RootLibrary = g.getBuiltin("http:/");
+               String = g.getBuiltin(CoreInitialization.LAYER0 + "String");
+               Library = g.getBuiltin(CoreInitialization.LAYER0 + "Library");
+               InstanceOf = g.getBuiltin(CoreInitialization.LAYER0 + "InstanceOf");
+               ConsistsOf = g.getBuiltin(CoreInitialization.LAYER0 + "ConsistsOf");
+               PartOf = g.getBuiltin(CoreInitialization.LAYER0 + "PartOf");
+               HasName = g.getBuiltin(CoreInitialization.LAYER0 + "HasName");
+               NameOf = g.getBuiltin(CoreInitialization.LAYER0 + "NameOf");
+       }
+
+       /* Preparation that is used when the core is empty. 
+        */
+       void initialPrepare(WriteOnlyGraph graph) throws DatabaseException {
+               findBuiltins(graph);
+               
+               resources = new Resource[tg.resourceCount];
+               
+               int Root = -1;
+               int SimanticsDomain = -1;
+               int Layer0 = -1;
+               
+               for(Identity identity : tg.identities) {
+                       if(identity.definition instanceof Internal) {
+                               Internal def = (Internal)identity.definition;
+                               Resource res = null;
+                               if(def.parent == Layer0) {
+                                       try {
+                                               res = graph.getBuiltin(CoreInitialization.LAYER0 + def.name);
+                                       } catch(ResourceNotFoundException e) {                                                                          
+                                       }
+                               }
+                               else if(def.parent == SimanticsDomain) {
+                                       if(def.name.equals("Layer0-1.1"))
+                                               Layer0 = identity.resource;
+                               }
+                               else if(def.parent == Root) {
+                                       if(def.name.equals("www.simantics.org"))
+                                               SimanticsDomain = identity.resource;
+                               }
+
+                               if(res == null)
+                                       res = createChild(graph, resources[def.parent], def.name);
+                               else
+                                       createChild(graph, res, resources[def.parent], def.name);
+                               resources[identity.resource] = res;
+                       }
+                       else if(identity.definition instanceof Root) {
+                               Root = identity.resource;
+                               resources[identity.resource] = RootLibrary;                             
+                       } 
+               }
+       }
+       
+       void addMissing(String external) {
+               Set<String> removals = new HashSet<String>();
+               for(String ext : missingExternals) if(ext.startsWith(external)) return;
+               for(String ext : missingExternals) if(external.startsWith(ext)) removals.add(ext);
+               missingExternals.removeAll(removals);
+               missingExternals.add(external);
+       }
+       
+       public void prepare(ReadGraph graph) throws DatabaseException {
+               findBuiltins(graph);
+               
+               Resource[] resources = new Resource[tg.resourceCount];
+               
+               for(Identity identity : tg.identities) {
+                       IdentityDefinition definition = identity.definition;
+                       if(definition instanceof External) {
+                               External def = (External)definition;
+                               if(def.parent == -1) {
+                                       resources[identity.resource] = RootLibrary;
+                               } else {
+                                       if("@inverse".equals(def.name)) {
+                                               Resource parent = resources[def.parent];
+                                               Resource child = graph.getInverse(parent);
+                                               resources[identity.resource] = child;
+                                       } else {
+                                               Resource parent = resources[def.parent];
+                                               // TODO: escape should be removed when names become well-behaving
+                                               if(parent != null) {
+                                                       Resource child = graph
+                                                       .syncRequest(new UnescapedChildMapOfResource(parent),
+                                                               new TransientCacheAsyncListener<Map<String, Resource>>())
+                                                               .get(def.name);
+                                                       if(child == null) {
+                                                               String uri = graph.getPossibleURI(parent);
+                                                               if(uri == null) {
+                                                                       addMissing(URIStringUtils.escape(NameUtils.getSafeName(graph, parent)) + " /" + URIStringUtils.escape(def.name));
+                                                               } else {
+                                                                       addMissing(graph.getURI(parent) + "/" + URIStringUtils.escape(def.name));
+                                                               }
+                                                       }
+                                                       resources[identity.resource] = child;
+                                               } else {
+                                                   addMissing(TransferableGraphUtils.getURI(tg, def.parent) + "/" + URIStringUtils.escape(def.name));
+                                               }
+                                       }
+                               }
+                       }
+                       else if(definition instanceof Internal) {
+                               // Do not do anything for now
+                       }
+                       else if(definition instanceof Root) {
+                               Root root = (Root)definition;
+                               if(root.name.equals(""))
+                                       resources[identity.resource] = RootLibrary;
+                               else {
+                                       Resource existing = advisor.analyzeRoot(graph, root);
+                                       if(existing != null)
+                                               resources[identity.resource] = existing;
+                               }
+                       }
+                       else if(definition instanceof Optional) {
+                               External def = (External)definition;
+                               Resource parent = resources[def.parent];
+                               if(parent != null)
+                                       resources[identity.resource] = 
+                                               graph.syncRequest(new UnescapedChildMapOfResource(parent)).get(def.name);                               
+                       }
+               }               
+               
+               this.resources = resources;
+               
+               if(!missingExternals.isEmpty()) throw new MissingDependencyException(this);
+               
+       }
+
+       Resource createChild(WriteOnlyGraph graph, Resource parent, String name) throws DatabaseException {
+               Resource child = graph.newResource();
+               //graph.claim(parent, ConsistsOf, PartOf, child);
+               Resource nameResource = graph.newResource();
+               graph.claim(nameResource, InstanceOf, null, String);
+               graph.claimValue(nameResource, name, WriteBindings.STRING);
+               graph.claim(child, HasName, NameOf, nameResource);
+               return child;
+       }
+
+       @Override
+       public Resource createChild(WriteOnlyGraph graph, Resource child, Resource parent, String name) throws DatabaseException {
+               graph.claim(parent, ConsistsOf, PartOf, child);
+               Resource nameResource = graph.newResource();
+               graph.claim(nameResource, InstanceOf, null, String);
+               graph.claimValue(nameResource, name, WriteBindings.STRING);
+               graph.claim(child, HasName, NameOf, nameResource);
+               return child;
+       }
+       
+       int[] getClustering() {
+               Variant v = tg.extensions.get(Extensions.CLUSTERING);
+               if(v == null) return null;
+               try {
+                       return (int[])v.getValue(Bindings.INT_ARRAY);
+               } catch (AdaptException e) {
+                       Logger.defaultLogError(e);
+                       return null;
+               }
+       }
+
+       class ResourceAdapter implements LongAdapter {
+           final SerialisationSupport ss;
+           final Value value;
+           Variant original;
+           ResourceAdapter(SerialisationSupport ss, Value value) {
+               this.ss = ss;
+               this.value = value;
+           }
+        @Override
+        public long adapt(long in) {
+            if(original == null) original = value.value.clone();
+            Resource res = handles[(int)in].resource(ss);
+            // Maybe throw?
+            if(res == null) return in;
+            return res.getResourceId();
+        }           
+       }
+       
+       Variant translate(SerialisationSupport ss, Value value, final ResourceHandle[] handles) throws DatabaseException {
+               
+               try {
+                   ResourceAdapter adapter = new ResourceAdapter(ss, value);
+                       resourceUtil.adaptValue( value.value.getBinding(), value.value.getValue(), adapter);
+                       Variant result = value.value;
+                       if(adapter.original != null) value.value = adapter.original;
+                       return result;
+               } catch (AccessorException e) {
+                       e.printStackTrace();
+               }               
+               
+               return value.value;
+               
+       }
+       
+    class ResourceAdapter2 implements LongAdapter {
+        final Value value;
+        Variant original;
+        ResourceAdapter2(Value value) {
+            this.value = value;
+        }
+        @Override
+        public long adapt(long in) {
+            if(original == null) original = value.value.clone();
+            Resource res = resources[(int)in];
+            // Maybe throw?
+            if(res == null) return in;
+            return res.getResourceId();
+        }           
+    }
+
+       Variant translate2(Value value, final Resource[] resources) throws DatabaseException {
+               
+        try {
+            ResourceAdapter2 adapter = new ResourceAdapter2(value);
+            resourceUtil.adaptValue( value.value.getBinding(), value.value.getValue(), adapter);
+            Variant result = value.value;
+            if(adapter.original != null) value.value = adapter.original;
+            return result;
+        } catch (AccessorException e) {
+            e.printStackTrace();
+        }       
+        
+        return value.value;
+               
+       }
+
+       public void write(WriteOnlyGraph graph) throws DatabaseException {
+
+               Resource[] resources = this.resources;
+
+               this.handles = new ResourceHandle[resources.length];
+               
+               ResourceHandle[] handles = this.handles; 
+
+               int[] clustering = getClustering();
+
+               // Internal identities          
+               for(Identity identity : tg.identities) {
+                       IdentityDefinition definition = identity.definition;
+                       if(resources[identity.resource] != null)
+                               continue;
+                       if(definition instanceof External) {
+                               // Already done everything
+                       }
+                       else if(definition instanceof Internal) {
+                               Internal def = (Internal)definition;
+                               resources[identity.resource] = 
+                                       createChild(graph, resources[def.parent], def.name);
+                       }
+                       else if(definition instanceof Root) {
+                               Root root = (Root)definition;                           
+                               resources[identity.resource] = advisor.createRoot(graph, root);                                 
+                       }
+                       else if(definition instanceof Optional) {
+                               Optional def = (Optional)definition;
+                               Resource child = createChild(graph, resources[def.parent], def.name);
+                               graph.claim(child, InstanceOf, null, Library); // ???
+                               resources[identity.resource] = child;                                   
+                       }
+               }               
+
+               ClusterBuilder builder = graph.getService(ClusterBuilder.class);
+               SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+
+               if(clustering != null) {
+                       
+               int i = 0;
+                       for(int c : clustering) {
+                               builder.newCluster();
+                               for(int r=0;r<c;r++, i++)
+                                       if(resources[i] == null)
+                                               handles[i] = builder.newResource();
+                                       else 
+                                               handles[i] = builder.resource(resources[i]);
+
+                       }
+
+                       for(;i<resources.length;++i)
+                               if(resources[i] == null)
+                                       handles[i] = builder.newResource();
+                               else 
+                                       handles[i] = builder.resource(resources[i]);
+                       
+               } else {
+               
+                       // Create blank resources
+                       for(int i=0;i<resources.length;++i)
+                               if(resources[i] == null)
+                                       handles[i] = builder.newResource();
+                               else 
+                                       handles[i] = builder.resource(resources[i]);
+
+               }
+               
+               // Write statements
+               int[] statements = tg.statements;
+               
+//             int internals = tg.resourceCount - tg.identities.length;
+               
+               for(int i=0;i<statements.length;i+=4) {
+
+                       int sub = statements[i];
+                       int pred = statements[i+1];
+                       int inv = statements[i+2];
+                       int obj = statements[i+3];
+
+                       ResourceHandle subject = handles[sub];
+                       ResourceHandle predicate = handles[pred];
+                       ResourceHandle object = handles[obj];
+
+                       if(resources[sub] == null) {
+                               subject.addStatement(graph, predicate, object); 
+                       } else {
+                               graph.claim(
+                                               handles[sub].resource(ss),
+                                               handles[pred].resource(ss),
+                                               null, handles[obj].resource(ss));
+                       }
+                       
+                       if(inv >= 0) {
+                               
+                               if(resources[obj] == null) {
+                                       ResourceHandle inverse = handles[inv];
+                                       object.addStatement(graph, inverse, subject);   
+                               } else {
+                                   Resource s = handles[obj].resource(ss);
+                                   if(!graph.isImmutable(s))
+                                       graph.claim(
+                                                       s,
+                                                       handles[inv].resource(ss),
+                                                       null, handles[sub].resource(ss));
+                               }
+                               
+                       }
+                       
+                       if(LOG) {
+                               log("[STATEMENT] " + resources[statements[i]].getResourceId() + ", " + resources[statements[i+1]].getResourceId() + ", " + resources[statements[i+3]].getResourceId());
+                       }
+                       
+               }
+                               
+               // Write values
+               for(Value value : tg.values) {
+                       Variant variant = translate(ss, value, handles);
+                       int file = value.resource & 0x80000000;
+                       int resource = value.resource & 0x7FFFFFFF;
+                       if (file != 0) {
+                           throw new UnsupportedOperationException();
+                               //graph.claimValue(handles[resource].resource(), value.value, Bindings.BYTE_ARRAY);
+                       } else {
+                               graph.claimValue(handles[resource].resource(ss), variant.getValue(), variant.getBinding());
+                       }
+               }
+       }
+
+       private int updatePercentage(int percentage, int done, int total) {
+           if(monitor != null && (done & 63) == 0) {
+               int current = 100*done / total;
+               if(current > percentage) {
+                   percentage = current;
+                   monitor.status(percentage);
+               }
+           }
+        return percentage;
+       }
+       
+       void write2(WriteOnlyGraph graph) throws DatabaseException {
+               Resource[] resources = this.resources;
+               
+               // Internal identities          
+               for(Identity identity : tg.identities) {
+                       IdentityDefinition definition = identity.definition;
+                       if(resources[identity.resource] != null)
+                               continue;
+                       if(definition instanceof External) {
+                               // Already done everything
+                       }
+                       else if(definition instanceof Internal) {
+                               Internal def = (Internal)definition;
+                               resources[identity.resource] = 
+                                       createChild(graph, resources[def.parent], def.name);
+                       }
+                       else if(definition instanceof Root) {                           
+                               Root root = (Root)definition;                           
+                               resources[identity.resource] = advisor.createRoot(graph, root);                                 
+                       }
+                       else if(definition instanceof Optional) {
+                               Optional def = (Optional)definition;
+                               Resource child = createChild(graph, resources[def.parent], def.name);
+                               graph.claim(child, InstanceOf, null, Library); // ???
+                               resources[identity.resource] = child;                                   
+                       }
+               }               
+               
+               // Create blank resources
+               for(int i=0;i<resources.length;++i)
+                       if(resources[i] == null)
+                               resources[i] = graph.newResource();
+               
+               int total = tg.statements.length + tg.values.length;
+               int done = 0;
+               int percentage = 0;
+               
+               // Write statements
+               int[] statements = tg.statements;
+               
+               for(int i=0;i<statements.length;i+=4) {
+                       int inv = statements[i+2];
+                       graph.claim(
+                                       resources[statements[i]],
+                                       resources[statements[i+1]],
+                                       inv < 0 ? null : resources[inv],
+                                       resources[statements[i+3]]
+                                       );
+                       if(LOG) {
+                               log("[STATEMENT] " + resources[statements[i]].getResourceId() + ", " + resources[statements[i+1]].getResourceId() + ", " + resources[statements[i+3]].getResourceId());
+                       }
+                       percentage = updatePercentage(percentage, done++, total);
+               }
+
+               // Write values
+               for(Value value : tg.values) {
+                       Variant variant = translate2(value, resources);
+                       int file = value.resource & 0x80000000;
+                       int resource = value.resource & 0x7FFFFFFF;
+                       if (file != 0) {
+                           throw new UnsupportedOperationException();
+                               //graph.claimValue(resources[resource], value.value, Bindings.BYTE_ARRAY);
+                       } else {
+                           graph.claimValue(resources[resource], variant.getValue(), variant.getBinding());
+                       }
+            percentage = updatePercentage(percentage, done++, total);
+               }
+               
+       }
+       
+       public long[] getResourceIds(SerialisationSupport serializer) throws DatabaseException {
+               final int count = resources.length;
+               long[] resourceIds = new long[count];
+               if(handles != null) {
+                       for(int i=0;i<count;++i)
+                               resourceIds[i] = serializer.getRandomAccessId(handles[i].resource(serializer));
+               } else {
+                       for(int i=0;i<count;++i)
+                               resourceIds[i] = serializer.getRandomAccessId(resources[i]);
+               }
+               return resourceIds;
+       }
 }
\ No newline at end of file