-package org.simantics.db.layer0.util;\r
-\r
-import java.io.Closeable;\r
-import java.io.DataInput;\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.nio.file.Files;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.TreeMap;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Databoard;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.container.DataContainer;\r
-import org.simantics.databoard.serialization.Serializer;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.databoard.util.binary.ByteBufferReadable;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.RuntimeDatabaseException;\r
-import org.simantics.db.exception.ValidationException;\r
-import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;\r
-import org.simantics.db.layer0.util.TransferableGraphConfiguration2.RootSpec;\r
-import org.simantics.db.service.SerialisationSupport;\r
-import org.simantics.graph.db.TransferableGraphSource;\r
-import org.simantics.graph.representation.External;\r
-import org.simantics.graph.representation.Identity;\r
-import org.simantics.graph.representation.Root;\r
-import org.simantics.graph.representation.Value;\r
-import org.simantics.layer0.Layer0;\r
-\r
-import gnu.trove.list.array.TIntArrayList;\r
-import gnu.trove.procedure.TIntIntProcedure;\r
-\r
-public class ModelTransferableGraphSource implements TransferableGraphSource {\r
-\r
- final private TransferableGraphConfiguration2 configuration;\r
- final private DomainProcessorState state;\r
- final private int externalBase;\r
- final private int resourceCount;\r
- final private File[] files;\r
- final private TGValueModifier valueModifier;\r
-\r
- private volatile boolean closed = false;\r
-\r
- TIntArrayList externalParents = new TIntArrayList();\r
- ArrayList<String> externalNames = new ArrayList<String>();\r
-\r
- public ModelTransferableGraphSource(final ReadGraph graph, TransferableGraphConfiguration2 configuration, final DomainProcessorState state, File ... fs) throws DatabaseException {\r
-\r
- this.configuration = configuration;\r
- this.state = state;\r
- this.files = fs;\r
- this.valueModifier = state.valueModifier;\r
-\r
- SerialisationSupport ss = graph.getService(SerialisationSupport.class);\r
-\r
- // At this point ids contains all internal resources. Now add roots and externals.\r
- \r
- // Root Library\r
- state.ids.put(ss.getTransientId(graph.getRootLibrary()), state.id++);\r
- \r
- // External roots - internal roots were already processed as internal resources by domain processor\r
- for(RootSpec rs : configuration.roots) {\r
- if(!rs.internal) {\r
- int resourceId = ss.getTransientId(rs.resource);\r
- state.ids.put(resourceId, state.id++);\r
- // The fixed roots have been seen as externals by domain processor. Now remove them from external set.\r
- state.externals.remove(resourceId);\r
- }\r
- }\r
- \r
- this.externalBase = state.id;\r
-\r
- final Collection<String> errors = new HashSet<String>();\r
-\r
- // All resource considered as not internal by domain processor. Can also contain roots.\r
- int[] externals = state.externals.toArray();\r
- \r
- // Build up the state.externals, externalNames and externalParents\r
- for(int i=0;i<externals.length;i++) {\r
- getId(graph, externals[i], errors);\r
- }\r
- \r
- state.inverses.forEachEntry(new TIntIntProcedure() {\r
- \r
- @Override\r
- public boolean execute(int predicate, int inverse) {\r
- try {\r
- getId(graph, predicate, errors);\r
- if(inverse != 0) getId(graph, inverse, errors);\r
- } catch (DatabaseException e) {\r
- throw new RuntimeDatabaseException(e);\r
- }\r
- return true;\r
- }\r
- \r
- });\r
- \r
- if(!errors.isEmpty()) {\r
- ArrayList<String> sorted = new ArrayList<String>(errors);\r
- Collections.sort(sorted);\r
- StringBuilder message = new StringBuilder();\r
- message.append("Errors in exported model:\n");\r
- for(String error : sorted) {\r
- message.append(error);\r
- message.append("\n");\r
- }\r
- throw new DatabaseException(message.toString());\r
- }\r
- \r
- this.resourceCount = state.id;\r
- \r
- }\r
-\r
- int indent = 0;\r
- \r
- public boolean validateExternal(Resource ext) {\r
- if(configuration.validate) {\r
- ExtentStatus status = configuration.preStatus.get(ext);\r
- if(status != null) {\r
- if(ExtentStatus.INTERNAL.equals(status)) return false;\r
- else if(ExtentStatus.EXCLUDED.equals(status)) return false;\r
- }\r
- }\r
- return true;\r
- }\r
- \r
- private Resource getResource(ReadGraph graph, int r) throws DatabaseException {\r
- SerialisationSupport ss = graph.getService(SerialisationSupport.class);\r
- return ss.getResource(r);\r
- }\r
- \r
- final public int getExistingId(ReadGraph graph, int r) throws DatabaseException {\r
- \r
- int ret = state.ids.get(r);\r
- if(ret != -1) {\r
- return ret;\r
- } else {\r
- SerialisationSupport ss = graph.getService(SerialisationSupport.class);\r
- throw new DatabaseException("Id has not been created for " + NameUtils.getSafeName(graph, ss.getResource(r)));\r
- }\r
-\r
- }\r
- \r
- /*\r
- * \r
- * @return -2 if r is not really external and the statement should be excluded\r
- * \r
- */\r
- public int getId(ReadGraph graph, int r, Collection<String> errors) throws DatabaseException {\r
-\r
-// // First external is root library\r
-// if(r == rootId) return internalCount;\r
- \r
- SerialisationSupport ss = graph.getService(SerialisationSupport.class);\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- \r
- if(state.ids.containsKey(r)) {\r
- int ret = state.ids.get(r);\r
- if(ret == -1) {\r
- for(int i=0;i<=indent;++i)\r
- System.out.print(" ");\r
- System.out.println("Cycle!!!"); // with " + GraphUtils.getReadableName(g, r));\r
- }\r
- return ret;\r
- }\r
- else {\r
- Resource res = getResource(graph, r);\r
- if(!validateExternal(res)) {\r
- errors.add("Illegal reference to " + graph.getPossibleURI(getResource(graph, r)));\r
- return -2;\r
- }\r
- Collection<Resource> parents = graph.getObjects(res, L0.PartOf); \r
- if(parents.size() != 1) {\r
- throw new ValidationException("Reference to external resource " \r
- + NameUtils.getSafeName(graph, getResource(graph, r), true) + " without unique uri (" + parents.size() + " parents).");\r
- }\r
- int pid = 0;\r
- for(Resource p : parents) {\r
- ++indent;\r
- pid = getId(graph, ss.getTransientId(p), errors);\r
- if(pid == -2) {\r
- errors.add("Illegal reference to " + graph.getPossibleURI(getResource(graph, r)));\r
- return -2;\r
- }\r
- }\r
- --indent;\r
- String name = graph.getRelatedValue(res, L0.HasName);\r
- // Record the external entry\r
- externalParents.add(pid);\r
- externalNames.add(name);\r
- state.ids.put(r, state.id);\r
- // Ensure that this resource is included into the set of externals to maintain the total number of externals \r
- state.externals.add(r);\r
- return state.id++;\r
- }\r
- }\r
- \r
- @Override\r
- public DataContainer getHeader() throws Exception {\r
- return null;\r
- }\r
- \r
- @Override\r
- public int getResourceCount() {\r
- return resourceCount;\r
- }\r
- \r
- @Override\r
- public int getIdentityCount() {\r
- return configuration.roots.size() + state.externals.size() + 1;\r
- }\r
- \r
- @Override\r
- public int getStatementCount() {\r
- return state.statementCount;\r
- }\r
- \r
- @Override\r
- public int getValueCount() {\r
- return state.valueCount;\r
- }\r
-\r
- @Override\r
- public void forStatements(ReadGraph graph, TransferableGraphSourceProcedure<int[]> procedure) throws Exception {\r
- \r
- int[] value = new int[4];\r
- long length = state.otherStatementsInput.length();\r
- state.otherStatementsInput.position(0);\r
- \r
- while(state.otherStatementsInput.position() < length && !state.monitor.isCanceled()) {\r
- \r
- int s = state.otherStatementsInput.readInt();\r
- int subjectId = state.ids.get(s);\r
- \r
- boolean exclude = subjectId == -1;\r
- \r
- int size = state.otherStatementsInput.readInt();\r
- for(int i=0;i<size;i++) {\r
- int p = state.otherStatementsInput.readInt();\r
- int o = state.otherStatementsInput.readInt();\r
- if(!exclude) {\r
- if(state.excludedShared.contains(o)) {\r
- System.err.println("excluding shared " + s + " " + p + " " + o);\r
- } else {\r
- \r
- int objectId = getExistingId(graph, o);\r
- // The statement can be denied still\r
- if(objectId != -2) {\r
- value[0] = subjectId;\r
- value[1] = getExistingId(graph, p);\r
- int inverse = state.inverses.get(p);\r
- if(inverse != 0) {\r
- value[2] = getExistingId(graph, inverse);\r
- } else {\r
- value[2] = -1;\r
- }\r
- value[3] = objectId;\r
-\r
- procedure.execute(value);\r
- \r
- } else {\r
- System.err.println("Denied (" + NameUtils.getSafeName(graph, getResource(graph, s)) + ", " + NameUtils.getSafeName(graph, getResource(graph, p)) + "," + NameUtils.getSafeName(graph, getResource(graph, o)) + ")");\r
- } \r
- \r
- }\r
- } else {\r
- System.err.println("excluding shared " + s);\r
- }\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- public void forValues(ReadGraph graph, TransferableGraphSourceProcedure<Value> procedure) throws Exception {\r
-\r
- Serializer variantSerializer = graph.getService(Databoard.class).getSerializerUnchecked(Bindings.VARIANT);\r
- List<Object> idContext = new ArrayList<>();\r
- long length = state.valueInput.length();\r
- state.valueInput.position(0);\r
-\r
- while(state.valueInput.position() < length && !state.monitor.isCanceled()) {\r
-\r
- // Ignore value type tag\r
- int s = state.valueInput.readInt();\r
- byte valueType = state.valueInput.readByte();\r
- switch (valueType) {\r
- case TAG_RAW_COPY_VARIANT_VALUE:\r
- state.valueInput.readInt();\r
- // Intentional fallthrough.\r
-\r
- case TAG_POTENTIALLY_MODIFIED_VARIANT_VALUE: {\r
- idContext.clear();\r
- Variant variant = (Variant) variantSerializer.deserialize((DataInput)state.valueInput, idContext);\r
- if (valueModifier.mayNeedModification(variant.type())) {\r
- Object currentObject = variant.getValue();\r
- Object newObject = valueModifier.modify(state, variant.getBinding(), currentObject);\r
- if (newObject != currentObject)\r
- variant = new Variant(variant.getBinding(), newObject);\r
- }\r
- procedure.execute(new Value(state.ids.get(s), variant));\r
- break;\r
- }\r
-\r
- default:\r
- throw new IllegalArgumentException("Unrecognized variant value type encountered: " + valueType);\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- public void forValues2(ReadGraph graph, TransferableGraphSourceValueProcedure procedure) throws Exception {\r
-\r
- Serializer datatypeSerializer = graph.getService(Databoard.class).getSerializerUnchecked(Bindings.getBindingUnchecked(Datatype.class));\r
- List<Object> idContext = new ArrayList<>();\r
- long length = state.valueInput.length();\r
- state.valueInput.position(0);\r
-\r
- while(state.valueInput.position() < length && !state.monitor.isCanceled()) {\r
-\r
- int s = state.valueInput.readInt();\r
- byte valueType = state.valueInput.readByte();\r
-\r
- switch (valueType) {\r
- case TAG_RAW_COPY_VARIANT_VALUE: {\r
- // Variant data could be copied raw, no need for modifications\r
- // Note that the variant data is a concatenation of the\r
- // variant datatype serialization and the value serialization.\r
- // variantLength contains both datatype and value data.\r
- int variantLength = state.valueInput.readInt();\r
- procedure.rawCopy(state.ids.get(s), variantLength, state.valueInput);\r
- break;\r
- }\r
-\r
- case TAG_POTENTIALLY_MODIFIED_VARIANT_VALUE: {\r
- // Variant data may need to be modified.\r
- // Cannot optimize this case with raw copying.\r
- idContext.clear();\r
- Datatype type = (Datatype)datatypeSerializer.deserialize((DataInput)state.valueInput, idContext);\r
-\r
- if (valueModifier.mayNeedModification(type)) {\r
- Binding binding = Bindings.getBinding(type);\r
- Serializer serializer = Bindings.getSerializerUnchecked(binding);\r
- Object value = serializer.deserialize((DataInput)state.valueInput);\r
- value = valueModifier.modify(state, binding, value);\r
- byte[] bytes = serializer.serialize(value);\r
- procedure.execute(state.ids.get(s), type, new ByteBufferReadable(bytes));\r
- } else {\r
- procedure.execute(state.ids.get(s), type, state.valueInput);\r
- }\r
- break;\r
- }\r
-\r
- default:\r
- throw new IllegalArgumentException("Unrecognized variant value type encountered: " + valueType);\r
- }\r
- }\r
- }\r
-\r
- protected Identity getRootIdentity(DomainProcessorState state, SerialisationSupport support, Resource rootLibrary) throws DatabaseException {\r
- return new Identity(state.ids.get(support.getTransientId(rootLibrary)), new External(-1, ""));\r
- }\r
-\r
- @Override\r
- public void forIdentities(ReadGraph graph, TransferableGraphSourceProcedure<Identity> procedure) throws Exception {\r
- \r
- SerialisationSupport support = graph.getService(SerialisationSupport.class);\r
- Layer0 L0 = Layer0.getInstance(graph);\r
-\r
- // TODO: this should be Root with name ""\r
- procedure.execute(getRootIdentity(state, support, graph.getRootLibrary()));\r
-\r
- // Declare internal and external roots\r
- for(RootSpec r : configuration.roots) {\r
- Resource type = graph.getPossibleType(r.resource, L0.Entity);\r
- if(type == null) type = L0.Entity;\r
- procedure.execute(new Identity(\r
- state.ids.get(support.getTransientId(r.resource)),\r
- new Root(r.name, graph.getURI(type))));\r
- }\r
-\r
- for(int i = 0; i < state.externals.size() ; i++) {\r
- int parent = externalParents.get(i);\r
- String name = externalNames.get(i);\r
- procedure.execute(new Identity(externalBase + i, new External(parent,name)));\r
- }\r
- \r
- }\r
-\r
- @Override\r
- public TreeMap<String, Variant> getExtensions() {\r
- return state.extensions;\r
- }\r
-\r
- public File[] getFiles() {\r
- return files;\r
- }\r
-\r
- private static <T> T tryClose(T c) throws IOException {\r
- if (c != null && c instanceof Closeable)\r
- ((Closeable) c).close();\r
- return null;\r
- }\r
-\r
- public void closeStreams() throws IOException {\r
- state.valueInput = tryClose(state.valueInput);\r
- state.otherStatementsInput = tryClose(state.otherStatementsInput);\r
- state.statementsOutput = tryClose(state.statementsOutput);\r
- state.valueOutput = tryClose(state.valueOutput);\r
- }\r
-\r
- @Override\r
- public void reset() throws Exception {\r
- throw new UnsupportedOperationException();\r
- }\r
- \r
- public long[] getResourceArray(ReadGraph graph) throws DatabaseException {\r
- final SerialisationSupport ss = graph.getService(SerialisationSupport.class);\r
- final long[] result = new long[state.ids.size()];\r
- state.ids.forEachEntry(new TIntIntProcedure() {\r
-\r
- @Override\r
- public boolean execute(int a, int b) {\r
- \r
- try {\r
- Resource r = ss.getResource(a);\r
- result[b] = r.getResourceId();\r
- } catch (DatabaseException e) {\r
- e.printStackTrace();\r
- }\r
- \r
- return true;\r
- \r
- }\r
- });\r
- return result;\r
- }\r
- \r
- public DomainProcessorState getState() {\r
- return state;\r
- }\r
- \r
- public void forResourceStatements(ReadGraph graph, TransferableGraphSourceProcedure<int[]> procedure) throws Exception {\r
- \r
- int[] value = new int[4];\r
- long length = state.otherStatementsInput.length();\r
- state.otherStatementsInput.position(0);\r
- \r
- while(state.otherStatementsInput.position() < length) {\r
- \r
- int s = state.otherStatementsInput.readInt();\r
- int subjectId = state.ids.get(s);\r
- \r
- boolean exclude = subjectId == -1;\r
- \r
- int size = state.otherStatementsInput.readInt();\r
- for(int i=0;i<size;i++) {\r
- int p = state.otherStatementsInput.readInt();\r
- int o = state.otherStatementsInput.readInt();\r
- if(!exclude) {\r
- if(state.excludedShared.contains(o)) {\r
- System.err.println("excluding shared " + s + " " + p + " " + o);\r
- } else {\r
- \r
- int objectId = getExistingId(graph, o);\r
- // The statement can be denied still\r
- if(objectId != -2) {\r
- value[0] = s;\r
- value[1] = p;\r
- int inverse = state.inverses.get(p);\r
- if(inverse != 0) {\r
- value[2] = inverse;\r
- } else {\r
- value[2] = -1;\r
- }\r
- value[3] = o;\r
-\r
- procedure.execute(value);\r
- \r
- } else {\r
- System.err.println("Denied (" + NameUtils.getSafeName(graph, getResource(graph, s)) + ", " + NameUtils.getSafeName(graph, getResource(graph, p)) + "," + NameUtils.getSafeName(graph, getResource(graph, o)) + ")");\r
- }\r
- \r
- }\r
- } else {\r
- System.err.println("excluding shared " + s);\r
- }\r
- }\r
- }\r
- }\r
-\r
- public void forValueResources(ReadGraph graph, TransferableGraphSourceProcedure<int[]> procedure) throws Exception {\r
- int[] value = { 0 };\r
- long length = state.valueInput.length();\r
- while (state.valueInput.position() < length) {\r
- value[0] = state.valueInput.readInt();\r
- procedure.execute(value);\r
- }\r
- }\r
-\r
- public TransferableGraphConfiguration2 getConfiguration() {\r
- return configuration;\r
- }\r
-\r
- @Override\r
- public void close() throws IOException {\r
- synchronized (this) {\r
- if (closed)\r
- return;\r
- closed = true;\r
- }\r
- closeStreams();\r
- if (files != null) {\r
- for (File f : files) {\r
- Files.deleteIfExists(f.toPath());\r
- }\r
- }\r
- }\r
-\r
+package org.simantics.db.layer0.util;
+
+import java.io.Closeable;
+import java.io.DataInput;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.TreeMap;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Databoard;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.container.DataContainer;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.util.binary.ByteBufferReadable;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
+import org.simantics.db.layer0.util.ConsistsOfProcess.ConsistsOfProcessEntry;
+import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec;
+import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec.SeedSpecType;
+import org.simantics.db.service.SerialisationSupport;
+import org.simantics.graph.db.TransferableGraphSource;
+import org.simantics.graph.representation.External;
+import org.simantics.graph.representation.Identity;
+import org.simantics.graph.representation.Internal;
+import org.simantics.graph.representation.Root;
+import org.simantics.graph.representation.Value;
+import org.simantics.layer0.Layer0;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.procedure.TIntIntProcedure;
+
+public class ModelTransferableGraphSource implements TransferableGraphSource {
+
+ private static final Logger LOGGER = LoggerFactory
+ .getLogger(ModelTransferableGraphSource.class);
+
+ final private TransferableGraphConfiguration2 configuration;
+
+ final private DomainProcessorState state;
+
+ final private int externalBase;
+
+ final private int resourceCount;
+
+ final private File[] files;
+
+ final private TGValueModifier valueModifier;
+
+ private volatile boolean closed = false;
+
+ TIntArrayList externalParents = new TIntArrayList();
+
+ ArrayList<String> externalNames = new ArrayList<>();
+
+ TreeMap<String, String> downloads = new TreeMap<String, String>();
+
+ public ModelTransferableGraphSource(final ReadGraph graph, TransferableGraphConfiguration2 configuration,
+ final DomainProcessorState state, File... fs) throws DatabaseException {
+
+ this.configuration = configuration;
+ this.state = state;
+ this.files = fs;
+ this.valueModifier = state.valueModifier;
+
+ SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+
+ // At this point ids contains all internal resources. Now add roots and
+ // externals.
+
+ // Root Library
+ state.ids.put(ss.getTransientId(graph.getRootLibrary()), state.id++);
+
+ // External roots - internal roots were already processed as internal
+ // resources by domain processor
+ for (SeedSpec spec : configuration.seeds) {
+ if (SeedSpecType.SPECIAL_ROOT.equals(spec.specType)) {
+ int resourceId = ss.getTransientId(spec.resource);
+ state.ids.put(resourceId, state.id++);
+ // The fixed roots have been seen as externals by domain
+ // processor. Now remove them from external set.
+ state.externals.remove(resourceId);
+ }
+ }
+
+ this.externalBase = state.id;
+
+ final Collection<String> errors = new HashSet<>();
+
+ // All resource considered as not internal by domain processor. Can also
+ // contain roots.
+ int[] externals = state.externals.toArray();
+
+ // Build up the state.externals, externalNames and externalParents
+ for (int i = 0; i < externals.length; i++) {
+ getId(graph, externals[i], errors);
+ }
+
+ state.inverses.forEachEntry(new TIntIntProcedure() {
+
+ @Override
+ public boolean execute(int predicate, int inverse) {
+ try {
+ getId(graph, predicate, errors);
+ if (inverse != 0)
+ getId(graph, inverse, errors);
+ } catch (DatabaseException e) {
+ throw new RuntimeDatabaseException(e);
+ }
+ return true;
+ }
+
+ });
+
+ if (!errors.isEmpty()) {
+ ArrayList<String> sorted = new ArrayList<>(errors);
+ Collections.sort(sorted);
+ StringBuilder message = new StringBuilder();
+ message.append("Errors in exported model:\n");
+ for (String error : sorted) {
+ message.append(error);
+ message.append("\n");
+ }
+ throw new DatabaseException(message.toString());
+ }
+
+ this.resourceCount = state.id;
+
+ state.extensions.put(ExternalDownloadBean.EXTENSION_KEY,
+ new Variant(ExternalDownloadBean.BINDING, new ExternalDownloadBean(downloads)));
+
+ }
+
+ int indent = 0;
+
+ public boolean validateExternal(Resource ext) {
+ if (configuration.validate) {
+ ExtentStatus status = configuration.preStatus.get(ext);
+ if (status != null) {
+ if (ExtentStatus.INTERNAL.equals(status))
+ return false;
+ else if (ExtentStatus.EXCLUDED.equals(status))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private Resource getResource(ReadGraph graph, int r) throws DatabaseException {
+ SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+ return ss.getResource(r);
+ }
+
+ final public int getExistingId(ReadGraph graph, int r) throws DatabaseException {
+
+ int ret = state.ids.get(r);
+ if (ret != -1) {
+ return ret;
+ } else {
+ SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+ throw new DatabaseException(
+ "Id has not been created for " + NameUtils.getSafeName(graph, ss.getResource(r)));
+ }
+
+ }
+
+ /*
+ *
+ * @return -2 if r is not really external and the statement should be
+ * excluded
+ *
+ */
+ public int getId(ReadGraph graph, int r, Collection<String> errors) throws DatabaseException {
+
+// // First external is root library
+// if(r == rootId) return internalCount;
+
+ SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ if (state.ids.containsKey(r)) {
+ int ret = state.ids.get(r);
+ if (ret == -1) {
+ for (int i = 0; i <= indent; ++i)
+ System.out.print(" ");
+ System.out.println("Cycle!!!"); // with " +
+ // GraphUtils.getReadableName(g,
+ // r));
+ }
+ return ret;
+ } else {
+ Resource res = getResource(graph, r);
+ if (!validateExternal(res)) {
+ errors.add("Illegal reference to " + graph.getPossibleURI(getResource(graph, r)));
+ return -2;
+ }
+ Collection<Resource> parents = graph.getObjects(res, L0.PartOf);
+ if (parents.size() != 1) {
+ throw new ValidationException(
+ "Reference to external resource " + NameUtils.getSafeName(graph, getResource(graph, r), true)
+ + " without unique uri (" + parents.size() + " parents).");
+ }
+ int pid = 0;
+ for (Resource p : parents) {
+ ++indent;
+ pid = getId(graph, ss.getTransientId(p), errors);
+ if (pid == -2) {
+ errors.add("Illegal reference to " + graph.getPossibleURI(getResource(graph, r)));
+ return -2;
+ }
+ }
+ --indent;
+ String name = graph.getRelatedValue(res, L0.HasName);
+ // Record the external entry
+ externalParents.add(pid);
+ externalNames.add(name);
+ state.ids.put(r, state.id);
+ // Ensure that this resource is included into the set of externals
+ // to maintain the total number of externals
+ state.externals.add(r);
+ String download = graph.getPossibleRelatedValue(res, L0.Ontology_download, Bindings.STRING);
+ if (download != null) {
+ String uri = graph.getURI(res);
+ downloads.put(uri, download);
+ }
+ return state.id++;
+ }
+ }
+
+ @Override
+ public DataContainer getHeader() throws Exception {
+ return null;
+ }
+
+ @Override
+ public int getResourceCount() {
+ return resourceCount;
+ }
+
+ private int countRootSeeds() {
+ int result = 0;
+ for (SeedSpec spec : configuration.seeds) {
+ if (SeedSpecType.INTERNAL.equals(spec.specType))
+ continue;
+ result++;
+ }
+ return result;
+ }
+
+ @Override
+ public int getIdentityCount() {
+ return countRootSeeds() + state.externals.size() + state.internalEntries.size() + 1;
+ }
+
+ @Override
+ public int getStatementCount() {
+ return state.statementCount;
+ }
+
+ @Override
+ public int getValueCount() {
+ return state.valueCount;
+ }
+
+ @Override
+ public void forStatements(ReadGraph graph, TransferableGraphSourceProcedure<int[]> procedure) throws Exception {
+
+ int[] value = new int[4];
+ long length = state.otherStatementsInput.length();
+ state.otherStatementsInput.position(0);
+
+ while (state.otherStatementsInput.position() < length && !state.monitor.isCanceled()) {
+
+ int s = state.otherStatementsInput.readInt();
+ int subjectId = state.ids.get(s);
+
+ boolean exclude = subjectId == -1;
+
+ int size = state.otherStatementsInput.readInt();
+ for (int i = 0; i < size; i++) {
+ int p = state.otherStatementsInput.readInt();
+ int o = state.otherStatementsInput.readInt();
+ if (!exclude) {
+ if (state.pending.contains(o)) {
+ System.err.println("excluding garbage statement " + s + " " + p + " " + o
+ + ", object resource is garbage");
+ } else if (state.excludedShared.contains(o)) {
+ System.err.println("excluding shared " + s + " " + p + " " + o);
+ } else {
+
+ int objectId = getExistingId(graph, o);
+ // The statement can be denied still
+ if (objectId != -2) {
+ value[0] = subjectId;
+ value[1] = getExistingId(graph, p);
+ int inverse = state.inverses.get(p);
+ if (inverse != 0) {
+ value[2] = getExistingId(graph, inverse);
+ } else {
+ value[2] = -1;
+ }
+ value[3] = objectId;
+
+ try {
+ procedure.execute(value);
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a statement in transferable graph source", e);
+ }
+
+ } else {
+ System.err.println("Denied (" + NameUtils.getSafeName(graph, getResource(graph, s)) + ", "
+ + NameUtils.getSafeName(graph, getResource(graph, p)) + ","
+ + NameUtils.getSafeName(graph, getResource(graph, o)) + ")");
+ }
+
+ }
+ } else {
+ System.err.println("excluding shared " + s);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void forValues(ReadGraph graph, TransferableGraphSourceProcedure<Value> procedure) throws Exception {
+
+ Serializer variantSerializer = graph.getService(Databoard.class).getSerializerUnchecked(Bindings.VARIANT);
+ List<Object> idContext = new ArrayList<>();
+ long length = state.valueInput.length();
+ state.valueInput.position(0);
+
+ while (state.valueInput.position() < length && !state.monitor.isCanceled()) {
+
+ // Ignore value type tag
+ int s = state.valueInput.readInt();
+ byte valueType = state.valueInput.readByte();
+ switch (valueType) {
+ case TAG_RAW_COPY_VARIANT_VALUE:
+ state.valueInput.readInt();
+ // Intentional fallthrough.
+
+ case TAG_POTENTIALLY_MODIFIED_VARIANT_VALUE: {
+ idContext.clear();
+ Variant variant = (Variant) variantSerializer.deserialize((DataInput) state.valueInput, idContext);
+ if (valueModifier.mayNeedModification(variant.type())) {
+ Object currentObject = variant.getValue();
+ Object newObject = valueModifier.modify(state, variant.getBinding(), currentObject);
+ if (newObject != currentObject)
+ variant = new Variant(variant.getBinding(), newObject);
+ }
+ try {
+ procedure.execute(new Value(state.ids.get(s), variant));
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a value in transferable graph source", e);
+ }
+ break;
+ }
+
+ default:
+ throw new IllegalArgumentException("Unrecognized variant value type encountered: " + valueType);
+ }
+ }
+ }
+
+ @Override
+ public void forValues2(ReadGraph graph, TransferableGraphSourceValueProcedure procedure) throws Exception {
+
+ Serializer datatypeSerializer = graph.getService(Databoard.class)
+ .getSerializerUnchecked(Bindings.getBindingUnchecked(Datatype.class));
+ List<Object> idContext = new ArrayList<>();
+ long length = state.valueInput.length();
+ state.valueInput.position(0);
+
+ while (state.valueInput.position() < length && !state.monitor.isCanceled()) {
+
+ int s = state.valueInput.readInt();
+ byte valueType = state.valueInput.readByte();
+
+ switch (valueType) {
+ case TAG_RAW_COPY_VARIANT_VALUE: {
+ // Variant data could be copied raw, no need for
+ // modifications
+ // Note that the variant data is a concatenation of the
+ // variant datatype serialization and the value
+ // serialization.
+ // variantLength contains both datatype and value data.
+ int variantLength = state.valueInput.readInt();
+ try {
+ procedure.rawCopy(state.ids.get(s), variantLength, state.valueInput);
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a raw value in transferable graph source", e);
+ }
+ break;
+ }
+
+ case TAG_POTENTIALLY_MODIFIED_VARIANT_VALUE: {
+ // Variant data may need to be modified.
+ // Cannot optimize this case with raw copying.
+ idContext.clear();
+ Datatype type = (Datatype) datatypeSerializer.deserialize((DataInput) state.valueInput, idContext);
+
+ if (valueModifier.mayNeedModification(type)) {
+ Binding binding = Bindings.getBinding(type);
+ Serializer serializer = Bindings.getSerializerUnchecked(binding);
+ Object value = serializer.deserialize((DataInput) state.valueInput);
+ value = valueModifier.modify(state, binding, value);
+ byte[] bytes = serializer.serialize(value);
+ try {
+ procedure.execute(state.ids.get(s), type, new ByteBufferReadable(bytes));
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a data type in transferable graph source", e);
+ }
+ } else {
+ try {
+ procedure.execute(state.ids.get(s), type, state.valueInput);
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a raw value in transferable graph source", e);
+ }
+ }
+ break;
+ }
+
+ default:
+ throw new IllegalArgumentException("Unrecognized variant value type encountered: " + valueType);
+ }
+ }
+ }
+
+ protected Identity getRootIdentity(DomainProcessorState state, SerialisationSupport support, Resource rootLibrary)
+ throws DatabaseException {
+ return new Identity(state.ids.get(support.getTransientId(rootLibrary)), new External(-1, ""));
+ }
+
+ @Override
+ public void forIdentities(ReadGraph graph, TransferableGraphSourceProcedure<Identity> procedure) throws Exception {
+
+ SerialisationSupport support = graph.getService(SerialisationSupport.class);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ // TODO: this should be Root with name ""
+ try {
+ procedure.execute(getRootIdentity(state, support, graph.getRootLibrary()));
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a root identity in transferable graph source", e);
+ }
+
+ TIntObjectMap<Identity> internalMap = new TIntObjectHashMap<>(100, 0.5f, Integer.MIN_VALUE);
+
+ // Declare internal and external roots
+ for (SeedSpec r : configuration.seeds) {
+ if (SeedSpecType.INTERNAL.equals(r.specType))
+ continue;
+ String typeId = r.type;
+ if (typeId == null) {
+ Resource type = graph.getPossibleType(r.resource, L0.Entity);
+ typeId = type != null ? graph.getURI(type) : Layer0.URIs.Entity;
+ }
+ int id = state.ids.get(support.getTransientId(r.resource));
+ Root root = new Root(r.name, typeId);
+ Identity rootId = new Identity(id, root);
+ internalMap.put(id, rootId);
+ try {
+ procedure.execute(rootId);
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a root in transferable graph source", e);
+ }
+ }
+
+ for (int i = 0; i < state.externals.size(); i++) {
+ int parent = externalParents.get(i);
+ String name = externalNames.get(i);
+ try {
+ procedure.execute(new Identity(externalBase + i, new External(parent, name)));
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a an external identity in transferable graph source", e);
+ }
+ }
+
+ if (state.internalEntries != null) {
+ for (ConsistsOfProcessEntry ie : state.internalEntries) {
+ if (ie.parent != null) {
+ if (ie.name != null) {
+ try {
+ procedure.execute(resolveInternal(graph, support, ie, internalMap));
+ } catch (Exception e) {
+ LOGGER.error("Error while processing an internal identity in transferable graph source", e);
+ }
+ } else {
+ // In this case there is a child that has no HasName =>
+ // this should be treated as a blank
+ }
+ } else {
+ try {
+ procedure.execute(resolveInternal(graph, support, ie, internalMap));
+ } catch (Exception e) {
+ LOGGER.error("Error while processing an internal identity in transferable graph source", e);
+ }
+ }
+ }
+ }
+
+ }
+
+ private Identity resolveInternal(ReadGraph graph, SerialisationSupport ss, ConsistsOfProcessEntry entry,
+ TIntObjectMap<Identity> internalMap) throws DatabaseException {
+ int id = state.ids.get(ss.getTransientId(entry.resource));
+ Identity existing = internalMap.get(id);
+ if (existing != null)
+ return existing;
+
+ if (entry.parent == null) {
+ Layer0 L0 = Layer0.getInstance(graph);
+ Resource possibleParent = graph.getPossibleObject(entry.resource, L0.PartOf);
+ if (possibleParent == null)
+ throw new DatabaseException("Invalid root or internal parent path: " + entry.resource);
+ int externalId = state.ids.get(ss.getTransientId(possibleParent));
+ Identity result = new Identity(id, new Internal(externalId, entry.name));
+ internalMap.put(id, result);
+ return result;
+ } else {
+ Identity parent = resolveInternal(graph, ss, entry.parent, internalMap);
+ Identity result = new Identity(id, new Internal(parent.resource, entry.name));
+ internalMap.put(id, result);
+ return result;
+ }
+ }
+
+ @Override
+ public TreeMap<String, Variant> getExtensions() {
+ return state.extensions;
+ }
+
+ public File[] getFiles() {
+ return files;
+ }
+
+ private static <T> T tryClose(T c) throws IOException {
+ if (c != null && c instanceof Closeable)
+ ((Closeable) c).close();
+ return null;
+ }
+
+ public void closeStreams() throws IOException {
+ state.valueInput = tryClose(state.valueInput);
+ state.otherStatementsInput = tryClose(state.otherStatementsInput);
+ state.statementsOutput = tryClose(state.statementsOutput);
+ state.valueOutput = tryClose(state.valueOutput);
+ }
+
+ @Override
+ public void reset() throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ public long[] getResourceArray(ReadGraph graph) throws DatabaseException {
+ final SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+ final long[] result = new long[state.ids.size()];
+ state.ids.forEachEntry(new TIntIntProcedure() {
+
+ @Override
+ public boolean execute(int a, int b) {
+
+ try {
+ Resource r = ss.getResource(a);
+ result[b] = r.getResourceId();
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ }
+
+ return true;
+
+ }
+ });
+ return result;
+ }
+
+ public DomainProcessorState getState() {
+ return state;
+ }
+
+ public void forResourceStatements(ReadGraph graph, TransferableGraphSourceProcedure<int[]> procedure)
+ throws Exception {
+
+ int[] value = new int[4];
+ long length = state.otherStatementsInput.length();
+ state.otherStatementsInput.position(0);
+
+ while (state.otherStatementsInput.position() < length) {
+
+ int s = state.otherStatementsInput.readInt();
+ int subjectId = state.ids.get(s);
+
+ boolean exclude = subjectId == -1;
+
+ int size = state.otherStatementsInput.readInt();
+ for (int i = 0; i < size; i++) {
+ int p = state.otherStatementsInput.readInt();
+ int o = state.otherStatementsInput.readInt();
+ if (!exclude) {
+ if (state.excludedShared.contains(o)) {
+ System.err.println("excluding shared " + s + " " + p + " " + o);
+ } else {
+
+ int objectId = getExistingId(graph, o);
+ // The statement can be denied still
+ if (objectId != -2) {
+ value[0] = s;
+ value[1] = p;
+ int inverse = state.inverses.get(p);
+ if (inverse != 0) {
+ value[2] = inverse;
+ } else {
+ value[2] = -1;
+ }
+ value[3] = o;
+
+ try {
+ procedure.execute(value);
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a statement in transferable graph source", e);
+ }
+
+ } else {
+ System.err.println("Denied (" + NameUtils.getSafeName(graph, getResource(graph, s)) + ", "
+ + NameUtils.getSafeName(graph, getResource(graph, p)) + ","
+ + NameUtils.getSafeName(graph, getResource(graph, o)) + ")");
+ }
+
+ }
+ } else {
+ System.err.println("excluding shared " + s);
+ }
+ }
+ }
+ }
+
+ public void forValueResources(ReadGraph graph, TransferableGraphSourceProcedure<int[]> procedure) throws Exception {
+ int[] value = { 0 };
+ long length = state.valueInput.length();
+ while (state.valueInput.position() < length) {
+ value[0] = state.valueInput.readInt();
+ try {
+ procedure.execute(value);
+ } catch (Exception e) {
+ LOGGER.error("Error while processing a value in transferable graph source", e);
+ }
+ }
+ }
+
+ public TransferableGraphConfiguration2 getConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public void close() throws IOException {
+ synchronized (this) {
+ if (closed)
+ return;
+ closed = true;
+ }
+ closeStreams();
+ if (files != null) {
+ for (File f : files) {
+ Files.deleteIfExists(f.toPath());
+ }
+ }
+ }
+
}
\ No newline at end of file