--- /dev/null
+package org.simantics.interop.diagram;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.RequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
+import org.simantics.db.common.request.ResourceRead;
+import org.simantics.db.common.utils.OrderedSetUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
+import org.simantics.db.exception.NoSingleResultException;
+import org.simantics.db.exception.ServiceException;
+import org.simantics.db.layer0.adapter.Template;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
+import org.simantics.g2d.page.DiagramDesc;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.operation.Layer0X;
+import org.simantics.simulation.ontology.SimulationResource;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.utils.datastructures.Arrays;
+import org.simantics.utils.page.PageDesc;
+
+
+/**
+ * @author Marko Luukkainen
+ */
+public abstract class Diagram<T extends Symbol> {
+
+ public static boolean DO_NO_MIX_SECTION_NAMES = false;
+ public static boolean USE_MERGE_CONNECTS = true;
+
+ private Resource composite;
+ private Resource diagram;
+
+ private Map<Resource,Integer> indexMap = new HashMap<Resource, Integer>();
+
+ private Map<Resource,T> elementToSymbolMap = new HashMap<Resource, T>();
+
+ private Map<Resource,Diagram<T>> compositeToDiagramMap = new HashMap<Resource, Diagram<T>>();
+
+ protected Diagram(ReadGraph g, Resource composite, Resource diagram) throws DatabaseException {
+ this.composite = composite;
+ this.diagram = diagram;
+ }
+
+ protected abstract Diagram<T> construct(ReadGraph g, Resource composite, Resource diagram) throws DatabaseException;
+ protected abstract T constructSymbol(ReadGraph g, Resource element, Resource component) throws DatabaseException;
+
+ public Resource getComposite() {
+ return composite;
+ }
+
+ public Resource getDiagram() {
+ return diagram;
+ }
+
+
+ public void clearCaches() {
+ for (Diagram<T> d : compositeToDiagramMap.values()) {
+ for (T s : d.elementToSymbolMap.values())
+ s.dispose();
+ d.elementToSymbolMap.clear();
+ }
+ compositeToDiagramMap.clear();
+ }
+
+
+ public String generateName(ReadGraph g, Resource type, String name) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(g);
+ Layer0X l0x = Layer0X.getInstance(g);
+ String prefix = g.getPossibleRelatedValue(type, l0x.HasGeneratedNamePrefix);
+ if (prefix == null || prefix.length() == 0)
+ prefix = g.getRelatedValue(type, l0.HasName);
+ prefix += "_";
+ Set<String> reserved = null;
+ if (name != null) {
+ reserved = getAllModuleNamesForModel(g, composite);
+ int index = 0;
+ String realname = name + "_" + prefix;
+ while (true) {
+ String toTry = realname + Integer.toString(index);
+ if (!reserved.contains(toTry))
+ break;
+ index++;
+ }
+ realname += Integer.toString(index);
+ return realname;
+ }
+ Integer index = indexMap.get(type);
+ if (index != null) {
+ index++;
+ } else {
+ if (reserved == null)
+ reserved = getAllModuleNamesForModel(g, composite);
+ index = 0;
+ while (true) {
+ String toTry = prefix + Integer.toString(index);
+ if (!reserved.contains(toTry))
+ break;
+ index++;
+ }
+
+ }
+ indexMap.put(type, index);
+ return prefix + index;
+ }
+
+ private Set<String> getAllModuleNamesForModel(ReadGraph graph, final Resource res) throws DatabaseException {
+
+ Resource model = DiagramUtils.getModel(graph, res);
+ Resource configuration = DiagramUtils.getConfiguration(graph, model);
+ Set<String> names = new HashSet<String>();
+ Collection<Resource> composites = getAllComposites(graph, configuration);
+ for (Resource composite : composites) {
+ names.addAll(getAllModuleNamesForComposite(graph, composite));
+ }
+ return names;
+ }
+
+ protected abstract Resource getGraphicalCompositeType(ReadGraph graph) throws DatabaseException;
+ protected abstract Resource getFolderType(ReadGraph graph) throws DatabaseException;
+
+ @SuppressWarnings("unchecked")
+ private Collection<Resource> getAllComposites(RequestProcessor processor, Resource configuration) throws DatabaseException {
+ return (Set<Resource>)processor.syncRequest(new ResourceRead<Object>(configuration) {
+ @Override
+ public Object perform(ReadGraph graph) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(graph);
+ Set<Resource> composites = new HashSet<Resource>();
+ Stack<Resource> resources = new Stack<Resource>();
+ Resource graphicalCompositeType = getGraphicalCompositeType(graph);
+ Resource folderType = getFolderType(graph);
+ resources.add(resource);
+ while (!resources.isEmpty()) {
+ Resource r = resources.pop();
+ if (graph.isInstanceOf(r, graphicalCompositeType)) {
+ composites.add(r);
+ } else if (folderType != null && graph.isInstanceOf(r, folderType)){
+ resources.addAll(graph.getObjects(r, l0.ConsistsOf));
+ }
+ }
+ return composites;
+ }
+ }, TransientCacheListener.instance());
+ }
+
+ @SuppressWarnings("unchecked")
+ private Set<String> getAllModuleNamesForComposite(RequestProcessor processor, Resource composite) throws DatabaseException {
+ return (Set<String>)processor.syncRequest(new ResourceRead<Object>(composite) {
+ @Override
+ public Object perform(ReadGraph graph) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(graph);
+ Set<String> names = new HashSet<String>();
+ Collection<Resource> components = graph.getObjects(resource, l0.ConsistsOf);
+ for (Resource component : components) {
+ String n = graph.getPossibleRelatedValue(component, l0.HasName, Bindings.STRING);
+ if (n != null)
+ names.add(n);
+ }
+ return names;
+ }
+ }, TransientCacheListener.instance());
+
+ }
+
+ public Diagram<T> createDiagram(WriteGraph g,String name, Resource compositeType, Resource parent) throws DatabaseException {
+ return createDiagram(g, name, null, null,compositeType, parent);
+ }
+
+
+
+ /**
+ * Creates a new Diagram
+ * @param g
+ * @param name name of the diagram
+ * @param compositeType composite type of the diagram
+ * @param parent resource where diagram is added
+ * @return
+ * @throws DatabaseException
+ */
+ @SuppressWarnings("deprecation")
+ public Diagram<T> createDiagram(WriteGraph g,String name, DiagramDesc desc, Template tpl, Resource compositeType, Resource parent) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(g);
+ Layer0X l0x = Layer0X.getInstance(g);
+ ModelingResources m = ModelingResources.getInstance(g);
+
+ // create composite
+ Resource composite = g.newResource();
+ g.claim(composite, l0.InstanceOf, compositeType);
+
+ // create diagram
+ Resource diagramType = getDiagramFromComposite(g, compositeType);
+
+ Resource diagram = OrderedSetUtils.create(g, diagramType);
+
+ g.claim(composite, m.CompositeToDiagram, diagram);
+
+ // link to parent and set name
+ g.claimLiteral(composite, l0.HasName, name);
+ g.claim(composite, l0.PartOf, parent);
+
+ // activate mapping
+ Resource mapping = g.newResource();
+ g.claim(mapping, l0.InstanceOf, m.DiagramToCompositeMapping);
+ g.claim(diagram, l0x.HasTrigger, mapping);
+
+ if (tpl != null) {
+ Map<String,Object> params = new HashMap<String, Object>();
+ params.put("diagram", diagram);
+ tpl.apply(g, params);
+ }
+
+
+ // Make diagram part of a dummy container library attached to the parent
+ // composite if it's not already part of something.
+ // This gives the diagram a proper URI without connecting it directly to the composite with ConsistsOf.
+ // This would cause problems because a diagram is a structural composite/component also.
+ g.claimLiteral(diagram, l0.HasName, name, Bindings.STRING);
+ Resource container = g.newResource();
+ g.claim(container, l0.InstanceOf, null, l0.Library);
+ g.addLiteral(container, l0.HasName, l0.NameOf, l0.String, "__CONTAINER__", Bindings.STRING);
+ g.claim(container, l0.ConsistsOf, diagram);
+ g.claim(composite, l0.ConsistsOf, container);
+
+ if (desc != null)
+ DiagramGraphUtil.setDiagramDesc(g, diagram, desc);
+
+ Diagram<T> diag = construct(g, composite, diagram);
+ diag.compositeToDiagramMap = compositeToDiagramMap;
+ compositeToDiagramMap.put(composite, diag);
+ return diag;
+ }
+
+ public Diagram<T> fromExisting(ReadGraph g, Resource diagram) throws DatabaseException {
+ ModelingResources m = ModelingResources.getInstance(g);
+ StructuralResource2 s = StructuralResource2.getInstance(g);
+ Resource composite = null;
+ if (g.isInstanceOf(diagram, s.Composite)) {
+ composite = diagram;
+ diagram = g.getPossibleObject(composite, m.CompositeToDiagram);
+ if (diagram == null)
+ return null;
+ } else {
+ composite = g.getPossibleObject(diagram, m.DiagramToComposite);
+ if (composite == null)
+ return null;
+ }
+
+ Diagram<T> diag = compositeToDiagramMap.get(composite);
+ if (diag != null)
+ return diag;
+
+ diag = construct(g,composite, diagram);
+ diag.compositeToDiagramMap = compositeToDiagramMap;
+ compositeToDiagramMap.put(composite, diag);
+ return diag;
+ }
+
+
+
+
+
+ /**
+ * Returns diagram type from composite type
+ * @param g
+ * @param compositeType
+ * @return diagram type
+ * @throws NoSingleResultException
+ * @throws ManyObjectsForFunctionalRelationException
+ * @throws ServiceException
+ */
+ private static Resource getDiagramFromComposite(ReadGraph g, Resource compositeType) throws DatabaseException {
+ ModelingResources m = ModelingResources.getInstance(g);
+ Collection<Resource> diagramTemplates = g.getAssertedObjects(compositeType, m.HasModelingTemplate);
+ for (Resource diagramTemplate : diagramTemplates) {
+ Resource diagramType = g.getPossibleObject(diagramTemplate, m.HasDiagramType);
+ if (diagramType != null)
+ return diagramType;
+
+ }
+ throw new RuntimeException("Cannot find diagramType for composite " + compositeType);
+ }
+
+
+
+
+ /**
+ * Adds new symbol to a diagram
+ * @param g
+ * @param symbolType
+ * @return
+ * @throws DatabaseException
+ */
+ public T addSymbol(WriteGraph g, Resource symbolType) throws DatabaseException {
+ return addSymbol(g, symbolType, 0, 0);
+ }
+
+ /**
+ * Adds new symbol to a diagram
+ * @param g
+ * @param symbolType
+ * @param name
+ * @return
+ * @throws DatabaseException
+ */
+ public T addSymbol(WriteGraph g, Resource symbolType, String name) throws DatabaseException {
+ return addSymbol(g, symbolType, name, 0, 0);
+ }
+
+ /**
+ * Adds new symbol to a diagram
+ * @param g
+ * @param diagramConf Diagram configuration
+ * @param symbolType type of the new symbol
+ * @param x
+ * @param y
+ * @return configuration of the new Symbol
+ * @throws DatabaseException
+ */
+ public T addSymbol(WriteGraph g, Resource symbolType, double x, double y) throws DatabaseException {
+ return addSymbol(g, symbolType,null,x,y);
+ }
+
+ /**
+ * Adds new symbol to a diagram
+ * @param g
+ * @param elementType
+ * @param name
+ * @param x
+ * @param y
+ * @return
+ * @throws DatabaseException
+ */
+ public T addSymbol(WriteGraph g, Resource elementType, String name, double x, double y) throws DatabaseException {
+ if (elementType == null)
+ throw new NullPointerException("Element type is null");
+ Layer0 l0 = Layer0.getInstance(g);
+
+ DiagramResource d = DiagramResource.getInstance(g);
+ ModelingResources m = ModelingResources.getInstance(g);
+
+ Resource componentType = null;
+ if (g.isInheritedFrom(elementType, d.DefinedElement))
+ componentType = Symbol.getComponentTypeFromSymbolType(g, elementType);
+ else {
+ componentType = elementType;
+ elementType = Symbol.getSymbolTypeFromComponentType(g,componentType);
+ }
+
+
+ Resource element = g.newResource();
+ g.claim(element, l0.InstanceOf, elementType);
+
+ Resource module = g.newResource();
+ g.claim(module, l0.InstanceOf, componentType);
+
+ g.claim(module, m.ComponentToElement, element);
+ g.claim(module, m.Mapped, module);
+
+ String id = generateName(g, componentType, name);
+ g.claimLiteral(module, l0.HasName, id);
+ g.claimLiteral(element, l0.HasName, id);
+
+ OrderedSetUtils.add(g, this.diagram, element);
+ g.claim(this.diagram, l0.ConsistsOf, element);
+ g.claim(this.composite, l0.ConsistsOf, module);
+
+ T s = constructSymbol(g, element, module);
+ s.setSymbolTranslation(g, x, y);
+
+ elementToSymbolMap.put(element, s);
+ return s;
+ }
+
+ /**
+ * Returns a Symbol for given resource.
+ * @param g
+ * @param element Element or Component of the Symbol.
+ * @return
+ * @throws ManyObjectsForFunctionalRelationException
+ * @throws ServiceException
+ * @throws NoSingleResultException
+ */
+ public T getSymbol(ReadGraph g, Resource element) throws DatabaseException {
+ ModelingResources mr = ModelingResources.getInstance(g);
+ DiagramResource dr = DiagramResource.getInstance(g);
+ if (g.isInstanceOf(element, dr.Element))
+ return getSymbol(g, element, g.getPossibleObject(element, mr.ElementToComponent));
+ else
+ return getSymbol(g, g.getSingleObject(element, mr.ComponentToElement), element);
+ }
+
+ /**
+ * Returns a Symbol for given resource.
+ * @param g
+ * @param element Element Resource of the Symbol.
+ * @param component Component Resource of the symbol.
+ * @return
+ */
+ public T getSymbol(ReadGraph g, Resource element, Resource component) throws DatabaseException {
+ T s = elementToSymbolMap.get(element);
+ if (s == null) {
+ // TODO : check that symbol actually belongs to this diagram
+ s = constructSymbol(g, element, component);
+ elementToSymbolMap.put(element, s);
+ } else {
+ if (s.component == null)
+ s.component = component;
+ else if (!s.component.equals(component)) {
+ // FIXME : ?
+ return constructSymbol(g, element, component);
+ }
+ }
+ return s;
+ }
+
+ /**
+ * Adds new element to a diagram
+ * @param g
+ * @param symbolType type of the element.
+ * @param x
+ * @param y
+ * @return
+ * @throws DatabaseException
+ */
+ public T addElement(WriteGraph g, Resource symbolType, double x, double y) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(g);
+
+ Resource element = g.newResource();
+ g.claim(element, l0.InstanceOf, symbolType);
+
+ DiagramUtils.addElement(g, this, element);
+
+ T s = constructSymbol(g,element,null);
+
+ s.setSymbolTranslation(g, x, y);
+
+ elementToSymbolMap.put(element, s);
+ return s;
+ }
+
+ public T getSingleSymbol(ReadGraph g, String symbolName) throws DatabaseException {
+ List<T> matching = getSymbol(g, symbolName);
+ if (matching.size() == 1)
+ return matching.get(0);
+ if (matching.size() == 0)
+ return null;
+ throw new NoSingleResultException("There are multiple symbols with name '" + symbolName);
+ }
+
+ public T getPossibleSymbol(ReadGraph g, String symbolName) throws DatabaseException {
+ List<T> matching = getSymbol(g, symbolName);
+ if (matching.size() == 1)
+ return matching.get(0);
+ return null;
+ }
+
+ /**
+ * Returns all symbols on the diagram
+ * @param g
+ * @return
+ * @throws DatabaseException
+ */
+ public List<T> getSymbols(ReadGraph g) throws DatabaseException {
+ ModelingResources m = ModelingResources.getInstance(g);
+ List<T> matching = new ArrayList<T>();
+ for (Resource element : OrderedSetUtils.toList(g, diagram)) {
+ Resource component = g.getPossibleObject(element, m.ElementToComponent);
+ matching.add(getSymbol(g,element, component));
+ }
+ return matching;
+ }
+
+ /**
+ * Returns symbols that have matching name.
+ *
+ * Prioritizes L0.HasLabel over L0.HasName (If symbol has label, it is used for comparison).
+ *
+ * ';' character acts as a splitter, allowing input parameter and a label contain multiple identifiers.
+ *
+ * All the splits
+ *
+ * @param g
+ * @param symbolName
+ * @return
+ * @throws DatabaseException
+ */
+ public List<T> getSymbol(ReadGraph g, String symbolName) throws DatabaseException {
+ ModelingResources m = ModelingResources.getInstance(g);
+ Layer0 b = Layer0.getInstance(g);
+ List<T> matching = new ArrayList<T>();
+
+ String splitId[] = symbolName.split(";");
+
+ for (Resource element : OrderedSetUtils.toList(g, diagram)) {
+ Resource component = g.getPossibleObject(element, m.ElementToComponent);
+ if (component == null)
+ component = g.getPossibleObject(element, m.HasParentComponent);
+ if (component == null)
+ continue;
+ String label = g.getPossibleRelatedValue(component, b.HasLabel);
+ String name = g.getRelatedValue(component, b.HasName);
+ if (label != null) {
+ String splitLabel[] = label.split(";");
+
+ boolean match = true;
+ for (int i = 0; i < splitId.length; i++) {
+ if(!Arrays.contains(splitLabel, splitId[i])) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ matching.add(getSymbol(g,element, component));
+ } else {
+ if (label.equals(symbolName) || name.equals(symbolName)) {
+ matching.add(getSymbol(g,element, component));
+
+ }
+ }
+
+ } else {
+ for (String split : splitId) {
+ if (name.equals(split)) {
+ matching.add(getSymbol(g,element, component));
+ }
+ }
+
+ }
+ }
+ return matching;
+ }
+
+ /**
+ * Returns a single symbol matching given name and type. If matching symbol cannot be found, returns null.
+ * Throws a NoSingleResultException if the re are multiple symbols matching the criteria.
+ *
+ * @param g
+ * @param symbolName
+ * @param symbolType
+ * @return
+ * @throws DatabaseException
+ */
+ public T getSingleSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
+ List<T> matching = getSymbol(g, symbolName, symbolType);
+ if (matching.size() == 1)
+ return matching.get(0);
+ if (matching.size() == 0)
+ return null;
+ throw new NoSingleResultException("There are multiple symbols with name '" + symbolName + "' and type " + symbolType);
+ }
+
+ public T getPossibleSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
+ List<T> matching = getSymbol(g, symbolName, symbolType);
+ if (matching.size() == 1)
+ return matching.get(0);
+ return null;
+ }
+
+ /**
+ * Returns symbols matching given name and type.
+ *
+ * @param g
+ * @param symbolName
+ * @param symbolType
+ * @return
+ * @throws DatabaseException
+ */
+ public List<T> getSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
+
+ List<T> nameMatching = getSymbol(g, symbolName);
+ List<T> matching = new ArrayList<T>();
+ for (T s : nameMatching) {
+ if ((g.isInstanceOf(s.getElement(), symbolType)||
+ g.isInstanceOf(s.getComponent(), symbolType))) {
+ matching.add(s);
+ }
+ }
+ return matching;
+ }
+
+ public Symbol getFlag(ReadGraph g, Resource flagType, String symbolName, Resource symbolType) throws DatabaseException {
+ Layer0 b = Layer0.getInstance(g);
+ DiagramResource dr = DiagramResource.getInstance(g);
+ List<Symbol> matching = new ArrayList<Symbol>();
+ for (Resource flag : OrderedSetUtils.toList(g, diagram)) {
+ if (!g.isInstanceOf(flag, dr.Flag))
+ continue;
+ if (!g.getSingleObject(flag, dr.HasFlagType).equals(flagType))
+ continue;
+ Symbol flagSymbol = getSymbol(g,flag, null);
+
+ Symbol connectedSymbol = flagSymbol.getDiagramSingleConnected(g, dr.Flag_ConnectionPoint);
+ Resource component = connectedSymbol.getComponent();
+ if (component == null)
+ continue;
+ String label = g.getPossibleRelatedValue(component, b.HasLabel);
+ String name = g.getRelatedValue(component, b.HasName);
+ if (label != null) {
+ String splitId[] = symbolName.split(";");
+ if (splitId.length > 1) {
+ String splitLabel[] = label.split(";");
+ boolean match = true;
+ for (int i = 0; i < splitId.length; i++) {
+ if(!Arrays.contains(splitLabel, splitId[i])) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
+ g.isInstanceOf(component, symbolType)) {
+ matching.add(getSymbol(g,flag, null));
+ }
+
+ }
+ } else {
+ if (label.equals(symbolName) || name.equals(symbolName)) {
+ if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
+ g.isInstanceOf(component, symbolType)) {
+ matching.add(getSymbol(g,flag, null));
+ }
+
+ }
+ }
+
+ } else {
+ if (name.equals(symbolName)) {
+ if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
+ g.isInstanceOf(component, symbolType)) {
+ matching.add(getSymbol(g,flag, null));
+ }
+ }
+
+ }
+ }
+ if (matching.size() == 1)
+ return matching.get(0);
+ if (matching.size() == 0)
+ return null;
+ throw new NoSingleResultException("There are multiple flags connecting symbol with name '" + symbolName + "' and type " + symbolType);
+
+ }
+
+ public PageDesc getPageDesc(ReadGraph g) throws DatabaseException {
+ PageDesc pDesc = DiagramGraphUtil.getPageDesc(g, diagram, PageDesc.DEFAULT);
+ return pDesc;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (this.getClass() != o.getClass())
+ return false;
+ Diagram other = (Diagram)o;
+ return diagram.equals(other.diagram);
+ }
+
+ @Override
+ public int hashCode() {
+ return diagram.hashCode();
+ }
+
+ void merge(Symbol to, Symbol from) {
+ Resource element = from.getElement();
+ for (Symbol s : elementToSymbolMap.values()) {
+ if (s.element.equals(element)) {
+ s.element = to.element;
+ s.component = to.component;
+ }
+ }
+ from.element = to.element;
+ from.component = to.component;
+ }
+
+ /**
+ * Returns a model containing the diagram.
+ * @param g
+ * @return
+ * @throws DatabaseException
+ */
+ public Resource getModel(ReadGraph g) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(g);
+ SimulationResource sim = SimulationResource.getInstance(g);
+ Resource r = composite;
+ while (true) {
+ Resource parent = g.getSingleObject(r, l0.PartOf);
+ if (g.isInstanceOf(parent, sim.Model))
+ return parent;
+ r = parent;
+ }
+ }
+
+
+
+}
+
--- /dev/null
+package org.simantics.interop.diagram;
+
+import java.awt.geom.AffineTransform;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Statement;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.common.utils.OrderedSetUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
+import org.simantics.db.exception.NoSingleResultException;
+import org.simantics.db.exception.ServiceException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.diagram.stubs.G2DResource;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.structural2.utils.StructuralUtils;
+
+
+
+/**
+ * @author Marko Luukkainen
+ */
+public abstract class Symbol {
+
+ private static boolean USE_UNRELIABLE_CONNECT = false;
+ private static boolean PREVENT_SELF_CONNECTIONS = false;
+
+ private Diagram diagram;
+ Resource element;
+ Resource component;
+
+ /**
+ * Use Diagram.getSymbol() to get Symbols.
+ * @param diagram
+ * @param element
+ * @param component
+ */
+ public Symbol(Diagram diagram, Resource element, Resource component) {
+ assert(diagram != null);
+ assert(element != null);
+ this.diagram = diagram;
+ this.element = element;
+ this.component = component;
+ }
+
+ public Diagram getDiagram() {
+ return diagram;
+ }
+
+ public Resource getComponent() {
+ return component;
+ }
+
+ public Resource getElement() {
+ return element;
+ }
+
+ /**
+ * Connects two Symbols, chooses connection type automatically.
+ * @param g
+ * @param symbolConf2 other symbol.
+ * @param componentConRel1 symbol's terminal relation.
+ * @param componentConRel2 other symbol's terminal relation.
+ * @return SymbolConnetionData instance describing the connection. Return value is never null.
+ * @throws DatabaseException on database failure.
+ */
+ public SymbolConnectionData connect(WriteGraph g, Symbol symbolConf2, Resource componentConRel1, Resource componentConRel2) throws DatabaseException {
+ return connect(g, symbolConf2, componentConRel1, componentConRel2, false);
+ }
+
+ protected Collection<Resource> getConnectionRel(ReadGraph g, Symbol symbolConf2, Resource componentConRel1, Resource componentConRel2, Collection<Resource> matching) throws DatabaseException {
+ return matching;
+ }
+
+ protected SymbolConnectionData customConnect(WriteGraph g, Symbol symbolConf2, Resource componentConRel1, Resource componentConRel2, Resource connType) throws DatabaseException {
+ return null;
+ }
+
+ /**
+ * Connects two Symbols, chooses connection type automatically.
+ * @param g
+ * @param symbolConf2 other symbol.
+ * @param componentConRel1 symbol's terminal relation.
+ * @param componentConRel2 other symbol's terminal relation.
+ * @param forceFlag creates flag connection even if symbols are on the same diagram.
+ * @return SymbolConnetionData instance describing the connection. Return value is never null.
+ * @throws DatabaseException on database failure.
+ */
+ public SymbolConnectionData connect(WriteGraph g, Symbol symbolConf2, Resource componentConRel1, Resource componentConRel2, boolean forceFlag) throws DatabaseException {
+ if (this.equals(symbolConf2)) {
+ if (PREVENT_SELF_CONNECTIONS) {
+ String err = "Preventing connection to self: " + component + " " + NameUtils.getSafeName(g, component) + " terminals: " + g.getPossibleURI(componentConRel1) + " "+ componentConRel1 + " " + g.getPossibleURI(componentConRel2) + " "+ componentConRel2;
+ Logger.defaultLogError(err);
+ return new ConnectionErrorImpl(err);
+ }
+ if (componentConRel1.equals(componentConRel2)) {
+ String err = "Preventing connection to self: " + component + " " + NameUtils.getSafeName(g, component) + " terminals: " + g.getPossibleURI(componentConRel1) + " "+ componentConRel1 + " " + g.getPossibleURI(componentConRel2) + " "+ componentConRel2;
+ Logger.defaultLogError(err);
+ return new ConnectionErrorImpl(err);
+ }
+ }
+ StructuralResource2 sr = StructuralResource2.getInstance(g);
+ Collection<Resource> connType1 = g.getObjects(componentConRel1, sr.AllowsConnectionType);
+ Collection<Resource> connType2 = g.getObjects(componentConRel2, sr.AllowsConnectionType);
+ Collection<Resource> matching = new HashSet<Resource>();
+ for (Resource r : connType2) {
+ if (connType1.contains(r))
+ matching.add(r);
+ }
+ if (matching.size() > 1) {
+ matching = getConnectionRel(g, symbolConf2, componentConRel1, componentConRel2, matching);
+ }
+ Resource usedConnType = null;
+ if (matching.size() != 1) {
+ String err;
+ if (USE_UNRELIABLE_CONNECT) {
+ err = "Unreliable connect " + component + " " + NameUtils.getSafeName(g, component) + " to " + symbolConf2.component + " " + NameUtils.getSafeName(g, symbolConf2.component) + " cannot find proper connection type, using Name Reference";
+ } else {
+ err = "Unable to connect " + component + " " + NameUtils.getSafeName(g, component) + " to " + symbolConf2.component + " " + NameUtils.getSafeName(g, symbolConf2.component) + " cannot find proper connection type for terminals " + g.getPossibleURI(componentConRel1) + " "+ componentConRel1 + " " + g.getPossibleURI(componentConRel2) + " "+ componentConRel2;
+ }
+ Logger.defaultLogInfo(err);
+ return new ConnectionErrorImpl(err);
+ } else {
+ usedConnType = matching.iterator().next();
+ }
+
+ SymbolConnectionData data = customConnect(g, symbolConf2, componentConRel1, componentConRel2, usedConnType);
+ if (data == null) {
+ if (!forceFlag && diagram.equals(symbolConf2.diagram))
+ return _connect(g, symbolConf2, componentConRel1, componentConRel2,usedConnType);
+ else
+ return connectWithFlag(g, symbolConf2, componentConRel1, componentConRel2,usedConnType);
+ } else {
+ return data;
+ }
+ }
+
+ /**
+ * Connects two symbols with chosen connection type. Does not work with signal connections.
+ * @param g
+ * @param symbolConf2 other symbol.
+ * @param componentConRel1 symbol's terminal relation.
+ * @param componentConRel2 other symbol's terminal relation.
+ * @param connectionType used connection type.
+ * @return SymbolConnetionData instance describing the connection. Return value is never null.
+ * @throws DatabaseException on database failure.
+ */
+ public SymbolConnectionData connect(WriteGraph g, Symbol symbolConf2, Resource componentConRel1, Resource componentConRel2, Resource connectionType) throws DatabaseException {
+ if (diagram.equals(symbolConf2.diagram))
+ return _connect(g, symbolConf2, componentConRel1, componentConRel2, connectionType);
+ else
+ return connectWithFlag(g, symbolConf2, componentConRel1, componentConRel2, connectionType);
+ }
+
+ protected SymbolConnectionData connectToExisting(WriteGraph g, Symbol symbolConf2, Symbol current, Resource componentConRel1, Resource componentConRel2, Resource connectorType, boolean firstSame) throws DatabaseException {
+ return new ConnectionErrorImpl("Symbol is already connected");
+ }
+
+ private SymbolConnectionData _connect(WriteGraph g, Symbol symbolConf2, Resource componentConRel1, Resource componentConRel2, Resource connectorType) throws DatabaseException {
+ Layer0 b = Layer0.getInstance(g);
+ StructuralResource2 s = StructuralResource2.getInstance(g);
+ DiagramResource d = DiagramResource.getInstance(g);
+ ModelingResources m = ModelingResources.getInstance(g);
+
+
+ if (g.isInstanceOf(componentConRel1, b.FunctionalRelation) && getSingleConnected(g, componentConRel1) != null) {
+ Symbol current = getSingleConnected(g, componentConRel1);
+ if (current.component.equals(symbolConf2.component))
+ return new SymbolExistsImpl();
+
+ return connectToExisting(g, symbolConf2, current, componentConRel1, componentConRel2, connectorType, true);
+ }
+ if (g.isInstanceOf(componentConRel2, b.FunctionalRelation) && symbolConf2.getSingleConnected(g, componentConRel2) != null) {
+ Symbol current = symbolConf2.getSingleConnected(g, componentConRel2);
+ if (current.component.equals(component))
+ return new SymbolExistsImpl();
+ return connectToExisting(g, symbolConf2, current, componentConRel1, componentConRel2, connectorType, false);
+
+ }
+
+ // connection object in module level
+ Resource moduleConnection = g.newResource();
+ g.claim(moduleConnection, b.InstanceOf, s.Connection);
+
+ // connect the modules
+
+ g.claim(component, componentConRel1, moduleConnection);
+ g.claim(symbolConf2.component, componentConRel2, moduleConnection);
+
+ // connection object in diagram level
+ Resource diagramConnection = g.newResource();
+ g.claim(diagramConnection, b.InstanceOf, d.RouteGraphConnection);
+ DiagramUtils.addElementFirst(g, diagram, diagramConnection);
+
+ g.claim(diagramConnection, s.HasConnectionType, connectorType);
+
+ // Relation from element1 to connector1
+ Resource isConnected1 = getDiagramConnectionRelation(g, element, componentConRel1);
+
+ // connector1
+ Resource connector1 = g.newResource();
+ g.claim(connector1, b.InstanceOf, d.Connector);
+ g.claim(element, isConnected1, connector1);
+ g.claim(diagramConnection, d.HasPlainConnector, connector1);
+
+ // Relation from element2 to connector2
+ Resource isConnected2 = getDiagramConnectionRelation(g, symbolConf2.element, componentConRel2);
+
+ // connector2
+ Resource connector2 = g.newResource();
+ g.claim(connector2, b.InstanceOf, d.Connector);
+ g.claim(symbolConf2.element, isConnected2, connector2);
+ g.claim(diagramConnection, d.HasArrowConnector, connector2);
+
+ // connect connectors
+ g.claim(connector1, d.AreConnected, connector2);
+
+ g.claim(moduleConnection, m.ConnectionToDiagramConnection, diagramConnection);
+
+ return new ConnectorDataImpl(diagramConnection);
+ }
+
+
+ private SymbolConnectionData connectWithFlag(WriteGraph g, Symbol symbolConf2, Resource componentConRel1, Resource componentConRel2, Resource connectionType) throws DatabaseException {
+
+ Diagram diagram2 = symbolConf2.diagram;
+ Layer0 l0 = Layer0.getInstance(g);
+ StructuralResource2 s = StructuralResource2.getInstance(g);
+ DiagramResource d = DiagramResource.getInstance(g);
+ ModelingResources m = ModelingResources.getInstance(g);
+
+ if (g.isInstanceOf(componentConRel1, l0.FunctionalRelation) && getSingleConnected(g, componentConRel1) != null) {
+ String err = "Cannot flag connect " + component + " " + NameUtils.getSafeName(g, component) + " to " + symbolConf2.component + " " + NameUtils.getSafeName(g, symbolConf2.component) + " since the first terminal is already reserved";
+ Logger.defaultLogError(err);
+ return new ConnectionErrorImpl(err);
+ }
+ if (g.isInstanceOf(componentConRel2, l0.FunctionalRelation) && symbolConf2.getSingleConnected(g, componentConRel2) != null) {
+ String err = "Cannot flag connect " + component + " " + NameUtils.getSafeName(g, component) + " to " + symbolConf2.component + " " + NameUtils.getSafeName(g, symbolConf2.component) + " since the second terminal is already reserved";
+ Logger.defaultLogError(err);
+ return new ConnectionErrorImpl(err);
+ }
+
+ double t = 20.0;
+ double[] t1 = getSymbolTranslation(g);
+ double[] t2 = symbolConf2.getSymbolTranslation(g);
+
+ Symbol flag1 = diagram.addElement(g, d.Flag, t1[0]+t, t1[1]);
+ Symbol flag2 = diagram2.addElement(g, d.Flag, t2[0]-t, t2[1]);
+
+ Resource connectionJoin = g.newResource();
+ g.claim(connectionJoin, l0.InstanceOf, s.ConnectionJoin);
+ g.claim(diagram.getComposite(), s.HasConnectionJoin, connectionJoin);
+ g.claim(diagram2.getComposite(), s.HasConnectionJoin, connectionJoin);
+
+ Resource connection1 = g.newResource();
+ g.claim(connection1, l0.InstanceOf, s.Connection);
+
+ Resource connection2 = g.newResource();
+ g.claim(connection2, l0.InstanceOf, s.Connection);
+
+ g.claim(component, componentConRel1, connection1);
+ g.claim(symbolConf2.component, componentConRel2, connection2);
+ g.claim(connection1, s.IsJoinedBy, connectionJoin);
+ g.claim(connection2, s.IsJoinedBy, connectionJoin);
+
+ g.claim(flag1.element, d.FlagIsJoinedBy, connectionJoin);
+ g.claim(flag2.element, d.FlagIsJoinedBy, connectionJoin);
+
+ Resource diagConnection1 = g.newResource();
+ g.claim(diagConnection1, l0.InstanceOf, d.RouteGraphConnection);
+ DiagramUtils.addElementFirst(g, diagram, diagConnection1);
+ g.claim(diagConnection1, s.HasConnectionType, connectionType);
+
+ Resource diagConnection2 = g.newResource();
+ g.claim(diagConnection2, l0.InstanceOf, d.RouteGraphConnection);
+ DiagramUtils.addElementFirst(g, diagram2, diagConnection2);
+ g.claim(diagConnection2, s.HasConnectionType, connectionType);
+
+ g.claim(connection1, m.ConnectionToDiagramConnection, diagConnection1);
+ g.claim(connection2, m.ConnectionToDiagramConnection, diagConnection2);
+
+ // Relation from element1 to connector1
+ Resource isConnected1 = getDiagramConnectionRelation(g, element, componentConRel1);
+
+ // connector1
+ Resource connector1_1 = g.newResource();
+ g.claim(connector1_1, l0.InstanceOf, d.Connector);
+ g.claim(element, isConnected1, connector1_1);
+ g.claim(diagConnection1, d.HasPlainConnector, connector1_1);
+
+ Resource connector1_2 = g.newResource();
+ g.claim(connector1_2, l0.InstanceOf, d.Connector);
+ g.claim(flag1.element, d.Flag_ConnectionPoint, connector1_2);
+ g.claim(diagConnection1, d.HasArrowConnector, connector1_2);
+
+ g.claim(connector1_1, d.AreConnected, connector1_2);
+
+ // Relation from element2 to connector2
+ Resource isConnected2 = getDiagramConnectionRelation(g, symbolConf2.element, componentConRel2);
+
+ // connector1
+ Resource connector2_1 = g.newResource();
+ g.claim(connector2_1, l0.InstanceOf, d.Connector);
+ g.claim(flag2.element, d.Flag_ConnectionPoint, connector2_1);
+ g.claim(diagConnection2, d.HasPlainConnector, connector2_1);
+
+ Resource connector2_2 = g.newResource();
+ g.claim(connector2_2, l0.InstanceOf, d.Connector);
+ g.claim(symbolConf2.element, isConnected2, connector2_2);
+ g.claim(diagConnection2, d.HasArrowConnector, connector2_2);
+
+ g.claim(connector2_1, d.AreConnected, connector2_2);
+
+ return new FlagConnectionDataImpl(flag1, flag2, diagConnection1, diagConnection2);
+ }
+
+ /**
+ * Returns diagram connection relation for an element and its component connection relation
+ * @param g
+ * @param element
+ * @param componentConnRel
+ * @return
+ * @throws ServiceException
+ * @throws NoSingleResultException
+ * @throws ValidationException
+ */
+ public static Resource getDiagramConnectionRelation(ReadGraph g, Resource element, Resource componentConnRel) throws DatabaseException {
+ ModelingResources m = ModelingResources.getInstance(g);
+ Collection<Resource> diagramConnectionRels = g.getObjects(componentConnRel, m.ConnectionRelationToDiagramConnectionRelation);
+ if (diagramConnectionRels.size() == 1)
+ return diagramConnectionRels.iterator().next();
+ if (diagramConnectionRels.size() > 1) {
+ List<Resource> matching = new ArrayList<Resource>();
+ for (Resource r : diagramConnectionRels) {
+ if (g.hasStatement(element, r))
+ matching.add(r);
+ }
+ if (matching.size() == 1)
+ return matching.get(0);
+ }
+ Layer0 b = Layer0.getInstance(g);
+ Collection<Resource> elementTypes = g.getObjects(element, b.InstanceOf);
+ if (elementTypes.size() != 1)
+ throw new RuntimeException("Cannot handle multi-instances " + element + " " + NameUtils.getSafeName(g, element));
+ Resource elementType = elementTypes.iterator().next();
+ Collection<Resource> rels = StructuralUtils.getConnectionRelations(g, elementType);
+ if (rels.size() == 1)
+ return rels.iterator().next();
+ for (Resource rel : rels) {
+ if (diagramConnectionRels.contains(rel))
+ return rel;
+ }
+ throw new RuntimeException("Cannot find diagram level relation for relation " + NameUtils.getSafeName(g, componentConnRel) + " " + componentConnRel + " , element " + NameUtils.getSafeName(g, element) + " " + element + " , elementType " + NameUtils.getSafeName(g, elementType) + " " + elementType );
+ }
+
+ public static Resource getComponentConnectionRelation(ReadGraph g, Resource diagraromConnRel) throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
+ ModelingResources mr = ModelingResources.getInstance(g);
+ return g.getSingleObject(diagraromConnRel, mr.DiagramConnectionRelationToConnectionRelation);
+ }
+
+// public static Resource getSymbolRelation(ReadGraph g, Symbol conf, Resource genericRel) throws DatabaseException {
+// Layer0 b = Layer0.getInstance(g);
+// if (g.isInstanceOf(conf.element, ab.CalculationLevelReferenceElement)) {
+// ModelingResources m = ModelingResources.getInstance(g);
+// //return g.getInverse(g.getSingleObject(conf.element, m.HasReferenceRelation));
+// return g.getSingleObject(conf.element, m.HasReferenceRelation);
+// }
+//
+// Resource compType = g.getSingleObject(conf.getComponent(), b.InstanceOf);
+//
+// for (Resource rel : StructuralUtils.getConnectionRelations(g, compType))
+// if (g.isSubrelationOf(rel, genericRel))
+// return rel;
+// return null;
+// }
+
+ /**
+ * Returns symbol where given symbol is connected using given relation. Returns null if the symbol is not connected using the relation.
+ * @param g
+ * @param componentConRel
+ * @return
+ * @throws DatabaseException
+ */
+ public Symbol getSingleConnected(ReadGraph g, Resource componentConRel) throws DatabaseException {
+ Collection<Symbol> symbols = getConnected(g, componentConRel);
+ if (symbols.size() > 1)
+ throw new NoSingleResultException("Symbol " + component + " is connected more than once using relation " + componentConRel);
+ if (symbols.size() == 1)
+ return symbols.iterator().next();
+ return null;
+ }
+
+ public Symbol getSingleConnected(ReadGraph g, Resource componentConRel, Resource otherComponentConRel) throws DatabaseException {
+ Collection<Symbol> symbols = getConnected(g, componentConRel, otherComponentConRel);
+ if (symbols.size() > 1)
+ throw new NoSingleResultException("Symbol " + component + " is connected more than once using relation " + componentConRel);
+ if (symbols.size() == 1)
+ return symbols.iterator().next();
+ return null;
+ }
+
+ public Collection<Symbol> getConnected(ReadGraph g, Resource componentConRel, Resource otherComponentConRel) throws DatabaseException {
+ assert(componentConRel != null);
+ Layer0 l0 = Layer0.getInstance(g);
+ StructuralResource2 sr = StructuralResource2.getInstance(g);
+ ModelingResources mr = ModelingResources.getInstance(g);
+ Collection<Symbol> result = new ArrayList<Symbol>();
+ Collection<Resource> modConn1s = g.getObjects(this.component, componentConRel);
+ for (Resource modConn1 : modConn1s) {
+
+ Collection<Statement> connected = g.getStatements(modConn1, sr.Connects);
+ Collection<Resource> connectionJoins = g.getObjects(modConn1, sr.IsJoinedBy);
+ Collection<Resource> connectedComponents = new ArrayList<Resource>();
+
+ for (Statement stm : connected) {
+ if (!stm.getObject().equals(this.component)) {
+ if (g.getInverse(stm.getPredicate()).equals(otherComponentConRel)) {
+ connectedComponents.add(stm.getObject());
+ }
+ }
+ }
+
+ for (Resource connectionJoin : connectionJoins) {
+ Collection<Resource> joinedConns = g.getObjects(connectionJoin, sr.Joins);
+ for (Resource conn : joinedConns) {
+ if (!conn.equals(modConn1)) {
+ // TODO : check ConnectionJoins?
+ for (Statement stm : g.getStatements(conn, sr.Connects)) {
+ if (g.getInverse(stm.getPredicate()).equals(otherComponentConRel))
+ connectedComponents.add(stm.getObject());
+ }
+ }
+ }
+ }
+ for (Resource connectedComponent : connectedComponents) {
+
+ Resource pointElem = g.getSingleObject(connectedComponent, mr.ComponentToElement);
+
+ Diagram diag = diagram.fromExisting(g, g.getSingleObject(connectedComponent, l0.PartOf));
+ result.add(diag.getSymbol(g, pointElem,connectedComponent));
+ }
+
+ }
+ return result;
+ }
+
+ public Collection<Symbol> getConnected(ReadGraph g, Resource componentConRel) throws DatabaseException {
+ assert(componentConRel != null);
+ Layer0 l0 = Layer0.getInstance(g);
+ StructuralResource2 sr = StructuralResource2.getInstance(g);
+ ModelingResources mr = ModelingResources.getInstance(g);
+
+ Collection<Resource> modConn1s = g.getObjects(this.component, componentConRel);
+ Collection<Symbol> result = new ArrayList<Symbol>();
+ for (Resource modConn1 : modConn1s) {
+
+ Collection<Resource> connected = g.getObjects(modConn1, sr.Connects);
+ Collection<Resource> connectionJoins = g.getObjects(modConn1, sr.IsJoinedBy);
+ Collection<Resource> connectedComponents = new ArrayList<Resource>();
+
+ for (Resource r : connected) {
+ if (!r.equals(this.component)) {
+ connectedComponents.add(r);
+ }
+ }
+ for (Resource connectionJoin : connectionJoins) {
+ Collection<Resource> joinedConns = g.getObjects(connectionJoin, sr.Joins);
+ for (Resource conn : joinedConns) {
+ if (!conn.equals(modConn1)) {
+ // TODO : check ConnectionJoins?
+ for (Resource obj : g.getObjects(conn, sr.Connects))
+ connectedComponents.add(obj);
+ }
+ }
+ }
+ for (Resource connectedComponent : connectedComponents) {
+
+ Resource pointElem = g.getSingleObject(connectedComponent, mr.ComponentToElement);
+
+ Diagram diag = diagram.fromExisting(g, g.getSingleObject(connectedComponent, l0.PartOf));
+ result.add(diag.getSymbol(g, pointElem,connectedComponent));
+ }
+ }
+ return result;
+
+ }
+
+ /**
+ * Returns connected symbols on diagram level. Searches through branchpoints.
+ * @param g
+ * @param diagramConnRel
+ * @param otherConnRel
+ * @return
+ * @throws DatabaseException
+ */
+ public Collection<Symbol> getDiagramConnected(ReadGraph g, Resource diagramConnRel, Resource otherConnRel) throws DatabaseException {
+ DiagramResource dr = DiagramResource.getInstance(g);
+ Collection<Resource> connectors = g.getObjects(element, diagramConnRel);
+ Collection<Symbol> result = new ArrayList<Symbol>();
+ for (Resource connector : connectors) {
+ Resource otherConnector = g.getSingleObject(connector, dr.AreConnected);
+ if (g.isInstanceOf(otherConnector, dr.Connector)) {
+ getConnectorConnectors(g, otherConnector, otherConnRel, result);
+ } else if (g.isInstanceOf(otherConnector, dr.RouteLine)) {
+ getBranchPointConnectors(g, connector, otherConnector, otherConnRel, result);
+ } else {
+ throw new DatabaseException("Connector " + g.getPossibleURI(otherConnector) + " " + otherConnector + " han unknown type");
+ }
+ }
+ return result;
+ }
+
+ private void getConnectorConnectors(ReadGraph g, Resource connector, Resource otherConnRel, Collection<Symbol> result) throws DatabaseException{
+ StructuralResource2 sr = StructuralResource2.getInstance(g);
+ DiagramResource dr = DiagramResource.getInstance(g);
+ Collection<Statement> stms = g.getStatements(connector, sr.Connects);
+ Statement stm = null;
+ for (Statement s : stms) {
+ if (!g.isInstanceOf(s.getObject(), dr.Connection)) {
+ stm = s;
+ }
+ }
+ if (stm == null)
+ return;
+ if (otherConnRel != null) {
+ Resource rel = g.getInverse(stm.getPredicate());
+ if (!rel.equals(otherConnRel))
+ return;
+ }
+ Resource element = stm.getObject();
+ result.add(diagram.getSymbol(g, element));
+ }
+
+ private void getBranchPointConnectors(ReadGraph g, Resource origin, Resource branchPoint, Resource otherConnRel, Collection<Symbol> result) throws DatabaseException {
+ DiagramResource dr = DiagramResource.getInstance(g);
+
+ Collection<Resource> branchConnected = g.getObjects(branchPoint, dr.AreConnected);
+ for (Resource branchConnector : branchConnected) {
+ if (branchConnector.equals(origin))
+ continue;
+ if (g.isInstanceOf(branchConnector, dr.Connector)) {
+ getConnectorConnectors(g, branchConnector, otherConnRel, result);
+ } else if (g.isInstanceOf(branchConnector, dr.RouteLine)) {
+ getBranchPointConnectors(g, branchPoint, branchConnector, otherConnRel, result);
+ } else {
+ throw new DatabaseException("Connector " + g.getPossibleURI(branchConnector) + " " + branchConnector + " han unknown type");
+ }
+ }
+ }
+
+ public Collection<Symbol> getDiagramConnected(ReadGraph g, Resource diagramConnRel) throws DatabaseException {
+ return getDiagramConnected(g, diagramConnRel,null);
+ }
+
+ public Collection<Symbol> getDiagramInverseConnected(ReadGraph g, Resource otherConnRel) throws DatabaseException {
+ StructuralResource2 sr = StructuralResource2.getInstance(g);
+ return getDiagramConnected(g, sr.IsConnectedTo, otherConnRel);
+
+ }
+
+ public Collection<Symbol> getDiagramConnected(ReadGraph g) throws DatabaseException {
+ StructuralResource2 sr = StructuralResource2.getInstance(g);
+ return getDiagramConnected(g, sr.IsConnectedTo, null);
+ }
+
+ public Symbol getDiagramSingleConnected(ReadGraph g, Resource diagramConnRel) throws DatabaseException {
+ Collection<Symbol> symbols = getDiagramConnected(g, diagramConnRel);
+ if (symbols.size() > 1) {
+ throw new NoSingleResultException("Symbol " + element + " has more than one connection with " + diagramConnRel);
+ } else if (symbols.size() == 1) {
+ return symbols.iterator().next();
+ }
+ return null;
+ }
+
+ public Symbol getOtherFlag(ReadGraph g) throws DatabaseException {
+ DiagramResource dr = DiagramResource.getInstance(g);
+ Resource connectionJoin = g.getPossibleObject(element, dr.FlagIsJoinedBy);
+ if (connectionJoin == null)
+ return null;
+ Collection<Resource> flags = g.getObjects(connectionJoin, dr.JoinsFlag);
+ Resource otherFlag = null;
+ for (Resource f : flags) {
+ if (!f.equals(element)) {
+ otherFlag = f;
+ break;
+ }
+ }
+
+ if (otherFlag == null) {
+ return null;
+ }
+ Resource otherDiagramR = OrderedSetUtils.getSingleOwnerList(g, otherFlag);
+ Diagram otherDiagram = diagram.fromExisting(g, otherDiagramR);
+ return otherDiagram.getSymbol(g, otherFlag, null);
+
+ }
+
+ /**
+ * Returns concatenated translation of the symbol.
+ * @param g
+ * @return
+ * @throws DatabaseException
+ */
+ public double[] getSymbolTranslation(ReadGraph g) throws DatabaseException {
+ DiagramResource d = DiagramResource.getInstance(g);
+ ModelingResources mr = ModelingResources.getInstance(g);
+
+ Resource e = element;
+ AffineTransform at = new AffineTransform();
+ while (e != null) {
+ double transform[] = g.getPossibleRelatedValue(e, d.HasTransform);
+ if (transform == null)
+ break;
+ AffineTransform at2 = new AffineTransform(transform);
+ at.preConcatenate(at2);
+ Resource component = g.getPossibleObject(e, mr.HasParentComponent);
+ if (component != null) {
+ e = g.getPossibleObject(component, mr.ComponentToElement);
+ } else {
+ e = null;
+ }
+ }
+
+ return new double[]{at.getTranslateX(),at.getTranslateY()};
+ }
+
+ /**
+ * Returns transformation of the symbol.
+ * @param g
+ * @return
+ * @throws DatabaseException
+ */
+ public double[] getSymbolTransformation(ReadGraph g) throws DatabaseException{
+ DiagramResource d = DiagramResource.getInstance(g);
+ double transform[] = g.getPossibleRelatedValue(element, d.HasTransform);
+ return transform;
+ }
+
+ /**
+ * Sets translation of symbol. The scale is set to 1.0.
+ * @param g
+ * @param x
+ * @param y
+ * @throws DatabaseException
+ */
+ public void setSymbolTranslation(WriteGraph g, double x, double y) throws DatabaseException {
+ DiagramResource d = DiagramResource.getInstance(g);
+ G2DResource g2d = G2DResource.getInstance(g);
+ g.claimLiteral(element, d.HasTransform, g2d.Transform, new double[]{1.0,0.0,0.0,1.0,x,y});
+ }
+
+ public void setSymbolTransformation(WriteGraph g, AffineTransform at) throws DatabaseException {
+ DiagramResource d = DiagramResource.getInstance(g);
+ G2DResource g2d = G2DResource.getInstance(g);
+ double arr[] = new double[6];
+ at.getMatrix(arr);
+ g.claimLiteral(element, d.HasTransform, g2d.Transform, arr);
+ }
+
+ /**
+ * Set the scale of symbol.
+ * @param g
+ * @param scale
+ * @throws DatabaseException
+ */
+ public void setScale(WriteGraph g, double scale) throws DatabaseException {
+ DiagramResource d = DiagramResource.getInstance(g);
+ double transform[] = g.getPossibleRelatedValue(element, d.HasTransform);
+ g.claimLiteral(element, d.HasTransform, new double[]{scale,0.0,0.0,scale,transform[4],transform[5]});
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (this.getClass() != o.getClass())
+ return false;
+ Symbol other = (Symbol)o;
+ return element.equals(other.element);
+ }
+
+ @Override
+ public int hashCode() {
+ return element.hashCode();
+ }
+
+
+
+ /**
+ * Returns component type from symbol type
+ * @param g
+ * @param symbolType
+ * @return
+ * @throws NoSingleResultException
+ * @throws ManyObjectsForFunctionalRelationException
+ * @throws ServiceException
+ */
+ public static Resource getComponentTypeFromSymbolType(ReadGraph g, Resource symbolType) throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
+ ModelingResources m = ModelingResources.getInstance(g);
+ Resource component = g.getPossibleObject(symbolType, m.SymbolToComponentType);
+ return component;
+ }
+
+ public static Resource getSymbolTypeFromComponentType(ReadGraph g, Resource componentType) throws NoSingleResultException, ServiceException, ManyObjectsForFunctionalRelationException {
+ ModelingResources m = ModelingResources.getInstance(g);
+ Collection<Resource> symbols = g.getObjects(componentType, m.ComponentTypeToSymbol);
+ if (symbols.size() == 0)
+ return null;
+ return symbols.iterator().next();
+ }
+
+ public void dispose() {
+ diagram = null;
+ component = null;
+ element = null;
+ }
+
+ /**
+ * Common interface for Symbol.connect return value.
+ *
+ */
+ public interface SymbolConnectionData {
+
+ }
+
+ /**
+ * Interface for returning diagram level connectors.
+ *
+ */
+ public interface DiagramConnectionData extends SymbolConnectionData {
+ public int getConnectionCount();
+ public Resource getConnection(int index);
+ }
+
+ /**
+ * Interface for flag connections.
+ *
+ */
+ public interface FlagConnectionData extends SymbolConnectionData {
+ public Symbol getFirstFlag();
+ public Symbol getSecondFlag();
+ }
+
+
+ /**
+ * Interface for signal connections.
+ *
+ */
+ public interface SignalConnectionData extends SymbolConnectionData {
+ public Resource getSignalComponent();
+ }
+
+ /**
+ * Interface for Point connections.
+ *
+ */
+ public interface PointConnectionData extends SymbolConnectionData {
+ Symbol getPoint();
+ }
+
+ /**
+ * Interface for "connection" that merged the connected symbols into one symbol.
+ *
+ */
+ public interface MergeSymbolData extends SymbolConnectionData {
+ Symbol getResultSymbol();
+ }
+
+ /**
+ * Return value for a connection that already exists.
+ *
+ */
+ public interface SymbolExists extends SymbolConnectionData {
+
+ }
+
+ /**
+ * Return value for an error.
+ *
+ */
+ public interface ConnectionError extends SymbolConnectionData {
+ String getReason();
+ }
+
+ private static class ConnectionErrorImpl implements ConnectionError {
+ private String error;
+
+ public ConnectionErrorImpl(String error) {
+ this.error = error;
+ }
+
+ @Override
+ public String getReason() {
+ return error;
+ }
+ }
+
+ private static class SymbolExistsImpl implements SymbolExists {
+
+ }
+
+ private static class ConnectorDataImpl implements DiagramConnectionData {
+
+ private Resource[] connectors;
+
+ public ConnectorDataImpl(Resource... connectors) {
+ this.connectors = connectors;
+ }
+
+ @Override
+ public Resource getConnection(int index) {
+ return connectors[index];
+ }
+
+ @Override
+ public int getConnectionCount() {
+ return connectors.length;
+ }
+ }
+
+ private static class PointConnectionDataImpl implements PointConnectionData {
+
+ private Symbol point;
+
+ public PointConnectionDataImpl(Symbol point) {
+ this.point = point;
+ }
+
+ @Override
+ public Symbol getPoint() {
+ return point;
+ }
+ }
+
+ private static class SignalConnectionDataImpl implements SignalConnectionData, DiagramConnectionData{
+
+ private Resource signalComponent;
+ private Resource[] connectors;
+
+ public SignalConnectionDataImpl(Resource signalComponent, Resource... connectors) {
+ this.signalComponent = signalComponent;
+ this.connectors = connectors;
+ }
+
+ @Override
+ public Resource getSignalComponent() {
+ return signalComponent;
+ }
+
+ @Override
+ public Resource getConnection(int index) {
+ return connectors[index];
+ }
+
+ @Override
+ public int getConnectionCount() {
+ return connectors.length;
+ }
+
+ }
+
+ private static class FlagConnectionDataImpl implements FlagConnectionData, DiagramConnectionData {
+
+ private Symbol firstFlag;
+ private Symbol secondFlag;
+ private Resource[] connectors;
+
+ public FlagConnectionDataImpl(Symbol firstFlag, Symbol secondFlag, Resource... connectors) {
+ this.firstFlag = firstFlag;
+ this.secondFlag = secondFlag;
+ this.connectors = connectors;
+ }
+
+ @Override
+ public Symbol getFirstFlag() {
+ return firstFlag;
+ }
+
+ @Override
+ public Symbol getSecondFlag() {
+ return secondFlag;
+ }
+
+ @Override
+ public Resource getConnection(int index) {
+ return connectors[index];
+ }
+
+ @Override
+ public int getConnectionCount() {
+ return connectors.length;
+ }
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, double value) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, float value) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, boolean value) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, int value) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, String value) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, double value[]) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, float value[]) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, int value[]) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setComponentValue(WriteGraph graph, Resource property, boolean value[]) throws DatabaseException{
+ setValue(graph, component, property, value);
+ }
+
+ public void setElementValue(WriteGraph graph, Resource property, double value) throws DatabaseException{
+ setValue(graph, element, property, value);
+ }
+
+ public void setElementValue(WriteGraph graph, Resource property, float value) throws DatabaseException{
+ setValue(graph, element, property, value);
+ }
+
+ public void setElementValue(WriteGraph graph, Resource property, boolean value) throws DatabaseException{
+ setValue(graph, element, property, value);
+ }
+
+ public void setElementValue(WriteGraph graph, Resource property, int value) throws DatabaseException{
+ setValue(graph, element, property, value);
+ }
+
+ public void setElementValue(WriteGraph graph, Resource property, double value[]) throws DatabaseException{
+ setValue(graph, element, property, value);
+ }
+
+ public void setElementValue(WriteGraph graph, Resource property, float value[]) throws DatabaseException{
+ setValue(graph, element, property, value);
+ }
+
+ public void setElementValue(WriteGraph graph, Resource property, int value[]) throws DatabaseException{
+ setValue(graph, element, property, value);
+ }
+
+ public void setElementValue(WriteGraph graph, Resource property, boolean value[]) throws DatabaseException{
+ setValue(graph, element, property, value);
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * Note: This method support only some basic L0 data types.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, double value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (l0.Double.equals(range)) {
+ graph.claimLiteral(object, property, value, Bindings.DOUBLE);
+ } else if (l0.Float.equals(range)) {
+ graph.claimLiteral(object, property, (float)value, Bindings.FLOAT);
+ } else if (l0.Integer.equals(range)) {
+ graph.claimLiteral(object, property, (int)value, Bindings.INTEGER);
+ } else if (l0.Long.equals(range)) {
+ graph.claimLiteral(object, property, (long)value, Bindings.LONG);
+ } else if (l0.Boolean.equals(range)) {
+ graph.claimLiteral(object, property, value > 0.0, Bindings.BOOLEAN);
+ } else if (l0.String.equals(range)) {
+ graph.claimLiteral(object, property, Double.toString(value), Bindings.STRING);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.DOUBLE);
+ }
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * Note: This method support only some basic L0 data types.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, float value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (l0.Double.equals(range)) {
+ graph.claimLiteral(object, property, (double)value, Bindings.DOUBLE);
+ } else if (l0.Float.equals(range)) {
+ graph.claimLiteral(object, property, value, Bindings.FLOAT);
+ } else if (l0.Integer.equals(range)) {
+ graph.claimLiteral(object, property, (int)value, Bindings.INTEGER);
+ } else if (l0.Long.equals(range)) {
+ graph.claimLiteral(object, property, (long)value, Bindings.LONG);
+ } else if (l0.Boolean.equals(range)) {
+ graph.claimLiteral(object, property, value > 0.f, Bindings.BOOLEAN);
+ } else if (l0.String.equals(range)) {
+ graph.claimLiteral(object, property, Float.toString(value), Bindings.STRING);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.FLOAT);
+ }
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * Note: This method support only some basic L0 data types.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, int value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (l0.Double.equals(range)) {
+ graph.claimLiteral(object, property, (double)value, Bindings.DOUBLE);
+ } else if (l0.Float.equals(range)) {
+ graph.claimLiteral(object, property, (float) value, Bindings.FLOAT);
+ } else if (l0.Integer.equals(range)) {
+ graph.claimLiteral(object, property, (int)value, Bindings.INTEGER);
+ } else if (l0.Long.equals(range)) {
+ graph.claimLiteral(object, property, (long)value, Bindings.LONG);
+ } else if (l0.Boolean.equals(range)) {
+ graph.claimLiteral(object, property, value > 0, Bindings.BOOLEAN);
+ } else if (l0.String.equals(range)) {
+ graph.claimLiteral(object, property, Integer.toString(value), Bindings.STRING);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.INTEGER);
+ }
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, String value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (range == null) {
+ graph.claimLiteral(object, property, value, Bindings.STRING);
+ } else {
+ if (graph.isInheritedFrom(range, l0.String)) {
+ graph.claimLiteral(object, property, value, Bindings.STRING);
+ } else if (graph.isInheritedFrom(range, l0.Double)) {
+ graph.claimLiteral(object, property, Double.parseDouble(value), Bindings.DOUBLE);
+ } else if (graph.isInheritedFrom(range, l0.Float)) {
+ graph.claimLiteral(object, property, Float.parseFloat(value), Bindings.FLOAT);
+ } else if (graph.isInheritedFrom(range, l0.Integer)) {
+ graph.claimLiteral(object, property, Integer.parseInt(value), Bindings.INTEGER);
+ } else if (graph.isInheritedFrom(range, l0.Long)) {
+ graph.claimLiteral(object, property, Long.parseLong(value), Bindings.LONG);
+ } else if (graph.isInheritedFrom(range, l0.Boolean)) {
+ graph.claimLiteral(object, property, Boolean.parseBoolean(value), Bindings.BOOLEAN);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.STRING);
+ }
+ }
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * Note: This method support only some basic L0 data types.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, boolean value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (l0.Boolean.equals(range)) {
+ graph.claimLiteral(object, property, value , Bindings.BOOLEAN);
+ } else if (l0.String.equals(range)) {
+ graph.claimLiteral(object, property, Boolean.toString(value), Bindings.STRING);
+ } else if (l0.Integer.equals(range)) {
+ graph.claimLiteral(object, property, value ? 1 : 0, Bindings.INTEGER);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.BOOLEAN);
+ }
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * Note: This method support only some basic L0 data types.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, double[] value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (l0.DoubleArray.equals(range)) {
+ graph.claimLiteral(object, property, value, Bindings.DOUBLE_ARRAY);
+ } else if (l0.FloatArray.equals(range)) {
+ float arr[] = new float[value.length];
+ for (int i = 0; i < value.length; i++)
+ arr[i] = (float) value[i];
+ graph.claimLiteral(object, property, arr, Bindings.FLOAT_ARRAY);
+ } else if (l0.IntegerArray.equals(range)) {
+ int arr[] = new int[value.length];
+ for (int i = 0; i < value.length; i++)
+ arr[i] = (int) value[i];
+ graph.claimLiteral(object, property, arr, Bindings.INT_ARRAY);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.DOUBLE_ARRAY);
+ }
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * Note: This method support only some basic L0 data types.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, float[] value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (l0.FloatArray.equals(range)) {
+ graph.claimLiteral(object, property, value, Bindings.FLOAT_ARRAY);
+ } else if (l0.DoubleArray.equals(range)) {
+ double arr[] = new double[value.length];
+ for (int i = 0; i < value.length; i++)
+ arr[i] = (double) value[i];
+ graph.claimLiteral(object, property, arr, Bindings.DOUBLE_ARRAY);
+ } else if (l0.IntegerArray.equals(range)) {
+ int arr[] = new int[value.length];
+ for (int i = 0; i < value.length; i++)
+ arr[i] = (int) value[i];
+ graph.claimLiteral(object, property, arr, Bindings.INT_ARRAY);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.FLOAT_ARRAY);
+ }
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * Note: This method support only some basic L0 data types.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, int[] value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (l0.IntegerArray.equals(range)) {
+ graph.claimLiteral(object, property, value, Bindings.INT_ARRAY);
+ } else if (l0.DoubleArray.equals(range)) {
+ double arr[] = new double[value.length];
+ for (int i = 0; i < value.length; i++)
+ arr[i] = (double) value[i];
+ graph.claimLiteral(object, property, arr, Bindings.DOUBLE_ARRAY);
+ } else if (l0.FloatArray.equals(range)) {
+ float arr[] = new float[value.length];
+ for (int i = 0; i < value.length; i++)
+ arr[i] = (float) value[i];
+ graph.claimLiteral(object, property, arr, Bindings.FLOAT_ARRAY);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.INT_ARRAY);
+ }
+ }
+
+ /**
+ * Sets literal value. Does data conversion if required.
+ *
+ * Note: This method support only some basic L0 data types.
+ *
+ * @param graph
+ * @param object
+ * @param property
+ * @param value
+ * @throws DatabaseException
+ */
+ public static void setValue(WriteGraph graph, Resource object, Resource property, boolean[] value) throws DatabaseException{
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource range = graph.getPossibleObject(property, l0.HasRange);
+ if (l0.BooleanArray.equals(range)) {
+ graph.claimLiteral(object, property, value, Bindings.BOOLEAN_ARRAY);
+ } else if (l0.IntegerArray.equals(range)) {
+ int arr[] = new int[value.length];
+ for (int i = 0; i < value.length; i++)
+ arr[i] = value[i] ? 1 : 0;
+ graph.claimLiteral(object, property, arr, Bindings.INT_ARRAY);
+ } else {
+ graph.claimLiteral(object, property, value, Bindings.BOOLEAN_ARRAY);
+ }
+ }
+
+}
\ No newline at end of file