+ 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;
+