--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.impl.graph;\r
+\r
+\r
+import java.io.DataInput;\r
+import java.io.DataOutput;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.nio.ByteBuffer;\r
+import java.nio.channels.FileChannel;\r
+import java.util.ArrayList;\r
+import java.util.HashSet;\r
+import java.util.IdentityHashMap;\r
+import java.util.List;\r
+import java.util.Set;\r
+import java.util.TreeMap;\r
+import java.util.UUID;\r
+\r
+import org.eclipse.core.runtime.Platform;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.accessor.Accessor;\r
+import org.simantics.databoard.accessor.reference.ChildReference;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.error.BindingConstructionException;\r
+import org.simantics.databoard.binding.impl.BindingPrintContext;\r
+import org.simantics.databoard.serialization.SerializationException;\r
+import org.simantics.databoard.serialization.Serializer;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.util.IdentityPair;\r
+import org.simantics.databoard.util.binary.RandomAccessBinary;\r
+import org.simantics.db.Metadata;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.WriteOnlyGraph;\r
+import org.simantics.db.common.MetadataUtils;\r
+import org.simantics.db.common.request.WriteOnlyRequest;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.db.exception.BindingException;\r
+import org.simantics.db.exception.ClusterSetExistException;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
+import org.simantics.db.exception.NoSingleResultException;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.impl.DebugPolicy;\r
+import org.simantics.db.impl.ResourceImpl;\r
+import org.simantics.db.request.DelayedWrite;\r
+import org.simantics.db.request.WriteOnly;\r
+import org.simantics.db.request.WriteResult;\r
+import org.simantics.db.request.WriteTraits;\r
+import org.simantics.db.service.ByteReader;\r
+import org.simantics.db.service.ClusteringSupport;\r
+import org.simantics.db.service.TransferableGraphSupport;\r
+import org.simantics.db.service.XSupport;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+import gnu.trove.list.array.TIntArrayList;\r
+import gnu.trove.map.hash.TIntIntHashMap;\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+\r
+/**\r
+ * Write graph implementation that does not modify the database\r
+ * immediately but with an explicit commit method. All read operations\r
+ * return results based on the old graph. \r
+ */\r
+public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, ByteReader {\r
+ \r
+ private static final boolean DEBUG = false;\r
+ public static int BUFFER = 65536;\r
+\r
+ static class Haxx extends Binding {\r
+\r
+ static final Serializer serializer = new Serializer() {\r
+ \r
+ public byte[] serialize(Object obj) throws SerializationException {\r
+ return (byte[])obj;\r
+ }\r
+\r
+ @Override\r
+ public void serialize(DataOutput out,\r
+ TObjectIntHashMap<Object> identities, Object obj)\r
+ throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public void serialize(DataOutput out, Object obj)\r
+ throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public Object deserialize(DataInput in, List<Object> identities)\r
+ throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public Object deserialize(DataInput in) throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public void deserializeTo(DataInput in, List<Object> identities,\r
+ Object obj) throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public void deserializeTo(DataInput in, Object obj)\r
+ throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public void skip(DataInput in, List<Object> identities)\r
+ throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public void skip(DataInput in) throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public Integer getConstantSize() {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public int getSize(Object obj, TObjectIntHashMap<Object> identities)\r
+ throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public int getSize(Object obj) throws IOException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public int getMinSize() {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ };\r
+ \r
+ @Override\r
+ public Serializer serializer() {\r
+ return serializer;\r
+ }\r
+ \r
+ @Override\r
+ public void accept(Visitor1 v, Object obj) {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public <T> T accept(Visitor<T> v) {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public boolean isInstance(Object obj) {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public void assertInstaceIsValid(Object obj, Set<Object> validInstances)\r
+ throws org.simantics.databoard.binding.error.BindingException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public int deepHashValue(Object value,\r
+ IdentityHashMap<Object, Object> hashedObjects)\r
+ throws org.simantics.databoard.binding.error.BindingException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public int deepCompare(Object o1, Object o2,\r
+ Set<IdentityPair<Object, Object>> compareHistory)\r
+ throws org.simantics.databoard.binding.error.BindingException {\r
+ throw new Error("Not supported.");\r
+ }\r
+ \r
+ @Override\r
+ public void readFrom(Binding srcBinding, Object src, Object dst)\r
+ throws org.simantics.databoard.binding.error.BindingException {\r
+ throw new Error("Not supported.");\r
+ }\r
+ \r
+ @Override\r
+ public Object readFromTry(Binding srcBinding, Object src, Object dst)\r
+ throws org.simantics.databoard.binding.error.BindingException {\r
+ throw new Error("Not supported.");\r
+ }\r
+ \r
+ @Override\r
+ protected void toString(Object value, BindingPrintContext ctx) throws org.simantics.databoard.binding.error.BindingException {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public int getComponentCount() {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public Binding getComponentBinding(int index) {\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public Binding getComponentBinding(ChildReference path) {\r
+ throw new Error("Not supported.");\r
+ }\r
+ \r
+ }\r
+ \r
+ private static final Haxx haxx = new Haxx();\r
+\r
+ private final int TERM = 0;\r
+ private final int CLAIM = 1;\r
+ private final int CLAIM_NOINVERSE = 2;\r
+ private final int CLAIM_VALUE_B = 4;\r
+ private final int DENY = 5;\r
+ private final int DENY_VALUE = 6;\r
+ private final int COMMIT_AND_CONTINUE = 7;\r
+ \r
+ static class ClusterSet {\r
+ public Resource resource;\r
+ ClusterSet() {\r
+ ids = new TIntArrayList();\r
+ old = false;\r
+ }\r
+ ClusterSet(boolean old, Resource r) {\r
+ ids = new TIntArrayList();\r
+ this.old = old;\r
+ this.resource = r;\r
+ }\r
+ void add(int id) {\r
+ ids.add(id);\r
+ }\r
+ private TIntArrayList ids;\r
+ private final boolean old; // true if\r
+ boolean isNew() {\r
+ return !old;\r
+ }\r
+ }\r
+ public class State {\r
+ public File tempFile;\r
+ public FileOutputStream out;\r
+ public ArrayList<Resource> idToResource = new ArrayList<Resource>();\r
+ public TIntIntHashMap externalToId = new TIntIntHashMap(); \r
+ public ArrayList<Binding> idToBinding = new ArrayList<Binding>();\r
+ public TObjectIntHashMap<Binding> bindingToId = new TObjectIntHashMap<Binding>();\r
+ public Set<Resource> clusterSets = new HashSet<Resource>();\r
+ public Set<Resource> clusterSetsForExistingResources = new HashSet<Resource>();\r
+ public int clusterCount = 0;\r
+ public long defaultCluster;\r
+ public Resource defaultClusterSet;\r
+ public int statementCount = 0;\r
+ public int valueCount = 0;\r
+ public int fileCount = 0;\r
+ }\r
+ \r
+ public State writeState;\r
+ public TreeMap<String,byte[]> metadata = new TreeMap<String,byte[]>();\r
+ \r
+ Layer0 b;\r
+ Session session;\r
+ public static Resource convertDelayedResource(Resource r) {\r
+ if (r instanceof InternalResource) {\r
+ InternalResource ri = (InternalResource)r;\r
+ return ri.resource;\r
+ }\r
+ return r;\r
+ }\r
+ private static class InternalResource implements Resource {\r
+\r
+ int id;\r
+ long clusterId = 0;\r
+ Resource resource = null;\r
+ Resource clusterSet = null;\r
+ \r
+ public InternalResource(int id, long clusterId) {\r
+ this.id = id;\r
+ this.clusterId = clusterId;\r
+ }\r
+\r
+ public InternalResource(int id, Resource clusterSet) {\r
+ this.id = id;\r
+ this.clusterSet = clusterSet;\r
+ }\r
+ \r
+ @Override\r
+ public long getResourceId() {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public Resource get() {\r
+ return this;\r
+ }\r
+ \r
+ @Override\r
+ public boolean isPersistent() {\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public int compareTo(Resource o) {\r
+ if(o instanceof InternalResource) {\r
+ return Integer.compare(id, ((InternalResource)o).id);\r
+ } else {\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + id;\r
+ return result;\r
+ }\r
+ \r
+ @Override\r
+ public int getThreadHash() {\r
+ return hashCode();\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (!(obj instanceof InternalResource))\r
+ return false;\r
+ InternalResource other = (InternalResource) obj;\r
+ if (id != other.id)\r
+ return false;\r
+ return true;\r
+ }\r
+ \r
+\r
+ @Override\r
+ public boolean equalsResource(Resource other) {\r
+ return equals(other);\r
+ }\r
+ @Override\r
+ public String toString() {\r
+ StringBuilder sb = new StringBuilder(32);\r
+ if(DebugPolicy.VERBOSE) {\r
+ sb.append("[delayed id=");\r
+ sb.append(id);\r
+ sb.append("]");\r
+ } else {\r
+ sb.append("[did=");\r
+ sb.append(id);\r
+ sb.append("]");\r
+ }\r
+ return sb.toString();\r
+ }\r
+ }\r
+\r
+ private int getId(Resource resource) {\r
+ if(resource instanceof InternalResource)\r
+ return ((InternalResource)resource).id;\r
+ else {\r
+ ResourceImpl r = (ResourceImpl)resource;\r
+ int id = writeState.externalToId.get(r.id);\r
+ if(id != 0) {\r
+ return id;\r
+ } else {\r
+ id = writeState.idToResource.size();\r
+ writeState.idToResource.add(resource);\r
+ writeState.externalToId.put(r.id, id);\r
+ return id;\r
+ }\r
+ }\r
+ }\r
+ \r
+ private Resource getResource(int id) {\r
+ return writeState.idToResource.get(id);\r
+ }\r
+ \r
+ private int getBindingId(Binding binding) {\r
+ if(writeState.bindingToId.contains(binding))\r
+ return writeState.bindingToId.get(binding);\r
+ else {\r
+ int id = writeState.idToBinding.size();\r
+ writeState.idToBinding.add(binding);\r
+ writeState.bindingToId.put(binding, id);\r
+ return id;\r
+ }\r
+ }\r
+\r
+ public DelayedWriteGraph(ReadGraph g) throws IOException {\r
+ super((ReadGraphImpl)g);\r
+ writeState = new State();\r
+ session = g.getSession();\r
+ b = Layer0.getInstance(g);\r
+ writeState.defaultCluster = newCluster();\r
+ } \r
+ \r
+ public DelayedWriteGraph(ReadGraph g, State state) {\r
+ super((ReadGraphImpl)g);\r
+ session = g.getSession();\r
+ b = Layer0.getInstance(g);\r
+ this.writeState = state;\r
+ } \r
+\r
+ public DelayedWriteGraph newSync() {\r
+ return new DelayedWriteGraph(this, writeState);\r
+ }\r
+ \r
+ @Override\r
+ public void claim(Resource subject, Resource predicate, Resource object)\r
+ throws ServiceException {\r
+ assert(subject != null);\r
+ assert(predicate != null);\r
+ assert(object != null);\r
+ \r
+ Resource inverse = getPossibleInverse(predicate);\r
+ claim(subject, predicate, inverse, object);\r
+ }\r
+\r
+ @Override\r
+ public void addLiteral(Resource resource, Resource predicate, Resource inverse, Resource type, Object value,\r
+ Binding binding) throws BindingException,\r
+ ManyObjectsForFunctionalRelationException, ServiceException {\r
+ Resource valueResource = newResource();\r
+ claimValue(valueResource, value, binding);\r
+ claim(valueResource, b.InstanceOf, null, type);\r
+ claim(resource, predicate, inverse, valueResource); \r
+ }\r
+ \r
+ @Override\r
+ public void addLiteral(Resource resource, Resource predicate,\r
+ Resource inverse, Object value, Binding binding)\r
+ throws BindingException, ManyObjectsForFunctionalRelationException,\r
+ ServiceException {\r
+ \r
+ Resource type = getType(value);\r
+ if(type == null) {\r
+ Resource literal = newResource();\r
+ type = b.Literal;\r
+ Resource dataType = newResource();\r
+ claim(dataType, b.InstanceOf, null, b.DataType);\r
+ claimValue(dataType, binding.type(), DATA_TYPE_BINDING_INTERNAL);\r
+ claim(literal, b.HasDataType, null, dataType);\r
+ claim(literal, b.InstanceOf, null, type);\r
+ claimValue(literal, value, binding); \r
+ claim(resource, predicate, inverse, literal);\r
+ } else {\r
+ addLiteral(resource, predicate, inverse, type, value, binding);\r
+ }\r
+ \r
+ }\r
+\r
+ @Override\r
+ public <T extends Accessor> T newLiteral(Resource resource, Resource predicate, Datatype datatype, Object initialValue)\r
+ throws DatabaseException {\r
+\r
+ throw new UnsupportedOperationException();\r
+\r
+ }\r
+\r
+ @Override\r
+ public RandomAccessBinary createRandomAccessBinary (Resource resource, Resource predicate, Datatype datatype, Object initialValue) throws DatabaseException {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+ \r
+ @Override\r
+ public RandomAccessBinary createRandomAccessBinary(Resource resource, Datatype datatype, Object initialValue) throws DatabaseException {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public void claimLiteral(Resource resource, Resource predicate, Object value) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
+\r
+ try {\r
+ Binding b = Bindings.getBinding(value.getClass());\r
+ claimLiteral(resource, predicate, value, b);\r
+ } catch (BindingConstructionException e) {\r
+ throw new IllegalArgumentException(e);\r
+ } catch (BindingException e) {\r
+ throw new IllegalArgumentException(e);\r
+ }\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void claimLiteral(Resource resource, Resource predicate, Object value, Binding binding) throws BindingException,\r
+ ManyObjectsForFunctionalRelationException, ServiceException {\r
+\r
+ Statement valueStatement = null;\r
+ if(!(resource instanceof InternalResource)) valueStatement = getPossibleStatement(resource, predicate);\r
+\r
+ if(valueStatement != null && resource.equals(valueStatement.getSubject())) {\r
+\r
+ claimValue(valueStatement.getObject(), value, binding);\r
+\r
+ } else {\r
+\r
+ Resource type = getType(value);\r
+ Resource literal = newResource();\r
+ if (type == null) {\r
+ type = b.Literal;\r
+ Resource dataType = newResource();\r
+ claim(dataType, b.InstanceOf, null, b.DataType);\r
+ claimValue(dataType, binding.type(), DATA_TYPE_BINDING_INTERNAL);\r
+ claim(literal, b.HasDataType, dataType);\r
+ }\r
+ claim(literal, b.InstanceOf, null, type);\r
+ claimValue(literal, value, binding); \r
+ claim(resource, predicate, literal);\r
+ \r
+ }\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void claimLiteral(Resource resource, Resource predicate,\r
+ Resource inverse, Resource type, Object value)\r
+ throws BindingException, ManyObjectsForFunctionalRelationException,\r
+ ServiceException {\r
+\r
+ try {\r
+ Binding b = Bindings.getBinding(value.getClass());\r
+ claimLiteral(resource, predicate, inverse, type, value, b);\r
+ } catch (BindingConstructionException e) {\r
+ throw new IllegalArgumentException(e);\r
+ } catch (BindingException e) {\r
+ throw new IllegalArgumentException(e);\r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void claimLiteral(Resource resource, Resource predicate,\r
+ Resource inverse, Resource type, Object value, Binding binding)\r
+ throws BindingException, ManyObjectsForFunctionalRelationException,\r
+ ServiceException {\r
+\r
+ Statement valueStatement = (resource instanceof InternalResource) ? null : getPossibleStatement(resource, predicate);\r
+\r
+ if(valueStatement != null && resource.equals(valueStatement.getSubject())) {\r
+\r
+ claimValue(valueStatement.getObject(), value, binding);\r
+\r
+ } else {\r
+\r
+ Resource valueResource = newResource();\r
+ claim(valueResource, b.InstanceOf, null, type);\r
+ claim(resource, predicate, inverse, valueResource);\r
+ claimValue(valueResource, value, binding);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ @Override\r
+ public void claimLiteral(Resource resource, Resource predicate,\r
+ Resource type, Object value) throws BindingException,\r
+ ManyObjectsForFunctionalRelationException, ServiceException {\r
+\r
+ try {\r
+ Binding b = Bindings.getBinding(value.getClass());\r
+ claimLiteral(resource, predicate, type, value, b);\r
+ } catch (BindingConstructionException e) {\r
+ throw new IllegalArgumentException(e);\r
+ } catch (BindingException e) {\r
+ throw new IllegalArgumentException(e);\r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void claimLiteral(Resource resource, Resource predicate,\r
+ Resource type, Object value, Binding binding)\r
+ throws BindingException, ManyObjectsForFunctionalRelationException,\r
+ ServiceException {\r
+\r
+ try {\r
+ Resource inverse = getSingleObject(predicate, b.InverseOf);\r
+ claimLiteral(resource, predicate, inverse, type, value, binding);\r
+ } catch (NoSingleResultException e) {\r
+ throw new ServiceException(e);\r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void deny(Resource subject) throws ServiceException {\r
+ assert(subject != null);\r
+ if(!(subject instanceof InternalResource)) {\r
+ try {\r
+ for (Statement statement : getStatements(subject, b.IsWeaklyRelatedTo)) {\r
+ deny(statement);\r
+ }\r
+ } catch (ManyObjectsForFunctionalRelationException e) {\r
+ throw new ServiceException(e);\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void deny(Resource subject, Resource predicate)\r
+ throws ServiceException {\r
+ assert(subject != null);\r
+ if(!(subject instanceof InternalResource)) {\r
+ for (Resource object : getObjects(subject, predicate)) {\r
+ deny(subject, predicate, object);\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void deny(Resource subject, Resource predicate, Resource object) throws ServiceException {\r
+ denyStatement(subject, predicate, object);\r
+ }\r
+\r
+ @Override\r
+ public void denyStatement(Resource subject, Resource predicate, Resource object) throws ServiceException {\r
+ deny(subject, predicate, getPossibleInverse(predicate), object);\r
+ }\r
+\r
+ @Override\r
+ public void deny(Statement statement) throws ServiceException {\r
+ Resource predicate = statement.getPredicate();\r
+ deny(statement.getSubject(), predicate, getPossibleInverse(predicate), statement.getObject());\r
+ }\r
+\r
+ @Override\r
+ public void denyValue(Resource resource, Resource predicate)\r
+ throws ManyObjectsForFunctionalRelationException, ServiceException {\r
+ assert(resource != null);\r
+ assert(predicate != null);\r
+\r
+ if(!(resource instanceof InternalResource)) {\r
+ Statement valueStatement = getPossibleStatement(resource, predicate);\r
+\r
+ if (valueStatement != null && !valueStatement.isAsserted(resource)) {\r
+ Resource value = valueStatement.getObject();\r
+ denyValue(value);\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Resource newResource() throws ServiceException {\r
+ if(writeState.defaultClusterSet != null) return newResource(writeState.defaultClusterSet);\r
+ else return newResource(writeState.defaultCluster);\r
+ }\r
+\r
+ @Override\r
+ public Resource newResource(long clusterId) throws ServiceException {\r
+ int id = writeState.idToResource.size();\r
+ InternalResource ret = new InternalResource(id, clusterId);\r
+ writeState.idToResource.add(ret);\r
+ return ret;\r
+ }\r
+\r
+ @Override\r
+ public Resource newResource(Resource clusterSet) throws ServiceException {\r
+ \r
+ if ((clusterSet instanceof InternalResource)) {\r
+ if(!writeState.clusterSets.contains(clusterSet))\r
+ throw new ClusterSetExistException("Cluster set does not exist. Resource=" + clusterSet);\r
+ } else {\r
+ WriteSupport ws = session.getService(WriteSupport.class);\r
+ if (!ws.hasClusterSet(null, clusterSet))\r
+ if(!writeState.clusterSetsForExistingResources.contains(clusterSet))\r
+ throw new ClusterSetExistException("Cluster set does not exist. Resource=" + clusterSet);\r
+ }\r
+ \r
+ int id = writeState.idToResource.size();\r
+ InternalResource ret = new InternalResource(id, clusterSet);\r
+ writeState.idToResource.add(ret);\r
+ return ret;\r
+ }\r
+\r
+ @Override\r
+ public void newClusterSet(Resource clusterSet) throws ServiceException {\r
+ if (DEBUG)\r
+ System.out.println("new cluster set=" + clusterSet);\r
+ boolean existingResource = !(clusterSet instanceof InternalResource);\r
+ if (existingResource) {\r
+ WriteSupport ws = session.getService(WriteSupport.class);\r
+ if (ws.hasClusterSet(null, clusterSet))\r
+ throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);\r
+ writeState.clusterSetsForExistingResources.add(clusterSet); \r
+ } else { \r
+ if(!writeState.clusterSets.add(clusterSet))\r
+ throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);\r
+ }\r
+ }\r
+ @Override\r
+ public Resource setClusterSet4NewResource(Resource clusterSet)\r
+ throws ServiceException {\r
+ Resource existing = writeState.defaultClusterSet; \r
+ writeState.defaultClusterSet = clusterSet;\r
+ return existing;\r
+ }\r
+ \r
+ @Override\r
+ public void claim(Resource subject, Resource predicate, Resource inverse,\r
+ Resource object) throws ServiceException {\r
+ assert(subject != null);\r
+ assert(predicate != null);\r
+ assert(object != null);\r
+ try {\r
+ if(inverse != null && !(subject.equals(object) && inverse.equals(predicate))) {\r
+ writeByte(CLAIM);\r
+ writeInt(getId(subject));\r
+ writeInt(getId(predicate));\r
+ writeInt(getId(inverse));\r
+ writeInt(getId(object));\r
+ } else {\r
+ writeByte(CLAIM_NOINVERSE);\r
+ writeInt(getId(subject));\r
+ writeInt(getId(predicate));\r
+ writeInt(getId(object));\r
+ }\r
+ } catch(Exception e) {\r
+ throw new ServiceException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void deny(Resource subject, Resource predicate, Resource inverse,\r
+ Resource object) throws ServiceException {\r
+ assert(subject != null);\r
+ assert(predicate != null);\r
+ assert(object != null);\r
+ try {\r
+ writeByte(DENY);\r
+ writeInt(getId(subject));\r
+ writeInt(getId(predicate));\r
+ if(inverse != null) writeInt(getId(inverse));\r
+ else writeInt(0);\r
+ writeInt(getId(object));\r
+ } catch(Exception e) {\r
+ throw new ServiceException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void deny(Resource subject, Resource predicate, Resource inverse,\r
+ Resource object, VirtualGraph graph) throws ServiceException {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+ \r
+ @Override\r
+ public void claimValue(Resource resource, Object value)\r
+ throws ServiceException {\r
+ try {\r
+ Binding binding = Bindings.getBinding(value.getClass());\r
+ claimValue(resource, value, binding);\r
+ } catch (BindingConstructionException e) {\r
+ throw new ServiceException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void claimValue(Resource resource, Object value, Binding binding)\r
+ throws ServiceException {\r
+ try {\r
+ \r
+ writeByte(CLAIM_VALUE_B);\r
+ writeInt(getId(resource));\r
+ Serializer serializer = binding.serializer();\r
+ int size = serializer.getSize(value);\r
+ writeInt(size);\r
+ serializer.serialize(new OutputStream() {\r
+ \r
+ @Override\r
+ public void write(int b) throws IOException {\r
+ writeByte(b);\r
+ }\r
+ \r
+ }, value);\r
+ \r
+ } catch(IOException e) {\r
+ Logger.defaultLogError(e);\r
+ throw new ServiceException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void denyValue(Resource resource) throws ServiceException {\r
+ writeByte(DENY_VALUE);\r
+ writeInt(getId(resource));\r
+ }\r
+\r
+ @Override\r
+ public void denyValue(Resource resource, VirtualGraph graph) throws ServiceException {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public void flushCluster() throws ServiceException {\r
+ writeState.defaultCluster = newCluster();\r
+ }\r
+\r
+ @Override\r
+ public void flushCluster(Resource r) throws ServiceException {\r
+ throw new ServiceException("Operation flushCluster(" + r + " not implemented.");\r
+ }\r
+ \r
+ private FileChannel channel;\r
+ byte[] bytes = new byte[BUFFER];\r
+ byte[] buffer = new byte[BUFFER];\r
+ ByteBuffer bb = ByteBuffer.wrap(bytes);\r
+ int byteIndex = 0;\r
+ \r
+ private void writeReset(int size) {\r
+\r
+ byteIndex = 0;\r
+ bb.position(0);\r
+ bb.limit(size);\r
+ try {\r
+\r
+ if(writeState.tempFile == null) {\r
+\r
+ File workspace = Platform.getLocation().toFile();\r
+ File temp = new File(workspace, "tempFiles");\r
+ temp.mkdirs();\r
+\r
+ File base = new File(temp, "delayed");\r
+ base.mkdirs();\r
+ writeState.tempFile = new File(base, UUID.randomUUID().toString());\r
+ writeState.out = new FileOutputStream(writeState.tempFile);\r
+ channel = writeState.out.getChannel();\r
+ \r
+ }\r
+\r
+ for (int got=0;got < size;) {\r
+ int n = channel.write(bb); \r
+ if (n <= 0) {\r
+ new Exception().printStackTrace();\r
+ return;\r
+ }\r
+ got += n;\r
+ }\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ private void reset() {\r
+ byteIndex = 0;\r
+ try {\r
+ bb.clear();\r
+ for(int got=0; got < BUFFER;) {\r
+ int n = channel.read(bb); \r
+ if (n <= 0)\r
+ return;\r
+ got += n;\r
+ }\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ private void writeInt(int i) {\r
+ if(byteIndex < (BUFFER-4)) {\r
+ bytes[byteIndex++] = (byte)(i&0xff);\r
+ bytes[byteIndex++] = (byte)((i>>>8)&0xff);\r
+ bytes[byteIndex++] = (byte)((i>>>16)&0xff);\r
+ bytes[byteIndex++] = (byte)((i>>>24)&0xff);\r
+ if (byteIndex == BUFFER)\r
+ writeReset(BUFFER);\r
+ } else {\r
+ int has = BUFFER-byteIndex;\r
+ if(has == 0) writeReset(BUFFER);\r
+ bytes[byteIndex++] = (byte)(i&0xff);\r
+ if(has == 1) writeReset(BUFFER);\r
+ bytes[byteIndex++] = (byte)((i>>>8)&0xff);\r
+ if(has == 2) writeReset(BUFFER);\r
+ bytes[byteIndex++] = (byte)((i>>>16)&0xff);\r
+ if(has == 3) writeReset(BUFFER);\r
+ bytes[byteIndex++] = (byte)((i>>>24)&0xff);\r
+ if(has == 4) writeReset(BUFFER);\r
+ }\r
+ }\r
+ \r
+ private int readInt() {\r
+ if(byteIndex < (BUFFER-4)) {\r
+ int result = (int) \r
+ ((bytes[byteIndex++] & 0xff) | \r
+ ((bytes[byteIndex++] & 0xff)<<8) | \r
+ ((bytes[byteIndex++] & 0xff)<<16) | \r
+ ((bytes[byteIndex++] & 0xff)<<24)); \r
+ return result;\r
+ } else {\r
+ int has = BUFFER-byteIndex;\r
+ int result = 0;\r
+ if(has == 0) reset();\r
+ result = (int)(bytes[byteIndex++] & 0xff);\r
+ if(has == 1) reset();\r
+ result |= (int)((bytes[byteIndex++] & 0xff) <<8);\r
+ if(has == 2) reset();\r
+ result |= (int)((bytes[byteIndex++] & 0xff) <<16);\r
+ if(has == 3) reset();\r
+ result |= (int)((bytes[byteIndex++] & 0xff) <<24);\r
+ if(has == 4) reset();\r
+ return result;\r
+ }\r
+ }\r
+ \r
+ private byte readByte() {\r
+ byte result = bytes[byteIndex++]; \r
+ if(byteIndex == BUFFER) reset();\r
+ return result;\r
+ }\r
+\r
+ private void writeByte(int b) {\r
+ bytes[byteIndex++] = (byte)b;\r
+ if(byteIndex == BUFFER) writeReset(BUFFER);\r
+ }\r
+ \r
+ private void writeBytes(byte[] data) {\r
+ int has = BUFFER-byteIndex;\r
+ int amount = data.length;\r
+ if(has > amount) {\r
+ System.arraycopy(data, 0, bytes, byteIndex, amount);\r
+ byteIndex += amount;\r
+ } else {\r
+ System.arraycopy(data, 0, bytes, byteIndex, has);\r
+ writeReset(BUFFER);\r
+ ByteBuffer bb2 = ByteBuffer.wrap(data);\r
+ bb2.position(has);\r
+ try {\r
+ channel.write(bb2);\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+ \r
+ public byte[] readBytes(int amount) {\r
+ return readBytes(buffer, amount);\r
+ }\r
+ \r
+ public byte[] readBytes(byte[] result, int amount) {\r
+ if(result == null) result = new byte[amount];\r
+ int has = BUFFER-byteIndex;\r
+ if(has > amount) {\r
+ System.arraycopy(bytes, byteIndex, result, 0, amount);\r
+ byteIndex += amount;\r
+ } else {\r
+ System.arraycopy(bytes, byteIndex, result, 0, has);\r
+ ByteBuffer bb2 = ByteBuffer.wrap(result);\r
+ bb2.position(has);\r
+ for(int got=has;got<amount;)\r
+ try {\r
+ got += channel.read(bb2);\r
+ if(got == -1) {\r
+ new Exception().printStackTrace();\r
+ return result;\r
+ }\r
+ \r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ reset();\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ public void commit(final WriteOnlyGraph w, final WriteTraits traits) throws ServiceException {\r
+ writeState.bindingToId = null;\r
+ writeState.externalToId = null;\r
+ try {\r
+ \r
+ writeByte(TERM);\r
+ if(byteIndex > 0) {\r
+ writeReset(byteIndex);\r
+ }\r
+ channel.force(false);\r
+ writeState.out.close();\r
+\r
+ FileInputStream fs = new FileInputStream(writeState.tempFile);\r
+ channel = fs.getChannel();\r
+ \r
+ } catch (IOException e) {\r
+ throw new ServiceException(e);\r
+ }\r
+ \r
+ w.getMetadata().putAll(metadata);\r
+ \r
+ TransferableGraphSupport tgs = w.getService(TransferableGraphSupport.class);\r
+\r
+ // First create all resources defined by clusterId\r
+ MapList<Long,InternalResource> clusterAssignment = new MapList<Long,InternalResource>();\r
+ for(Resource r : writeState.idToResource) {\r
+ if(r instanceof InternalResource) {\r
+ InternalResource ir = (InternalResource)r;\r
+ if(ir.clusterId < 0) {\r
+ if (DEBUG)\r
+ System.out.println("ASSIGN CLUSTER " + ir + " => " + ir.clusterId);\r
+ clusterAssignment.add(ir.clusterId, ir);\r
+ } else if(ir.clusterId > 0) {\r
+ if (DEBUG)\r
+ System.out.println("-CREATED RESOURCE WITH EXISTING CLUSTER ID: " + ir);\r
+ ir.resource = w.newResource(ir.clusterId);\r
+ writeState.idToResource.set(ir.id, ir.resource);\r
+ if (writeState.clusterSets.contains(ir)) {\r
+ w.newClusterSet(ir.resource);\r
+ if (DEBUG)\r
+ System.out.println("--CREATED NEW INTERNAL RESOURCE CLUSTER SET: " + ir.resource);\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+ \r
+ for(Long clusterKey : clusterAssignment.getKeys()) {\r
+ if (DEBUG)\r
+ System.out.println("CREATE LOGICAL CLUSTER: " + clusterKey);\r
+ w.flushCluster();\r
+ for(InternalResource ir : clusterAssignment.getValuesUnsafe(clusterKey)) {\r
+ if (DEBUG)\r
+ System.out.println("-CREATED RESOURCE: " + ir);\r
+ ir.resource = w.newResource();\r
+ writeState.idToResource.set(ir.id, ir.resource);\r
+ if (writeState.clusterSets.contains(ir)) {\r
+ w.newClusterSet(ir.resource);\r
+ if (DEBUG)\r
+ System.out.println("--CREATED NEW INTERNAL RESOURCE CLUSTER SET: " + ir.resource);\r
+ }\r
+ }\r
+ }\r
+ \r
+ // Create cluster sets for all existing resources (not InternalResource)\r
+ // before proceeding to create resources.\r
+ for(Resource existingResource : writeState.clusterSetsForExistingResources) {\r
+ w.newClusterSet(existingResource);\r
+ if (DEBUG)\r
+ System.out.println("CREATED NEW CLUSTER SET: " + existingResource);\r
+ }\r
+ \r
+ // Then create all resources defined by cluster set\r
+ for(Resource r : writeState.idToResource) {\r
+ if(r instanceof InternalResource) {\r
+ InternalResource ir = (InternalResource)r;\r
+ Resource clusterSet = ir.clusterSet;\r
+ \r
+ if (clusterSet != null) {\r
+ if (DEBUG)\r
+ System.out.println("NEW RESOURCE " + ir + " for cluster set " + clusterSet);\r
+ if(clusterSet instanceof InternalResource) {\r
+ ir.resource = w.newResource(((InternalResource)clusterSet).resource);\r
+ } else {\r
+ ir.resource = w.newResource(clusterSet);\r
+ }\r
+ if (DEBUG)\r
+ System.out.println(" => " + ir.resource);\r
+ writeState.idToResource.set(ir.id, ir.resource);\r
+ if(writeState.clusterSets.contains(ir)) {\r
+ if (DEBUG)\r
+ System.out.println(" ==> NEW CLUSTER SET");\r
+ w.newClusterSet(ir.resource);\r
+ }\r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ reset();\r
+ bb.limit(BUFFER);\r
+ \r
+ try {\r
+ while(true) {\r
+ byte method = readByte();\r
+ switch(method) { \r
+ case TERM: {\r
+ return;\r
+ }\r
+ case CLAIM: {\r
+ writeState.statementCount += 2;\r
+ Resource subject = getResource(readInt());\r
+ Resource predicate = getResource(readInt());\r
+ Resource inverse = getResource(readInt());\r
+ Resource object = getResource(readInt());\r
+ w.claim(subject, predicate, inverse, object);\r
+ } break;\r
+ case CLAIM_NOINVERSE: {\r
+ ++writeState.statementCount;\r
+ Resource subject = getResource(readInt());\r
+ Resource predicate = getResource(readInt());\r
+ Resource object = getResource(readInt());\r
+ w.claim(subject, predicate, null, object);\r
+ } break;\r
+ case DENY: {\r
+ Resource subject = getResource(readInt());\r
+ Resource predicate = getResource(readInt());\r
+ int inv = readInt();\r
+ Resource inverse = null;\r
+ if(inv > 0) inverse = getResource(inv);\r
+ Resource object = getResource(readInt());\r
+ if(!subject.isPersistent() || !object.isPersistent()) {\r
+ VirtualGraph statementProvider1 = processor.getProvider(subject, predicate, object);\r
+ if(inv > 0) {\r
+ VirtualGraph statementProvider2 = processor.getProvider(object, inverse, subject);\r
+ if(statementProvider2 != null)\r
+ w.deny(object, inverse, null, subject, statementProvider2);\r
+ }\r
+ if(statementProvider1 != null)\r
+ w.deny(subject, predicate, null, object, statementProvider1);\r
+ } else {\r
+ w.deny(subject, predicate, inverse, object, null);\r
+ }\r
+ } break;\r
+ case DENY_VALUE: {\r
+ Resource subject = getResource(readInt());\r
+ if(!subject.isPersistent()) {\r
+ VirtualGraph provider = processor.getValueProvider(subject);\r
+ if(provider != null)\r
+ w.denyValue(subject, provider);\r
+ } else {\r
+ w.denyValue(subject);\r
+ }\r
+ } break;\r
+ case CLAIM_VALUE_B: {\r
+ ++writeState.valueCount;\r
+ Resource resource = getResource(readInt());\r
+ int len = readInt();\r
+ tgs.setValue(w, resource, null, this, len);\r
+// byte[] bytes = readBytes(len);\r
+// tgs.setValue(resource, null, bytes);\r
+ } break;\r
+ case COMMIT_AND_CONTINUE: {\r
+ XSupport xs = w.getService(XSupport.class);\r
+ xs.commitAndContinue(w, traits);\r
+ } break;\r
+ }\r
+ }\r
+ } catch(Exception e) {\r
+ if(e instanceof ServiceException)\r
+ throw (ServiceException)e;\r
+ else\r
+ throw new ServiceException(e);\r
+ } finally {\r
+ try {\r
+ channel.close();\r
+ channel = null;\r
+ } catch (IOException e) {\r
+ throw new ServiceException(e);\r
+ }\r
+ }\r
+// System.out.println("Resources: " + state.resourceCount);\r
+// System.out.println("Statements: " + state.statementCount);\r
+// System.out.println("Values: " + state.valueCount);\r
+ }\r
+ \r
+ private Resource getType(Object value) {\r
+ Class<?> clazz = value.getClass();\r
+ Resource dataType = \r
+ clazz == Float.class ? b.Float\r
+ : clazz == Double.class ? b.Double\r
+ : clazz == Integer.class ? b.Integer\r
+ : clazz == String.class ? b.String\r
+ : clazz == Boolean.class ? b.Boolean\r
+ : clazz == Byte.class ? b.Byte\r
+ : clazz == Long.class ? b.Long\r
+ : clazz == float[].class ? b.FloatArray\r
+ : clazz == double[].class ? b.DoubleArray\r
+ : clazz == int[].class ? b.IntegerArray\r
+ : clazz == String[].class ? b.StringArray\r
+ : clazz == boolean[].class ? b.BooleanArray\r
+ : clazz == byte[].class ? b.ByteArray\r
+ : clazz == long[].class ? b.LongArray \r
+ : null\r
+ ;\r
+ return dataType;\r
+ }\r
+ \r
+ public long newCluster() {\r
+ return -1 - (++writeState.clusterCount);\r
+ }\r
+\r
+ public long getDefaultCluster() {\r
+ return writeState.defaultCluster;\r
+ }\r
+ \r
+ public void setDefaultCluster(long cluster) {\r
+ writeState.defaultCluster = cluster;\r
+ }\r
+ \r
+ @Override\r
+ public void syncRequest(final DelayedWrite request) throws DatabaseException {\r
+ \r
+ try {\r
+\r
+ final DelayedWriteGraph dwg = new DelayedWriteGraph(this);\r
+ request.perform(dwg);\r
+\r
+ syncRequest(new WriteOnlyRequest() {\r
+\r
+ @Override\r
+ public void perform(WriteOnlyGraph graph) throws DatabaseException {\r
+ dwg.commit(graph, request);\r
+ }\r
+\r
+ });\r
+\r
+ } catch (DatabaseException e) {\r
+ \r
+ throw e;\r
+ \r
+ } catch (Throwable e) {\r
+ \r
+ throw new DatabaseException(e);\r
+ \r
+ } finally {\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void syncRequest(WriteOnly request) throws DatabaseException {\r
+ \r
+ Resource defaultClusterSet = setClusterSet4NewResource(null);\r
+ \r
+ try {\r
+ WriteSupport ws = session.getService(WriteSupport.class);\r
+ ws.performWriteRequest(this, request);\r
+ } catch (DatabaseException e) {\r
+ throw e;\r
+ } catch (Throwable t) {\r
+ throw new DatabaseException(t);\r
+ } finally {\r
+ setClusterSet4NewResource(defaultClusterSet);\r
+ }\r
+ \r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <T> T getService(Class<T> api) {\r
+ \r
+ if(ClusteringSupport.class == api) {\r
+\r
+ final ClusteringSupport support = (ClusteringSupport)super.getService(api); \r
+\r
+ return (T)new ClusteringSupport() {\r
+ \r
+ @Override\r
+ public Resource getResourceByIndexAndCluster(int resourceIndex, long clusterId)\r
+ throws DatabaseException, ResourceNotFoundException {\r
+ return support.getResourceByIndexAndCluster(resourceIndex, clusterId);\r
+ }\r
+ \r
+ @Override\r
+ public Resource getResourceByKey(int resourceKey) throws ResourceNotFoundException {\r
+ return support.getResourceByKey(resourceKey);\r
+ }\r
+ \r
+ @Override\r
+ public int getNumberOfResources(long clusterId)\r
+ throws DatabaseException {\r
+ return support.getNumberOfResources(clusterId);\r
+ }\r
+ \r
+ @Override\r
+ public long getCluster(Resource r) {\r
+ return support.getCluster(r);\r
+ }\r
+ \r
+ @Override\r
+ public long createCluster() {\r
+ return newCluster();\r
+ }\r
+ \r
+ @Override\r
+ public boolean isClusterSet(Resource r) throws DatabaseException {\r
+ return support.isClusterSet(r);\r
+ }\r
+\r
+ @Override\r
+ public Resource getClusterSetOfCluster(Resource r) throws DatabaseException {\r
+ return support.getClusterSetOfCluster(r);\r
+ }\r
+ \r
+ @Override\r
+ public Resource getClusterSetOfCluster(long cluster) throws DatabaseException {\r
+ return support.getClusterSetOfCluster(cluster);\r
+ }\r
+\r
+ };\r
+ \r
+ } else if (TransferableGraphSupport.class == api) {\r
+ \r
+ final TransferableGraphSupport parentSupport = session.getService(TransferableGraphSupport.class);\r
+ \r
+ return (T)new TransferableGraphSupport() {\r
+\r
+ @Override\r
+ public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, byte[] raw) {\r
+ writeByte(CLAIM_VALUE_B);\r
+ writeInt(getId(resource));\r
+ writeInt(raw.length);\r
+ writeBytes(raw);\r
+ writeInt(getBindingId(haxx));\r
+ }\r
+ \r
+ @Override\r
+ public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, ByteReader reader, int amount)\r
+ throws DatabaseException {\r
+ writeByte(CLAIM_VALUE_B);\r
+ writeInt(getId(resource));\r
+ writeInt(amount);\r
+ writeBytes(reader.readBytes(null, amount));\r
+ writeInt(getBindingId(haxx));\r
+ }\r
+ \r
+ @Override\r
+ public byte[] getValue(ReadGraph graph, Resource resource) {\r
+ return parentSupport.getValue(graph, resource);\r
+ }\r
+ \r
+ @Override\r
+ public InputStream getValueStream(ReadGraph graph, Resource resource) {\r
+ return parentSupport.getValueStream(graph, resource);\r
+ }\r
+ \r
+ };\r
+\r
+ }\r
+ \r
+ return super.getService(api);\r
+ \r
+ }\r
+\r
+ @Override\r
+ public <T> void addMetadata(Metadata data) throws ServiceException {\r
+ MetadataUtils.addMetadata(session, metadata, data);\r
+ }\r
+ \r
+ public void addCommitAndContinue() {\r
+ writeByte(COMMIT_AND_CONTINUE);\r
+ }\r
+\r
+ @Override\r
+ public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {\r
+ return MetadataUtils.getMetadata(session, metadata, clazz);\r
+ }\r
+\r
+ @Override\r
+ public TreeMap<String, byte[]> getMetadata() {\r
+ return metadata;\r
+ }\r
+ @Override\r
+ public <T> T syncRequest(WriteResult<T> request) throws DatabaseException {\r
+ \r
+ return request.perform(this);\r
+ \r
+ }\r
+\r
+ @Override\r
+ public VirtualGraph getProvider() {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public void clearUndoList(WriteTraits writeTraits) {\r
+ WriteSupport ws = session.getService(WriteSupport.class);\r
+ if (null != ws)\r
+ ws.clearUndoList(writeTraits);\r
+ }\r
+\r
+ @Override\r
+ public void markUndoPoint() {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ @Override\r
+ public <T> T getPossibleRelatedValue(final Resource subject, final Resource relation, final Binding binding)\r
+ throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException {\r
+ if(!(subject instanceof InternalResource)) {\r
+ return super.getPossibleRelatedValue(subject, relation, binding);\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ final public Resource getPossibleObject(final Resource subject, final Resource relation)\r
+ throws ManyObjectsForFunctionalRelationException, ServiceException {\r
+ if(!(subject instanceof InternalResource)) {\r
+ return super.getPossibleObject(subject, relation);\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r