import org.simantics.databoard.type.UnionType;
import org.simantics.databoard.type.VariantType;
import org.simantics.databoard.util.ObjectUtils;
+import org.simantics.datatypes.literal.GUID;
import org.simantics.db.ChangeSetIdentifier;
import org.simantics.db.Operation;
import org.simantics.db.ReadGraph;
import org.simantics.db.common.request.ObjectsWithType;
import org.simantics.db.common.request.PossibleChild;
import org.simantics.db.common.request.PossibleIndexRoot;
+import org.simantics.db.common.request.WriteRequest;
import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.event.ChangeListener;
import org.simantics.db.exception.CancelTransactionException;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.exception.ServiceException;
import org.simantics.db.layer0.adapter.GenericRelationIndex;
import org.simantics.db.layer0.adapter.PasteHandler;
import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler;
+import org.simantics.db.layer0.adapter.impl.EntityRemover;
import org.simantics.db.layer0.adapter.impl.TGRemover;
import org.simantics.db.layer0.genericrelation.IndexedRelations;
import org.simantics.db.layer0.internal.SimanticsInternal;
import org.simantics.db.service.ClusteringSupport;
import org.simantics.db.service.CollectionSupport;
import org.simantics.db.service.DebugSupport;
+import org.simantics.db.service.GraphChangeListenerSupport;
import org.simantics.db.service.ManagementSupport;
import org.simantics.db.service.UndoRedoSupport;
import org.simantics.db.service.XSupport;
@SuppressWarnings("rawtypes")
public static final ThreadLocal SCL_GRAPH = new ThreadLocal();
- final public static Binding datatype_binging = Bindings.getBindingUnchecked(Datatype.class);
-
public static Resource literal(WriteGraph g, String value) throws DatabaseException {
Layer0 L0 = Layer0.getInstance(g);
Resource r = g.newResource();
Resource range = graph.getPossibleObject(property, L0.HasRange);
if(range != null && !L0.Value.equals(range)) return range;
- Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
+ Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, Bindings.DATATYPE);
if(requiredDataType != null) return getLiteralType(graph, requiredDataType);
String requiredValueType = graph.getPossibleRelatedValue(property, L0.RequiresValueType, Bindings.STRING);
Layer0 L0 = Layer0.getInstance(graph);
Layer0X L0X = Layer0X.getInstance(graph);
- Datatype literalDatatype = graph.getPossibleRelatedValue(value, L0.HasDataType, datatype_binging);
+ Datatype literalDatatype = graph.getPossibleRelatedValue(value, L0.HasDataType, Bindings.DATATYPE);
if(literalDatatype != null) return getSCLType(literalDatatype);
String literalValueType = graph.getPossibleRelatedValue(value, L0.HasValueType, Bindings.STRING);
if(predicate != null) {
- Datatype requiredDataType = graph.getPossibleRelatedValue(predicate, L0X.RequiresDataType, datatype_binging);
+ Datatype requiredDataType = graph.getPossibleRelatedValue(predicate, L0X.RequiresDataType, Bindings.DATATYPE);
if(requiredDataType != null) return getSCLType(requiredDataType);
throw new DatabaseException("Unidentified literal data type for property " + NameUtils.getURIOrSafeNameInternal(graph, predicate));
}
public static Datatype getPossibleDatatype(ReadGraph graph, Variable variable) throws DatabaseException {
+ return getPossibleDatatype(graph, variable, null, true);
+ }
+ private static Datatype getPossibleDatatype(ReadGraph graph, Variable variable, PropertyInfo info, boolean checkPropertyDatatype) throws DatabaseException {
Layer0 L0 = Layer0.getInstance(graph);
Layer0X L0X = Layer0X.getInstance(graph);
Resource property = variable.getPossiblePredicateResource(graph);
- if(property != null) {
-// Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
- Datatype requiredDataType = graph.syncRequest(new PossibleRelatedValue<Datatype>(property, L0X.RequiresDataType, datatype_binging));
+ if(checkPropertyDatatype && property != null) {
+ Datatype requiredDataType = graph.syncRequest(new PossibleRelatedValue<Datatype>(property, L0X.RequiresDataType, Bindings.DATATYPE));
if(requiredDataType != null) return requiredDataType;
}
Resource literal = variable.getPossibleRepresents(graph);
if(literal != null) {
- Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), datatype_binging);
- if(literalDatatype != null) return literalDatatype;
+ Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), Bindings.DATATYPE);
+ if(literalDatatype != null) return literalDatatype;
}
if(property != null) {
- String requiredValueType = graph.getPossibleRelatedValue(property, L0.RequiresValueType, Bindings.STRING);
+ String requiredValueType = info != null
+ ? info.requiredValueType
+ : graph.getPossibleRelatedValue(property, L0.RequiresValueType, Bindings.STRING);
if(requiredValueType != null) {
Datatype datatype = getPossibleDatatypeForValueType(requiredValueType);
if(datatype != null) return datatype;
}
return null;
-
}
private static Datatype getPossibleDatatypeForValueType(String requiredValueType) throws DatabaseException {
arrayType = requiredValueType.substring(1, requiredValueType.length()-1);
}
- if(arrayType != null) {
- Datatype arrayDataType = getArrayDataTypeForType(arrayType);
- if(arrayDataType != null)
- return arrayDataType;
- }
+ Datatype arrayDataType = getDatatypeForType(arrayType != null ? arrayType : requiredValueType, arrayType != null);
+ if(arrayDataType != null)
+ return arrayDataType;
Datatype dt = Datatypes.getDatatype(requiredValueType);
if(dt != null) return dt;
return null;
}
-
}
- private static Datatype getArrayDataTypeForType(String type) {
- if("Double".equals(type)) return Datatypes.DOUBLE_ARRAY;
- else if("String".equals(type)) return Datatypes.STRING_ARRAY;
- else if("Integer".equals(type)) return Datatypes.INTEGER_ARRAY;
- else if("Long".equals(type)) return Datatypes.LONG_ARRAY;
- else if("Float".equals(type)) return Datatypes.FLOAT_ARRAY;
- else if("Byte".equals(type)) return Datatypes.BYTE_ARRAY;
- else if("Boolean".equals(type)) return Datatypes.BOOLEAN_ARRAY;
- else if("Variant".equals(type)) return Datatypes.VARIANT_ARRAY;
+ private static Datatype getDatatypeForType(String type, boolean isArray) {
+ switch (type) {
+ case "Double": return isArray ? Datatypes.DOUBLE_ARRAY : Datatypes.DOUBLE;
+ case "String": return isArray ? Datatypes.STRING_ARRAY : Datatypes.STRING;
+ case "Integer": return isArray ? Datatypes.INTEGER_ARRAY : Datatypes.INTEGER;
+ case "Long": return isArray ? Datatypes.LONG_ARRAY : Datatypes.LONG;
+ case "Float": return isArray ? Datatypes.FLOAT_ARRAY : Datatypes.FLOAT;
+ case "Byte": return isArray ? Datatypes.BYTE_ARRAY : Datatypes.BYTE;
+ case "Boolean": return isArray ? Datatypes.BOOLEAN_ARRAY : Datatypes.BOOLEAN;
+ case "Variant": return isArray ? Datatypes.VARIANT_ARRAY : Datatypes.VARIANT;
+ }
return null;
}
}
Datatype type = getDatatype(graph, variable);
- if (type == null)
- throw new DatabaseException("No datatype available for variable " + variable.getURI(graph));
return Bindings.getBinding(type);
}
public static Binding getPossibleDefaultBinding(ReadGraph graph, Variable variable) throws DatabaseException {
Resource property = variable.getPossiblePredicateResource(graph);
+ PropertyInfo info = null;
if(property != null) {
- PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(property), TransientCacheAsyncListener.<PropertyInfo>instance());
+ info = graph.syncRequest(new PropertyInfoRequest(property), TransientCacheAsyncListener.<PropertyInfo>instance());
if(info.defaultBinding != null) return info.defaultBinding;
}
- Datatype type = getPossibleDatatype(graph, variable);
+ Datatype type = getPossibleDatatype(graph, variable, info, false);
if (type == null) return null;
return Bindings.getBinding(type);
if(literal == null)
return "";
- Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), datatype_binging);
+ Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), Bindings.DATATYPE);
if(literalDatatype != null) {
String unit = getPossibleUnit(literalDatatype);
if(unit != null) return unit;
Resource property = variable.getPossiblePredicateResource(graph);
if(property != null) {
- Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
+ Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, Bindings.DATATYPE);
if(requiredDataType != null) {
String unit = getPossibleUnit(requiredDataType);
if(unit != null) return unit;
}
- public static void claimAdaptedValue(WriteGraph graph, Resource objectResource, Object value, Binding binding, Datatype datatype) throws DatabaseException {
+ public static void claimAdaptedValue(WriteGraph graph, Resource objectResource, Object value, Binding binding, Datatype targetDatatype) throws DatabaseException {
try {
- Datatype source = binding.type();
- if(source.equals(datatype)) {
+ Datatype sourceDatatype = binding.type();
+ if(sourceDatatype.equals(targetDatatype)) {
graph.claimValue(objectResource, value, binding);
} else {
- Binding target = Bindings.getBinding(datatype);
- Adapter adapter = Bindings.getAdapter(binding, target);
+ Binding target = Bindings.getBinding(targetDatatype);
+ Adapter adapter = Bindings.getTypeAdapter(binding, target);
graph.claimValue(objectResource, adapter.adapt(value), target);
}
public static Collection<Resource> copyTo(WriteGraph graph, Resource targetContainer, PasteEventHandler handler, CopyHandler copyHandler, PasteHandler pasteHandler) throws DatabaseException {
SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();
- copyHandler.copyToClipboard(graph, clipboard);
+ copyHandler.copyToClipboard(graph, clipboard, new NullProgressMonitor());
if(targetContainer != null) {
if(pasteHandler == null) pasteHandler = graph.adapt(targetContainer, PasteHandler.class);
return pasteHandler.pasteFromClipboard(graph, clipboard, handler);
return stm != null && stm.isAsserted(subject);
}
+ /*
+ * Works around problems in WriteGraph methods with similar signature.
+ * Especially handles better some cases with existing literals.
+ *
+ */
+ public static void claimLiteral(WriteGraph graph, Resource r, Resource p, Resource i, Resource t, Object value, Binding binding) throws DatabaseException {
+ Statement stm = graph.getPossibleStatement(r, p);
+ if(stm != null && !stm.isAsserted(r)) {
+ if(graph.isInstanceOf(stm.getObject(), t)) {
+ // Existing statement is compatible, reuse the literal
+ graph.claimValue(stm.getObject(), value, binding);
+ return;
+ } else {
+ // Existing statement is incompatible - remove it
+ graph.deny(stm);
+ }
+ }
+ // Create new statement
+ graph.claimLiteral(r, p, i, t, value, binding);
+ }
+
public static void setExpression(WriteGraph graph, Variable context, String text, Resource expressionValueType) throws DatabaseException {
Resource value = context.getRepresents(graph);
Resource indexRoot = graph.syncRequest(new PossibleVariableIndexRoot(variable));
if(indexRoot == null) return false;
- if(variable.equals(indexRoot)) return false;
+ Resource represents = variable.getPossibleRepresents(graph);
+ if(represents != null && represents.equals(indexRoot)) return false;
return isPublished(graph, indexRoot);
}
SimanticsClipboardImpl cp = new SimanticsClipboardImpl();
CopyHandler c1 = graph.adapt(r, CopyHandler.class);
- c1.copyToClipboard(graph, cp);
+ c1.copyToClipboard(graph, cp, null);
Collection<Set<Representation>> reps = cp.getContents();
if(reps.size() != 1) return null;
return ClipboardUtils.accept(graph, reps.iterator().next(), SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
SimanticsClipboardImpl cp = new SimanticsClipboardImpl();
CopyHandler c1 = graph.adapt(r, CopyHandler.class);
- c1.copyToClipboard(graph, cp);
+ c1.copyToClipboard(graph, cp, null);
Collection<Set<Representation>> reps = cp.getContents();
if(reps.size() != 1) return null;
return ClipboardUtils.accept(graph, reps.iterator().next(), SimanticsKeys.KEY_TRANSFERABLE_GRAPH_SOURCE);
emptyTrashBin(monitor, SimanticsInternal.getSession(), SimanticsInternal.getProject());
}
- public static void emptyTrashBin(final IProgressMonitor monitor, Session session, final Resource project) throws ServiceException {
+ public static void emptyTrashBin(final IProgressMonitor monitor, Session session, final Resource project)
+ throws ServiceException {
final SubMonitor mon = SubMonitor.convert(monitor, "Emptying Trash Bin...", 10000);
try {
+ ArrayList<Resource> unhandled = new ArrayList<Resource>();
session.syncRequest(new DelayedWriteRequest() {
@Override
public void perform(WriteGraph graph) throws DatabaseException {
Layer0X L0X = Layer0X.getInstance(graph);
Resource parent = graph.getSingleObject(project, L0.PartOf);
Resource trashBin = Layer0Utils.getPossibleChild(graph, parent, "TrashBin");
- Collection<Resource> trashes = trashBin != null
- ? graph.getObjects(trashBin, L0.ConsistsOf)
- : Collections.<Resource>emptyList();
+ Collection<Resource> trashes = trashBin != null ? graph.getObjects(trashBin, L0.ConsistsOf)
+ : Collections.<Resource> emptyList();
if (trashes.isEmpty())
throw new CancelTransactionException();
mon.setWorkRemaining((2 + trashes.size()) * 1000);
- for(Resource trash : trashes) {
+ for (Resource trash : trashes) {
if (mon.isCanceled())
throw new CancelTransactionException();
mon.subTask(NameUtils.getSafeName(graph, trash));
+ boolean isIndexRoot = graph.isInstanceOf(trash, L0.IndexRoot);
TGRemover remo = new TGRemover(mon.newChild(1000, SubMonitor.SUPPRESS_ALL_LABELS), trash);
- remo.remove(graph);
- if(graph.isInstanceOf(trash, L0.IndexRoot)) {
- // TODO: this should be an utility
- GenericRelationIndex index = graph.adapt(L0X.DependenciesRelation, GenericRelationIndex.class);
- IndexedRelations ir = graph.getService(IndexedRelations.class);
- // Deletes index files
- ir.reset(null, graph, L0X.DependenciesRelation, trash);
- // Notifies DB listeners
- index.reset(graph, trash);
+ try {
+ remo.remove(graph);
+ unhandled.addAll(remo.getRoots());
+ } catch (DatabaseException e) {
+ // Something went wrong - try to remove this later
+ // with EntityRemover
+ unhandled.add(trash);
+ }
+ if (isIndexRoot) {
+ // TODO: this should be an utility
+ GenericRelationIndex index = graph.adapt(L0X.DependenciesRelation,
+ GenericRelationIndex.class);
+ IndexedRelations ir = graph.getService(IndexedRelations.class);
+ // Deletes index files
+ ir.reset(null, graph, L0X.DependenciesRelation, trash);
+ // Notifies DB listeners
+ index.reset(graph, trash);
}
}
if (mon.isCanceled())
mon.newChild(1000);
}
});
+
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ for (Resource r : unhandled)
+ EntityRemover.remove(graph, r);
+ }
+ });
+
if (mon.isCanceled())
return;
mon.subTask("Purging Database");
}
return result;
}
+
+ public static Resource getPossiblePredicateByNameFromType(ReadGraph graph, Resource type, String name) throws DatabaseException {
+ Map<String,Resource> domain = getDomainOf(graph, type);
+ return domain.get(name);
+ }
public static Resource getPossiblePredicateByName(ReadGraph graph, Resource instance, String predicateName) throws DatabaseException {
for(Resource type : graph.getPrincipalTypes(instance)) {
return PrettyPrintTG.print(tg, ignoreIdentifiers);
}
+ /**
+ * Adds a random {@link GUID} as a value for <code>L0.identifier</code>
+ *
+ * @param graph
+ * @param component
+ * for which the identifier is added
+ * @param add
+ * <code>true</code> to invoke addLiteral, <code>false</code> to
+ * invoke claimLiteral
+ * @throws DatabaseException
+ */
+ public static void claimNewIdentifier(WriteGraph graph, Resource component, boolean add) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ GUID guid = GUID.random();
+ if (add)
+ graph.addLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, guid, GUID.BINDING);
+ else
+ graph.claimLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, guid, GUID.BINDING);
+ }
+
+ /**
+ * Sets a new random unique identifier for the specified entity if it already
+ * has an identifier. If the entity does not have a previous identifier, nothing
+ * is done.
+ *
+ * @param graph
+ * @param entity
+ * for which the identifier is added
+ * @return <code>true</code> if the identifier was renewed, <code>false</code>
+ * otherwise
+ * @throws DatabaseException
+ * @see {@link #claimNewIdentifier(WriteGraph, Resource, boolean)}
+ */
+ public static boolean renewIdentifier(WriteGraph graph, Resource entity) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ Statement stm = graph.getPossibleStatement(entity, L0.identifier);
+ if (stm != null) {
+ graph.claimValue(stm.getObject(), GUID.random(), GUID.BINDING);
+ return true;
+ }
+ return false;
+ }
+
+ public static void addMetadataListener(ChangeListener listener) {
+ SimanticsInternal.getSession().getService(GraphChangeListenerSupport.class).addMetadataListener(listener);
+ }
+
+ public static void removeMetadataListener(ChangeListener listener) {
+ SimanticsInternal.getSession().getService(GraphChangeListenerSupport.class).removeMetadataListener(listener);
+ }
+
}