]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / util / Layer0Utils.java
1 /*******************************************************************************
2  * Copyright (c) 2012 Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.layer0.util;
13
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.TreeSet;
24
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.core.runtime.SubMonitor;
27 import org.simantics.databoard.Bindings;
28 import org.simantics.databoard.Datatypes;
29 import org.simantics.databoard.adapter.AdaptException;
30 import org.simantics.databoard.adapter.Adapter;
31 import org.simantics.databoard.adapter.AdapterConstructionException;
32 import org.simantics.databoard.binding.Binding;
33 import org.simantics.databoard.binding.NumberBinding;
34 import org.simantics.databoard.binding.StringBinding;
35 import org.simantics.databoard.binding.error.BindingException;
36 import org.simantics.databoard.binding.mutable.MutableStringBinding;
37 import org.simantics.databoard.parser.repository.DataTypeSyntaxError;
38 import org.simantics.databoard.parser.repository.DataValueRepository;
39 import org.simantics.databoard.primitives.MutableString;
40 import org.simantics.databoard.type.ArrayType;
41 import org.simantics.databoard.type.BooleanType;
42 import org.simantics.databoard.type.ByteType;
43 import org.simantics.databoard.type.Datatype;
44 import org.simantics.databoard.type.DoubleType;
45 import org.simantics.databoard.type.FloatType;
46 import org.simantics.databoard.type.IntegerType;
47 import org.simantics.databoard.type.LongType;
48 import org.simantics.databoard.type.MapType;
49 import org.simantics.databoard.type.NumberType;
50 import org.simantics.databoard.type.OptionalType;
51 import org.simantics.databoard.type.RecordType;
52 import org.simantics.databoard.type.StringType;
53 import org.simantics.databoard.type.UnionType;
54 import org.simantics.databoard.type.VariantType;
55 import org.simantics.databoard.util.ObjectUtils;
56 import org.simantics.db.ChangeSetIdentifier;
57 import org.simantics.db.Operation;
58 import org.simantics.db.ReadGraph;
59 import org.simantics.db.RelationContext;
60 import org.simantics.db.Resource;
61 import org.simantics.db.Session;
62 import org.simantics.db.Statement;
63 import org.simantics.db.WriteGraph;
64 import org.simantics.db.WriteOnlyGraph;
65 import org.simantics.db.common.CommentMetadata;
66 import org.simantics.db.common.Indexing;
67 import org.simantics.db.common.StandardStatement;
68 import org.simantics.db.common.primitiverequest.PossibleRelatedValue;
69 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
70 import org.simantics.db.common.request.DelayedWriteRequest;
71 import org.simantics.db.common.request.ObjectsWithType;
72 import org.simantics.db.common.request.PossibleChild;
73 import org.simantics.db.common.request.PossibleIndexRoot;
74 import org.simantics.db.common.utils.NameUtils;
75 import org.simantics.db.exception.CancelTransactionException;
76 import org.simantics.db.exception.DatabaseException;
77 import org.simantics.db.exception.ServiceException;
78 import org.simantics.db.layer0.adapter.CopyHandler;
79 import org.simantics.db.layer0.adapter.CopyHandler2;
80 import org.simantics.db.layer0.adapter.GenericRelationIndex;
81 import org.simantics.db.layer0.adapter.PasteHandler;
82 import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler;
83 import org.simantics.db.layer0.adapter.impl.TGRemover;
84 import org.simantics.db.layer0.genericrelation.IndexedRelations;
85 import org.simantics.db.layer0.internal.SimanticsInternal;
86 import org.simantics.db.layer0.migration.OntologiesFromLibrary;
87 import org.simantics.db.layer0.property.OrderedResource;
88 import org.simantics.db.layer0.request.GlobalOntologies;
89 import org.simantics.db.layer0.request.PossibleVariableIndexRoot;
90 import org.simantics.db.layer0.request.PropertyInfo;
91 import org.simantics.db.layer0.request.PropertyInfoRequest;
92 import org.simantics.db.layer0.util.SimanticsClipboard.Representation;
93 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
94 import org.simantics.db.layer0.variable.Variable;
95 import org.simantics.db.service.ClusterCollectorPolicy;
96 import org.simantics.db.service.ClusterControl;
97 import org.simantics.db.service.ClusteringSupport;
98 import org.simantics.db.service.CollectionSupport;
99 import org.simantics.db.service.DebugSupport;
100 import org.simantics.db.service.ManagementSupport;
101 import org.simantics.db.service.UndoRedoSupport;
102 import org.simantics.db.service.XSupport;
103 import org.simantics.graph.db.TransferableGraphSource;
104 import org.simantics.graph.db.TransferableGraphs;
105 import org.simantics.graph.diff.Diff;
106 import org.simantics.graph.diff.TransferableGraphDelta1;
107 import org.simantics.graph.refactoring.GraphRefactoringUtils;
108 import org.simantics.graph.representation.TransferableGraph1;
109 import org.simantics.layer0.Layer0;
110 import org.simantics.operation.Layer0X;
111 import org.simantics.scl.compiler.environment.Environments;
112 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
113 import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
114 import org.simantics.scl.compiler.types.Type;
115 import org.simantics.scl.osgi.SCLOsgi;
116 import org.simantics.scl.runtime.function.Function;
117 import org.simantics.scl.runtime.function.Function1;
118 import org.simantics.scl.runtime.function.FunctionImpl1;
119
120 public class Layer0Utils {
121
122         @SuppressWarnings("rawtypes")
123         public static final ThreadLocal SCL_GRAPH = new ThreadLocal();
124
125         final public static Binding datatype_binging = Bindings.getBindingUnchecked(Datatype.class);
126
127         public static Resource literal(WriteGraph g, String value) throws DatabaseException {
128                 Layer0 L0 = Layer0.getInstance(g);
129                 Resource r = g.newResource();
130                 g.claimValue(r, value, Bindings.STRING);
131                 g.claim(r, L0.InstanceOf, L0.String);
132                 return r;
133         }
134
135         public static Resource literal(WriteGraph g, double value) throws DatabaseException {
136                 Layer0 L0 = Layer0.getInstance(g);
137                 Resource r = g.newResource();
138                 g.claimValue(r, value, Bindings.DOUBLE);
139                 g.claim(r, L0.InstanceOf, L0.Double);
140                 return r;
141         }
142
143         public static Resource literal(WriteGraph g, int value) throws DatabaseException {
144                 Layer0 L0 = Layer0.getInstance(g);
145                 Resource r = g.newResource();
146                 g.claimValue(r, value, Bindings.INTEGER);
147                 g.claim(r, L0.InstanceOf, L0.Integer);
148                 return r;
149         }
150
151         public static void assert_(WriteGraph g, Resource type, Resource predicate, Resource object) throws DatabaseException {
152                 Layer0 L0 = Layer0.getInstance(g);
153                 Resource assertion = g.newResource();
154                 g.claim(type, L0.Asserts, assertion);
155                 g.claim(assertion, L0.InstanceOf, L0.Assertion);
156                 g.claim(assertion, L0.HasPredicate, predicate);
157                 g.claim(assertion, L0.HasObject, object);
158         }
159
160         public static Resource relation(WriteGraph g, Resource parent, String name, Resource superrelation) throws DatabaseException {
161                 Layer0 L0 = Layer0.getInstance(g);
162                 Resource relation = g.newResource();
163                 g.claim(relation, L0.SubrelationOf, superrelation);
164                 g.claim(relation, L0.HasName, literal(g, name));
165                 g.claim(parent, L0.ConsistsOf, relation);
166
167                 Resource superrelationInverse = g.getInverse(superrelation);
168                 if(superrelationInverse != null) {
169                         Resource inverse = g.newResource();
170                         g.claim(inverse, L0.SubrelationOf, superrelationInverse);
171                         g.claim(relation, L0.ConsistsOf, inverse);
172                         g.claim(inverse, L0.HasName, literal(g, "Inverse"));
173                 }
174                 return relation;
175         }
176
177         private static Resource getLiteralType(ReadGraph graph, Datatype type) throws DatabaseException {
178                 Layer0 L0 = Layer0.getInstance(graph);
179                 if(type instanceof DoubleType) return L0.Double;
180                 else if(type instanceof StringType) return L0.String;
181                 else if(type instanceof IntegerType) return L0.Integer;
182                 else if(type instanceof LongType) return L0.Long;
183                 else if(type instanceof FloatType) return L0.Float;
184                 else if(type instanceof ByteType) return L0.Byte;
185                 else if(type instanceof BooleanType) return L0.Boolean;
186                 else if(type instanceof ArrayType) {
187                         ArrayType at = (ArrayType)type;
188                         if(at.componentType instanceof DoubleType) return L0.DoubleArray;
189                         else if(at.componentType instanceof StringType) return L0.StringArray;
190                         else if(at.componentType instanceof IntegerType) return L0.IntegerArray;
191                         else if(at.componentType instanceof LongType) return L0.LongArray;
192                         else if(at.componentType instanceof FloatType) return L0.FloatArray;
193                         else if(at.componentType instanceof ByteType) return L0.ByteArray;
194                         else if(at.componentType instanceof BooleanType) return L0.BooleanArray;
195                         else if(at.componentType instanceof VariantType) return L0.VariantArray;
196                 }
197                 throw new DatabaseException("Unidentified literal type for datatype " + type);
198         }
199
200         private static Resource getPossibleLiteralType(ReadGraph graph, String type) throws DatabaseException {
201
202                 Layer0 L0 = Layer0.getInstance(graph);
203                 if("Double".equals(type)) return L0.Double;
204                 else if("String".equals(type)) return L0.String;
205                 else if("Integer".equals(type)) return L0.Integer;
206                 else if("Long".equals(type)) return L0.Long;
207                 else if("Float".equals(type)) return L0.Float;
208                 else if("Byte".equals(type)) return L0.Byte;
209                 else if("Boolean".equals(type)) return L0.Boolean;
210                 else if("[Double]".equals(type)) return L0.DoubleArray;
211                 else if("[String]".equals(type)) return L0.StringArray;
212                 else if("[Integer]".equals(type)) return L0.IntegerArray;
213                 else if("[Long]".equals(type)) return L0.LongArray;
214                 else if("[Float]".equals(type)) return L0.FloatArray;
215                 else if("[Byte]".equals(type)) return L0.ByteArray;
216                 else if("[Boolean]".equals(type)) return L0.BooleanArray;
217                 else if("[Variant]".equals(type)) return L0.VariantArray;
218                 else if("Array Double".equals(type)) return L0.DoubleArray;
219                 else if("Array String".equals(type)) return L0.StringArray;
220                 else if("Array Integer".equals(type)) return L0.IntegerArray;
221                 else if("Array Long".equals(type)) return L0.LongArray;
222                 else if("Array Float".equals(type)) return L0.FloatArray;
223                 else if("Array Byte".equals(type)) return L0.ByteArray;
224                 else if("Array Boolean".equals(type)) return L0.BooleanArray;
225                 else if("Array Variant".equals(type)) return L0.VariantArray;
226                 else if("Vector Double".equals(type)) return L0.DoubleArray;
227                 else if("Vector String".equals(type)) return L0.StringArray;
228                 else if("Vector Integer".equals(type)) return L0.IntegerArray;
229                 else if("Vector Long".equals(type)) return L0.LongArray;
230                 else if("Vector Float".equals(type)) return L0.FloatArray;
231                 else if("Vector Byte".equals(type)) return L0.ByteArray;
232                 else if("Vector Boolean".equals(type)) return L0.BooleanArray;
233                 else if("Vector Variant".equals(type)) return L0.VariantArray;
234                 else if("Datatype".equals(type)) return L0.DataType;
235                 else if("Variant".equals(type)) return L0.Variant;
236                 else return null;
237         }
238
239         public static Resource getPossibleLiteralType(ReadGraph graph, Variable variable) throws DatabaseException {
240                 Resource predicate = variable.getPossiblePredicateResource(graph);
241                 if(predicate == null) return null;
242                 return getPossibleLiteralType(graph, predicate);
243         }
244
245         public static Resource getLiteralType(ReadGraph graph, Variable variable) throws DatabaseException {
246                 Resource result = getPossibleLiteralType(graph, variable);
247                 if(result == null) throw new DatabaseException("Unidentified literal type for variable " + variable.getURI(graph));
248                 return result;
249         }
250
251         public static Resource getLiteralType(ReadGraph graph, Resource property) throws DatabaseException {
252                 Resource result = getPossibleLiteralType(graph, property);
253                 if(result == null) throw new DatabaseException("Unidentified literal type for property " + graph.getURI(property));
254                 return result;
255         }
256
257         public static Resource getPossibleLiteralType(ReadGraph graph, Resource property) throws DatabaseException {
258
259                 Layer0 L0 = Layer0.getInstance(graph);
260                 Layer0X L0X = Layer0X.getInstance(graph);
261
262                 Resource defaultLiteralType = graph.getPossibleObject(property, L0.HasDefaultLiteralType);
263                 if(defaultLiteralType != null) return defaultLiteralType;
264
265                 Resource range = graph.getPossibleObject(property, L0.HasRange);
266                 if(range != null && !L0.Value.equals(range)) return range;
267
268                 Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
269                 if(requiredDataType != null) return getLiteralType(graph, requiredDataType);
270
271                 String requiredValueType = graph.getPossibleRelatedValue(property, L0.RequiresValueType, Bindings.STRING);
272                 if(requiredValueType == null) return null;
273
274                 return getPossibleLiteralType(graph, requiredValueType);
275
276         }
277
278         /**
279          * @param type any data type definition
280          * @return SCL type that matches the specified data type on a basic level.
281          *         Data type metadata is/cannot be converted into SCL types.
282          * @throws IllegalArgumentException
283          *             if the input datatype can't be converted into an SCL type
284          */
285         public static String getSCLType(Datatype type) throws IllegalArgumentException {
286                 return buildSCLType(type, null).toString();
287         }
288
289         /**
290          * Only used internally by {@link #buildSCLType(Datatype, StringBuilder)}
291          * @param s
292          * @param toBuilder
293          * @return
294          * @see #buildSCLType(Datatype, StringBuilder)
295          */
296         private static StringBuilder append(StringBuilder toBuilder, String s) {
297                 return toBuilder != null ? toBuilder.append(s) : new StringBuilder(s);
298         }
299
300         private static CharSequence append(CharSequence to, String s) {
301                 if (to instanceof StringBuilder)
302                         return ((StringBuilder) to).append(s);
303                 return new StringBuilder(to.length() + s.length()).append(to).append(s);
304         }
305
306         private static CharSequence stringOrBuilder(StringBuilder toBuilder, String s) {
307                 return toBuilder != null ? toBuilder.append(s) : s;
308         }
309
310         /**
311          * @param type any data type definition
312          * @return SCL type that matches the specified data type on a basic level.
313          *         Data type metadata is/cannot be converted into SCL types.
314          * @throws IllegalArgumentException
315          *             if the input datatype can't be converted into an SCL type
316          */
317         private static CharSequence buildSCLType(Datatype type, StringBuilder result) throws IllegalArgumentException {
318                 if(type instanceof DoubleType) return stringOrBuilder(result, "Double");
319                 else if(type instanceof StringType) return stringOrBuilder(result, "String");
320                 else if(type instanceof IntegerType) return stringOrBuilder(result, "Integer");
321                 else if(type instanceof FloatType) return stringOrBuilder(result, "Float");
322                 else if(type instanceof BooleanType) return stringOrBuilder(result, "Boolean");
323                 else if(type instanceof ByteType) return stringOrBuilder(result, "Byte");
324                 else if(type instanceof LongType) return stringOrBuilder(result, "Long");
325                 else if(type instanceof VariantType) return stringOrBuilder(result, "Variant");
326                 else if(type instanceof ArrayType) {
327                         ArrayType at = (ArrayType) type;
328                         // Optimization to prevent allocations in the most basic array cases
329                         if(at.componentType instanceof DoubleType) return stringOrBuilder(result, "Vector Double");
330                         else if(at.componentType instanceof StringType) return stringOrBuilder(result, "Vector String");
331                         else if(at.componentType instanceof IntegerType) return stringOrBuilder(result, "Vector Integer");
332                         else if(at.componentType instanceof FloatType) return stringOrBuilder(result, "Vector Float");
333                         else if(at.componentType instanceof BooleanType) return stringOrBuilder(result, "Vector Boolean");
334                         else if(at.componentType instanceof ByteType) return stringOrBuilder(result, "Vector Byte");
335                         else if(at.componentType instanceof LongType) return stringOrBuilder(result, "Vector Long");
336                         else if(at.componentType instanceof VariantType) return stringOrBuilder(result, "Vector Variant");
337                         else return buildSCLType(at.componentType, append(result, "Vector "));
338                 } else if(type instanceof OptionalType) {
339                         OptionalType ot = (OptionalType) type;
340                         return append(buildSCLType(ot.componentType, append(result, "Maybe (")), ")");
341                 } else if (type instanceof RecordType) {
342                         throw new IllegalArgumentException("Unable to convert datatype into SCL type: " + type);
343                 } else if (type instanceof MapType) {
344                         throw new IllegalArgumentException("Unable to convert datatype into SCL type: " + type);
345                 } else if (type instanceof UnionType) {
346                         throw new IllegalArgumentException("Unable to convert datatype into SCL type: " + type);
347                 }
348                 throw new IllegalArgumentException("Unable to convert datatype into SCL type: " + type);
349         }
350
351
352         public static Type getSCLType(ReadGraph graph, RuntimeEnvironment runtimeEnvironment, String typeText) throws DatabaseException {
353         try {
354                         return Environments.getType(runtimeEnvironment.getEnvironment(), typeText);
355                 } catch (SCLExpressionCompilationException e) {
356                         throw new DatabaseException(e);
357                 }
358         }
359
360         public static Type getSCLType(ReadGraph graph, Variable property) throws DatabaseException {
361
362                 RuntimeEnvironment runtimeEnvironment = graph.syncRequest(new RuntimeEnvironmentRequest(property.getIndexRoot(graph)));
363                 return getSCLType(graph, runtimeEnvironment, getSCLTypeString(graph, property));
364
365         }
366
367                 
368         public static String getSCLTypeString(ReadGraph graph, Variable context) throws DatabaseException {
369                 return getSCLTypeString(graph, context.getPossiblePredicateResource(graph), context.getRepresents(graph));
370         }
371
372
373         public static String getSCLTypeString(ReadGraph graph, Resource predicate, Resource value) throws DatabaseException {
374
375                 if(predicate != null) {
376                     String requiredValueTypes = graph.getPossibleRelatedValue(predicate, Layer0.getInstance(graph).RequiresValueType, Bindings.STRING);
377                     if(requiredValueTypes != null)
378                         return requiredValueTypes;
379                 }
380
381                 Layer0 L0 = Layer0.getInstance(graph);
382                 Layer0X L0X = Layer0X.getInstance(graph);
383
384                 Datatype literalDatatype = graph.getPossibleRelatedValue(value, L0.HasDataType, datatype_binging);
385                 if(literalDatatype != null) return getSCLType(literalDatatype);
386
387                 String literalValueType = graph.getPossibleRelatedValue(value, L0.HasValueType, Bindings.STRING);
388                 if(literalValueType != null) return literalValueType;
389
390                 if(predicate != null) {
391
392                         Datatype requiredDataType = graph.getPossibleRelatedValue(predicate, L0X.RequiresDataType, datatype_binging);
393                         if(requiredDataType != null) return getSCLType(requiredDataType);
394
395                         throw new DatabaseException("Unidentified literal data type for property " + NameUtils.getURIOrSafeNameInternal(graph, predicate));
396
397                 }
398
399                 throw new DatabaseException("Unidentified literal data type");
400
401         }
402
403         public static Datatype getDatatype(ReadGraph graph, Variable variable) throws DatabaseException {
404                 Datatype result = getPossibleDatatype(graph, variable);
405                 if(result != null) return result;
406                 throw new DatabaseException("Unidentified literal data type for property " + variable.getURI(graph));
407         }
408
409         public static Datatype getPossibleDatatype(ReadGraph graph, Variable variable) throws DatabaseException {
410
411                 Layer0 L0 = Layer0.getInstance(graph);
412                 Layer0X L0X = Layer0X.getInstance(graph);
413
414                 Resource property = variable.getPossiblePredicateResource(graph);
415                 if(property != null) {
416 //                      Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
417                         Datatype requiredDataType = graph.syncRequest(new PossibleRelatedValue<Datatype>(property, L0X.RequiresDataType, datatype_binging));
418                         if(requiredDataType != null) return requiredDataType;
419                 }
420
421                 Resource literal = variable.getPossibleRepresents(graph);
422                 if(literal != null) {
423                     Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), datatype_binging);
424                     if(literalDatatype != null) return literalDatatype;
425                 }
426
427                 if(property != null) {
428
429                         String requiredValueType = graph.getPossibleRelatedValue(property, L0.RequiresValueType, Bindings.STRING);
430                         if(requiredValueType != null) {
431                                 Datatype datatype = getPossibleDatatypeForValueType(requiredValueType);
432                                 if(datatype != null) return datatype;
433                         }
434
435                         Resource subject = variable.getParent(graph).getPossibleRepresents(graph);
436                         if(subject != null) {
437                                 Set<Resource> asses = new HashSet<Resource>();
438                                 for(Resource type : graph.getTypes(subject)) {
439                                         asses.addAll(graph.getAssertedObjects(type, property));
440                                 }
441                                 if(asses.size() == 1) {
442                                         Resource ass = asses.iterator().next();
443                                         Datatype dt = graph.getPossibleRelatedValue(ass, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class));
444                                         if(dt != null) return dt;
445                                 }
446                         }
447
448                 }
449
450                 return null;
451
452         }
453
454         private static Datatype getPossibleDatatypeForValueType(String requiredValueType) throws DatabaseException {
455
456                 String[] split = requiredValueType.split(" ");
457                 String arrayType = null;
458                 if(split.length == 2 && "Array".equals(split[0])) {
459                         arrayType = split[1];
460                 } else if(requiredValueType.startsWith("[") && requiredValueType.endsWith("]")) {
461                         arrayType = requiredValueType.substring(1, requiredValueType.length()-1);
462                 }
463
464                 if(arrayType != null) {
465                         Datatype arrayDataType = getArrayDataTypeForType(arrayType);
466                         if(arrayDataType != null)
467                                 return arrayDataType;
468                 }
469
470                 Datatype dt = Datatypes.getDatatype(requiredValueType);
471                 if(dt != null) return dt;
472
473                 try {
474                         return Datatypes.translate(requiredValueType);
475                 } catch (DataTypeSyntaxError e) {
476                         return null;
477                 }
478
479
480         }
481
482         private static Datatype getArrayDataTypeForType(String type) {
483                 if("Double".equals(type)) return Datatypes.DOUBLE_ARRAY;
484                 else if("String".equals(type)) return Datatypes.STRING_ARRAY;
485                 else if("Integer".equals(type)) return Datatypes.INTEGER_ARRAY;
486                 else if("Long".equals(type)) return Datatypes.LONG_ARRAY;
487                 else if("Float".equals(type)) return Datatypes.FLOAT_ARRAY;
488                 else if("Byte".equals(type)) return Datatypes.BYTE_ARRAY;
489                 else if("Boolean".equals(type)) return Datatypes.BOOLEAN_ARRAY;
490                 else if("Variant".equals(type)) return Datatypes.VARIANT_ARRAY;
491                 return null;
492         }
493
494         public static Binding getDefaultBinding(ReadGraph graph, Variable variable) throws DatabaseException {
495
496                 Resource property = variable.getPossiblePredicateResource(graph);
497                 if(property != null) {
498                         PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(property), TransientCacheAsyncListener.<PropertyInfo>instance());
499                         if(info.defaultBinding != null) return info.defaultBinding;
500                 }
501
502                 Datatype type = getDatatype(graph, variable);
503                 if (type == null)
504                         throw new DatabaseException("No datatype available for variable " + variable.getURI(graph));
505                 return Bindings.getBinding(type);
506
507         }
508
509         public static Binding getPossibleDefaultBinding(ReadGraph graph, Variable variable) throws DatabaseException {
510
511                 Resource property = variable.getPossiblePredicateResource(graph);
512                 if(property != null) {
513                         PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(property), TransientCacheAsyncListener.<PropertyInfo>instance());
514                         if(info.defaultBinding != null) return info.defaultBinding;
515                 }
516
517                 Datatype type = getPossibleDatatype(graph, variable);
518                 if (type == null) return null;
519
520                 return Bindings.getBinding(type);
521
522         }
523
524         public static String getPossibleUnit(Datatype dt) {
525                 if (dt == null)
526                         return null;
527                 else if (dt instanceof NumberType) {
528                         return ((NumberType) dt).getUnit();
529                 } else if (dt instanceof ArrayType) {
530                         ArrayType at = (ArrayType) dt;
531                         Datatype cdt = at.componentType();
532                         if (cdt instanceof NumberType) {
533                                 return ((NumberType) cdt).getUnit();
534                         }
535                 }
536                 return null;
537
538         }
539
540         public static String getUnit(ReadGraph graph, Variable variable) throws DatabaseException {
541
542                 Layer0 L0 = Layer0.getInstance(graph);
543                 Layer0X L0X = Layer0X.getInstance(graph);
544
545                 Resource literal = variable.getPossibleRepresents(graph);
546                 if(literal == null)
547                     return "";
548
549                 Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), datatype_binging);
550                 if(literalDatatype != null) {
551                         String unit = getPossibleUnit(literalDatatype);
552                         if(unit != null) return unit;
553                 }
554
555                 Resource property = variable.getPossiblePredicateResource(graph);
556                 if(property != null) {
557
558                         Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
559                         if(requiredDataType != null) {
560                                 String unit = getPossibleUnit(requiredDataType);
561                                 if(unit != null) return unit;
562                         }
563
564                 }
565
566                 return "";
567
568         }
569
570         public static void claimAdaptedValue(WriteGraph graph, Resource objectResource, Object value, Binding binding, Datatype datatype) throws DatabaseException {
571
572                 try {
573
574                         Datatype source = binding.type();
575                         if(source.equals(datatype)) {
576                                 graph.claimValue(objectResource, value, binding);
577                         } else {
578                                 Binding target = Bindings.getBinding(datatype);
579                                 Adapter adapter = Bindings.getAdapter(binding, target);
580                                 graph.claimValue(objectResource, adapter.adapt(value), target);
581                         }
582
583                 } catch (AdapterConstructionException e) {
584                         throw new DatabaseException(e);
585                 } catch (AdaptException e) {
586                         throw new DatabaseException(e);
587                 }
588
589         }
590
591         public static String toString(Object value, Binding binding) throws DatabaseException {
592                 try {
593                         if(value instanceof String) return (String)value;
594                         StringBuilder sb = new StringBuilder();
595                         DataValueRepository rep = new DataValueRepository();
596                         binding.printValue(value, sb, rep, false);
597                         return sb.toString();
598                 } catch (BindingException e) {
599                         throw new DatabaseException(e);
600                 } catch (IOException e) {
601                         throw new DatabaseException(e);
602                 }
603         }
604
605         public static Object parseValue(String text, Binding binding) throws DatabaseException {
606                 try {
607                         if(binding.isInstance(text)) return text;
608                         DataValueRepository rep = new DataValueRepository();
609                         return binding.parseValue(text, rep);
610                 } catch (BindingException e) {
611                         throw new DatabaseException(e);
612                 } catch (DataTypeSyntaxError e) {
613                         throw new DatabaseException(e);
614                 }
615         }
616
617         @SuppressWarnings("unchecked")
618         public static <T> T getValueAdaptedToBinding(ReadGraph graph, Resource literal, Binding targetBinding) throws DatabaseException {
619                 Datatype sourceDatatype = graph.getDataType(literal);
620                 Datatype targetDatatype = targetBinding.type();
621                 if (sourceDatatype.equals(targetDatatype))
622                         return graph.getValue(literal, targetBinding);
623
624                 Binding sourceBinding = Bindings.getBinding(sourceDatatype);
625                 try {
626                         Adapter adapter = Bindings.adapterFactory.getAdapter(Bindings.getBinding(sourceDatatype), targetBinding, true, false);
627                         Object value = graph.getValue(literal, sourceBinding);
628                         return (T) adapter.adaptUnchecked(value);
629                 } catch (AdapterConstructionException e) {
630                         throw new DatabaseException(e);
631                 }
632         }
633
634         public static Statement getStatementInLocal(Resource subject, Statement statement) {
635                 if(statement.isAsserted(subject)) return new StandardStatement(subject, statement.getPredicate(), statement.getObject());
636                 else return statement;
637         }
638
639         public static Resource browsePossible(ReadGraph graph, Resource root, String suffix) throws DatabaseException {
640                 return graph.getPossibleResource(graph.getURI(root) + suffix);
641         }
642
643         public static Resource getPossibleChild(ReadGraph graph, Resource resource, String name) throws DatabaseException {
644                 return graph.sync(new PossibleChild(resource, name));
645         }
646
647         public static Resource getPossibleChild(ReadGraph graph, Resource resource, Resource type, String name) throws DatabaseException {
648                 Resource child = graph.sync(new PossibleChild(resource, name));
649                 if(child == null) return null;
650                 if(!graph.isInstanceOf(child, type)) return null;
651                 return child;
652         }
653
654         public static RelationContext relationContext(ReadGraph graph, Resource subject, Resource predicate) throws DatabaseException {
655                 Statement stm = graph.getSingleStatement(subject, predicate);
656                 return new RelationContextImpl(subject, stm);
657         }
658
659         public static RelationContext relationContext(Statement stm) throws DatabaseException {
660                 return new RelationContextImpl(stm.getSubject(), stm);
661         }
662
663         public static <T> T valueInRelationContext(ReadGraph graph, Resource subject, Statement stm) throws DatabaseException {
664                 return graph.getValue2(subject, Layer0Utils.relationContext(stm));
665         }
666
667         public static <T> T valueInRelationContext(ReadGraph graph, Resource subject, Statement stm, Binding binding) throws DatabaseException {
668                 return graph.getValue2(subject, Layer0Utils.relationContext(stm), binding);
669         }
670
671         public static <T> T relatedValueInRelationContext(ReadGraph graph, Resource subject, Resource relation) throws DatabaseException {
672                 Statement stm = getStatementInLocal(subject, graph.getSingleStatement(subject, relation));
673                 return valueInRelationContext(graph, stm.getObject(), stm);
674         }
675
676         public static <T> T relatedValueInRelationContext(ReadGraph graph, Resource subject, Resource relation, Binding binding) throws DatabaseException {
677                 Statement stm = getStatementInLocal(subject, graph.getSingleStatement(subject, relation));
678                 return valueInRelationContext(graph, stm.getObject(), stm, binding);
679         }
680
681         public static Statement possibleObtainedStatementInternal(ReadGraph graph, Resource subject, Resource relation) throws DatabaseException {
682
683                 Layer0X L0X = Layer0X.getInstance(graph);
684
685                 for(Resource ob : graph.getObjects(subject, L0X.DefinesObtainedStatement)) {
686                         Resource pred = graph.getSingleObject(ob, L0X.ObtainedStatement_predicate);
687                         if(graph.isSubrelationOf(pred, relation)) {
688                                 Resource object = graph.getSingleObject(ob, L0X.ObtainedStatement_object);
689                                 return new StandardStatement(subject, pred, object);
690                         }
691                 }
692
693                 ArrayList<OrderedResource> order = new ArrayList<OrderedResource>();
694                 for(Statement stm : graph.getStatements(subject, L0X.ObtainsProperty)) {
695                         Integer position = graph.getRelatedValue(stm.getPredicate(), L0X.NaturalNumberOrderRelation, Bindings.INTEGER);
696                         order.add(new OrderedResource(position, stm.getObject()));
697                 }
698
699                 for(OrderedResource or : order) {
700                         Statement stm = possibleObtainedStatementInternal(graph, or.r, relation);
701                         if(stm != null) return stm;
702                 }
703
704                 return null;
705
706         }
707
708         public static <T> T possibleObtainedValue(ReadGraph graph, RelationContext ctx, Binding binding) throws DatabaseException {
709
710                 Statement stm = ctx.getStatement();
711                 Statement obj = Layer0Utils.possibleObtainedStatementInternal(graph, stm.getSubject(), stm.getPredicate());
712
713                 if(obj != null) {
714                         return Layer0Utils.valueInRelationContext(graph, obj.getObject(), obj, binding);
715                 } else {
716                         return null;
717                 }
718
719         }
720
721         public static void addObtainedStatement(WriteGraph graph, Resource subject, Resource predicate, Resource object) throws DatabaseException {
722                 Layer0 L0 = Layer0.getInstance(graph);
723                 Layer0X L0X = Layer0X.getInstance(graph);
724                 Resource ob = graph.newResource();
725                 graph.claim(ob, L0.InstanceOf, null, L0X.ObtainedStatement);
726                 graph.claim(ob, L0X.ObtainedStatement_predicate, null, predicate);
727                 graph.claim(ob, L0X.ObtainedStatement_object, null, object);
728                 graph.claim(subject, L0X.DefinesObtainedStatement, null, ob);
729         }
730
731         public static void addObtainedValue(WriteGraph graph, Resource subject, Resource predicate, Resource type, Object value, Binding binding) throws DatabaseException {
732                 Layer0 L0 = Layer0.getInstance(graph);
733                 Resource object = graph.newResource();
734                 graph.claim(object, L0.InstanceOf, type);
735                 graph.claimValue(object, value, binding);
736                 Layer0Utils.addObtainedStatement(graph, subject, predicate, object);
737         }
738
739         //-------------------------------------------------------------------------
740         // Indexing state query utilities idle handling utilities
741         //-------------------------------------------------------------------------
742
743         /**
744          * This method waits until the indexing engine becomes idle.
745          * @since 1.8
746          */
747         public static void waitIndexPending() {
748                 Indexing.waitIndexPending();
749         }
750
751         /**
752          * @param graph an active database write handle to prove one is in a write
753          *        transaction and wants to disable dependencies indexing for this
754          *        transaction only.
755          * @return previous value
756          * @since 1.8
757          */
758         public static boolean setDependenciesIndexingDisabled(WriteOnlyGraph graph, boolean disabled) {
759                 return Indexing.setDependenciesIndexingDisabled(graph, disabled);
760         }
761
762         public static String undo() throws DatabaseException {
763
764             Session session = SimanticsInternal.getSession();
765
766         UndoRedoSupport support = session.getService(UndoRedoSupport.class);
767
768         List<Operation> ops = support.undoAndReturnOperations(session, 1);
769         if(ops.isEmpty())
770             return "Undo history is empty.";
771
772         Operation mainOperation = ops.get(0);
773
774         long csId = mainOperation.getCSId();
775
776         ManagementSupport management = session.getService(ManagementSupport.class);
777         Collection<ChangeSetIdentifier> ids = management.getChangeSetIdentifiers(csId, csId);
778
779         return "Undo reverted " + ids.size() + " change sets.";
780
781         }
782
783         public static String undoOperations(int amountOfOperations) throws DatabaseException {
784
785             Session session = SimanticsInternal.getSession();
786
787         UndoRedoSupport support = session.getService(UndoRedoSupport.class);
788
789         List<Operation> ops = support.undoAndReturnOperations(session, amountOfOperations);
790         if(ops.isEmpty())
791             return "Undo history is empty.";
792
793         Operation mainOperation = ops.get(0);
794
795         long csId = mainOperation.getCSId();
796
797         ManagementSupport management = session.getService(ManagementSupport.class);
798         Collection<ChangeSetIdentifier> ids = management.getChangeSetIdentifiers(csId, csId);
799
800         return "Undo reverted " + ids.size() + " change sets.";
801
802         }
803
804         public static String redo() throws DatabaseException {
805
806             Session session = SimanticsInternal.getSession();
807
808         UndoRedoSupport support = session.getService(UndoRedoSupport.class);
809
810         List<Operation> ops = support.redo(session, 1);
811         if(ops.isEmpty())
812             return "Redo history is empty.";
813
814         Operation mainOperation = ops.get(0);
815
816         long csId = mainOperation.getCSId();
817
818         ManagementSupport management = session.getService(ManagementSupport.class);
819         Collection<ChangeSetIdentifier> ids = management.getChangeSetIdentifiers(csId, csId);
820
821         return "Redo redid " + ids.size() + " change sets.";
822
823         }
824
825         public static String getComment(Session session, ChangeSetIdentifier id) {
826             byte[] data = id.getMetadata().get(CommentMetadata.class.getName());
827             if(data == null)
828                 return "Undescribed operation.";
829             String comment = CommentMetadata.deserialise(session, data).toString().trim();
830             if(comment.isEmpty())
831                 return "Undescribed operation.";
832             return comment;
833         }
834
835     /**
836      * This method adds CommentMetadata for write transaction. CommentMetadata is used e.g. in Undo view.
837      * @param graph
838      *    graph handle
839      * @param string
840      *    comment
841      * @throws ServiceException
842      */
843     public static void addCommentMetadata(WriteOnlyGraph graph, String string) throws ServiceException {
844         // Add a comment to metadata.
845         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
846         graph.addMetadata(cm.add(ObjectUtils.toString(string)));
847     }
848
849         //-------------------------------------------------------------------------
850
851         /**
852          * Copy the specified source resource into the specified container using the
853          * specified write transaction handle.
854          *
855          * @param graph write transaction handle
856          * @param targetContainer target container resource of the created copy. The
857          *        exact logic of how the copy will be contained by the target
858          *        container is up to the PasteHandler to decide
859          * @param source the source resource to copy
860          * @throws DatabaseException
861          * @since 1.8
862          */
863         public static Collection<Resource> copyTo(WriteGraph graph, Resource targetContainer, Resource source) throws DatabaseException {
864                 return copyTo(graph, targetContainer, source, null, null, null);
865         }
866
867         public static Collection<Resource> copyTo(WriteGraph graph, Resource targetContainer, Resource source, PasteEventHandler handler) throws DatabaseException {
868                 return copyTo(graph, targetContainer, source, handler, null, null);
869         }
870
871         public static Collection<Resource> copyTo(WriteGraph graph, Resource targetContainer, Resource source, PasteEventHandler handler, CopyHandler copyHandler, PasteHandler pasteHandler) throws DatabaseException {
872                 if(copyHandler == null) copyHandler = graph.adapt(source, CopyHandler.class);
873                 return copyTo(graph, targetContainer, handler, copyHandler, pasteHandler);
874         }
875
876         public static Collection<Resource> copyTo(WriteGraph graph, Resource targetContainer, PasteEventHandler handler, CopyHandler copyHandler, PasteHandler pasteHandler) throws DatabaseException {
877                 SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();
878                 copyHandler.copyToClipboard(graph, clipboard);
879                 if(targetContainer != null) {
880                         if(pasteHandler == null) pasteHandler = graph.adapt(targetContainer, PasteHandler.class);
881                         return pasteHandler.pasteFromClipboard(graph, clipboard, handler);
882                 } else {
883                         DefaultPasteHandler ph = new DefaultPasteHandler(null);
884                         return ph.pasteFromClipboard(graph, clipboard, handler);
885                 }
886         }
887
888         public static CopyHandler2 getPossibleCopyHandler(ReadGraph graph, Collection<Resource> rs) throws DatabaseException {
889         CopyHandler2 ch = null;
890         for(Resource r : rs) {
891             if(ch == null) {
892                 CopyHandler ch2_ = graph.adapt(r, CopyHandler.class);
893                 if(ch2_ instanceof CopyHandler2) {
894                     ch = (CopyHandler2)ch2_;
895                 }
896             } else {
897                 CopyHandler ch2_ = graph.adapt(r, CopyHandler.class);
898                 if(ch2_ instanceof CopyHandler2) {
899                     CopyHandler2 ch2 = (CopyHandler2)ch2_;
900                     ch = ch.combine(ch2);
901                 }
902             }
903         }
904         return ch;
905         }
906
907         public static ClusterCollectorPolicy setClusterCollectorPolicy(ClusterCollectorPolicy policy) {
908                 Session session = SimanticsInternal.getSession();
909                 ClusterControl cc = session.getService(ClusterControl.class);
910                 return cc.setPolicy(policy);
911         }
912
913         private static String decodeType(ReadGraph graph, Variable variable) throws DatabaseException {
914                 Datatype dt = getDatatype(graph, variable);
915                 return dt.toSingleLineString();
916         }
917
918         private static boolean isAsserted(ReadGraph graph, Resource subject, Resource predicate) throws DatabaseException {
919                 Statement stm = graph.getPossibleStatement(subject, predicate);
920                 return stm != null && stm.isAsserted(subject);
921         }
922
923         public static void setExpression(WriteGraph graph, Variable context, String text, Resource expressionValueType) throws DatabaseException {
924                 
925                 Resource value = context.getRepresents(graph);
926                 Resource predicateResource = context.getPredicateResource(graph);
927                 Variable parent = context.getParent(graph);
928                 Resource parentResource = parent.getRepresents(graph);
929                 setExpression(graph, parentResource, predicateResource, value, text, expressionValueType);
930
931         }
932
933         public static void setExpression(WriteGraph graph, Resource parentResource, Resource predicateResource, Resource value, String text, Resource expressionValueType) throws DatabaseException {
934
935                 Layer0 L0 = Layer0.getInstance(graph);
936                 boolean hasExpression = graph.isInstanceOf(value, expressionValueType);
937                 String t = getSCLTypeString(graph, predicateResource, value);
938                 String expression = text.substring(1).trim();
939                 if(isAsserted(graph, parentResource, predicateResource)) {
940                         Resource newValue = graph.newResource();
941                         graph.claim(newValue, L0.InstanceOf, expressionValueType);
942                         graph.claimLiteral(newValue, L0.HasValueType, t, Bindings.STRING);
943                         graph.claimLiteral(newValue, L0.SCLValue_expression, expression, Bindings.STRING);
944                         graph.claim(parentResource, predicateResource, newValue);
945                 } else {
946                         if(hasExpression) {
947                                 graph.claimLiteral(value, L0.SCLValue_expression, expression, Bindings.STRING);
948                         } else {
949                                 Resource newValue = graph.newResource();
950                                 graph.claim(newValue, L0.InstanceOf, expressionValueType);
951                                 graph.claimLiteral(newValue, L0.HasValueType, t, Bindings.STRING);
952                                 graph.claimLiteral(newValue, L0.SCLValue_expression, expression, Bindings.STRING);
953                                 graph.deny(parentResource, predicateResource);
954                                 graph.claim(parentResource, predicateResource, newValue);
955                         }
956                 }
957
958         }
959
960         public static void clearExpression(WriteGraph graph, Variable property, Resource expressionValueType) throws DatabaseException {
961
962                 Resource object = property.getPossibleRepresents(graph);
963                 if(object != null) {
964                         boolean hasExpression = graph.isInstanceOf(object, expressionValueType);
965                         if(hasExpression) {
966                                 // There was an expression and now we go back to a value
967                                 Resource subject = property.getParent(graph).getPossibleRepresents(graph);
968                                 if(subject != null) {
969                                         Resource predicate = property.getPossiblePredicateResource(graph);
970                                         if(predicate != null) {
971                                                 graph.deny(subject, predicate, object);
972                                                 RemoverUtil.remove(graph, object);
973                                         }
974                                 }
975                         }
976                 }
977
978         }
979
980         public static boolean setOrClearExpression(WriteGraph graph, Variable property, String text, Resource expressionValueType) throws DatabaseException {
981
982                 if(text.startsWith("=")) {
983                         setExpression(graph, property, text, expressionValueType);
984                         return true;
985                 }
986
987                 clearExpression(graph, property, expressionValueType);
988
989                 return false;
990
991         }
992
993         public static void setValueAsString(WriteGraph graph, Variable property, String text, Resource expressionValueType) throws DatabaseException {
994
995                 try {
996
997                         if (setOrClearExpression(graph, property, text, expressionValueType))
998                                 return;
999
1000                         Object value = text;
1001                         Datatype type = property.getPossibleDatatype(graph);
1002                         if (type != null) {
1003
1004                                 Binding binding = Bindings.getBinding(type);
1005
1006                                 if (binding instanceof StringBinding) {
1007
1008                                         if (binding instanceof MutableStringBinding)
1009                                                 value = new MutableString(text);
1010                                         else
1011                                                 value = text;
1012
1013                                 } else {
1014
1015                                         if (binding instanceof NumberBinding) {
1016                                                 text = text.replace(",", ".");
1017                                         }
1018
1019                                         value = binding.parseValue(text, new DataValueRepository());
1020
1021                                 }
1022
1023                                 property.setValue(graph, value, binding);
1024
1025                         } else {
1026
1027                                 property.setValue(graph, value);
1028
1029                         }
1030
1031                         // Add a comment to metadata.
1032                         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
1033                         graph.addMetadata(cm.add("Set value " + ObjectUtils.toString(value)));
1034
1035                 } catch (DataTypeSyntaxError e) {
1036                         throw new DatabaseException(e);
1037                 } catch (BindingException e) {
1038                         throw new DatabaseException(e);
1039                 }
1040
1041         }
1042
1043
1044     public static String queryDebugSupport(String query) {
1045         Session session = SimanticsInternal.getSession();
1046         DebugSupport ds = session.getService(DebugSupport.class);
1047         return ds.query(session, "exec " + query);
1048     }
1049
1050     public static String queryListSupport (String query) {
1051         Session session = SimanticsInternal.getSession();
1052         DebugSupport ds = session.getService(DebugSupport.class);
1053         return ds.query(session, "list " + query);
1054     }
1055
1056     final public static Function1<Resource,Resource> resourceCluster = new FunctionImpl1<Resource, Resource>() {
1057                 @Override
1058                 public Resource apply(Resource p0) {
1059                         return p0;
1060                 }
1061         };
1062
1063         public static void sort(ReadGraph graph, List<Resource> collection) {
1064         CollectionSupport cos = graph.getService(CollectionSupport.class);
1065         cos.sort(collection);
1066         }
1067
1068         public static List<Resource> sortByCluster(ReadGraph graph, Collection<Resource> collection) {
1069         CollectionSupport cos = graph.getService(CollectionSupport.class);
1070         return cos.asSortedList(collection);
1071         }
1072
1073         public static List<Object> sortByCluster(final ReadGraph graph, List<Object> list, final Function1<Object,Resource> fn) {
1074         final ClusteringSupport cs = graph.getService(ClusteringSupport.class);
1075         ArrayList<Object> result = new ArrayList<Object>(list);
1076         Collections.sort(result, new Comparator<Object>() {
1077
1078                         @Override
1079                         public int compare(Object o1, Object o2) {
1080                                 Resource r1 = fn.apply(o1);
1081                                 Resource r2 = fn.apply(o2);
1082                                 long l1 = cs.getCluster(r1);
1083                                 long l2 = cs.getCluster(r2);
1084                                 if(l1 < l2) return -1;
1085                                 else if (l1 > l2) return 1;
1086                                 else return 0;
1087                         }
1088
1089         });
1090         return result;
1091     }
1092
1093     public static <T> List<T> sortByClusterT(final ReadGraph graph, Collection<T> list, final Function1<T,Resource> fn) {
1094         final ClusteringSupport cs = graph.getService(ClusteringSupport.class);
1095         ArrayList<T> result = new ArrayList<T>(list);
1096         Collections.sort(result, new Comparator<Object>() {
1097
1098             @Override
1099             public int compare(Object o1, Object o2) {
1100                 Resource r1 = fn.apply((T)o1);
1101                 Resource r2 = fn.apply((T)o2);
1102                 long l1 = cs.getCluster(r1);
1103                 long l2 = cs.getCluster(r2);
1104                 if(l1 < l2) return -1;
1105                 else if (l1 > l2) return 1;
1106                 else return 0;
1107             }
1108
1109         });
1110         return result;
1111     }
1112
1113     public static void makeSynchronous(ReadGraph graph, boolean value) throws DatabaseException {
1114         graph.setSynchronous(value);
1115     }
1116
1117     public static Set<Resource> listIndexRoots(ReadGraph graph) throws DatabaseException {
1118         
1119         Layer0 L0 = Layer0.getInstance(graph);
1120         
1121                 Set<Resource> indexRoots = new TreeSet<Resource>();
1122                 indexRoots.addAll(Layer0Utils.listOntologies(graph));
1123                 indexRoots.addAll(graph.syncRequest(new ObjectsWithType(SimanticsInternal.getProject(), L0.ConsistsOf, L0.IndexRoot)));
1124                 return indexRoots;
1125
1126     }
1127     
1128     public static List<Resource> listOntologies(ReadGraph graph) throws DatabaseException {
1129         return graph.syncRequest(new OntologiesFromLibrary(graph.getRootLibrary()));
1130     }
1131
1132     public static List<Resource> listGlobalOntologies(ReadGraph graph) throws DatabaseException {
1133         return graph.syncRequest(new GlobalOntologies(graph.getRootLibrary()));
1134     }
1135
1136     public static <T> T applySCL(String module, String function, ReadGraph graph, Object ... args) throws DatabaseException {
1137
1138                 try {
1139                         SCL_GRAPH.set(graph);
1140                         T t = (T)((Function)SCLOsgi.MODULE_REPOSITORY.getValue(module + "/" + function)).applyArray(args);
1141                         SCL_GRAPH.set(null);
1142                         return t;
1143                 } catch (Throwable t) {
1144                         throw new DatabaseException(t);
1145                 }
1146
1147     }
1148
1149     public static boolean isContainerPublished(ReadGraph graph, Variable variable) throws DatabaseException {
1150
1151         Resource indexRoot = graph.syncRequest(new PossibleVariableIndexRoot(variable));
1152         if(indexRoot == null) return false;
1153         if(variable.equals(indexRoot)) return false;
1154         return isPublished(graph, indexRoot);
1155
1156     }
1157
1158     public static boolean isContainerPublished(ReadGraph graph, Resource resource) throws DatabaseException {
1159
1160         Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(resource));
1161         if(indexRoot == null) return false;
1162         if(resource.equals(indexRoot)) return false;
1163         return isPublished(graph, indexRoot);
1164
1165     }
1166
1167     public static boolean isPublished(ReadGraph graph, Resource resource) throws DatabaseException {
1168
1169         Layer0 L0 = Layer0.getInstance(graph);
1170         Boolean value = graph.getPossibleRelatedValue(resource, L0.Entity_published, Bindings.BOOLEAN);
1171         if(value != null && value) return true;
1172
1173         // This is safety - root should not be published it child is not
1174         Resource root = graph.syncRequest(new PossibleIndexRoot(resource));
1175         if(root != null) {
1176                 value = graph.getPossibleRelatedValue(root, L0.Entity_published, Bindings.BOOLEAN);
1177                 if(value != null && value) return true;
1178         }
1179
1180         return false;
1181
1182     }
1183
1184     private static TransferableGraph1 makeTG(ReadGraph graph, Resource r) throws DatabaseException {
1185
1186         SimanticsClipboardImpl cp = new SimanticsClipboardImpl();
1187         CopyHandler c1 = graph.adapt(r, CopyHandler.class);
1188         c1.copyToClipboard(graph, cp);
1189         Collection<Set<Representation>> reps = cp.getContents();
1190         if(reps.size() != 1) return null;
1191         return ClipboardUtils.accept(graph, reps.iterator().next(), SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
1192
1193     }
1194
1195     private static TransferableGraphSource makeTGSource(ReadGraph graph, Resource r) throws DatabaseException {
1196
1197         SimanticsClipboardImpl cp = new SimanticsClipboardImpl();
1198         CopyHandler c1 = graph.adapt(r, CopyHandler.class);
1199         c1.copyToClipboard(graph, cp);
1200         Collection<Set<Representation>> reps = cp.getContents();
1201         if(reps.size() != 1) return null;
1202         return ClipboardUtils.accept(graph, reps.iterator().next(), SimanticsKeys.KEY_TRANSFERABLE_GRAPH_SOURCE);
1203
1204     }
1205
1206     /*
1207      * Modifies target to resemble source.
1208      */
1209     public static boolean merge(WriteGraph graph, Resource source, Resource target) throws DatabaseException {
1210
1211         TransferableGraphSource tgs1 = makeTGSource(graph, target);
1212         TransferableGraph1 tg1 = TransferableGraphs.create(graph, tgs1);
1213         TransferableGraph1 tg2 = makeTG(graph, source);
1214
1215         GraphRefactoringUtils.fixIncorrectRoot(tg1.identities);
1216         GraphRefactoringUtils.fixIncorrectRoot(tg2.identities);
1217
1218         ModelTransferableGraphSource mtgs = (ModelTransferableGraphSource)tgs1;
1219
1220                 Diff diff = new Diff(tg1, tg2);
1221                 TransferableGraphDelta1 delta = diff.diff();
1222
1223                 long[] oldResources = mtgs.getResourceArray(graph);
1224                 if(TransferableGraphs.hasChanges(graph, oldResources, delta)) {
1225                         TransferableGraphs.applyDelta(graph, mtgs.getResourceArray(graph), delta);
1226                         return true;
1227                 } else {
1228                         return false;
1229                 }
1230
1231     }
1232
1233     public static Resource inferLiteralTypeFromString(ReadGraph graph, String text) {
1234         return Layer0.getInstance(graph).String;
1235     }
1236
1237     public static void emptyTrashBin(IProgressMonitor monitor) throws ServiceException {
1238         emptyTrashBin(monitor, SimanticsInternal.getSession(), SimanticsInternal.getProject());
1239     }
1240
1241     public static void emptyTrashBin(final IProgressMonitor monitor, Session session, final Resource project) throws ServiceException {
1242         final SubMonitor mon = SubMonitor.convert(monitor, "Emptying Trash Bin...", 10000);
1243         try {
1244             session.syncRequest(new DelayedWriteRequest() {
1245                 @Override
1246                 public void perform(WriteGraph graph) throws DatabaseException {
1247                     Layer0Utils.setDependenciesIndexingDisabled(graph, true);
1248                     Layer0 L0 = Layer0.getInstance(graph);
1249                     Layer0X L0X = Layer0X.getInstance(graph);
1250                     Resource parent = graph.getSingleObject(project, L0.PartOf);
1251                     Resource trashBin = Layer0Utils.getPossibleChild(graph, parent, "TrashBin");
1252                     Collection<Resource> trashes = trashBin != null
1253                             ? graph.getObjects(trashBin, L0.ConsistsOf)
1254                             : Collections.<Resource>emptyList();
1255                     if (trashes.isEmpty())
1256                         throw new CancelTransactionException();
1257                     mon.setWorkRemaining((2 + trashes.size()) * 1000);
1258                     for(Resource trash : trashes) {
1259                         if (mon.isCanceled())
1260                             throw new CancelTransactionException();
1261                         mon.subTask(NameUtils.getSafeName(graph, trash));
1262                         TGRemover remo = new TGRemover(mon.newChild(1000, SubMonitor.SUPPRESS_ALL_LABELS), trash);
1263                         remo.remove(graph);
1264                         if(graph.isInstanceOf(trash, L0.IndexRoot)) {
1265                                 // TODO: this should be an utility 
1266                                         GenericRelationIndex index = graph.adapt(L0X.DependenciesRelation, GenericRelationIndex.class);
1267                                         IndexedRelations ir = graph.getService(IndexedRelations.class);
1268                                         // Deletes index files
1269                                         ir.reset(null, graph, L0X.DependenciesRelation, trash);
1270                                         // Notifies DB listeners
1271                                         index.reset(graph, trash);
1272                         }
1273                     }
1274                     if (mon.isCanceled())
1275                         throw new CancelTransactionException();
1276                     mon.subTask("Committing Changes");
1277                     mon.newChild(1000);
1278                 }
1279             });
1280             if (mon.isCanceled())
1281                 return;
1282             mon.subTask("Purging Database");
1283             mon.newChild(1000);
1284             XSupport xs = session.getService(XSupport.class);
1285             xs.purge();
1286         } catch (CancelTransactionException e) {
1287             // Ignore.
1288         } catch (DatabaseException e) {
1289             throw new ServiceException(e);
1290         }
1291     }
1292     
1293     public static Resource getSingleDomainOf(ReadGraph graph, Resource type, Resource target) throws DatabaseException {
1294         Resource result = null;
1295         for(Resource candidate : getDomainOf(graph, type).values()) {
1296                 if(graph.isInstanceOf(candidate, target)) {
1297                         if(result != null) throw new DatabaseException("Multiple relations found for target " + graph.getURI(target) + " in type " + graph.getURI(type));
1298                         else result = candidate;
1299                 }
1300         }
1301         if(result == null) throw new DatabaseException("Multiple relations found for target " + graph.getURI(target) + " in type " + graph.getURI(type));
1302         return result;
1303     }
1304
1305     public static Map<String, Resource> getDomainOf(ReadGraph graph, Resource type) throws DatabaseException {
1306         CollectionSupport cs = graph.getService(CollectionSupport.class);
1307         Map<String, Resource> result = cs.createObjectResourceMap(String.class);
1308         Layer0 L0 = Layer0.getInstance(graph);
1309         for(Resource r : graph.getObjects(type, L0.DomainOf)) {
1310                 String name = graph.getPossibleRelatedValue(r, L0.HasName, Bindings.STRING);
1311                 if(name != null) result.put(name, r);
1312         }
1313         for(Resource t : graph.getSupertypes(type)) {
1314                 for(Resource r : graph.getObjects(t, L0.DomainOf)) {
1315                         String name = graph.getPossibleRelatedValue(r, L0.HasName, Bindings.STRING);
1316                         if(name != null) result.put(name, r);
1317                 }
1318         }
1319         return result;
1320     }
1321     
1322     public static Resource getPossiblePredicateByName(ReadGraph graph, Resource instance, String predicateName) throws DatabaseException {
1323         for(Resource type : graph.getPrincipalTypes(instance)) {
1324                 Map<String, Resource> domainOf = getDomainOf(graph, type);
1325                 Resource predicate = domainOf.get(predicateName);
1326                 if(predicate != null) return predicate;
1327         }
1328         return null;
1329     }
1330     
1331     
1332     public static void claimLiteralDataboard(WriteGraph graph, Resource container, Resource property, String valueText) throws DatabaseException {
1333
1334         try {
1335                 PropertyInfo pi = graph.syncRequest(new PropertyInfoRequest(property));
1336                 if(pi.literalRange == null) throw new DatabaseException("No suitable literal type defined as range for property.");
1337                 if(pi.defaultBinding == null) throw new DatabaseException("No suitable default binding for property.");
1338                         Object value = pi.defaultBinding.parseValue(valueText, new DataValueRepository());
1339                         graph.claimLiteral(container, property, pi.literalRange, value, pi.defaultBinding);
1340                 } catch (DataTypeSyntaxError e) {
1341                         throw new DatabaseException(e);
1342                 } catch (BindingException e) {
1343                         throw new DatabaseException(e);
1344                 }
1345         
1346     }
1347
1348 }