X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.document.server%2Fsrc%2Forg%2Fsimantics%2Fdocument%2Fserver%2FDocumentServerUtils.java;fp=bundles%2Forg.simantics.document.server%2Fsrc%2Forg%2Fsimantics%2Fdocument%2Fserver%2FDocumentServerUtils.java;h=d059bd7b4db289839fae135a38fdb8797a823c66;hb=0db0b69c4abedc90b366631582c57e13f2f110b7;hp=5e1f5cc30e798aff45343b8f8c5f4483b6d8a9cc;hpb=512d469c3e490cdfc9a10fbbd6efe92ae6c0358a;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentServerUtils.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentServerUtils.java index 5e1f5cc30..d059bd7b4 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentServerUtils.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentServerUtils.java @@ -19,359 +19,353 @@ 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; - - } + 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 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)) { + 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.getConnection2().getConnectionPointDescriptors(graph, connectionPoint.getParent(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.getConnection2().getConnectionPointDescriptors(graph, connectionPoint.getParent(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.getConnection2().getConnectionPoints(graph, connectionPoint.getParent(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.getConnection2().getConnectionPoints(graph, connectionPoint.getParent(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 name = node.getName(graph); + if(ProxyChildVariable.CONTEXT_END.equals(name)) return ""; + else { + String parentId = getId(graph, node.getParent(graph)); + if(parentId.isEmpty()) return name; + else return parentId + "/" + name; + } + + } + + } + + 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); - } + } + 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 JSONObject perform(ReadGraph graph) throws DatabaseException { + + DocumentationResource DOC = DocumentationResource.getInstance(graph); + + DocumentProperties properties = variable.getPropertyValue(graph, DOC.Properties_primitiveProperties); + + return computeStatic(graph, variable, properties); + + } + + JSONObject computeStatic(ReadGraph graph, Variable variable, DocumentProperties statics) throws DatabaseException { + + JSONObject base = graph.syncRequest(new org.simantics.document.server.request.DefaultFields(variable)); + JSONObject object = base.clone(); + + for(String name : statics.getKeys(graph, variable)) { + try { + if (name.equals(NodeRequest.PROPERTY_VALUE_EXCEPTIONS)) { + @SuppressWarnings("unchecked") + Map exceptions = (Map)statics.getValue(graph, variable, name);//(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.addJSONField(name, statics.getValue(graph, variable, name)); + } + } 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 { + return Collections.emptyList(); + } + + public static Variable getPossibleDocumentRootVariable(ReadGraph graph, Variable documentPart) throws DatabaseException { + if(ProxyChildVariable.CONTEXT_END.equals(documentPart.getName(graph))) return documentPart; + Variable parent = documentPart.getParent(graph); + if(parent == null) return null; + return getPossibleDocumentRootVariable(graph, parent); + } }