package org.simantics.document.server; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.UnaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.VariableRead; import org.simantics.db.layer0.variable.ProxyChildVariable; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.document.base.ontology.DocumentationResource; import org.simantics.document.server.Functions.RootVariable; import org.simantics.document.server.request.NodeRequest; import org.simantics.document.server.request.NodeRequestUtils; import org.simantics.structural2.variables.Connection; import org.simantics.structural2.variables.VariableConnectionPointDescriptor; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.strings.AlphanumComparator; public class DocumentServerUtils { public static Collection getChildren(ReadGraph graph, Variable variable) throws DatabaseException { DocumentationResource DOC = DocumentationResource.getInstance(graph); ArrayList result = new ArrayList(); for(Variable property : variable.getProperties(graph)) { Collection classifications = property.getPossiblePropertyValue(graph, Variables.CLASSIFICATIONS); if(classifications != null) { if(classifications.contains(DocumentationResource.URIs.Document_ChildRelation)) { Connection conn = property.getValue(graph); Variable childConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, property, conn); if(childConnectionPoint != null) { result.add(childConnectionPoint.getParent(graph)); } } else if (DOC.Relations_partN.equals(property.getPossiblePredicateResource(graph))) { Connection conn = property.getValue(graph); for (Variable childConnectionPoint : DocumentServerUtils.getOtherConnectionPoints(graph, property, conn)) { result.add(childConnectionPoint.getParent(graph)); } } } } return result; } public static String findManualOrdinal(ReadGraph graph, Variable v) throws DatabaseException { DocumentationResource DOC = DocumentationResource.getInstance(graph); Integer j = null; while (j == null && v != null) { j = v.getPossiblePropertyValue(graph, DOC.Components_Component_manualOrdinal); v = v.getParent(graph); } if (j != null) { return Integer.toString(j); } else { return null; } } public static Collection getChildrenInOrdinalOrder(ReadGraph graph, Variable variable) throws DatabaseException { DocumentationResource DOC = DocumentationResource.getInstance(graph); SortedMap childMap = new TreeMap(AlphanumComparator.COMPARATOR); for(Variable property : variable.getProperties(graph, DocumentationResource.URIs.Document_ChildRelation)) { Resource cp = property.getPossiblePredicateResource(graph); String i = graph.getRelatedValue(cp, DOC.Document_ChildRelation_ordinal, Bindings.STRING); Connection conn = property.getValue(graph); Variable childConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, property, conn); if(childConnectionPoint != null) { childMap.put(i, childConnectionPoint.getParent(graph)); } } Variable property = variable.getPossibleProperty(graph, "partN"); if(property != null) { Connection conn = property.getValue(graph); for (Variable childConnectionPoint : DocumentServerUtils.getOtherConnectionPoints(graph, property, conn)) { Variable child = childConnectionPoint.getParent(graph); String i = findManualOrdinal(graph, child); if (i == null) { i = "0"; } childMap.put(i, child); } } return childMap.values(); } public static Collection collectNodes(ReadGraph graph, Variable variable, Collection nodes) throws DatabaseException { DocumentationResource DOC = DocumentationResource.getInstance(graph); Resource type = variable.getPossibleType(graph); if(type == null) return nodes; if(!graph.isInheritedFrom(type, DOC.Components_Component)) return nodes; Boolean enabled = variable.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN); if(enabled != null && !enabled) return nodes; if(graph.isInheritedFrom(type, DOC.Components_PrimitiveComponent)) { nodes.add(variable); } else { for(Variable child : variable.getChildren(graph)) { collectNodes(graph, child, nodes); } } return nodes; } public static Variable getPossibleOtherConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException { Collection descs = conn.getConnectionPointDescriptors(graph, null); if(descs.size() != 2) return null; for(VariableConnectionPointDescriptor desc : descs) { if(desc.isFlattenedFrom(graph, connectionPoint)) continue; return desc.getVariable(graph); } return null; } public static Variable getPossibleChildConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException { Collection descs = conn.getConnectionPointDescriptors(graph, null); if(descs.size() != 2) return null; DocumentationResource DOC = DocumentationResource.getInstance(graph); for(VariableConnectionPointDescriptor desc : descs) { Resource res = desc.getConnectionPointResource(graph); if(graph.isInstanceOf(res, DOC.Relations_parentRelation)) continue; //if(desc.isFlattenedFrom(graph, connectionPoint)) continue; return desc.getVariable(graph); } return null; } public static Collection getOtherConnectionPoints(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException { ArrayList connectionPoints = new ArrayList(); Collection descs = conn.getConnectionPointDescriptors(graph, null); for(VariableConnectionPointDescriptor desc : descs) { if(desc.isFlattenedFrom(graph, connectionPoint)) continue; connectionPoints.add(desc.getVariable(graph)); } return connectionPoints; } public static Variable getPossibleCommandTriggerConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException { Collection cpts = conn.getConnectionPoints(graph, null); Variable result = null; for(Variable cpt : cpts) { Set classifications = cpt.getClassifications(graph); if(classifications.contains(DocumentationResource.URIs.Relations_commandExecutorRelation)) { if(result != null) throw new DatabaseException("Multiple executor connection points in command connection"); result = cpt; } } return result; } public static Collection getPossibleOtherConnectionPoints(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException { Collection cpts = conn.getConnectionPoints(graph, null); if(cpts.size() < 2) return Collections.emptyList(); ArrayList result = new ArrayList(); for(Variable cpt : cpts) { if(!cpt.equals(connectionPoint)) result.add(cpt); } return result; } public static String getId(ReadGraph graph, Variable node) throws DatabaseException { if(node == null) return "root"; else { String uri = node.getURI(graph); int l = uri.lastIndexOf(ProxyChildVariable.CONTEXT_END); return uri.substring(l+4); } } public static Object getValue(ReadGraph graph, Variable attrib) throws DatabaseException { return graph.syncRequest(new DocumentValue(attrib)); } public static Variable getParentConnectionPoint(ReadGraph graph, Variable component) throws DatabaseException { Variable connectionPoint = component.getPossibleProperty(graph, "parent"); if(connectionPoint == null) { DocumentationResource DOC = DocumentationResource.getInstance(graph); Collection cps = component.getProperties(graph, DOC.Relations_parentRelation); if(cps.size() == 1) { connectionPoint = cps.iterator().next(); } else { return null; } } Connection conn = connectionPoint.getValue(graph); Variable otherCp = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, connectionPoint, conn); if (otherCp != null) { return otherCp; } else { Variable parentCp = graph.sync(new UnaryRead(conn) { @Override public Variable perform(ReadGraph graph) throws DatabaseException { DocumentationResource DOC = DocumentationResource.getInstance(graph); Collection descs = parameter.getConnectionPointDescriptors(graph, null); for(VariableConnectionPointDescriptor desc : descs) { if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) { return desc.getVariable(graph); } } return null; } }); if (parentCp != null) { return parentCp; } } return null; } /* Children */ public static Collection getChildConnections(ReadGraph graph, Variable variable) throws DatabaseException { return variable.getProperties(graph, DocumentationResource.getInstance(graph).Document_ChildRelation); } /* Command sequence */ public static Collection getTriggerCommands(ReadGraph graph, Variable variable) throws DatabaseException { ArrayList result = new ArrayList(); DocumentationResource DOC = DocumentationResource.getInstance(graph); for(Variable var : variable.getProperties(graph, DOC.Document_CommandRelation)) { if(DOC.Relations_broadcasted.equals(var.getPredicateResource(graph))) continue; result.add(var); } return result; } public static Collection getCommands(ReadGraph graph, Variable variable) throws DatabaseException { return variable.getProperties(graph, DocumentationResource.getInstance(graph).Document_CommandRelation); } /* Data definition */ public static Collection getDataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException { return variable.getProperties(graph, DocumentationResource.getInstance(graph).Document_DataDefinitionRelation); } /* Data relation */ public static Collection getDataRelations(ReadGraph graph, Variable variable) throws DatabaseException { return variable.getProperties(graph, DocumentationResource.getInstance(graph).Document_DataRelation); } /* Attributes */ public static Collection getAttributes(ReadGraph graph, DocumentationResource DOC, Variable variable) throws DatabaseException { return variable.getProperties(graph, DOC.Document_AttributeRelation); } public static class AttributesRequest extends VariableRead>> { public AttributesRequest(Variable variable) { super(variable); } @Override public Pair> perform(ReadGraph graph) throws DatabaseException { ArrayList statics = new ArrayList(); DocumentationResource DOC = DocumentationResource.getInstance(graph); Variable primitives = variable.getProperty(graph, DOC.Properties_primitiveProperties); for(Variable property : primitives.getProperties(graph)) { statics.add(property); // NO SUPPORT FOR DYNAMICS AT THIS STAGE } JSONObject staticContent = computeStatic(graph, variable, statics); return new Pair>(staticContent, Collections.emptyList()); } JSONObject computeStatic(ReadGraph graph, Variable variable, ArrayList statics) throws DatabaseException { JSONObject base = graph.syncRequest(new org.simantics.document.server.request.DefaultFields(variable)); JSONObject object = base.clone(); for(Variable attrib : statics) { String name = attrib.getName(graph); try { if (name.equals(NodeRequest.PROPERTY_VALUE_EXCEPTIONS)) { @SuppressWarnings("unchecked") Map exceptions = (Map)DocumentServerUtils.getValue(graph, attrib); List errorList = object.getJSONField(NodeRequest.ERRORS); if(errorList == null) errorList = new ArrayList(); for (Map.Entry entry : exceptions.entrySet()) { String errorMessage = NodeRequestUtils.formatErrorMessage(entry.getKey(), entry.getValue()); errorList.add(errorMessage); } object.addJSONField(NodeRequest.ERRORS, errorList); } else { Object value = DocumentServerUtils.getValue(graph, attrib); object.addJSONField(name, value); } } catch (Throwable t) { List errorList = object.getJSONField(NodeRequest.ERRORS); if(errorList == null) errorList = new ArrayList(); String errorMessage = NodeRequestUtils.formatErrorMessage(name, t); errorList.add(errorMessage); object.addJSONField(NodeRequest.ERRORS, errorList); } } return object; } } public static Collection getDynamicAttributes(ReadGraph graph, final DocumentationResource DOC, Variable variable) throws DatabaseException { Pair> attribs = graph.syncRequest(new AttributesRequest(variable)); return attribs.second; } public static Variable getPossibleDocumentRootVariable(ReadGraph graph, Variable documentPart) throws DatabaseException { if(documentPart instanceof RootVariable) return documentPart; Variable parent = documentPart.getParent(graph); if(parent == null) return null; return getPossibleDocumentRootVariable(graph, parent); } }