1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.layer0.variable;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Collection;
\r
16 import java.util.Collections;
\r
17 import java.util.LinkedList;
\r
18 import java.util.List;
\r
19 import java.util.Map;
\r
21 import org.simantics.databoard.binding.Binding;
\r
22 import org.simantics.databoard.binding.mutable.Variant;
\r
23 import org.simantics.databoard.type.Datatype;
\r
24 import org.simantics.databoard.type.NumberType;
\r
25 import org.simantics.databoard.util.URIStringUtils;
\r
26 import org.simantics.db.ReadGraph;
\r
27 import org.simantics.db.RequestProcessor;
\r
28 import org.simantics.db.Resource;
\r
29 import org.simantics.db.common.request.PossibleIndexRoot;
\r
30 import org.simantics.db.common.request.TernaryRead;
\r
31 import org.simantics.db.common.utils.Logger;
\r
32 import org.simantics.db.exception.DatabaseException;
\r
33 import org.simantics.db.layer0.exception.MissingVariableException;
\r
34 import org.simantics.db.layer0.request.Model;
\r
35 import org.simantics.db.layer0.request.PossibleActiveVariableFromVariable;
\r
36 import org.simantics.db.layer0.request.PossibleVariableIndexRoot;
\r
37 import org.simantics.db.layer0.request.PossibleVariableModel;
\r
38 import org.simantics.db.layer0.request.PropertyInfo;
\r
39 import org.simantics.db.layer0.request.PropertyInfoRequest;
\r
40 import org.simantics.db.layer0.request.ResourceURIToVariable;
\r
41 import org.simantics.db.layer0.request.VariableIndexRoot;
\r
42 import org.simantics.db.layer0.request.VariableURI;
\r
43 import org.simantics.layer0.Layer0;
\r
44 import org.simantics.operation.Layer0X;
\r
45 import org.simantics.project.ontology.ProjectResource;
\r
46 import org.simantics.scl.runtime.function.Function1;
\r
47 import org.simantics.scl.runtime.function.Function2;
\r
48 import org.simantics.scl.runtime.function.Function3;
\r
49 import org.simantics.simulation.ontology.SimulationResource;
\r
50 import org.simantics.simulator.variable.exceptions.NodeManagerException;
\r
51 import org.simantics.utils.datastructures.Pair;
\r
53 import gnu.trove.map.hash.TObjectIntHashMap;
\r
55 final public class Variables {
\r
57 public static final Variant PENDING_NODE_VALUE = new Variant();
\r
59 public static final NodeStructure PENDING_NODE_STRUCTURE = new NodeStructure(Collections.emptyMap(), Collections.emptyMap()) {
\r
60 public boolean equals(Object object) {
\r
61 return this == object;
\r
65 public static enum Role {
\r
67 CHILD("/"), PROPERTY("#");
\r
69 transient final String identifier;
\r
71 private Role(String identifier) {
\r
72 this.identifier = identifier;
\r
75 final public String getIdentifier() {
\r
79 public static Role getRole( String identifier ) {
\r
80 for (Role role : Role.values()) if (role.identifier.equals( identifier )) return role;
\r
87 //final public static String PREDICATE = "PREDICATE";
\r
91 final public static String NAME = "HasName";
\r
92 final public static String CLASSIFICATIONS = "classifications";
\r
93 final public static String EXPRESSION = "HasExpression";
\r
94 final public static String INPUT_VALIDATOR = "HasInputValidator";
\r
95 final public static String INPUT_MODIFIER = "HasInputModifier";
\r
96 final public static String FORMATTER = "HasFormatter";
\r
98 final public static String STANDARD_RESOURCE = "hasStandardResource";
\r
101 //final public static String REPRESENTS = "Represents";
\r
102 final public static String TYPE = "Type";
\r
103 final public static String URI = "URI";
\r
105 * @deprecated use {@link Variable#getRVI(ReadGraph)} and {@link RVI} instead.
\r
108 // final public static String SERIALISED = "Serialised";
\r
111 //final public static String PARENT = "Parent";
\r
112 //final public static String ROLE = "Role";
\r
113 //final public static String DATATYPE = "DATATYPE";
\r
114 //final public static String UNIT = "UNIT";
\r
116 final public static String VALID = "valid";
\r
117 final public static String REQUIRED = "required";
\r
118 final public static String DEFAULT = "default";
\r
119 final public static String READONLY = "readOnly";
\r
120 final public static String VALIDATOR = "validator";
\r
122 final public static String LABEL = "HasLabel";
\r
124 final public static String ENUMERATION_VALUES = "HasEnumerationValues";
\r
125 final public static String CUSTOM_MODIFIER = "HasCustomModifier";
\r
127 final public static String DISPLAY_COLUMN = "HasDisplayColumn";
\r
129 final public static String DISPLAY_PROPERTY = "HasDisplayProperty";
\r
130 final public static String DISPLAY_VALUE = "HasDisplayValue";
\r
131 final public static String DISPLAY_UNIT = "HasDisplayUnit";
\r
133 final public static String CONVERTED_VALUE = "convertedValue";
\r
136 * This property should exist for array valued property variables.
\r
138 final public static String ARRAY_SIZE = "ARRAY_SIZE";
\r
142 // use etc. variable.adapt(graph, Interface.class).getResource()
\r
143 final public static String RESOURCE = "Resource";
\r
145 final public static String CONTAINER_RESOURCE = "ContainerResource";
\r
147 final public static String PROPERTY_RESOURCE = "PROPERTY_RESOURCE";
\r
150 public final static String[] builtins = {
\r
151 TYPE, RESOURCE, URI
\r
155 public static Variable getPossibleVariable(ReadGraph graph, Resource resource) throws DatabaseException {
\r
156 String uri = graph.getPossibleURI(resource);
\r
157 return uri != null ? getPossibleVariable(graph, uri) : null;
\r
160 public static Variable getPossibleVariable(ReadGraph graph, String uri) throws DatabaseException {
\r
162 return getVariable(graph, uri);
\r
163 } catch (DatabaseException e) {
\r
168 public static Variable getVariable(ReadGraph graph, Resource resource) throws DatabaseException {
\r
169 return getVariable(graph, graph.getURI(resource));
\r
172 public static Variable getVariable(ReadGraph graph, String uri) throws DatabaseException {
\r
174 return graph.sync(new ResourceURIToVariable(uri));
\r
175 } catch (MissingVariableException e) {
\r
176 return VariableRepository.get(graph, uri);
\r
180 private static int commonPrefixLength(String a, String b) {
\r
181 int maxC = Math.min(a.length(), b.length());
\r
182 for(int c=0;c<maxC;++c) {
\r
183 if(a.charAt(c) != b.charAt(c))
\r
189 private static boolean isSplitPos(String str, int p) {
\r
190 if(p==str.length())
\r
192 char c = str.charAt(p);
\r
193 return c=='/' || c=='#';
\r
196 private static int pathLength(String path) {
\r
198 for(int i=0;i<path.length();++i) {
\r
199 char c = path.charAt(i);
\r
200 if(c=='/' || c=='#')
\r
206 private static String prefixByParentPath(int parentPathLength, String suffix) {
\r
207 StringBuilder b = new StringBuilder();
\r
208 for(int i=0;i<parentPathLength;++i)
\r
211 return b.toString();
\r
214 public static String getRVI(ReadGraph graph, Variable base, Variable other) throws DatabaseException {
\r
215 String baseURI = graph.syncRequest(new VariableURI(base));
\r
216 String otherURI = graph.syncRequest(new VariableURI(other));
\r
217 return getRelativeRVI(baseURI, otherURI);
\r
220 public static String getRelativeRVI(String baseURI, String otherURI) {
\r
221 int prefixLength = commonPrefixLength(baseURI, otherURI);
\r
222 if(!isSplitPos(baseURI, prefixLength) || !isSplitPos(otherURI, prefixLength)) {
\r
223 for(--prefixLength;prefixLength > 0 && !isSplitPos(baseURI, prefixLength);--prefixLength);
\r
225 if(prefixLength == baseURI.length())
\r
226 return otherURI.substring(prefixLength);
\r
228 return prefixByParentPath(
\r
229 pathLength(baseURI.substring(prefixLength)),
\r
230 otherURI.substring(prefixLength));
\r
233 public static String getRVI2(ReadGraph graph, Variable base, Variable other) throws DatabaseException {
\r
234 TObjectIntHashMap<Variable> baseLength = new TObjectIntHashMap<Variable>();
\r
235 for(int depth=0;base != null;base = base.getParent(graph),++depth)
\r
236 baseLength.put(base, depth);
\r
238 for(cur=other;!baseLength.containsKey(cur);cur=cur.getParent(graph));
\r
241 String curURI = cur.getURI(graph);
\r
242 String otherURI = other.getURI(graph);
\r
244 return prefixByParentPath(baseLength.get(cur), otherURI.substring(curURI.length()));
\r
247 public static String getProjectRVI(ReadGraph graph, Variable variable) throws DatabaseException {
\r
248 Resource project = getProject(graph, variable);
\r
249 String projectURI = graph.getURI(project);
\r
250 return variable.getURI(graph).substring(projectURI.length());
\r
253 private static int getSegmentEnd(String suffix) {
\r
255 for(pos=1;pos<suffix.length();++pos) {
\r
256 char c = suffix.charAt(pos);
\r
257 if(c == '/' || c == '#')
\r
263 public static String getRVI(String rvi, String suffix) throws DatabaseException {
\r
264 if(suffix.isEmpty()) return rvi;
\r
265 switch(suffix.charAt(0)) {
\r
267 return getRVI(URIStringUtils.getRVIParent(rvi), suffix.substring(1));
\r
270 int segmentEnd = getSegmentEnd(suffix);
\r
271 return getRVI(rvi + "#" + suffix.substring(1, segmentEnd), suffix.substring(segmentEnd));
\r
274 int segmentEnd = getSegmentEnd(suffix);
\r
275 return getRVI(rvi + "/" + suffix.substring(1, segmentEnd), suffix.substring(segmentEnd));
\r
283 public static Variable getRootVariable(ReadGraph graph) throws DatabaseException {
\r
284 return graph.adapt(graph.getRootLibrary(), Variable.class);
\r
287 public static Resource getPossibleIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {
\r
288 return graph.syncRequest(new PossibleVariableIndexRoot(variable));
\r
291 public static Resource getIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {
\r
292 return graph.syncRequest(new VariableIndexRoot(variable));
\r
295 public static Resource getModel(ReadGraph graph, Variable variable) throws DatabaseException {
\r
296 String URI = variable.getURI(graph);
\r
297 return VariablesImpl.getFirst(graph, SimulationResource.getInstance(graph).Model, URI, 8);
\r
300 public static Resource getPossibleModel(ReadGraph graph, Variable variable) throws DatabaseException {
\r
301 return graph.syncRequest(new PossibleVariableModel(variable));
\r
304 public static Resource getProject(ReadGraph graph, Variable variable) throws DatabaseException {
\r
305 String URI = variable.getURI(graph);
\r
306 return VariablesImpl.getFirst(graph, ProjectResource.getInstance(graph).Project, URI, 8);
\r
309 public static Variable getConfigurationContext(ReadGraph graph, Resource resource) throws DatabaseException {
\r
310 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
311 if(!graph.isInstanceOf(resource, SIMU.Model)) resource = graph.sync(new Model(resource));
\r
312 Resource configurationResource = graph.getSingleObject(resource, SIMU.HasConfiguration);
\r
313 return Variables.getVariable(graph, configurationResource);
\r
316 public static Resource getConfigurationContextResource(ReadGraph graph, Resource resource) throws DatabaseException {
\r
317 Variable config = getConfigurationContext(graph, resource);
\r
318 return config.getRepresents(graph);
\r
321 public static Variable getConfigurationContext(ReadGraph graph, Variable variable) throws DatabaseException {
\r
322 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
323 Resource model = Variables.getModel(graph, variable);
\r
324 Resource configurationResource = graph.getSingleObject(model, SIMU.HasConfiguration);
\r
325 return Variables.getVariable(graph, configurationResource);
\r
328 public static Resource getPossibleConfigurationContextResource(ReadGraph graph, Resource resource) throws DatabaseException {
\r
329 Variable config = getPossibleConfigurationContext(graph, resource);
\r
330 return config != null ? config.getPossibleRepresents(graph) : null;
\r
333 public static Variable getPossibleConfigurationContext(ReadGraph graph, Resource resource) throws DatabaseException {
\r
334 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
335 if (!graph.isInstanceOf(resource, SIMU.Model)) resource = graph.sync(new PossibleIndexRoot(resource));
\r
336 if (resource == null)
\r
338 Resource configurationResource = graph.getPossibleObject(resource, SIMU.HasConfiguration);
\r
339 if (configurationResource == null)
\r
341 return Variables.getPossibleVariable(graph, configurationResource);
\r
344 public static Variable getPossibleConfigurationContext(ReadGraph graph, Variable variable) throws DatabaseException {
\r
345 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
346 Resource model = getPossibleIndexRoot(graph, variable);
\r
349 Resource configurationResource = graph.getPossibleObject(model, SIMU.HasConfiguration);
\r
350 if (configurationResource == null)
\r
352 return Variables.getPossibleVariable(graph, configurationResource);
\r
355 public static Variable getConfigurationVariable(ReadGraph graph, Resource resource, String RVI) throws DatabaseException {
\r
356 Variable context = getConfigurationContext(graph, resource);
\r
357 return context.browse(graph, RVI);
\r
360 public static Variable getConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
\r
361 Variable context = getConfigurationContext(graph, variable);
\r
362 RVI rvi = variable.getRVI(graph);
\r
363 return rvi.resolve(graph, context);
\r
366 public static Variable getPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
\r
367 Variable context = getPossibleConfigurationContext(graph, variable);
\r
368 if (context == null)
\r
371 RVI rvi = variable.getRVI(graph);
\r
372 return rvi.resolvePossible(graph, context);
\r
373 } catch (MissingVariableException e) {
\r
379 public static Datatype getDatatype(ReadGraph graph, Resource resource, RVI rvi) throws DatabaseException {
\r
380 Variable var = rvi.resolve(graph, getConfigurationContext(graph, resource));
\r
381 return var.getDatatype(graph);
\r
385 public static Resource getRealization(ReadGraph graph, Variable variable) throws DatabaseException {
\r
386 String URI = variable.getURI(graph);
\r
387 return VariablesImpl.getFirst(graph, Layer0X.getInstance(graph).Realization, URI, 8);
\r
390 public static boolean isContext(ReadGraph graph, Variable variable) throws DatabaseException {
\r
391 Resource type = variable.getPossibleType(graph);
\r
393 if(graph.isInheritedFrom(type, Layer0.getInstance(graph).RVIContext)) return true;
\r
398 public static Variable getPossibleContext(ReadGraph graph, Variable variable) throws DatabaseException {
\r
399 if(isContext(graph, variable)) return variable;
\r
400 Variable parent = variable.getParent(graph);
\r
401 if(parent == null) return null;
\r
402 return getPossibleContext(graph, parent);
\r
405 public static Variable getContext(ReadGraph graph, Variable variable) throws DatabaseException {
\r
406 Variable context = getPossibleContext(graph, variable);
\r
407 if(context == null) throw new DatabaseException("No context found for " + variable.getURI(graph));
\r
408 else return context;
\r
411 public static RVI getRVI2(ReadGraph graph, Variable variable) throws DatabaseException {
\r
412 return variable.getRVI(graph);
\r
415 public static RVI getPossibleRVI2(ReadGraph graph, Variable variable) throws DatabaseException {
\r
417 return variable.getRVI(graph);
\r
418 } catch (DatabaseException e) {
\r
423 public static String getRVI(ReadGraph graph, Variable variable) throws DatabaseException {
\r
424 Resource realizationResource = getRealization(graph, variable);
\r
425 if (realizationResource == null)
\r
426 throw new DatabaseException("No realization found for " + variable.getURI(graph));
\r
427 return variable.getURI(graph).substring(graph.getURI(realizationResource).length());
\r
430 public static String getRVI(ReadGraph graph, Resource config) throws DatabaseException {
\r
431 Variable var = getVariable(graph, config);
\r
432 return getRVI(graph, var);
\r
435 public static String getPossibleRVI(ReadGraph graph, Resource config) throws DatabaseException {
\r
436 Variable var = getPossibleVariable(graph, config);
\r
437 return var != null ? getPossibleRVI(graph, var) : null;
\r
440 public static String getPossibleRVI(ReadGraph graph, Variable variable) throws DatabaseException {
\r
442 return getRVI(graph, variable);
\r
443 } catch (DatabaseException e) {
\r
448 public static List<Variable> getPath(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
\r
449 if(!isChild(graph, base, var)) return null;
\r
450 LinkedList<Variable> result = new LinkedList<Variable>();
\r
451 var = var.getParent(graph);
\r
452 while(!var.equals(base)) {
\r
453 result.addFirst(var);
\r
454 var = var.getParent(graph);
\r
459 public static Variable getChild(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
\r
460 List<Variable> path = getPath(graph, base, var);
\r
461 if(path == null || path.size() == 0) return null;
\r
462 return path.get(0);
\r
465 public static boolean isChild(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
\r
466 if(base.equals(var)) return false;
\r
467 return var.getURI(graph).startsWith(base.getURI(graph));
\r
470 public static Variable switchRealization(ReadGraph graph, Variable variable, Resource realization) throws DatabaseException {
\r
471 Resource current = getRealization(graph, variable);
\r
472 if(current == null) throw new DatabaseException("No current realization found for variable");
\r
473 return switchRealization(graph, variable, current, realization);
\r
476 public static Variable switchPossibleContext(ReadGraph graph, Variable variable, Resource realization) throws DatabaseException {
\r
477 Variable current = getPossibleContext(graph, variable);
\r
478 if (current == null)
\r
480 Resource currentContext = current.getPossibleRepresents(graph);
\r
481 if (currentContext == null)
\r
483 return switchPossibleRealization(graph, variable, currentContext, realization);
\r
486 public static Variable switchRealization(ReadGraph graph, Variable variable, Variable realization) throws DatabaseException {
\r
487 Resource current = getRealization(graph, variable);
\r
488 return switchRealization(graph, variable, current, realization);
\r
491 public static Variable switchRealization(ReadGraph graph, Variable variable, Resource currentRealization, Resource targetRealization) throws DatabaseException {
\r
492 String currentURI = graph.getURI(currentRealization);
\r
493 String targetURI = graph.getURI(targetRealization);
\r
494 String variableURI = variable.getURI(graph);
\r
495 String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
\r
496 return getVariable(graph, targetVariableURI);
\r
499 public static Variable switchRealization(ReadGraph graph, Variable variable, Resource currentRealization, Variable targetRealization) throws DatabaseException {
\r
500 String currentURI = graph.getURI(currentRealization);
\r
501 String targetURI = targetRealization.getURI(graph);
\r
502 String variableURI = variable.getURI(graph);
\r
503 String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
\r
504 return getVariable(graph, targetVariableURI);
\r
507 public static Variable switchPossibleRealization(ReadGraph graph, Variable variable, Resource currentRealization, Resource targetRealization) throws DatabaseException {
\r
508 String currentURI = graph.getURI(currentRealization);
\r
509 String targetURI = graph.getURI(targetRealization);
\r
510 String variableURI = variable.getURI(graph);
\r
511 String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
\r
512 return getPossibleVariable(graph, targetVariableURI);
\r
515 public static Variable toConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
\r
516 Variable config = getConfigurationContext(graph, variable);
\r
517 return switchRealization(graph, variable, config);
\r
520 public static Variable toPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
\r
522 Resource represents = variable.getPossibleRepresents(graph);
\r
523 if(represents == null) return null;
\r
524 Resource config = getPossibleConfigurationContextResource(graph, represents);
\r
525 if(config == null) return null;
\r
526 return switchPossibleContext(graph, variable, config);
\r
530 public static String toRVI(ReadGraph graph, List<Resource> compositePath) throws DatabaseException {
\r
531 Layer0 L0 = Layer0.getInstance(graph);
\r
532 StringBuilder rvi = new StringBuilder();
\r
533 for (Resource composite : compositePath) {
\r
534 String name = graph.getPossibleRelatedValue(composite, L0.HasName);
\r
539 String escapedName = URIStringUtils.escape(name);
\r
540 rvi.append(escapedName);
\r
542 return rvi.toString();
\r
545 public static String appendRVI(ReadGraph graph, String modelURI, String rvi, Resource configuration) throws DatabaseException {
\r
547 Layer0 L0 = Layer0.getInstance(graph);
\r
548 String partName = graph.getPossibleRelatedValue(configuration, L0.HasName);
\r
549 if(partName == null) throw new MissingVariableException("Can not append a child corresponding to " + configuration + " to rvi '" + rvi + "' since there is no name.");
\r
550 String escaped = URIStringUtils.escape(partName);
\r
551 return rvi + "/" + escaped;
\r
555 public static boolean isValid(ReadGraph graph, Variable variable) {
\r
556 if(variable == null) return false;
\r
558 variable.getURI(graph);
\r
559 } catch (DatabaseException e) {
\r
565 public static Variable possibleChildWithType(ReadGraph graph, Variable variable, Resource targetType) throws DatabaseException {
\r
566 Variable found = null;
\r
567 for(Variable child : variable.getChildren(graph)) {
\r
568 Resource type = child.getPossiblePropertyValue(graph, Variables.TYPE);
\r
569 if(type != null && graph.isInheritedFrom(type, targetType)) {
\r
570 if(found != null) return null;
\r
577 public static Collection<Variable> childrenWithType(ReadGraph graph, Variable variable, Resource targetType) throws DatabaseException {
\r
578 ArrayList<Variable> result = new ArrayList<Variable>();
\r
579 for(Variable child : variable.getChildren(graph)) {
\r
580 Resource type = child.getPossiblePropertyValue(graph, Variables.TYPE);
\r
581 if(graph.isInheritedFrom(type, targetType)) result.add(child);
\r
586 public static <T> T adapt(ReadGraph graph, Variable variable, String property, Class<T> clazz) throws DatabaseException {
\r
587 Resource resource = variable.getPropertyValue(graph, property);
\r
588 return graph.adapt(resource, clazz);
\r
591 public static <T> T getPossiblePropertyValue(RequestProcessor processor, Variable variable, Resource property, Binding binding) {
\r
593 return processor.sync(new TernaryRead<Variable,Resource,Binding,T>(variable, property, binding) {
\r
596 public T perform(ReadGraph graph) throws DatabaseException {
\r
597 return parameter.getPossiblePropertyValue(graph, parameter2, parameter3);
\r
601 } catch (DatabaseException e) {
\r
606 public static Variable possibleActiveVariable(ReadGraph graph, Variable variable) throws DatabaseException {
\r
607 Variable activeVariable = graph.sync(new PossibleActiveVariableFromVariable(variable));
\r
608 return activeVariable;
\r
611 public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node) throws DatabaseException {
\r
612 return requestNodeValue(graph, node, null);
\r
615 public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node, final Binding binding) throws DatabaseException {
\r
616 Variant value = graph.syncRequest(new NodeValueRequest(node, binding));
\r
617 if(PENDING_NODE_VALUE == value && graph.getSynchronous()) {
\r
618 // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
\r
620 ValueGetter getter = new ValueGetter(node, binding);
\r
622 node.support.manager.getRealm().syncExec(getter);
\r
623 } catch (InterruptedException e) {
\r
624 Logger.defaultLogError(e);
\r
627 if (getter.exception != null)
\r
628 throw new DatabaseException(getter.exception);
\r
630 return getter.result;
\r
635 public static class NodeStructure {
\r
636 // Immutable but wrapped with Collections.unmodifiableMap as an optimization
\r
637 public final Map<String,Object> children;
\r
638 // Immutable but not wrapped with Collections.unmodifiableMap as an optimization
\r
639 public final Map<String,Object> properties;
\r
640 private final int hash;
\r
642 public NodeStructure(Map<String, Object> children, Map<String, Object> properties) {
\r
643 this.children = children;
\r
644 this.properties = properties;
\r
645 this.hash = calcHash();
\r
648 private int calcHash() {
\r
649 return 31*children.hashCode() + 41*properties.hashCode();
\r
653 public int hashCode() {
\r
658 public boolean equals(Object object) {
\r
659 if (this == object)
\r
661 else if (object == null || object == Variables.PENDING_NODE_STRUCTURE)
\r
663 else if (!(object instanceof NodeStructure))
\r
665 NodeStructure r = (NodeStructure)object;
\r
666 return r.children.equals(children) && r.properties.equals(properties);
\r
670 public static NodeStructure requestNodeStructure(ReadGraph graph, VariableNode<?> node) throws DatabaseException {
\r
671 NodeStructure value = graph.syncRequest(new NodeStructureRequest(node));
\r
672 if (value == null) throw new DatabaseException("External data access error");
\r
673 if(PENDING_NODE_STRUCTURE == value && graph.getSynchronous()) {
\r
674 // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
\r
676 StructureGetter getter = new StructureGetter(node);
\r
678 node.support.manager.getRealm().syncExec(getter);
\r
679 } catch (InterruptedException e) {
\r
680 Logger.defaultLogError(e);
\r
681 throw new DatabaseException("External data access error", e);
\r
684 if (getter.exception != null)
\r
685 throw new DatabaseException("External data access error", getter.exception);
\r
686 if (getter.result == null)
\r
687 throw new DatabaseException("External data access error");
\r
689 return getter.result;
\r
696 public static String getPossibleUnit(ReadGraph graph, Variable variable) throws DatabaseException {
\r
700 Resource predicate = variable.getPossiblePredicateResource(graph);
\r
701 if(predicate != null) {
\r
702 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
\r
703 if(info.definedUnit != null) return info.definedUnit;
\r
706 Variant variant = variable.getVariantValue(graph);
\r
707 Binding binding = variant.getBinding();
\r
708 if(binding == null) return null;
\r
709 Datatype dt = binding.type();
\r
710 if(!(dt instanceof NumberType)) return null;
\r
711 NumberType nt = (NumberType)dt;
\r
712 return nt.getUnit();
\r
714 } catch (DatabaseException e) {
\r
723 * @param context1 primary context to use for resolving the specified RVI, must not be null
\r
724 * @param context2 secondary context to use for resolving the specified RVI, may be <code>null</code>
\r
725 * @return pair of variables where first is the resolved variable and second
\r
726 * is the context it was resolved with
\r
727 * @throws DatabaseException
\r
730 public static Pair<Variable, Variable> resolvePossible(ReadGraph graph, RVI rvi, Variable context1, Variable context2) throws DatabaseException {
\r
731 Variable v = rvi.resolvePossible(graph, context1);
\r
733 return new Pair<>(v, context1);
\r
734 if (context2 != null) {
\r
735 v = rvi.resolvePossible(graph, context2);
\r
737 return new Pair<>(v, context2);
\r
743 @SuppressWarnings("rawtypes")
\r
744 private static class ValueGetter implements VariableNodeReadRunnable {
\r
746 final VariableNode n;
\r
747 final Binding binding;
\r
749 Exception exception;
\r
751 public ValueGetter(VariableNode n, Binding binding) {
\r
753 this.binding = binding;
\r
756 @SuppressWarnings("unchecked")
\r
758 public void run() {
\r
760 if (binding != null)
\r
761 result = new Variant(binding, n.support.manager.getValue(n.node, binding));
\r
763 result = n.support.manager.getValue(n.node);
\r
764 } catch (Exception e) {
\r
765 Logger.defaultLogError(e);
\r
772 @SuppressWarnings("rawtypes")
\r
773 private static class StructureGetter implements VariableNodeReadRunnable {
\r
775 final VariableNode n;
\r
776 NodeStructure result;
\r
777 Exception exception;
\r
779 public StructureGetter(VariableNode n) {
\r
784 public void run() {
\r
786 result = NodeStructureRequest.get(n);
\r
787 } catch (NodeManagerException e) {
\r
788 Logger.defaultLogError(e);
\r
795 public static Variable tryGetProperty(ReadGraph graph, Resource entity, Resource property) throws DatabaseException {
\r
796 Variable v = Variables.getPossibleVariable(graph, entity);
\r
797 return v != null ? v.getPossibleProperty(graph, property) : null;
\r
800 public static ValueAccessor createValueAccessor(Function1<Variable, Object> getValue1, Function2<Variable, Binding, Object> getValue2,
\r
801 Function2<Variable, Object, Object> setValue2, Function3<Variable, Object, Binding, Object> setValue3,
\r
802 Function1<Variable, Datatype> getDatatype) {
\r
803 return new SCLValueAccessor(getValue1, getValue2, setValue2, setValue3, getDatatype);
\r