]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/DelayedWriteGraph.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / graph / DelayedWriteGraph.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.db.impl.graph;\r
13 \r
14 \r
15 import java.io.DataInput;\r
16 import java.io.DataOutput;\r
17 import java.io.File;\r
18 import java.io.FileInputStream;\r
19 import java.io.FileOutputStream;\r
20 import java.io.IOException;\r
21 import java.io.InputStream;\r
22 import java.io.OutputStream;\r
23 import java.nio.ByteBuffer;\r
24 import java.nio.channels.FileChannel;\r
25 import java.util.ArrayList;\r
26 import java.util.HashSet;\r
27 import java.util.IdentityHashMap;\r
28 import java.util.List;\r
29 import java.util.Set;\r
30 import java.util.TreeMap;\r
31 import java.util.UUID;\r
32 \r
33 import org.eclipse.core.runtime.Platform;\r
34 import org.simantics.databoard.Bindings;\r
35 import org.simantics.databoard.accessor.Accessor;\r
36 import org.simantics.databoard.accessor.reference.ChildReference;\r
37 import org.simantics.databoard.binding.Binding;\r
38 import org.simantics.databoard.binding.error.BindingConstructionException;\r
39 import org.simantics.databoard.binding.impl.BindingPrintContext;\r
40 import org.simantics.databoard.serialization.SerializationException;\r
41 import org.simantics.databoard.serialization.Serializer;\r
42 import org.simantics.databoard.type.Datatype;\r
43 import org.simantics.databoard.util.IdentityPair;\r
44 import org.simantics.databoard.util.binary.RandomAccessBinary;\r
45 import org.simantics.db.Metadata;\r
46 import org.simantics.db.ReadGraph;\r
47 import org.simantics.db.Resource;\r
48 import org.simantics.db.Session;\r
49 import org.simantics.db.Statement;\r
50 import org.simantics.db.VirtualGraph;\r
51 import org.simantics.db.WriteGraph;\r
52 import org.simantics.db.WriteOnlyGraph;\r
53 import org.simantics.db.common.MetadataUtils;\r
54 import org.simantics.db.common.request.WriteOnlyRequest;\r
55 import org.simantics.db.common.utils.Logger;\r
56 import org.simantics.db.exception.BindingException;\r
57 import org.simantics.db.exception.ClusterSetExistException;\r
58 import org.simantics.db.exception.DatabaseException;\r
59 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
60 import org.simantics.db.exception.NoSingleResultException;\r
61 import org.simantics.db.exception.ResourceNotFoundException;\r
62 import org.simantics.db.exception.ServiceException;\r
63 import org.simantics.db.impl.DebugPolicy;\r
64 import org.simantics.db.impl.ResourceImpl;\r
65 import org.simantics.db.request.DelayedWrite;\r
66 import org.simantics.db.request.WriteOnly;\r
67 import org.simantics.db.request.WriteResult;\r
68 import org.simantics.db.request.WriteTraits;\r
69 import org.simantics.db.service.ByteReader;\r
70 import org.simantics.db.service.ClusteringSupport;\r
71 import org.simantics.db.service.TransferableGraphSupport;\r
72 import org.simantics.db.service.XSupport;\r
73 import org.simantics.layer0.Layer0;\r
74 import org.simantics.utils.datastructures.MapList;\r
75 \r
76 import gnu.trove.list.array.TIntArrayList;\r
77 import gnu.trove.map.hash.TIntIntHashMap;\r
78 import gnu.trove.map.hash.TObjectIntHashMap;\r
79 \r
80 /**\r
81  * Write graph implementation that does not modify the database\r
82  * immediately but with an explicit commit method. All read operations\r
83  * return results based on the old graph. \r
84  */\r
85 public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, ByteReader {\r
86         \r
87         private static final boolean DEBUG = false;\r
88         public static int BUFFER = 65536;\r
89 \r
90         static class Haxx extends Binding {\r
91 \r
92                 static final Serializer serializer = new Serializer() {\r
93                         \r
94                         public byte[] serialize(Object obj) throws SerializationException {\r
95                                 return (byte[])obj;\r
96                         }\r
97 \r
98                         @Override\r
99                         public void serialize(DataOutput out,\r
100                                         TObjectIntHashMap<Object> identities, Object obj)\r
101                                         throws IOException {\r
102                                 throw new Error("Not supported.");\r
103                         }\r
104 \r
105                         @Override\r
106                         public void serialize(DataOutput out, Object obj)\r
107                                         throws IOException {\r
108                                 throw new Error("Not supported.");\r
109                         }\r
110 \r
111                         @Override\r
112                         public Object deserialize(DataInput in, List<Object> identities)\r
113                                         throws IOException {\r
114                                 throw new Error("Not supported.");\r
115                         }\r
116 \r
117                         @Override\r
118                         public Object deserialize(DataInput in) throws IOException {\r
119                                 throw new Error("Not supported.");\r
120                         }\r
121 \r
122                         @Override\r
123                         public void deserializeTo(DataInput in, List<Object> identities,\r
124                                         Object obj) throws IOException {\r
125                                 throw new Error("Not supported.");\r
126                         }\r
127 \r
128                         @Override\r
129                         public void deserializeTo(DataInput in, Object obj)\r
130                                         throws IOException {\r
131                                 throw new Error("Not supported.");\r
132                         }\r
133 \r
134                         @Override\r
135                         public void skip(DataInput in, List<Object> identities)\r
136                                         throws IOException {\r
137                                 throw new Error("Not supported.");\r
138                         }\r
139 \r
140                         @Override\r
141                         public void skip(DataInput in) throws IOException {\r
142                                 throw new Error("Not supported.");\r
143                         }\r
144 \r
145                         @Override\r
146                         public Integer getConstantSize() {\r
147                                 throw new Error("Not supported.");\r
148                         }\r
149 \r
150                         @Override\r
151                         public int getSize(Object obj, TObjectIntHashMap<Object> identities)\r
152                                         throws IOException {\r
153                                 throw new Error("Not supported.");\r
154                         }\r
155 \r
156                         @Override\r
157                         public int getSize(Object obj) throws IOException {\r
158                                 throw new Error("Not supported.");\r
159                         }\r
160 \r
161                         @Override\r
162                         public int getMinSize() {\r
163                                 throw new Error("Not supported.");\r
164                         }\r
165 \r
166                 };\r
167                 \r
168                 @Override\r
169                 public Serializer serializer() {\r
170                         return serializer;\r
171                 }\r
172                 \r
173                 @Override\r
174                 public void accept(Visitor1 v, Object obj) {\r
175                         throw new Error("Not supported.");\r
176                 }\r
177 \r
178                 @Override\r
179                 public <T> T accept(Visitor<T> v) {\r
180                         throw new Error("Not supported.");\r
181                 }\r
182 \r
183                 @Override\r
184                 public boolean isInstance(Object obj) {\r
185                         throw new Error("Not supported.");\r
186                 }\r
187 \r
188                 @Override\r
189                 public void assertInstaceIsValid(Object obj, Set<Object> validInstances)\r
190                                 throws org.simantics.databoard.binding.error.BindingException {\r
191                         throw new Error("Not supported.");\r
192                 }\r
193 \r
194                 @Override\r
195                 public int deepHashValue(Object value,\r
196                                 IdentityHashMap<Object, Object> hashedObjects)\r
197                                 throws org.simantics.databoard.binding.error.BindingException {\r
198                         throw new Error("Not supported.");\r
199                 }\r
200 \r
201                 @Override\r
202                 public int deepCompare(Object o1, Object o2,\r
203                                 Set<IdentityPair<Object, Object>> compareHistory)\r
204                                 throws org.simantics.databoard.binding.error.BindingException {\r
205                         throw new Error("Not supported.");\r
206                 }\r
207                 \r
208                 @Override\r
209                 public void readFrom(Binding srcBinding, Object src, Object dst)\r
210                                 throws org.simantics.databoard.binding.error.BindingException {\r
211                         throw new Error("Not supported.");\r
212                 }\r
213                 \r
214                 @Override\r
215                 public Object readFromTry(Binding srcBinding, Object src, Object dst)\r
216                                 throws org.simantics.databoard.binding.error.BindingException {\r
217                         throw new Error("Not supported.");\r
218                 }\r
219                 \r
220                 @Override\r
221                 protected void toString(Object value, BindingPrintContext ctx) throws org.simantics.databoard.binding.error.BindingException {\r
222                         throw new Error("Not supported.");\r
223                 }\r
224 \r
225                 @Override\r
226                 public int getComponentCount() {\r
227                         throw new Error("Not supported.");\r
228                 }\r
229 \r
230                 @Override\r
231                 public Binding getComponentBinding(int index) {\r
232                         throw new Error("Not supported.");\r
233                 }\r
234 \r
235                 @Override\r
236                 public Binding getComponentBinding(ChildReference path) {\r
237                         throw new Error("Not supported.");\r
238                 }\r
239                 \r
240         }\r
241         \r
242         private static final Haxx haxx = new Haxx();\r
243 \r
244         private final int TERM = 0;\r
245         private final int CLAIM = 1;\r
246     private final int CLAIM_NOINVERSE = 2;\r
247         private final int CLAIM_VALUE_B = 4;\r
248     private final int DENY = 5;\r
249     private final int DENY_VALUE = 6;\r
250     private final int COMMIT_AND_CONTINUE = 7;\r
251         \r
252     static class ClusterSet {\r
253         public Resource resource;\r
254         ClusterSet() {\r
255             ids = new TIntArrayList();\r
256             old = false;\r
257         }\r
258         ClusterSet(boolean old, Resource r) {\r
259             ids = new TIntArrayList();\r
260             this.old = old;\r
261             this.resource = r;\r
262         }\r
263         void add(int id) {\r
264             ids.add(id);\r
265         }\r
266         private TIntArrayList ids;\r
267         private final boolean old; // true if\r
268         boolean isNew() {\r
269             return !old;\r
270         }\r
271     }\r
272     public class State {\r
273         public File tempFile;\r
274         public FileOutputStream out;\r
275         public ArrayList<Resource> idToResource = new ArrayList<Resource>();\r
276         public TIntIntHashMap externalToId = new TIntIntHashMap(); \r
277         public ArrayList<Binding> idToBinding = new ArrayList<Binding>();\r
278         public TObjectIntHashMap<Binding> bindingToId = new TObjectIntHashMap<Binding>();\r
279         public Set<Resource> clusterSets = new HashSet<Resource>();\r
280         public Set<Resource> clusterSetsForExistingResources = new HashSet<Resource>();\r
281         public int clusterCount = 0;\r
282         public long defaultCluster;\r
283         public Resource defaultClusterSet;\r
284         public int statementCount = 0;\r
285         public int valueCount = 0;\r
286         public int fileCount = 0;\r
287     }\r
288     \r
289     public State writeState;\r
290     public TreeMap<String,byte[]> metadata = new TreeMap<String,byte[]>();\r
291         \r
292     Layer0 b;\r
293     Session session;\r
294     public static Resource convertDelayedResource(Resource r) {\r
295         if (r instanceof InternalResource) {\r
296             InternalResource ri = (InternalResource)r;\r
297             return ri.resource;\r
298         }\r
299         return r;\r
300     }\r
301     private static class InternalResource implements Resource {\r
302 \r
303         int id;\r
304         long clusterId = 0;\r
305         Resource resource = null;\r
306         Resource clusterSet = null;\r
307         \r
308         public InternalResource(int id, long clusterId) {\r
309             this.id = id;\r
310             this.clusterId = clusterId;\r
311         }\r
312 \r
313         public InternalResource(int id, Resource clusterSet) {\r
314             this.id = id;\r
315             this.clusterSet = clusterSet;\r
316         }\r
317         \r
318         @Override\r
319         public long getResourceId() {\r
320             throw new UnsupportedOperationException();\r
321         }\r
322 \r
323         @Override\r
324         public Resource get() {\r
325             return this;\r
326         }\r
327         \r
328         @Override\r
329         public boolean isPersistent() {\r
330             return false;\r
331         }\r
332 \r
333         @Override\r
334         public int compareTo(Resource o) {\r
335                 if(o instanceof InternalResource) {\r
336                         return Integer.compare(id, ((InternalResource)o).id);\r
337                 } else {\r
338                         return -1;\r
339                 }\r
340         }\r
341 \r
342         @Override\r
343         public int hashCode() {\r
344             final int prime = 31;\r
345             int result = 1;\r
346             result = prime * result + id;\r
347             return result;\r
348         }\r
349         \r
350         @Override\r
351         public int getThreadHash() {\r
352             return hashCode();\r
353         }\r
354 \r
355         @Override\r
356         public boolean equals(Object obj) {\r
357             if (this == obj)\r
358                 return true;\r
359             if (obj == null)\r
360                 return false;\r
361             if (!(obj instanceof InternalResource))\r
362                 return false;\r
363             InternalResource other = (InternalResource) obj;\r
364             if (id != other.id)\r
365                 return false;\r
366             return true;\r
367         }\r
368         \r
369 \r
370         @Override\r
371         public boolean equalsResource(Resource other) {\r
372             return equals(other);\r
373         }\r
374         @Override\r
375         public String toString() {\r
376             StringBuilder sb = new StringBuilder(32);\r
377             if(DebugPolicy.VERBOSE) {\r
378                 sb.append("[delayed id=");\r
379                 sb.append(id);\r
380                 sb.append("]");\r
381             } else {\r
382                 sb.append("[did=");\r
383                 sb.append(id);\r
384                 sb.append("]");\r
385             }\r
386             return sb.toString();\r
387         }\r
388     }\r
389 \r
390         private int getId(Resource resource) {\r
391                 if(resource instanceof InternalResource)\r
392                         return ((InternalResource)resource).id;\r
393                 else {\r
394                         ResourceImpl r = (ResourceImpl)resource;\r
395                         int id = writeState.externalToId.get(r.id);\r
396                         if(id != 0) {\r
397                                 return id;\r
398                         } else {\r
399                                 id = writeState.idToResource.size();\r
400                                 writeState.idToResource.add(resource);\r
401                                 writeState.externalToId.put(r.id, id);\r
402                                 return id;\r
403                         }\r
404                 }\r
405         }\r
406         \r
407         private Resource getResource(int id) {\r
408                 return writeState.idToResource.get(id);\r
409         }\r
410         \r
411         private int getBindingId(Binding binding) {\r
412                 if(writeState.bindingToId.contains(binding))\r
413                         return writeState.bindingToId.get(binding);\r
414                 else {\r
415                         int id = writeState.idToBinding.size();\r
416                         writeState.idToBinding.add(binding);\r
417                         writeState.bindingToId.put(binding, id);\r
418                         return id;\r
419                 }\r
420         }\r
421 \r
422         public DelayedWriteGraph(ReadGraph g) throws IOException {\r
423                 super((ReadGraphImpl)g);\r
424                 writeState = new State();\r
425                 session = g.getSession();\r
426                 b = Layer0.getInstance(g);\r
427                 writeState.defaultCluster = newCluster();\r
428         }       \r
429         \r
430     public DelayedWriteGraph(ReadGraph g, State state) {\r
431         super((ReadGraphImpl)g);\r
432         session = g.getSession();\r
433                 b = Layer0.getInstance(g);\r
434         this.writeState = state;\r
435     }   \r
436 \r
437         public DelayedWriteGraph newSync() {\r
438         return new DelayedWriteGraph(this, writeState);\r
439     }\r
440         \r
441         @Override\r
442         public void claim(Resource subject, Resource predicate, Resource object)\r
443                         throws ServiceException {\r
444                 assert(subject != null);\r
445         assert(predicate != null);\r
446         assert(object != null);\r
447         \r
448         Resource inverse = getPossibleInverse(predicate);\r
449         claim(subject, predicate, inverse, object);\r
450         }\r
451 \r
452     @Override\r
453     public void addLiteral(Resource resource, Resource predicate, Resource inverse, Resource type, Object value,\r
454             Binding binding) throws BindingException,\r
455             ManyObjectsForFunctionalRelationException, ServiceException {\r
456         Resource valueResource = newResource();\r
457         claimValue(valueResource, value, binding);\r
458         claim(valueResource, b.InstanceOf, null, type);\r
459         claim(resource, predicate, inverse, valueResource);  \r
460     }\r
461     \r
462     @Override\r
463     public void addLiteral(Resource resource, Resource predicate,\r
464                 Resource inverse, Object value, Binding binding)\r
465                 throws BindingException, ManyObjectsForFunctionalRelationException,\r
466                 ServiceException {\r
467         \r
468         Resource type = getType(value);\r
469         if(type == null) {\r
470             Resource literal = newResource();\r
471             type = b.Literal;\r
472             Resource dataType = newResource();\r
473             claim(dataType, b.InstanceOf, null, b.DataType);\r
474             claimValue(dataType, binding.type(), DATA_TYPE_BINDING_INTERNAL);\r
475             claim(literal, b.HasDataType, null, dataType);\r
476             claim(literal, b.InstanceOf, null, type);\r
477             claimValue(literal, value, binding); \r
478             claim(resource, predicate, inverse, literal);\r
479         } else {\r
480                 addLiteral(resource, predicate, inverse, type, value, binding);\r
481         }\r
482         \r
483     }\r
484 \r
485     @Override\r
486     public <T extends Accessor> T newLiteral(Resource resource, Resource predicate, Datatype datatype, Object initialValue)\r
487     throws DatabaseException {\r
488 \r
489         throw new UnsupportedOperationException();\r
490 \r
491     }\r
492 \r
493     @Override\r
494     public RandomAccessBinary createRandomAccessBinary (Resource resource, Resource predicate, Datatype datatype, Object initialValue) throws DatabaseException {\r
495         throw new UnsupportedOperationException();\r
496     }\r
497     \r
498     @Override\r
499     public RandomAccessBinary createRandomAccessBinary(Resource resource, Datatype datatype, Object initialValue) throws DatabaseException {\r
500         throw new UnsupportedOperationException();\r
501     }\r
502 \r
503     @Override\r
504     public void claimLiteral(Resource resource, Resource predicate, Object value) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
505 \r
506                 try {\r
507                         Binding b = Bindings.getBinding(value.getClass());\r
508                 claimLiteral(resource, predicate, value, b);\r
509                 } catch (BindingConstructionException e) {\r
510                         throw new IllegalArgumentException(e);\r
511                 } catch (BindingException e) {\r
512                         throw new IllegalArgumentException(e);\r
513                 }\r
514 \r
515     }\r
516     \r
517     @Override\r
518     public void claimLiteral(Resource resource, Resource predicate, Object value, Binding binding) throws BindingException,\r
519                 ManyObjectsForFunctionalRelationException, ServiceException {\r
520 \r
521         Statement valueStatement = null;\r
522         if(!(resource instanceof InternalResource)) valueStatement = getPossibleStatement(resource, predicate);\r
523 \r
524         if(valueStatement != null && resource.equals(valueStatement.getSubject())) {\r
525 \r
526             claimValue(valueStatement.getObject(), value, binding);\r
527 \r
528         } else {\r
529 \r
530             Resource type = getType(value);\r
531             Resource literal = newResource();\r
532             if (type == null) {\r
533                 type = b.Literal;\r
534                 Resource dataType = newResource();\r
535                 claim(dataType, b.InstanceOf, null, b.DataType);\r
536                 claimValue(dataType, binding.type(), DATA_TYPE_BINDING_INTERNAL);\r
537                 claim(literal, b.HasDataType, dataType);\r
538             }\r
539             claim(literal, b.InstanceOf, null, type);\r
540             claimValue(literal, value, binding); \r
541             claim(resource, predicate, literal);\r
542             \r
543         }\r
544 \r
545     }\r
546     \r
547     @Override\r
548     public void claimLiteral(Resource resource, Resource predicate,\r
549                 Resource inverse, Resource type, Object value)\r
550                 throws BindingException, ManyObjectsForFunctionalRelationException,\r
551                 ServiceException {\r
552 \r
553                 try {\r
554                         Binding b = Bindings.getBinding(value.getClass());\r
555                 claimLiteral(resource, predicate, inverse, type, value, b);\r
556                 } catch (BindingConstructionException e) {\r
557                         throw new IllegalArgumentException(e);\r
558                 } catch (BindingException e) {\r
559                         throw new IllegalArgumentException(e);\r
560                 }\r
561         \r
562     }\r
563     \r
564     @Override\r
565     public void claimLiteral(Resource resource, Resource predicate,\r
566                 Resource inverse, Resource type, Object value, Binding binding)\r
567                 throws BindingException, ManyObjectsForFunctionalRelationException,\r
568                 ServiceException {\r
569 \r
570         Statement valueStatement = (resource instanceof InternalResource) ? null : getPossibleStatement(resource, predicate);\r
571 \r
572         if(valueStatement != null && resource.equals(valueStatement.getSubject())) {\r
573 \r
574             claimValue(valueStatement.getObject(), value, binding);\r
575 \r
576         } else {\r
577 \r
578             Resource valueResource = newResource();\r
579             claim(valueResource, b.InstanceOf, null, type);\r
580             claim(resource, predicate, inverse, valueResource);\r
581             claimValue(valueResource, value, binding);\r
582 \r
583         }\r
584 \r
585     }\r
586 \r
587     @Override\r
588     public void claimLiteral(Resource resource, Resource predicate,\r
589                 Resource type, Object value) throws BindingException,\r
590                 ManyObjectsForFunctionalRelationException, ServiceException {\r
591 \r
592                 try {\r
593                         Binding b = Bindings.getBinding(value.getClass());\r
594                 claimLiteral(resource, predicate, type, value, b);\r
595                 } catch (BindingConstructionException e) {\r
596                         throw new IllegalArgumentException(e);\r
597                 } catch (BindingException e) {\r
598                         throw new IllegalArgumentException(e);\r
599                 }\r
600         \r
601     }\r
602     \r
603     @Override\r
604     public void claimLiteral(Resource resource, Resource predicate,\r
605                 Resource type, Object value, Binding binding)\r
606                 throws BindingException, ManyObjectsForFunctionalRelationException,\r
607                 ServiceException {\r
608 \r
609                 try {\r
610                 Resource inverse = getSingleObject(predicate, b.InverseOf);\r
611                 claimLiteral(resource, predicate, inverse, type, value, binding);\r
612                 } catch (NoSingleResultException e) {\r
613                         throw new ServiceException(e);\r
614                 }\r
615         \r
616     }\r
617     \r
618         @Override\r
619         public void deny(Resource subject) throws ServiceException {\r
620                 assert(subject != null);\r
621                 if(!(subject instanceof InternalResource)) {\r
622                         try {\r
623                                 for (Statement statement : getStatements(subject, b.IsWeaklyRelatedTo)) {\r
624                                         deny(statement);\r
625                                 }\r
626                         } catch (ManyObjectsForFunctionalRelationException e) {\r
627                                 throw new ServiceException(e);\r
628                         }\r
629                 }\r
630         }\r
631 \r
632         @Override\r
633         public void deny(Resource subject, Resource predicate)\r
634                         throws ServiceException {\r
635                 assert(subject != null);\r
636                 if(!(subject instanceof InternalResource)) {\r
637                         for (Resource object : getObjects(subject, predicate)) {\r
638                                 deny(subject, predicate, object);\r
639                         }\r
640                 }\r
641         }\r
642 \r
643         @Override\r
644         public void deny(Resource subject, Resource predicate, Resource object) throws ServiceException {\r
645                 denyStatement(subject, predicate, object);\r
646         }\r
647 \r
648         @Override\r
649         public void denyStatement(Resource subject, Resource predicate, Resource object) throws ServiceException {\r
650                 deny(subject, predicate, getPossibleInverse(predicate), object);\r
651         }\r
652 \r
653         @Override\r
654         public void deny(Statement statement) throws ServiceException {\r
655                 Resource predicate = statement.getPredicate();\r
656                 deny(statement.getSubject(), predicate, getPossibleInverse(predicate), statement.getObject());\r
657         }\r
658 \r
659         @Override\r
660         public void denyValue(Resource resource, Resource predicate)\r
661                         throws ManyObjectsForFunctionalRelationException, ServiceException {\r
662                 assert(resource != null);\r
663                 assert(predicate != null);\r
664 \r
665                 if(!(resource instanceof InternalResource)) {\r
666                 Statement valueStatement = getPossibleStatement(resource, predicate);\r
667 \r
668                 if (valueStatement != null && !valueStatement.isAsserted(resource)) {\r
669                     Resource value = valueStatement.getObject();\r
670                                 denyValue(value);\r
671                 }\r
672                 }\r
673         }\r
674 \r
675         @Override\r
676         public Resource newResource() throws ServiceException {\r
677                 if(writeState.defaultClusterSet != null) return newResource(writeState.defaultClusterSet);\r
678                 else return newResource(writeState.defaultCluster);\r
679         }\r
680 \r
681         @Override\r
682         public Resource newResource(long clusterId) throws ServiceException {\r
683                 int id = writeState.idToResource.size();\r
684                 InternalResource ret = new InternalResource(id, clusterId);\r
685                 writeState.idToResource.add(ret);\r
686                 return ret;\r
687         }\r
688 \r
689     @Override\r
690     public Resource newResource(Resource clusterSet) throws ServiceException {\r
691         \r
692         if ((clusterSet instanceof InternalResource)) {\r
693                 if(!writeState.clusterSets.contains(clusterSet))\r
694                         throw new ClusterSetExistException("Cluster set does not exist. Resource=" + clusterSet);\r
695         } else {\r
696                 WriteSupport ws = session.getService(WriteSupport.class);\r
697                 if (!ws.hasClusterSet(null, clusterSet))\r
698                         if(!writeState.clusterSetsForExistingResources.contains(clusterSet))\r
699                         throw new ClusterSetExistException("Cluster set does not exist. Resource=" + clusterSet);\r
700         }\r
701         \r
702         int id = writeState.idToResource.size();\r
703         InternalResource ret = new InternalResource(id, clusterSet);\r
704         writeState.idToResource.add(ret);\r
705         return ret;\r
706     }\r
707 \r
708     @Override\r
709     public void newClusterSet(Resource clusterSet) throws ServiceException {\r
710         if (DEBUG)\r
711             System.out.println("new cluster set=" + clusterSet);\r
712         boolean existingResource = !(clusterSet instanceof InternalResource);\r
713         if (existingResource) {\r
714                 WriteSupport ws = session.getService(WriteSupport.class);\r
715                 if (ws.hasClusterSet(null, clusterSet))\r
716                         throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);\r
717                 writeState.clusterSetsForExistingResources.add(clusterSet);             \r
718         } else {        \r
719                 if(!writeState.clusterSets.add(clusterSet))\r
720                         throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);\r
721         }\r
722     }\r
723     @Override\r
724     public Resource setClusterSet4NewResource(Resource clusterSet)\r
725     throws ServiceException {\r
726         Resource existing = writeState.defaultClusterSet; \r
727         writeState.defaultClusterSet = clusterSet;\r
728         return existing;\r
729     }\r
730         \r
731         @Override\r
732         public void claim(Resource subject, Resource predicate, Resource inverse,\r
733                         Resource object) throws ServiceException {\r
734                 assert(subject != null);\r
735                 assert(predicate != null);\r
736                 assert(object != null);\r
737                 try {\r
738                     if(inverse != null && !(subject.equals(object) && inverse.equals(predicate))) {\r
739                         writeByte(CLAIM);\r
740                         writeInt(getId(subject));\r
741                         writeInt(getId(predicate));\r
742                         writeInt(getId(inverse));\r
743                         writeInt(getId(object));\r
744                     } else {\r
745                         writeByte(CLAIM_NOINVERSE);\r
746                         writeInt(getId(subject));\r
747                         writeInt(getId(predicate));\r
748                         writeInt(getId(object));\r
749                     }\r
750                 } catch(Exception e) {\r
751                         throw new ServiceException(e);\r
752                 }\r
753         }\r
754 \r
755     @Override\r
756     public void deny(Resource subject, Resource predicate, Resource inverse,\r
757             Resource object) throws ServiceException {\r
758         assert(subject != null);\r
759         assert(predicate != null);\r
760         assert(object != null);\r
761         try {\r
762                 writeByte(DENY);\r
763                 writeInt(getId(subject));\r
764                 writeInt(getId(predicate));\r
765             if(inverse != null) writeInt(getId(inverse));\r
766             else writeInt(0);\r
767                 writeInt(getId(object));\r
768         } catch(Exception e) {\r
769             throw new ServiceException(e);\r
770         }\r
771     }\r
772 \r
773     @Override\r
774     public void deny(Resource subject, Resource predicate, Resource inverse,\r
775             Resource object, VirtualGraph graph) throws ServiceException {\r
776         throw new UnsupportedOperationException();\r
777     }\r
778     \r
779         @Override\r
780         public void claimValue(Resource resource, Object value)\r
781                         throws ServiceException {\r
782                 try {\r
783                     Binding binding = Bindings.getBinding(value.getClass());\r
784                     claimValue(resource, value, binding);\r
785                 } catch (BindingConstructionException e) {\r
786                         throw new ServiceException(e);\r
787                 }\r
788         }\r
789 \r
790         @Override\r
791         public void claimValue(Resource resource, Object value, Binding binding)\r
792                         throws ServiceException {\r
793                 try {\r
794                         \r
795                 writeByte(CLAIM_VALUE_B);\r
796                 writeInt(getId(resource));\r
797                 Serializer serializer = binding.serializer();\r
798                 int size = serializer.getSize(value);\r
799             writeInt(size);\r
800             serializer.serialize(new OutputStream() {\r
801                 \r
802                 @Override\r
803                 public void write(int b) throws IOException {\r
804                     writeByte(b);\r
805                 }\r
806                 \r
807             }, value);\r
808                         \r
809                 } catch(IOException e) {\r
810                 Logger.defaultLogError(e);\r
811                         throw new ServiceException(e);\r
812                 }\r
813         }\r
814 \r
815         @Override\r
816         public void denyValue(Resource resource) throws ServiceException {\r
817                 writeByte(DENY_VALUE);\r
818                 writeInt(getId(resource));\r
819         }\r
820 \r
821         @Override\r
822         public void denyValue(Resource resource, VirtualGraph graph) throws ServiceException {\r
823         throw new UnsupportedOperationException();\r
824         }\r
825 \r
826         @Override\r
827         public void flushCluster() throws ServiceException {\r
828         writeState.defaultCluster = newCluster();\r
829         }\r
830 \r
831     @Override\r
832     public void flushCluster(Resource r) throws ServiceException {\r
833         throw new ServiceException("Operation flushCluster(" + r + " not implemented.");\r
834     }\r
835         \r
836     private FileChannel channel;\r
837     byte[] bytes = new byte[BUFFER];\r
838     byte[] buffer = new byte[BUFFER];\r
839     ByteBuffer bb = ByteBuffer.wrap(bytes);\r
840     int byteIndex = 0;\r
841     \r
842     private void writeReset(int size) {\r
843 \r
844         byteIndex = 0;\r
845         bb.position(0);\r
846         bb.limit(size);\r
847         try {\r
848 \r
849             if(writeState.tempFile == null) {\r
850 \r
851                 File workspace = Platform.getLocation().toFile();\r
852                 File temp = new File(workspace, "tempFiles");\r
853                 temp.mkdirs();\r
854 \r
855                 File base = new File(temp, "delayed");\r
856                 base.mkdirs();\r
857                 writeState.tempFile = new File(base, UUID.randomUUID().toString());\r
858                 writeState.out = new FileOutputStream(writeState.tempFile);\r
859                 channel = writeState.out.getChannel();\r
860                 \r
861             }\r
862 \r
863             for (int got=0;got < size;) {\r
864                 int n = channel.write(bb); \r
865                 if (n <= 0) {\r
866                     new Exception().printStackTrace();\r
867                     return;\r
868                 }\r
869                 got += n;\r
870             }\r
871         } catch (IOException e) {\r
872             e.printStackTrace();\r
873         }\r
874     }\r
875 \r
876     private void reset() {\r
877         byteIndex = 0;\r
878         try {\r
879             bb.clear();\r
880             for(int got=0; got < BUFFER;) {\r
881                 int n = channel.read(bb); \r
882                 if (n <= 0)\r
883                     return;\r
884                 got += n;\r
885             }\r
886         } catch (IOException e) {\r
887             e.printStackTrace();\r
888         }\r
889     }\r
890 \r
891     private void writeInt(int i) {\r
892         if(byteIndex < (BUFFER-4)) {\r
893                 bytes[byteIndex++] = (byte)(i&0xff);\r
894                 bytes[byteIndex++] = (byte)((i>>>8)&0xff);\r
895                 bytes[byteIndex++] = (byte)((i>>>16)&0xff);\r
896                 bytes[byteIndex++] = (byte)((i>>>24)&0xff);\r
897                 if (byteIndex == BUFFER)\r
898                     writeReset(BUFFER);\r
899         } else {\r
900                 int has = BUFFER-byteIndex;\r
901                 if(has == 0) writeReset(BUFFER);\r
902                 bytes[byteIndex++] = (byte)(i&0xff);\r
903                 if(has == 1) writeReset(BUFFER);\r
904                 bytes[byteIndex++] = (byte)((i>>>8)&0xff);\r
905                 if(has == 2) writeReset(BUFFER);\r
906                 bytes[byteIndex++] = (byte)((i>>>16)&0xff);\r
907                 if(has == 3) writeReset(BUFFER);\r
908                 bytes[byteIndex++] = (byte)((i>>>24)&0xff);\r
909                 if(has == 4) writeReset(BUFFER);\r
910         }\r
911     }\r
912     \r
913     private int readInt() {\r
914         if(byteIndex < (BUFFER-4)) {\r
915                 int result = (int) \r
916                         ((bytes[byteIndex++] & 0xff) | \r
917                         ((bytes[byteIndex++] & 0xff)<<8) | \r
918                         ((bytes[byteIndex++] & 0xff)<<16) | \r
919                         ((bytes[byteIndex++] & 0xff)<<24)); \r
920                 return result;\r
921         } else {\r
922                 int has = BUFFER-byteIndex;\r
923                 int result = 0;\r
924                 if(has == 0) reset();\r
925                         result = (int)(bytes[byteIndex++] & 0xff);\r
926                 if(has == 1) reset();\r
927                 result |= (int)((bytes[byteIndex++] & 0xff) <<8);\r
928                 if(has == 2) reset();\r
929                 result |= (int)((bytes[byteIndex++] & 0xff) <<16);\r
930                 if(has == 3) reset();\r
931                 result |= (int)((bytes[byteIndex++] & 0xff) <<24);\r
932                 if(has == 4) reset();\r
933                 return result;\r
934         }\r
935     }\r
936     \r
937     private byte readByte() {\r
938         byte result = bytes[byteIndex++]; \r
939         if(byteIndex == BUFFER) reset();\r
940         return result;\r
941     }\r
942 \r
943     private void writeByte(int b) {\r
944         bytes[byteIndex++] = (byte)b;\r
945         if(byteIndex == BUFFER) writeReset(BUFFER);\r
946     }\r
947     \r
948     private void writeBytes(byte[] data) {\r
949                 int has = BUFFER-byteIndex;\r
950                 int amount = data.length;\r
951                 if(has > amount) {\r
952                         System.arraycopy(data, 0, bytes, byteIndex, amount);\r
953                         byteIndex += amount;\r
954                 } else {\r
955                         System.arraycopy(data, 0, bytes, byteIndex, has);\r
956                         writeReset(BUFFER);\r
957                         ByteBuffer bb2 = ByteBuffer.wrap(data);\r
958                         bb2.position(has);\r
959                         try {\r
960                                 channel.write(bb2);\r
961                         } catch (IOException e) {\r
962                                 e.printStackTrace();\r
963                         }\r
964                 }\r
965     }\r
966     \r
967     public byte[] readBytes(int amount) {\r
968         return readBytes(buffer, amount);\r
969     }\r
970     \r
971     public byte[] readBytes(byte[] result, int amount) {\r
972         if(result == null) result = new byte[amount];\r
973                 int has = BUFFER-byteIndex;\r
974                 if(has > amount) {\r
975                         System.arraycopy(bytes, byteIndex, result, 0, amount);\r
976                         byteIndex += amount;\r
977                 } else {\r
978                         System.arraycopy(bytes, byteIndex, result, 0, has);\r
979                         ByteBuffer bb2 = ByteBuffer.wrap(result);\r
980                         bb2.position(has);\r
981                         for(int got=has;got<amount;)\r
982                                 try {\r
983                                         got += channel.read(bb2);\r
984                                         if(got == -1) {\r
985                                                 new Exception().printStackTrace();\r
986                                                 return result;\r
987                                         }\r
988                                         \r
989                                 } catch (IOException e) {\r
990                                         e.printStackTrace();\r
991                                 }\r
992                         reset();\r
993                 }\r
994                 return result;\r
995     }\r
996     \r
997     public void commit(final WriteOnlyGraph w, final WriteTraits traits) throws ServiceException {\r
998             writeState.bindingToId = null;\r
999             writeState.externalToId = null;\r
1000                 try {\r
1001                         \r
1002                         writeByte(TERM);\r
1003                         if(byteIndex > 0) {\r
1004                                 writeReset(byteIndex);\r
1005                         }\r
1006                         channel.force(false);\r
1007                         writeState.out.close();\r
1008 \r
1009                 FileInputStream fs = new FileInputStream(writeState.tempFile);\r
1010                 channel = fs.getChannel();\r
1011                         \r
1012                 } catch (IOException e) {\r
1013                         throw new ServiceException(e);\r
1014                 }\r
1015                 \r
1016                 w.getMetadata().putAll(metadata);\r
1017                 \r
1018                 TransferableGraphSupport tgs = w.getService(TransferableGraphSupport.class);\r
1019 \r
1020                 // First create all resources defined by clusterId\r
1021                 MapList<Long,InternalResource> clusterAssignment = new MapList<Long,InternalResource>();\r
1022                 for(Resource r : writeState.idToResource) {\r
1023                         if(r instanceof InternalResource) {\r
1024                                 InternalResource ir = (InternalResource)r;\r
1025                                 if(ir.clusterId < 0) {\r
1026                                 if (DEBUG)\r
1027                                         System.out.println("ASSIGN CLUSTER " + ir + " => " + ir.clusterId);\r
1028                                         clusterAssignment.add(ir.clusterId, ir);\r
1029                                 } else if(ir.clusterId > 0) {\r
1030                                 if (DEBUG)\r
1031                                         System.out.println("-CREATED RESOURCE WITH EXISTING CLUSTER ID: " + ir);\r
1032                                         ir.resource = w.newResource(ir.clusterId);\r
1033                                         writeState.idToResource.set(ir.id, ir.resource);\r
1034                                         if (writeState.clusterSets.contains(ir)) {\r
1035                                                 w.newClusterSet(ir.resource);\r
1036                                         if (DEBUG)\r
1037                                                 System.out.println("--CREATED NEW INTERNAL RESOURCE CLUSTER SET: " + ir.resource);\r
1038                                         }\r
1039                                         \r
1040                                 }\r
1041                         }\r
1042                 }\r
1043                 \r
1044                 for(Long clusterKey : clusterAssignment.getKeys()) {\r
1045                 if (DEBUG)\r
1046                         System.out.println("CREATE LOGICAL CLUSTER: " + clusterKey);\r
1047                         w.flushCluster();\r
1048                         for(InternalResource ir : clusterAssignment.getValuesUnsafe(clusterKey)) {\r
1049                         if (DEBUG)\r
1050                                 System.out.println("-CREATED RESOURCE: " + ir);\r
1051                                 ir.resource = w.newResource();\r
1052                                 writeState.idToResource.set(ir.id, ir.resource);\r
1053                                 if (writeState.clusterSets.contains(ir)) {\r
1054                                         w.newClusterSet(ir.resource);\r
1055                                 if (DEBUG)\r
1056                                         System.out.println("--CREATED NEW INTERNAL RESOURCE CLUSTER SET: " + ir.resource);\r
1057                                 }\r
1058                         }\r
1059                 }\r
1060                 \r
1061                 // Create cluster sets for all existing resources (not InternalResource)\r
1062                 // before proceeding to create resources.\r
1063                 for(Resource existingResource : writeState.clusterSetsForExistingResources) {\r
1064                         w.newClusterSet(existingResource);\r
1065                 if (DEBUG)\r
1066                         System.out.println("CREATED NEW CLUSTER SET: " + existingResource);\r
1067                 }\r
1068                 \r
1069                 // Then create all resources defined by cluster set\r
1070                 for(Resource r : writeState.idToResource) {\r
1071                         if(r instanceof InternalResource) {\r
1072                                 InternalResource ir = (InternalResource)r;\r
1073                                 Resource clusterSet = ir.clusterSet;\r
1074                                 \r
1075                                 if (clusterSet != null) {\r
1076                                 if (DEBUG)\r
1077                                         System.out.println("NEW RESOURCE " + ir + " for cluster set " + clusterSet);\r
1078                                         if(clusterSet instanceof InternalResource) {\r
1079                                                 ir.resource = w.newResource(((InternalResource)clusterSet).resource);\r
1080                                         } else {\r
1081                                                 ir.resource = w.newResource(clusterSet);\r
1082                                         }\r
1083                                 if (DEBUG)\r
1084                                         System.out.println(" => " + ir.resource);\r
1085                                         writeState.idToResource.set(ir.id, ir.resource);\r
1086                                         if(writeState.clusterSets.contains(ir)) {\r
1087                                         if (DEBUG)\r
1088                                                 System.out.println(" ==> NEW CLUSTER SET");\r
1089                                                 w.newClusterSet(ir.resource);\r
1090                                         }\r
1091                                 }\r
1092                                 \r
1093                         }\r
1094                 }\r
1095                 \r
1096                 reset();\r
1097                 bb.limit(BUFFER);\r
1098                 \r
1099                 try {\r
1100                         while(true) {\r
1101                                 byte method = readByte();\r
1102                                 switch(method) {                \r
1103                                 case TERM: {\r
1104                                         return;\r
1105                                 }\r
1106                                 case CLAIM: {\r
1107                                         writeState.statementCount += 2;\r
1108                                         Resource subject = getResource(readInt());\r
1109                                         Resource predicate = getResource(readInt());\r
1110                     Resource inverse = getResource(readInt());\r
1111                                         Resource object = getResource(readInt());\r
1112                                         w.claim(subject, predicate, inverse, object);\r
1113                                 } break;\r
1114                 case CLAIM_NOINVERSE: {\r
1115                     ++writeState.statementCount;\r
1116                     Resource subject = getResource(readInt());\r
1117                     Resource predicate = getResource(readInt());\r
1118                     Resource object = getResource(readInt());\r
1119                     w.claim(subject, predicate, null, object);\r
1120                 } break;\r
1121                 case DENY: {\r
1122                     Resource subject = getResource(readInt());\r
1123                     Resource predicate = getResource(readInt());\r
1124                     int inv = readInt();\r
1125                     Resource inverse = null;\r
1126                     if(inv > 0) inverse = getResource(inv);\r
1127                     Resource object = getResource(readInt());\r
1128                     if(!subject.isPersistent() || !object.isPersistent()) {\r
1129                         VirtualGraph statementProvider1 = processor.getProvider(subject, predicate, object);\r
1130                         if(inv > 0) {\r
1131                                 VirtualGraph statementProvider2 = processor.getProvider(object, inverse, subject);\r
1132                                 if(statementProvider2 != null)\r
1133                                         w.deny(object, inverse, null, subject, statementProvider2);\r
1134                         }\r
1135                         if(statementProvider1 != null)\r
1136                                 w.deny(subject, predicate, null, object, statementProvider1);\r
1137                     } else {\r
1138                         w.deny(subject, predicate, inverse, object, null);\r
1139                     }\r
1140                 } break;\r
1141                 case DENY_VALUE: {\r
1142                     Resource subject = getResource(readInt());\r
1143                     if(!subject.isPersistent()) {\r
1144                         VirtualGraph provider = processor.getValueProvider(subject);\r
1145                         if(provider != null)\r
1146                                 w.denyValue(subject, provider);\r
1147                     } else {\r
1148                         w.denyValue(subject);\r
1149                     }\r
1150                 } break;\r
1151                                 case CLAIM_VALUE_B: {\r
1152                                         ++writeState.valueCount;\r
1153                                         Resource resource = getResource(readInt());\r
1154                                         int len = readInt();\r
1155                                         tgs.setValue(w, resource, null, this, len);\r
1156 //                                      byte[] bytes = readBytes(len);\r
1157 //                  tgs.setValue(resource, null, bytes);\r
1158                                 } break;\r
1159                                 case COMMIT_AND_CONTINUE: {\r
1160                                         XSupport xs = w.getService(XSupport.class);\r
1161                                         xs.commitAndContinue(w, traits);\r
1162                                 } break;\r
1163                                 }\r
1164                         }\r
1165                 } catch(Exception e) {\r
1166                         if(e instanceof ServiceException)\r
1167                                 throw (ServiceException)e;\r
1168                         else\r
1169                                 throw new ServiceException(e);\r
1170                 } finally {\r
1171                         try {\r
1172                                 channel.close();\r
1173                                 channel = null;\r
1174                         } catch (IOException e) {\r
1175                                 throw new ServiceException(e);\r
1176                         }\r
1177                 }\r
1178 //              System.out.println("Resources:  " + state.resourceCount);\r
1179 //              System.out.println("Statements: " + state.statementCount);\r
1180 //              System.out.println("Values:     " + state.valueCount);\r
1181         }\r
1182         \r
1183         private Resource getType(Object value) {\r
1184                 Class<?> clazz = value.getClass();\r
1185                 Resource dataType = \r
1186                           clazz == Float.class ? b.Float\r
1187                         : clazz == Double.class ? b.Double\r
1188                         : clazz == Integer.class ? b.Integer\r
1189                         : clazz == String.class ? b.String\r
1190                         : clazz == Boolean.class ? b.Boolean\r
1191                         : clazz == Byte.class ? b.Byte\r
1192                         : clazz == Long.class ? b.Long\r
1193                         : clazz == float[].class ? b.FloatArray\r
1194                         : clazz == double[].class ? b.DoubleArray\r
1195                         : clazz == int[].class ? b.IntegerArray\r
1196                         : clazz == String[].class ? b.StringArray\r
1197                         : clazz == boolean[].class ? b.BooleanArray\r
1198                         : clazz == byte[].class ? b.ByteArray\r
1199                         : clazz == long[].class ? b.LongArray                                   \r
1200                         : null\r
1201                         ;\r
1202                 return dataType;\r
1203         }\r
1204         \r
1205         public long newCluster() {\r
1206                 return -1 - (++writeState.clusterCount);\r
1207         }\r
1208 \r
1209         public long getDefaultCluster() {\r
1210                 return writeState.defaultCluster;\r
1211         }\r
1212         \r
1213         public void setDefaultCluster(long cluster) {\r
1214             writeState.defaultCluster = cluster;\r
1215         }\r
1216     \r
1217     @Override\r
1218     public void syncRequest(final DelayedWrite request) throws DatabaseException {\r
1219         \r
1220         try {\r
1221 \r
1222                 final DelayedWriteGraph dwg = new DelayedWriteGraph(this);\r
1223                 request.perform(dwg);\r
1224 \r
1225                 syncRequest(new WriteOnlyRequest() {\r
1226 \r
1227                         @Override\r
1228                         public void perform(WriteOnlyGraph graph) throws DatabaseException {\r
1229                                 dwg.commit(graph, request);\r
1230                         }\r
1231 \r
1232                 });\r
1233 \r
1234         } catch (DatabaseException e) {\r
1235                 \r
1236                 throw e;\r
1237                 \r
1238         } catch (Throwable e) {\r
1239                 \r
1240                 throw new DatabaseException(e);\r
1241                 \r
1242         } finally {\r
1243                 \r
1244         }\r
1245         \r
1246     }\r
1247     \r
1248     @Override\r
1249     public void syncRequest(WriteOnly request) throws DatabaseException {\r
1250         \r
1251         Resource defaultClusterSet = setClusterSet4NewResource(null);\r
1252         \r
1253         try {\r
1254             WriteSupport ws = session.getService(WriteSupport.class);\r
1255             ws.performWriteRequest(this, request);\r
1256         } catch (DatabaseException e) {\r
1257             throw e;\r
1258         } catch (Throwable t) {\r
1259             throw new DatabaseException(t);\r
1260         }  finally {\r
1261             setClusterSet4NewResource(defaultClusterSet);\r
1262         }\r
1263         \r
1264     }\r
1265 \r
1266     @SuppressWarnings("unchecked")\r
1267     @Override\r
1268     public <T> T getService(Class<T> api) {\r
1269         \r
1270         if(ClusteringSupport.class == api) {\r
1271 \r
1272             final ClusteringSupport support = (ClusteringSupport)super.getService(api); \r
1273 \r
1274             return (T)new ClusteringSupport() {\r
1275                 \r
1276                 @Override\r
1277                 public Resource getResourceByIndexAndCluster(int resourceIndex, long clusterId)\r
1278                         throws DatabaseException, ResourceNotFoundException {\r
1279                     return support.getResourceByIndexAndCluster(resourceIndex, clusterId);\r
1280                 }\r
1281                 \r
1282                 @Override\r
1283                 public Resource getResourceByKey(int resourceKey) throws ResourceNotFoundException {\r
1284                     return support.getResourceByKey(resourceKey);\r
1285                 }\r
1286                 \r
1287                 @Override\r
1288                 public int getNumberOfResources(long clusterId)\r
1289                                 throws DatabaseException {\r
1290                         return support.getNumberOfResources(clusterId);\r
1291                 }\r
1292                 \r
1293                 @Override\r
1294                 public long getCluster(Resource r) {\r
1295                     return support.getCluster(r);\r
1296                 }\r
1297                 \r
1298                 @Override\r
1299                 public long createCluster() {\r
1300                     return newCluster();\r
1301                 }\r
1302                 \r
1303                 @Override\r
1304                 public boolean isClusterSet(Resource r) throws DatabaseException {\r
1305                         return support.isClusterSet(r);\r
1306                 }\r
1307 \r
1308                 @Override\r
1309                 public Resource getClusterSetOfCluster(Resource r) throws DatabaseException {\r
1310                         return support.getClusterSetOfCluster(r);\r
1311                 }\r
1312                 \r
1313                 @Override\r
1314                 public Resource getClusterSetOfCluster(long cluster) throws DatabaseException {\r
1315                         return support.getClusterSetOfCluster(cluster);\r
1316                 }\r
1317 \r
1318             };\r
1319             \r
1320         } else if (TransferableGraphSupport.class == api) {\r
1321                 \r
1322                 final TransferableGraphSupport parentSupport = session.getService(TransferableGraphSupport.class);\r
1323                 \r
1324                 return (T)new TransferableGraphSupport() {\r
1325 \r
1326                         @Override\r
1327                         public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, byte[] raw) {\r
1328                                 writeByte(CLAIM_VALUE_B);\r
1329                                 writeInt(getId(resource));\r
1330                                 writeInt(raw.length);\r
1331                                 writeBytes(raw);\r
1332                                 writeInt(getBindingId(haxx));\r
1333                         }\r
1334                         \r
1335                         @Override\r
1336                         public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, ByteReader reader, int amount)\r
1337                                 throws DatabaseException {\r
1338                     writeByte(CLAIM_VALUE_B);\r
1339                     writeInt(getId(resource));\r
1340                     writeInt(amount);\r
1341                     writeBytes(reader.readBytes(null, amount));\r
1342                     writeInt(getBindingId(haxx));\r
1343                         }\r
1344                         \r
1345                         @Override\r
1346                         public byte[] getValue(ReadGraph graph, Resource resource) {\r
1347                                 return parentSupport.getValue(graph, resource);\r
1348                         }\r
1349                         \r
1350                         @Override\r
1351                         public InputStream getValueStream(ReadGraph graph, Resource resource) {\r
1352                                 return parentSupport.getValueStream(graph, resource);\r
1353                         }\r
1354                         \r
1355                 };\r
1356 \r
1357         }\r
1358         \r
1359         return super.getService(api);\r
1360         \r
1361     }\r
1362 \r
1363     @Override\r
1364     public <T> void addMetadata(Metadata data) throws ServiceException {\r
1365         MetadataUtils.addMetadata(session, metadata, data);\r
1366     }\r
1367     \r
1368     public void addCommitAndContinue() {\r
1369                 writeByte(COMMIT_AND_CONTINUE);\r
1370     }\r
1371 \r
1372     @Override\r
1373     public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {\r
1374         return MetadataUtils.getMetadata(session, metadata, clazz);\r
1375     }\r
1376 \r
1377     @Override\r
1378     public TreeMap<String, byte[]> getMetadata() {\r
1379         return metadata;\r
1380     }\r
1381     @Override\r
1382     public <T> T syncRequest(WriteResult<T> request) throws DatabaseException {\r
1383         \r
1384         return request.perform(this);\r
1385         \r
1386     }\r
1387 \r
1388     @Override\r
1389     public VirtualGraph getProvider() {\r
1390         return null;\r
1391     }\r
1392 \r
1393     @Override\r
1394     public void clearUndoList(WriteTraits writeTraits) {\r
1395         WriteSupport ws = session.getService(WriteSupport.class);\r
1396         if (null != ws)\r
1397             ws.clearUndoList(writeTraits);\r
1398     }\r
1399 \r
1400         @Override\r
1401         public void markUndoPoint() {\r
1402                 // TODO Auto-generated method stub\r
1403                 \r
1404         }\r
1405 \r
1406         @Override\r
1407         public <T> T getPossibleRelatedValue(final Resource subject, final Resource relation, final Binding binding)\r
1408                         throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException {\r
1409         if(!(subject instanceof InternalResource)) {\r
1410                 return super.getPossibleRelatedValue(subject, relation, binding);\r
1411         } else {\r
1412                 return null;\r
1413         }\r
1414         }\r
1415         \r
1416         @Override\r
1417         final public Resource getPossibleObject(final Resource subject, final Resource relation)\r
1418                         throws ManyObjectsForFunctionalRelationException, ServiceException {\r
1419         if(!(subject instanceof InternalResource)) {\r
1420                 return super.getPossibleObject(subject, relation);\r
1421         } else {\r
1422                 return null;\r
1423         }\r
1424         }\r
1425 \r
1426 }\r