ec65027ec0ad50994fb1116eddaa1c02e731c906
[simantics/platform.git] / bundles / org.simantics.document.server / src / org / simantics / document / server / DocumentServerUtils.java
1 package org.simantics.document.server;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9 import java.util.SortedMap;
10 import java.util.TreeMap;
11
12 import org.simantics.databoard.Bindings;
13 import org.simantics.db.ReadGraph;
14 import org.simantics.db.Resource;
15 import org.simantics.db.common.request.UnaryRead;
16 import org.simantics.db.exception.DatabaseException;
17 import org.simantics.db.layer0.request.VariableRead;
18 import org.simantics.db.layer0.variable.ProxyChildVariable;
19 import org.simantics.db.layer0.variable.Variable;
20 import org.simantics.db.layer0.variable.Variables;
21 import org.simantics.document.base.ontology.DocumentationResource;
22 import org.simantics.document.server.request.NodeRequest;
23 import org.simantics.document.server.request.NodeRequestUtils;
24 import org.simantics.structural2.variables.Connection;
25 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
26 import org.simantics.utils.strings.AlphanumComparator;
27
28 public class DocumentServerUtils {
29
30     public static Collection<Variable> getChildren(ReadGraph graph, Variable variable) throws DatabaseException {
31
32         DocumentationResource DOC = DocumentationResource.getInstance(graph);
33         
34                 ArrayList<Variable> result = new ArrayList<Variable>();
35                 for(Variable property : variable.getProperties(graph)) {
36                         Collection<String> classifications = property.getPossiblePropertyValue(graph, Variables.CLASSIFICATIONS);
37                         if(classifications != null) {
38                                 if(classifications.contains(DocumentationResource.URIs.Document_ChildRelation)) {
39                                         Connection conn = property.getValue(graph);
40                                         Variable childConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, property, conn);
41                                         if(childConnectionPoint != null) {
42                                                 result.add(childConnectionPoint.getParent(graph));
43                                         }
44                                 } else if (DOC.Relations_partN.equals(property.getPossiblePredicateResource(graph))) {
45                                         Connection conn = property.getValue(graph);
46                                         for (Variable childConnectionPoint : DocumentServerUtils.getOtherConnectionPoints(graph, property, conn)) {
47                                                 result.add(childConnectionPoint.getParent(graph));
48                                         }
49                                 }
50                         }
51                 }
52                 return result;
53
54         }
55     
56         public static String findManualOrdinal(ReadGraph graph, Variable v) throws DatabaseException {
57                 DocumentationResource DOC = DocumentationResource.getInstance(graph);
58                 Integer j = null;
59                 while (j == null && v != null) {
60                         j = v.getPossiblePropertyValue(graph, DOC.Components_Component_manualOrdinal);
61                         v = v.getParent(graph);
62                 }
63                 if (j != null) {
64                         return Integer.toString(j);
65                 } else {
66                         return null;
67                 }
68         }
69     
70     public static Collection<Variable> getChildrenInOrdinalOrder(ReadGraph graph, Variable variable) throws DatabaseException {
71         DocumentationResource DOC = DocumentationResource.getInstance(graph);
72         
73                 SortedMap<String, Variable> childMap = new TreeMap<String, Variable>(AlphanumComparator.COMPARATOR);
74                 
75                 for(Variable property : variable.getProperties(graph, DocumentationResource.URIs.Document_ChildRelation)) {
76                         Resource cp = property.getPossiblePredicateResource(graph);
77                         String i = graph.getRelatedValue(cp, DOC.Document_ChildRelation_ordinal, Bindings.STRING);
78                         Connection conn = property.getValue(graph);
79                         Variable childConnectionPoint = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, property, conn);
80                         if(childConnectionPoint != null) {
81                                 childMap.put(i, childConnectionPoint.getParent(graph));
82                         }
83                 }
84                 
85                 Variable property = variable.getPossibleProperty(graph, "partN");
86                 if(property != null) {
87                         Connection conn = property.getValue(graph);
88                         for (Variable childConnectionPoint : DocumentServerUtils.getOtherConnectionPoints(graph, property, conn)) {
89                                 Variable child = childConnectionPoint.getParent(graph);
90                                 String i = findManualOrdinal(graph, child);
91                                 if (i == null) {
92                                         i = "0";
93                                 }
94                                 childMap.put(i, child);
95                         }
96                 }
97
98                 return childMap.values();
99
100         }    
101
102         public static Collection<Variable> collectNodes(ReadGraph graph, Variable variable, Collection<Variable> nodes) throws DatabaseException {
103
104                 DocumentationResource DOC = DocumentationResource.getInstance(graph);
105
106                 Resource type = variable.getPossibleType(graph);
107                 if(type == null) return nodes;
108                 
109                 if(!graph.isInheritedFrom(type, DOC.Components_Component)) return nodes;
110
111                 Boolean enabled = variable.getPossiblePropertyValue(graph, DOC.Properties_exists, Bindings.BOOLEAN);
112                 if(enabled != null && !enabled) return nodes;
113
114                 if(graph.isInheritedFrom(type, DOC.Components_PrimitiveComponent)) {
115                         nodes.add(variable);
116                 } else {
117                         for(Variable child : variable.getChildren(graph)) {
118                                 collectNodes(graph, child, nodes);
119                         }
120                 }
121
122                 return nodes;
123
124         }
125
126         public static Variable getPossibleOtherConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
127
128                 Collection<VariableConnectionPointDescriptor> descs = conn.getConnection2().getConnectionPointDescriptors(graph, connectionPoint.getParent(graph), null);
129                 if(descs.size() != 2) return null;
130
131                 for(VariableConnectionPointDescriptor desc : descs) {
132                         if(desc.isFlattenedFrom(graph, connectionPoint)) continue;
133                         return desc.getVariable(graph);
134                 }
135                 
136                 return null;
137
138         }
139
140         public static Variable getPossibleChildConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
141
142                 Collection<VariableConnectionPointDescriptor> descs = conn.getConnection2().getConnectionPointDescriptors(graph, connectionPoint.getParent(graph), null);
143                 if(descs.size() != 2) return null;
144
145         DocumentationResource DOC = DocumentationResource.getInstance(graph);
146                 
147                 for(VariableConnectionPointDescriptor desc : descs) {
148                         Resource res = desc.getConnectionPointResource(graph);
149                         if(graph.isInstanceOf(res, DOC.Relations_parentRelation)) continue;
150                         //if(desc.isFlattenedFrom(graph, connectionPoint)) continue;
151                         return desc.getVariable(graph);
152                 }
153                 
154                 return null;
155
156         }
157         
158         public static Collection<Variable> getOtherConnectionPoints(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
159
160                 ArrayList<Variable> connectionPoints = new ArrayList<Variable>();
161                 
162                 Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, null);
163
164                 for(VariableConnectionPointDescriptor desc : descs) {
165                         if(desc.isFlattenedFrom(graph, connectionPoint)) continue;
166                         connectionPoints.add(desc.getVariable(graph));
167                 }
168                 
169                 return connectionPoints;
170
171         }
172
173         public static Variable getPossibleCommandTriggerConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
174
175                 Collection<Variable> cpts = conn.getConnection2().getConnectionPoints(graph, connectionPoint.getParent(graph), null);
176
177                 Variable result = null;
178                 
179                 for(Variable cpt : cpts) {
180                         Set<String> classifications = cpt.getClassifications(graph);
181                         if(classifications.contains(DocumentationResource.URIs.Relations_commandExecutorRelation)) {
182                                 if(result != null) throw new DatabaseException("Multiple executor connection points in command connection");
183                                 result = cpt;
184                         }
185                 }
186                 
187                 return result;
188
189         }
190
191         public static Collection<Variable> getPossibleOtherConnectionPoints(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
192
193             Collection<Variable> cpts = conn.getConnection2().getConnectionPoints(graph, connectionPoint.getParent(graph), null);
194             if(cpts.size() < 2) 
195                 return Collections.emptyList();
196
197             ArrayList<Variable> result = new ArrayList<Variable>();
198             for(Variable cpt : cpts) {
199                 if(!cpt.equals(connectionPoint)) 
200                     result.add(cpt);
201             }
202             return result;
203         }
204
205         public static String getId(ReadGraph graph, Variable node) throws DatabaseException {
206
207         if(node == null) return "root";
208         else {
209             String name = node.getName(graph);
210             if(ProxyChildVariable.CONTEXT_END.equals(name)) return "";
211             else {
212                 String parentId = getId(graph, node.getParent(graph));
213                 if(parentId.isEmpty()) return name;
214                 else return parentId + "/" + name; 
215             }
216             
217         }
218
219         }
220
221         public static Object getValue(ReadGraph graph, Variable attrib) throws DatabaseException {
222                 return graph.syncRequest(new DocumentValue(attrib));
223         }
224
225         public static Variable getParentConnectionPoint(ReadGraph graph, Variable component) throws DatabaseException {
226
227                 Variable connectionPoint = component.getPossibleProperty(graph, "parent");
228                 if(connectionPoint == null) {
229                         DocumentationResource DOC = DocumentationResource.getInstance(graph);
230                         Collection<Variable> cps = component.getProperties(graph, DOC.Relations_parentRelation);
231                         if(cps.size() == 1) {
232                                 connectionPoint = cps.iterator().next();
233                         } else {
234                                 return null;
235                         }
236                 }
237                 
238                 Connection conn = connectionPoint.getValue(graph);
239                 Variable otherCp = DocumentServerUtils.getPossibleOtherConnectionPoint(graph, connectionPoint, conn);
240                 if (otherCp != null) {
241                         return otherCp;
242                 } else {
243                         Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
244                     @Override
245                     public Variable perform(ReadGraph graph) throws DatabaseException {
246                         DocumentationResource DOC = DocumentationResource.getInstance(graph);
247                         Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
248
249                                 for(VariableConnectionPointDescriptor desc : descs) {
250                                         if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
251                                                 return desc.getVariable(graph);
252                                         }
253                                 }
254                                 return null;
255                     }
256                 });
257                         if (parentCp != null) {
258                                 return parentCp;
259                         }
260                 }
261                 return null;
262
263         }
264         
265         /* Children */
266         public static Collection<Variable> getChildConnections(ReadGraph graph, Variable variable) throws DatabaseException {
267                 return variable.getProperties(graph, DocumentationResource.getInstance(graph).Document_ChildRelation);
268         }
269
270         /* Command sequence */
271         public static Collection<Variable> getTriggerCommands(ReadGraph graph, Variable variable) throws DatabaseException {
272                 ArrayList<Variable> result = new ArrayList<Variable>();
273                 DocumentationResource DOC = DocumentationResource.getInstance(graph);
274                 for(Variable var : variable.getProperties(graph, DOC.Document_CommandRelation)) {
275             if(DOC.Relations_broadcasted.equals(var.getPredicateResource(graph))) continue;
276             result.add(var);
277                 }
278                 return result;
279         }
280
281         public static Collection<Variable> getCommands(ReadGraph graph, Variable variable) throws DatabaseException {
282                 return variable.getProperties(graph, DocumentationResource.getInstance(graph).Document_CommandRelation);
283         }
284
285         /* Data definition */
286         public static Collection<Variable> getDataDefinitions(ReadGraph graph, Variable variable) throws DatabaseException {
287                 return variable.getProperties(graph, DocumentationResource.getInstance(graph).Document_DataDefinitionRelation);
288         }
289
290         /* Data relation */
291         public static Collection<Variable> getDataRelations(ReadGraph graph, Variable variable) throws DatabaseException {
292                 return variable.getProperties(graph, DocumentationResource.getInstance(graph).Document_DataRelation);
293         }
294
295         /* Attributes */
296         public static Collection<Variable> getAttributes(ReadGraph graph, DocumentationResource DOC, Variable variable) throws DatabaseException {
297                 return variable.getProperties(graph, DOC.Document_AttributeRelation);
298         }
299
300         public static class AttributesRequest extends VariableRead<JSONObject> {
301
302                 public AttributesRequest(Variable variable) {
303                         super(variable);
304                 }
305
306                 @Override
307                 public JSONObject perform(ReadGraph graph) throws DatabaseException {
308                         DocumentationResource DOC = DocumentationResource.getInstance(graph);
309                         DocumentProperties properties = variable.getPropertyValue(graph, DOC.Properties_primitiveProperties);
310                         return computeStatic(graph, variable, properties);
311                 }
312
313                 JSONObject computeStatic(ReadGraph graph, Variable variable, DocumentProperties statics) throws DatabaseException {
314
315                         JSONObject base = graph.syncRequest(new org.simantics.document.server.request.DefaultFields(variable));
316                         JSONObject object = base.clone();
317
318                         for(String name : statics.getKeys(graph, variable)) {
319                                 try {
320                                         if (name.equals(NodeRequest.PROPERTY_VALUE_EXCEPTIONS)) {
321                                                 @SuppressWarnings("unchecked")
322                                                 Map<String, Exception> exceptions = (Map<String, Exception>)statics.getValue(graph, variable, name);
323
324                                                 List<String> errorList = object.getJSONField(NodeRequest.ERRORS);
325                                                 if(errorList == null)
326                                                         errorList = new ArrayList<>();
327
328                                                 for (Map.Entry<String, Exception> entry : exceptions.entrySet()) {
329                                                         String errorMessage = NodeRequestUtils.formatErrorMessage(entry.getKey(), entry.getValue());
330                                                         errorList.add(errorMessage);
331                                                 }
332                                                 object.addJSONField(NodeRequest.ERRORS, errorList);
333                                         } else {
334                                                 object.addJSONField(name, statics.getValue(graph, variable, name));
335                                         }
336                                 } catch (Throwable t) {
337                                         List<String> errorList = object.getJSONField(NodeRequest.ERRORS);
338                                         if(errorList == null)
339                                                 errorList = new ArrayList<>(1);
340
341                                         String errorMessage = NodeRequestUtils.formatErrorMessage(name, t);
342                                         errorList.add(errorMessage);
343                                         object.addJSONField(NodeRequest.ERRORS, errorList);
344                                 }
345
346                         }
347
348                         return object;
349
350                 }
351
352         }
353
354         public static Collection<Variable> getDynamicAttributes(ReadGraph graph, final DocumentationResource DOC, Variable variable) throws DatabaseException {
355                 return Collections.emptyList();
356         }
357
358         public static Variable getPossibleDocumentRootVariable(ReadGraph graph, Variable documentPart) throws DatabaseException {
359                 if(ProxyChildVariable.CONTEXT_END.equals(documentPart.getName(graph))) return documentPart;
360                 Variable parent = documentPart.getParent(graph);
361                 if(parent == null) return null;
362                 return getPossibleDocumentRootVariable(graph, parent);
363         }
364
365 }