1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.layer0.variable;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.LinkedList;
18 import java.util.List;
21 import org.simantics.databoard.Bindings;
22 import org.simantics.databoard.Databoard;
23 import org.simantics.databoard.binding.Binding;
24 import org.simantics.databoard.binding.mutable.Variant;
25 import org.simantics.databoard.type.Datatype;
26 import org.simantics.databoard.type.NumberType;
27 import org.simantics.databoard.util.URIStringUtils;
28 import org.simantics.db.ReadGraph;
29 import org.simantics.db.RequestProcessor;
30 import org.simantics.db.Resource;
31 import org.simantics.db.WriteGraph;
32 import org.simantics.db.common.request.PossibleIndexRoot;
33 import org.simantics.db.common.request.TernaryRead;
34 import org.simantics.db.common.utils.CommonDBUtils;
35 import org.simantics.db.exception.DatabaseException;
36 import org.simantics.db.layer0.exception.InvalidVariableException;
37 import org.simantics.db.layer0.exception.MissingVariableException;
38 import org.simantics.db.layer0.exception.MissingVariableValueException;
39 import org.simantics.db.layer0.request.Model;
40 import org.simantics.db.layer0.request.PossibleActiveVariableFromVariable;
41 import org.simantics.db.layer0.request.PossibleVariableIndexRoot;
42 import org.simantics.db.layer0.request.PossibleVariableModel;
43 import org.simantics.db.layer0.request.PropertyInfo;
44 import org.simantics.db.layer0.request.PropertyInfoRequest;
45 import org.simantics.db.layer0.request.ResourceURIToVariable;
46 import org.simantics.db.layer0.request.VariableIndexRoot;
47 import org.simantics.db.layer0.request.VariableURI;
48 import org.simantics.layer0.Layer0;
49 import org.simantics.operation.Layer0X;
50 import org.simantics.project.ontology.ProjectResource;
51 import org.simantics.scl.runtime.function.Function1;
52 import org.simantics.scl.runtime.function.Function2;
53 import org.simantics.scl.runtime.function.Function3;
54 import org.simantics.simulation.ontology.SimulationResource;
55 import org.simantics.simulator.variable.NodeManager;
56 import org.simantics.simulator.variable.exceptions.NodeManagerException;
57 import org.simantics.utils.datastructures.Pair;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 import gnu.trove.map.hash.TObjectIntHashMap;
63 final public class Variables {
65 private static final Logger LOGGER = LoggerFactory.getLogger(Variables.class);
67 public static final Variant PENDING_NODE_VALUE = NodeManager.PENDING_NODE_VALUE;
69 public static final NodeStructure PENDING_NODE_STRUCTURE = new NodeStructure(Collections.emptyMap(), Collections.emptyMap()) {
70 public boolean equals(Object object) {
71 return this == object;
75 public static enum Role {
77 CHILD("/"), PROPERTY("#");
79 transient final String identifier;
81 private Role(String identifier) {
82 this.identifier = identifier;
85 final public String getIdentifier() {
89 public static Role getRole( String identifier ) {
90 for (Role role : Role.values()) if (role.identifier.equals( identifier )) return role;
97 //final public static String PREDICATE = "PREDICATE";
101 final public static String NAME = "HasName";
102 final public static String CLASSIFICATIONS = "classifications";
103 final public static String EXPRESSION = "HasExpression";
104 final public static String INPUT_VALIDATOR = "HasInputValidator";
105 final public static String INPUT_MODIFIER = "HasInputModifier";
106 final public static String FORMATTER = "HasFormatter";
108 final public static String STANDARD_RESOURCE = "hasStandardResource";
111 //final public static String REPRESENTS = "Represents";
112 final public static String TYPE = "Type";
113 final public static String URI = "URI";
115 * @deprecated use {@link Variable#getRVI(ReadGraph)} and {@link RVI} instead.
118 // final public static String SERIALISED = "Serialised";
121 //final public static String PARENT = "Parent";
122 //final public static String ROLE = "Role";
123 //final public static String DATATYPE = "DATATYPE";
124 //final public static String UNIT = "UNIT";
126 final public static String VALID = "valid";
127 final public static String REQUIRED = "required";
128 final public static String DEFAULT = "default";
129 final public static String READONLY = "readOnly";
130 final public static String VALIDATOR = "validator";
132 final public static String LABEL = "HasLabel";
134 final public static String ENUMERATION_VALUES = "HasEnumerationValues";
135 final public static String CUSTOM_MODIFIER = "HasCustomModifier";
137 final public static String DISPLAY_COLUMN = "HasDisplayColumn";
139 final public static String DISPLAY_PROPERTY = "HasDisplayProperty";
140 final public static String DISPLAY_VALUE = "HasDisplayValue";
141 final public static String DISPLAY_UNIT = "HasDisplayUnit";
143 final public static String CONVERTED_VALUE = "convertedValue";
146 * This property should exist for array valued property variables.
148 final public static String ARRAY_SIZE = "ARRAY_SIZE";
152 // use etc. variable.adapt(graph, Interface.class).getResource()
153 final public static String RESOURCE = "Resource";
155 final public static String CONTAINER_RESOURCE = "ContainerResource";
157 final public static String PROPERTY_RESOURCE = "PROPERTY_RESOURCE";
160 public final static String[] builtins = {
165 public static Variable getPossibleVariable(ReadGraph graph, Resource resource) throws DatabaseException {
166 String uri = graph.getPossibleURI(resource);
168 return getPossibleVariable(graph, uri);
169 Resource parent = CommonDBUtils.getPossibleOwner(graph, resource);
172 Variable possibleVariable = getPossibleVariable(graph, parent);
173 if (possibleVariable == null)
175 String possibleName = graph.getPossibleRelatedValue(resource, Layer0.getInstance(graph).HasName, Bindings.STRING);
176 if (possibleName == null)
177 possibleName = VariableUtils.unnamedResourceName(resource);
178 Variable possibleChild = possibleVariable.getPossibleChild(graph, possibleName);
179 if (possibleChild != null)
180 return possibleChild;
181 for (Variable v : possibleVariable.getChildren(graph)) {
182 Resource vr = v.getPossibleRepresents(graph);
183 if (vr != null && vr.equals(resource)) {
190 public static Variable getPossibleVariable(ReadGraph graph, String uri) throws DatabaseException {
192 return getVariable(graph, uri);
193 } catch (DatabaseException e) {
198 public static Variable getVariable(ReadGraph graph, Resource resource) throws DatabaseException {
199 return getVariable(graph, graph.getURI(resource));
202 public static Variable getVariable(ReadGraph graph, String uri) throws DatabaseException {
204 return graph.sync(new ResourceURIToVariable(uri));
205 } catch (MissingVariableException e) {
206 return VariableRepository.get(graph, uri);
210 private static int commonPrefixLength(String a, String b) {
211 int maxC = Math.min(a.length(), b.length());
212 for(int c=0;c<maxC;++c) {
213 if(a.charAt(c) != b.charAt(c))
219 private static boolean isSplitPos(String str, int p) {
222 char c = str.charAt(p);
223 return c=='/' || c=='#';
226 private static int pathLength(String path) {
228 for(int i=0;i<path.length();++i) {
229 char c = path.charAt(i);
236 private static String prefixByParentPath(int parentPathLength, String suffix) {
237 StringBuilder b = new StringBuilder();
238 for(int i=0;i<parentPathLength;++i)
244 public static String getRVI(ReadGraph graph, Variable base, Variable other) throws DatabaseException {
245 String baseURI = graph.syncRequest(new VariableURI(base));
246 String otherURI = graph.syncRequest(new VariableURI(other));
247 return getRelativeRVI(baseURI, otherURI);
250 public static String getRelativeRVI(String baseURI, String otherURI) {
251 int prefixLength = commonPrefixLength(baseURI, otherURI);
252 if(!isSplitPos(baseURI, prefixLength) || !isSplitPos(otherURI, prefixLength)) {
253 for(--prefixLength;prefixLength > 0 && !isSplitPos(baseURI, prefixLength);--prefixLength);
255 if(prefixLength == baseURI.length())
256 return otherURI.substring(prefixLength);
258 return prefixByParentPath(
259 pathLength(baseURI.substring(prefixLength)),
260 otherURI.substring(prefixLength));
263 public static String getRVI2(ReadGraph graph, Variable base, Variable other) throws DatabaseException {
264 TObjectIntHashMap<Variable> baseLength = new TObjectIntHashMap<Variable>();
265 for(int depth=0;base != null;base = base.getParent(graph),++depth)
266 baseLength.put(base, depth);
268 for(cur=other;!baseLength.containsKey(cur);cur=cur.getParent(graph));
271 String curURI = cur.getURI(graph);
272 String otherURI = other.getURI(graph);
274 return prefixByParentPath(baseLength.get(cur), otherURI.substring(curURI.length()));
277 public static String getProjectRVI(ReadGraph graph, Variable variable) throws DatabaseException {
278 Resource project = getProject(graph, variable);
279 String projectURI = graph.getURI(project);
280 return variable.getURI(graph).substring(projectURI.length());
283 private static int getSegmentEnd(String suffix) {
285 for(pos=1;pos<suffix.length();++pos) {
286 char c = suffix.charAt(pos);
287 if(c == '/' || c == '#')
293 public static String getRVI(String rvi, String suffix) throws DatabaseException {
294 if(suffix.isEmpty()) return rvi;
295 switch(suffix.charAt(0)) {
297 return getRVI(URIStringUtils.getRVIParent(rvi), suffix.substring(1));
300 int segmentEnd = getSegmentEnd(suffix);
301 return getRVI(rvi + "#" + suffix.substring(1, segmentEnd), suffix.substring(segmentEnd));
304 int segmentEnd = getSegmentEnd(suffix);
305 return getRVI(rvi + "/" + suffix.substring(1, segmentEnd), suffix.substring(segmentEnd));
313 public static Variable getRootVariable(ReadGraph graph) throws DatabaseException {
314 return graph.adapt(graph.getRootLibrary(), Variable.class);
317 public static Resource getPossibleIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {
318 return graph.syncRequest(new PossibleVariableIndexRoot(variable));
321 public static Resource getIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {
322 return graph.syncRequest(new VariableIndexRoot(variable));
325 public static Resource getModel(ReadGraph graph, Variable variable) throws DatabaseException {
326 String URI = variable.getURI(graph);
327 return VariablesImpl.getFirst(graph, SimulationResource.getInstance(graph).Model, URI, 8);
330 public static Resource getPossibleModel(ReadGraph graph, Variable variable) throws DatabaseException {
331 return graph.syncRequest(new PossibleVariableModel(variable));
334 public static Resource getProject(ReadGraph graph, Variable variable) throws DatabaseException {
335 String URI = variable.getURI(graph);
336 return VariablesImpl.getFirst(graph, ProjectResource.getInstance(graph).Project, URI, 8);
339 public static Variable getConfigurationContext(ReadGraph graph, Resource resource) throws DatabaseException {
340 SimulationResource SIMU = SimulationResource.getInstance(graph);
341 if(!graph.isInstanceOf(resource, SIMU.Model)) resource = graph.sync(new Model(resource));
342 Resource configurationResource = graph.getSingleObject(resource, SIMU.HasConfiguration);
343 return Variables.getVariable(graph, configurationResource);
346 public static Resource getConfigurationContextResource(ReadGraph graph, Resource resource) throws DatabaseException {
347 Variable config = getConfigurationContext(graph, resource);
348 return config.getRepresents(graph);
351 public static Variable getConfigurationContext(ReadGraph graph, Variable variable) throws DatabaseException {
352 SimulationResource SIMU = SimulationResource.getInstance(graph);
353 Resource model = Variables.getModel(graph, variable);
354 Resource configurationResource = graph.getSingleObject(model, SIMU.HasConfiguration);
355 return Variables.getVariable(graph, configurationResource);
358 public static Resource getPossibleConfigurationContextResource(ReadGraph graph, Resource resource) throws DatabaseException {
359 Variable config = getPossibleConfigurationContext(graph, resource);
360 return config != null ? config.getPossibleRepresents(graph) : null;
363 public static Variable getPossibleConfigurationContext(ReadGraph graph, Resource resource) throws DatabaseException {
364 SimulationResource SIMU = SimulationResource.getInstance(graph);
365 if (!graph.isInstanceOf(resource, SIMU.Model)) resource = graph.sync(new PossibleIndexRoot(resource));
366 if (resource == null)
368 Resource configurationResource = graph.getPossibleObject(resource, SIMU.HasConfiguration);
369 if (configurationResource == null)
371 return Variables.getPossibleVariable(graph, configurationResource);
374 public static Variable getPossibleConfigurationContext(ReadGraph graph, Variable variable) throws DatabaseException {
375 SimulationResource SIMU = SimulationResource.getInstance(graph);
376 Resource model = getPossibleIndexRoot(graph, variable);
379 Resource configurationResource = graph.getPossibleObject(model, SIMU.HasConfiguration);
380 if (configurationResource == null)
382 return Variables.getPossibleVariable(graph, configurationResource);
385 public static Variable getConfigurationVariable(ReadGraph graph, Resource resource, String RVI) throws DatabaseException {
386 Variable context = getConfigurationContext(graph, resource);
387 return context.browse(graph, RVI);
390 public static Variable getConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
391 Variable context = getConfigurationContext(graph, variable);
392 RVI rvi = variable.getRVI(graph);
393 return rvi.resolve(graph, context);
396 public static Variable getPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
397 Variable context = getPossibleConfigurationContext(graph, variable);
401 RVI rvi = variable.getRVI(graph);
402 return rvi.resolvePossible(graph, context);
403 } catch (MissingVariableException e) {
409 public static Datatype getDatatype(ReadGraph graph, Resource resource, RVI rvi) throws DatabaseException {
410 Variable var = rvi.resolve(graph, getConfigurationContext(graph, resource));
411 return var.getDatatype(graph);
415 public static Resource getRealization(ReadGraph graph, Variable variable) throws DatabaseException {
416 String URI = variable.getURI(graph);
417 return VariablesImpl.getFirst(graph, Layer0X.getInstance(graph).Realization, URI, 8);
420 public static boolean isContext(ReadGraph graph, Variable variable) throws DatabaseException {
421 Resource type = variable.getPossibleType(graph);
423 if(graph.isInheritedFrom(type, Layer0.getInstance(graph).RVIContext)) return true;
428 public static Variable getPossibleContext(ReadGraph graph, Variable variable) throws DatabaseException {
429 if(isContext(graph, variable)) return variable;
430 Variable parent = variable.getParent(graph);
431 if(parent == null) return null;
432 return getPossibleContext(graph, parent);
435 public static Variable getContext(ReadGraph graph, Variable variable) throws DatabaseException {
436 Variable context = getPossibleContext(graph, variable);
438 throw new MissingVariableException("No context found for " + variable.getURI(graph), variable.getPossibleRepresents(graph));
442 public static RVI getRVI2(ReadGraph graph, Variable variable) throws DatabaseException {
443 return variable.getRVI(graph);
446 public static RVI getPossibleRVI2(ReadGraph graph, Variable variable) throws DatabaseException {
448 return variable.getRVI(graph);
449 } catch (DatabaseException e) {
454 public static String getRVI(ReadGraph graph, Variable variable) throws DatabaseException {
455 Resource realizationResource = getRealization(graph, variable);
456 if (realizationResource == null)
457 throw new InvalidVariableException("No realization found for " + variable.getURI(graph));
458 return variable.getURI(graph).substring(graph.getURI(realizationResource).length());
461 public static String getRVI(ReadGraph graph, Resource config) throws DatabaseException {
462 Variable var = getVariable(graph, config);
463 return getRVI(graph, var);
466 public static String getPossibleRVI(ReadGraph graph, Resource config) throws DatabaseException {
467 Variable var = getPossibleVariable(graph, config);
468 return var != null ? getPossibleRVI(graph, var) : null;
471 public static String getPossibleRVI(ReadGraph graph, Variable variable) throws DatabaseException {
473 return getRVI(graph, variable);
474 } catch (DatabaseException e) {
479 public static List<Variable> getPath(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
480 if(!isChild(graph, base, var)) return null;
481 LinkedList<Variable> result = new LinkedList<Variable>();
482 var = var.getParent(graph);
483 while(!var.equals(base)) {
484 result.addFirst(var);
485 var = var.getParent(graph);
490 public static Variable getChild(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
491 List<Variable> path = getPath(graph, base, var);
492 if(path == null || path.size() == 0) return null;
496 public static boolean isChild(ReadGraph graph, Variable base, Variable var) throws DatabaseException {
497 if(base.equals(var)) return false;
498 return var.getURI(graph).startsWith(base.getURI(graph));
501 public static Variable switchRealization(ReadGraph graph, Variable variable, Resource realization) throws DatabaseException {
502 Resource current = getRealization(graph, variable);
504 throw new InvalidVariableException("No current realization found for variable");
505 return switchRealization(graph, variable, current, realization);
508 public static Variable switchPossibleContext(ReadGraph graph, Variable variable, Resource realization) throws DatabaseException {
509 Variable current = getPossibleContext(graph, variable);
512 Resource currentContext = current.getPossibleRepresents(graph);
513 if (currentContext == null)
515 return switchPossibleRealization(graph, variable, currentContext, realization);
518 public static Variable switchRealization(ReadGraph graph, Variable variable, Variable realization) throws DatabaseException {
519 Resource current = getRealization(graph, variable);
520 return switchRealization(graph, variable, current, realization);
523 public static Variable switchRealization(ReadGraph graph, Variable variable, Resource currentRealization, Resource targetRealization) throws DatabaseException {
524 String currentURI = graph.getURI(currentRealization);
525 String targetURI = graph.getURI(targetRealization);
526 String variableURI = variable.getURI(graph);
527 String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
528 return getVariable(graph, targetVariableURI);
531 public static Variable switchRealization(ReadGraph graph, Variable variable, Resource currentRealization, Variable targetRealization) throws DatabaseException {
532 String currentURI = graph.getURI(currentRealization);
533 String targetURI = targetRealization.getURI(graph);
534 String variableURI = variable.getURI(graph);
535 String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
536 return getVariable(graph, targetVariableURI);
539 public static Variable switchPossibleRealization(ReadGraph graph, Variable variable, Resource currentRealization, Resource targetRealization) throws DatabaseException {
540 String currentURI = graph.getURI(currentRealization);
541 String targetURI = graph.getURI(targetRealization);
542 String variableURI = variable.getURI(graph);
543 String targetVariableURI = targetURI + variableURI.substring(currentURI.length());
544 return getPossibleVariable(graph, targetVariableURI);
547 public static Variable toConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
548 Variable config = getConfigurationContext(graph, variable);
549 return switchRealization(graph, variable, config);
552 public static Variable toPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
554 Resource represents = variable.getPossibleRepresents(graph);
555 if(represents == null) return null;
556 Resource config = getPossibleConfigurationContextResource(graph, represents);
557 if(config == null) return null;
558 return switchPossibleContext(graph, variable, config);
562 public static String toRVI(ReadGraph graph, List<Resource> compositePath) throws DatabaseException {
563 Layer0 L0 = Layer0.getInstance(graph);
564 StringBuilder rvi = new StringBuilder();
565 for (Resource composite : compositePath) {
566 String name = graph.getPossibleRelatedValue(composite, L0.HasName);
571 String escapedName = URIStringUtils.escape(name);
572 rvi.append(escapedName);
574 return rvi.toString();
577 public static String appendRVI(ReadGraph graph, String modelURI, String rvi, Resource configuration) throws DatabaseException {
578 Layer0 L0 = Layer0.getInstance(graph);
579 String partName = graph.getPossibleRelatedValue(configuration, L0.HasName);
580 if (partName == null)
581 throw new MissingVariableException("Can not append a child corresponding to " + configuration + " to rvi '"
582 + rvi + "' since there is no name.", configuration);
583 String escaped = URIStringUtils.escape(partName);
584 return rvi + "/" + escaped;
587 public static boolean isValid(ReadGraph graph, Variable variable) {
588 if(variable == null) return false;
590 variable.getURI(graph);
591 } catch (DatabaseException e) {
597 public static Variable possibleChildWithType(ReadGraph graph, Variable variable, Resource targetType) throws DatabaseException {
598 Variable found = null;
599 for(Variable child : variable.getChildren(graph)) {
600 Resource type = child.getPossiblePropertyValue(graph, Variables.TYPE);
601 if(type != null && graph.isInheritedFrom(type, targetType)) {
602 if(found != null) return null;
609 public static Collection<Variable> childrenWithType(ReadGraph graph, Variable variable, Resource targetType) throws DatabaseException {
610 ArrayList<Variable> result = new ArrayList<Variable>();
611 for(Variable child : variable.getChildren(graph)) {
612 Resource type = child.getPossiblePropertyValue(graph, Variables.TYPE);
613 if(graph.isInheritedFrom(type, targetType)) result.add(child);
618 public static <T> T adapt(ReadGraph graph, Variable variable, String property, Class<T> clazz) throws DatabaseException {
619 Resource resource = variable.getPropertyValue(graph, property);
620 return graph.adapt(resource, clazz);
623 public static <T> T getPossiblePropertyValue(RequestProcessor processor, Variable variable, Resource property, Binding binding) {
625 return processor.sync(new TernaryRead<Variable,Resource,Binding,T>(variable, property, binding) {
628 public T perform(ReadGraph graph) throws DatabaseException {
629 return parameter.getPossiblePropertyValue(graph, parameter2, parameter3);
633 } catch (DatabaseException e) {
638 public static Variable possibleActiveVariable(ReadGraph graph, Variable variable) throws DatabaseException {
639 Variable activeVariable = graph.sync(new PossibleActiveVariableFromVariable(variable));
640 return activeVariable;
643 public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node) throws DatabaseException {
644 return requestNodeValue(graph, node, null);
647 public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node, final Binding binding) throws DatabaseException {
648 Variant value = graph.syncRequest(new NodeValueRequest(node, binding));
649 if(PENDING_NODE_VALUE == value && graph.getSynchronous()) {
650 // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
652 ValueGetter getter = new ValueGetter(node, binding);
654 node.support.manager.getRealm().syncExec(getter);
655 } catch (InterruptedException e) {
656 LOGGER.error("Error while getting node value", e);
657 throw new InvalidVariableException("External data access error " + String.valueOf(node), e);
660 if (getter.exception != null)
661 throw new MissingVariableValueException("No value for node " + node, getter.exception);
663 return getter.result;
668 public static class NodeStructure {
669 // Immutable but wrapped with Collections.unmodifiableMap as an optimization
670 public final Map<String,Object> children;
671 // Immutable but not wrapped with Collections.unmodifiableMap as an optimization
672 public final Map<String,Object> properties;
673 private final int hash;
675 public NodeStructure(Map<String, Object> children, Map<String, Object> properties) {
676 this.children = children;
677 this.properties = properties;
678 this.hash = calcHash();
681 private int calcHash() {
682 return 31*children.hashCode() + 41*properties.hashCode();
686 public int hashCode() {
691 public boolean equals(Object object) {
694 else if (object == null || object == Variables.PENDING_NODE_STRUCTURE)
696 else if (!(object instanceof NodeStructure))
698 NodeStructure r = (NodeStructure)object;
699 return r.children.equals(children) && r.properties.equals(properties);
703 public static NodeStructure requestNodeStructure(ReadGraph graph, VariableNode<?> node) throws DatabaseException {
704 NodeStructure value = graph.syncRequest(new NodeStructureRequest(node));
706 throw new InvalidVariableException("External data access error " + String.valueOf(node));
707 if(PENDING_NODE_STRUCTURE == value && graph.getSynchronous()) {
708 // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
710 StructureGetter getter = new StructureGetter(node);
712 node.support.manager.getRealm().syncExec(getter);
713 } catch (InterruptedException e) {
714 LOGGER.error("Error while getting node structure", e);
715 throw new InvalidVariableException("External data access error " + String.valueOf(node), e);
718 if (getter.exception != null)
719 throw new InvalidVariableException("External data access error " + String.valueOf(node), getter.exception);
720 if (getter.result == null)
721 throw new InvalidVariableException("External data access error " + String.valueOf(node));
723 return getter.result;
730 public static String getPossibleUnit(ReadGraph graph, Variable variable) throws DatabaseException {
734 Resource predicate = variable.getPossiblePredicateResource(graph);
735 if(predicate != null) {
736 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
737 if(info.definedUnit != null) return info.definedUnit;
740 Variant variant = variable.getVariantValue(graph);
741 Binding binding = variant.getBinding();
742 if(binding == null) return null;
743 Datatype dt = binding.type();
744 if(!(dt instanceof NumberType)) return null;
745 NumberType nt = (NumberType)dt;
748 } catch (DatabaseException e) {
757 * @param context1 primary context to use for resolving the specified RVI, must not be null
758 * @param context2 secondary context to use for resolving the specified RVI, may be <code>null</code>
759 * @return pair of variables where first is the resolved variable and second
760 * is the context it was resolved with
761 * @throws DatabaseException
764 public static Pair<Variable, Variable> resolvePossible(ReadGraph graph, RVI rvi, Variable context1, Variable context2) throws DatabaseException {
765 Variable v = rvi.resolvePossible(graph, context1);
767 return new Pair<>(v, context1);
768 if (context2 != null) {
769 v = rvi.resolvePossible(graph, context2);
771 return new Pair<>(v, context2);
777 @SuppressWarnings("rawtypes")
778 private static class ValueGetter implements VariableNodeReadRunnable {
780 final VariableNode n;
781 final Binding binding;
785 public ValueGetter(VariableNode n, Binding binding) {
787 this.binding = binding;
790 @SuppressWarnings("unchecked")
795 result = new Variant(binding, n.support.manager.getValue(n.node, binding));
797 result = n.support.manager.getValue(n.node);
798 } catch (NodeManagerException e) {
800 } catch (Exception e) {
801 LOGGER.error("Error while getting node value", e);
808 @SuppressWarnings("rawtypes")
809 private static class StructureGetter implements VariableNodeReadRunnable {
811 final VariableNode n;
812 NodeStructure result;
815 public StructureGetter(VariableNode n) {
822 result = NodeStructureRequest.get(n);
823 } catch (NodeManagerException e) {
830 public static Variable tryGetProperty(ReadGraph graph, Resource entity, Resource property) throws DatabaseException {
831 Variable v = Variables.getPossibleVariable(graph, entity);
832 return v != null ? v.getPossibleProperty(graph, property) : null;
835 public static ValueAccessor createValueAccessor(Function1<Variable, Object> getValue1, Function2<Variable, Binding, Object> getValue2,
836 Function2<Variable, Object, Object> setValue2, Function3<Variable, Object, Binding, Object> setValue3,
837 Function1<Variable, Datatype> getDatatype) {
838 return new SCLValueAccessor(getValue1, getValue2, setValue2, setValue3, getDatatype);
841 public static void setRVIProperty(WriteGraph graph, Variable variable, RVI rvi) throws DatabaseException {
842 Layer0 L0 = Layer0.getInstance(graph);
843 Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class );
844 Resource predicate = variable.getPredicateResource(graph);
845 Resource subject = variable.getParent(graph).getRepresents(graph);
846 graph.deny(subject, predicate);
847 graph.claimLiteral(subject, predicate, L0.RVI, rvi, rviBinding);