From: Marko Luukkainen Date: Tue, 12 Mar 2019 16:48:36 +0000 (+0200) Subject: Java API for diagrams, work in progress X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=3e6e743ffe75f5724406e1dd01589386efe04782;p=simantics%2Finterop.git Java API for diagrams, work in progress gitlab #7 Change-Id: I05295206618511bd3d55589fd588fa1079f042e2 --- diff --git a/org.simantics.interop.diagram/.classpath b/org.simantics.interop.diagram/.classpath new file mode 100644 index 0000000..eca7bdb --- /dev/null +++ b/org.simantics.interop.diagram/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.simantics.interop.diagram/.gitignore b/org.simantics.interop.diagram/.gitignore new file mode 100644 index 0000000..65776c3 --- /dev/null +++ b/org.simantics.interop.diagram/.gitignore @@ -0,0 +1 @@ +/bin/ \ No newline at end of file diff --git a/org.simantics.interop.diagram/.project b/org.simantics.interop.diagram/.project new file mode 100644 index 0000000..409c5f0 --- /dev/null +++ b/org.simantics.interop.diagram/.project @@ -0,0 +1,28 @@ + + + org.simantics.interop.diagram + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.simantics.interop.diagram/.settings/org.eclipse.jdt.core.prefs b/org.simantics.interop.diagram/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..0c68a61 --- /dev/null +++ b/org.simantics.interop.diagram/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/org.simantics.interop.diagram/META-INF/MANIFEST.MF b/org.simantics.interop.diagram/META-INF/MANIFEST.MF new file mode 100644 index 0000000..0967fb6 --- /dev/null +++ b/org.simantics.interop.diagram/META-INF/MANIFEST.MF @@ -0,0 +1,21 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Interop Diagram +Bundle-SymbolicName: org.simantics.interop.diagram +Bundle-Version: 1.0.0.qualifier +Automatic-Module-Name: org.simantics.interop.diagram +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.13.0", + org.simantics.db;bundle-version="1.1.0", + org.simantics.db.layer0;bundle-version="1.1.0", + org.simantics.layer0;bundle-version="1.1.0", + org.simantics.g2d.ontology;bundle-version="1.1.0", + org.simantics.diagram.ontology;bundle-version="2.2.0", + org.simantics.structural.ontology;bundle-version="1.2.0", + org.simantics.modeling.ontology;bundle-version="1.2.0", + org.simantics;bundle-version="1.0.0", + org.simantics.g2d;bundle-version="1.1.1", + org.simantics.diagram;bundle-version="1.1.1", + org.simantics.structural.ui;bundle-version="1.1.1", + org.simantics.structural2;bundle-version="1.1.1" +Export-Package: org.simantics.interop.diagram diff --git a/org.simantics.interop.diagram/build.properties b/org.simantics.interop.diagram/build.properties new file mode 100644 index 0000000..34d2e4d --- /dev/null +++ b/org.simantics.interop.diagram/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/org.simantics.interop.diagram/src/org/simantics/interop/diagram/Diagram.java b/org.simantics.interop.diagram/src/org/simantics/interop/diagram/Diagram.java new file mode 100644 index 0000000..5695798 --- /dev/null +++ b/org.simantics.interop.diagram/src/org/simantics/interop/diagram/Diagram.java @@ -0,0 +1,711 @@ +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 { + + public static boolean DO_NO_MIX_SECTION_NAMES = false; + public static boolean USE_MERGE_CONNECTS = true; + + private Resource composite; + private Resource diagram; + + private Map indexMap = new HashMap(); + + private Map elementToSymbolMap = new HashMap(); + + private Map> compositeToDiagramMap = new HashMap>(); + + protected Diagram(ReadGraph g, Resource composite, Resource diagram) throws DatabaseException { + this.composite = composite; + this.diagram = diagram; + } + + protected abstract Diagram 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 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 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 getAllModuleNamesForModel(ReadGraph graph, final Resource res) throws DatabaseException { + + Resource model = DiagramUtils.getModel(graph, res); + Resource configuration = DiagramUtils.getConfiguration(graph, model); + Set names = new HashSet(); + Collection 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 getAllComposites(RequestProcessor processor, Resource configuration) throws DatabaseException { + return (Set)processor.syncRequest(new ResourceRead(configuration) { + @Override + public Object perform(ReadGraph graph) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + Set composites = new HashSet(); + Stack resources = new Stack(); + 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 getAllModuleNamesForComposite(RequestProcessor processor, Resource composite) throws DatabaseException { + return (Set)processor.syncRequest(new ResourceRead(composite) { + @Override + public Object perform(ReadGraph graph) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + Set names = new HashSet(); + Collection 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 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 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 params = new HashMap(); + 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 diag = construct(g, composite, diagram); + diag.compositeToDiagramMap = compositeToDiagramMap; + compositeToDiagramMap.put(composite, diag); + return diag; + } + + public Diagram 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 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 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 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 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 getSymbols(ReadGraph g) throws DatabaseException { + ModelingResources m = ModelingResources.getInstance(g); + List matching = new ArrayList(); + 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 getSymbol(ReadGraph g, String symbolName) throws DatabaseException { + ModelingResources m = ModelingResources.getInstance(g); + Layer0 b = Layer0.getInstance(g); + List matching = new ArrayList(); + + 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 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 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 getSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException { + + List nameMatching = getSymbol(g, symbolName); + List matching = new ArrayList(); + 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 matching = new ArrayList(); + 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; + } + } + + + +} + diff --git a/org.simantics.interop.diagram/src/org/simantics/interop/diagram/DiagramUtils.java b/org.simantics.interop.diagram/src/org/simantics/interop/diagram/DiagramUtils.java new file mode 100644 index 0000000..29f3e21 --- /dev/null +++ b/org.simantics.interop.diagram/src/org/simantics/interop/diagram/DiagramUtils.java @@ -0,0 +1,90 @@ +package org.simantics.interop.diagram; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.Layer0; +import org.simantics.simulation.ontology.SimulationResource; + +/** + * + * @author Marko Luukkainen + * + */ +public class DiagramUtils { + + + public static void addElement(WriteGraph g, Diagram diagram, Resource element) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(g); + OrderedSetUtils.add(g, diagram.getDiagram(), element); + generateName(g, diagram, element); + g.claim(diagram.getDiagram(), l0.ConsistsOf, element); + } + + public static void addElementFirst(WriteGraph g, Diagram diagram, Resource element) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(g); + OrderedSetUtils.addFirst(g, diagram.getDiagram(), element); + generateName(g, diagram, element); + g.claim(diagram.getDiagram(), l0.ConsistsOf, element); + } + + public static void generateName(WriteGraph g, Diagram diagram, Resource element) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(g); + if (g.getPossibleRelatedValue(element, l0.HasName) != null) + return; + Resource type = g.getSingleType(element); + + String name = NameUtils.findFreshEscapedName(g, (String)g.getRelatedValue(type, l0.HasName), diagram.getDiagram(),l0.ConsistsOf); + g.claimLiteral(element, l0.HasName, name); + } + + + public static Resource createRelation(WriteGraph w, Layer0 b, Resource superrelation) throws DatabaseException { + Resource relation = w.newResource(); + Resource invRelation = w.newResource(); + w.claim(relation, b.InverseOf, invRelation); + w.claim(relation, b.ConsistsOf, invRelation); + w.claimLiteral(invRelation, b.HasName, "Inverse"); + + w.claim(relation, b.SubrelationOf, b.SuperrelationOf, superrelation); + w.claim(invRelation, b.SubrelationOf, b.SuperrelationOf, w.getInverse(superrelation)); + + //w.claim(relation, b.InstanceOf, ab.ReferenceProvider); + return relation; + } + + public static Resource createRelation(WriteGraph w, Layer0 b, Resource... superrelation) throws DatabaseException { + Resource relation = w.newResource(); + Resource invRelation = w.newResource(); + w.claim(relation, b.InverseOf, invRelation); + w.claim(relation, b.ConsistsOf, invRelation); + w.claimLiteral(invRelation, b.HasName, "Inverse"); + for (Resource rel : superrelation) { + w.claim(relation, b.SubrelationOf, null, rel); + Resource inv = w.getPossibleInverse(rel); + if (inv != null) + w.claim(invRelation, b.SubrelationOf, null, inv); + } + return relation; + } + + public static Resource getModel(ReadGraph graph, Resource res) throws DatabaseException{ + Layer0 l0 = Layer0.getInstance(graph); + SimulationResource sim = SimulationResource.getInstance(graph); + Resource r = res; + while (r != null) { + if (graph.isInstanceOf(r, sim.Model)) + return r; + r = graph.getPossibleObject(r, l0.PartOf); + } + return r; + } + + public static Resource getConfiguration(ReadGraph graph, Resource model) throws DatabaseException { + SimulationResource sim = SimulationResource.getInstance(graph); + return graph.getSingleObject(model, sim.HasConfiguration); + } +} diff --git a/org.simantics.interop.diagram/src/org/simantics/interop/diagram/Symbol.java b/org.simantics.interop.diagram/src/org/simantics/interop/diagram/Symbol.java new file mode 100644 index 0000000..22160aa --- /dev/null +++ b/org.simantics.interop.diagram/src/org/simantics/interop/diagram/Symbol.java @@ -0,0 +1,1245 @@ +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 getConnectionRel(ReadGraph g, Symbol symbolConf2, Resource componentConRel1, Resource componentConRel2, Collection 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 connType1 = g.getObjects(componentConRel1, sr.AllowsConnectionType); + Collection connType2 = g.getObjects(componentConRel2, sr.AllowsConnectionType); + Collection matching = new HashSet(); + 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 diagramConnectionRels = g.getObjects(componentConnRel, m.ConnectionRelationToDiagramConnectionRelation); + if (diagramConnectionRels.size() == 1) + return diagramConnectionRels.iterator().next(); + if (diagramConnectionRels.size() > 1) { + List matching = new ArrayList(); + 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 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 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 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 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 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 result = new ArrayList(); + Collection modConn1s = g.getObjects(this.component, componentConRel); + for (Resource modConn1 : modConn1s) { + + Collection connected = g.getStatements(modConn1, sr.Connects); + Collection connectionJoins = g.getObjects(modConn1, sr.IsJoinedBy); + Collection connectedComponents = new ArrayList(); + + 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 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 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 modConn1s = g.getObjects(this.component, componentConRel); + Collection result = new ArrayList(); + for (Resource modConn1 : modConn1s) { + + Collection connected = g.getObjects(modConn1, sr.Connects); + Collection connectionJoins = g.getObjects(modConn1, sr.IsJoinedBy); + Collection connectedComponents = new ArrayList(); + + for (Resource r : connected) { + if (!r.equals(this.component)) { + connectedComponents.add(r); + } + } + for (Resource connectionJoin : connectionJoins) { + Collection 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 getDiagramConnected(ReadGraph g, Resource diagramConnRel, Resource otherConnRel) throws DatabaseException { + DiagramResource dr = DiagramResource.getInstance(g); + Collection connectors = g.getObjects(element, diagramConnRel); + Collection result = new ArrayList(); + 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 result) throws DatabaseException{ + StructuralResource2 sr = StructuralResource2.getInstance(g); + DiagramResource dr = DiagramResource.getInstance(g); + Collection 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 result) throws DatabaseException { + DiagramResource dr = DiagramResource.getInstance(g); + + Collection 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 getDiagramConnected(ReadGraph g, Resource diagramConnRel) throws DatabaseException { + return getDiagramConnected(g, diagramConnRel,null); + } + + public Collection getDiagramInverseConnected(ReadGraph g, Resource otherConnRel) throws DatabaseException { + StructuralResource2 sr = StructuralResource2.getInstance(g); + return getDiagramConnected(g, sr.IsConnectedTo, otherConnRel); + + } + + public Collection 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 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 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 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