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