1 package org.simantics.structural2.variables;
\r
3 import gnu.trove.map.hash.THashMap;
\r
4 import gnu.trove.set.hash.THashSet;
\r
6 import java.util.ArrayList;
\r
7 import java.util.Collection;
\r
8 import java.util.Collections;
\r
9 import java.util.HashMap;
\r
10 import java.util.HashSet;
\r
11 import java.util.List;
\r
12 import java.util.Map;
\r
13 import java.util.Set;
\r
15 import org.simantics.databoard.Bindings;
\r
16 import org.simantics.db.ReadGraph;
\r
17 import org.simantics.db.Resource;
\r
18 import org.simantics.db.Statement;
\r
19 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
\r
20 import org.simantics.db.common.request.BinaryRead;
\r
21 import org.simantics.db.common.request.ResourceRead;
\r
22 import org.simantics.db.common.request.TransientUnaryRead;
\r
23 import org.simantics.db.common.utils.CommonDBUtils;
\r
24 import org.simantics.db.common.utils.NameUtils;
\r
25 import org.simantics.db.exception.DatabaseException;
\r
26 import org.simantics.db.exception.NoSingleResultException;
\r
27 import org.simantics.db.layer0.exception.MissingVariableException;
\r
28 import org.simantics.db.layer0.exception.MissingVariableValueException;
\r
29 import org.simantics.db.layer0.request.VariableRead;
\r
30 import org.simantics.db.layer0.variable.Variable;
\r
31 import org.simantics.db.service.CollectionSupport;
\r
32 import org.simantics.db.service.QueryControl;
\r
33 import org.simantics.layer0.Layer0;
\r
34 import org.simantics.modeling.ModelingResources;
\r
35 import org.simantics.structural.stubs.StructuralResource2;
\r
36 import org.simantics.structural2.Functions;
\r
37 import org.simantics.structural2.Functions.InterfaceResolution;
\r
38 import org.simantics.structural2.queries.ConnectionSet;
\r
39 import org.simantics.structural2.variables.StandardProceduralChildVariable.FixedConnection;
\r
40 import org.simantics.utils.datastructures.Pair;
\r
42 public class ConnectionBrowser {
\r
45 * Finds the components connected by the connection. Also connections
\r
49 * @param connection A connection whose related modules are searched.
\r
50 * @param configuration A variable that represents the composite where the connection belongs to.
\r
51 * @return A map whose keys are components and they are mapped to
\r
52 * related variables.
\r
54 public static Collection<ResourceWithContext> findConnectedComponents(
\r
55 ReadGraph graph, Resource connection, Variable configuration)
\r
56 throws DatabaseException {
\r
58 ArrayList<ResourceWithContext> result =
\r
59 new ArrayList<ResourceWithContext>();
\r
60 THashSet<Resource> visitedConnections = new THashSet<Resource>();
\r
63 findConnectedComponents(graph, connection, configuration, result,
\r
64 visitedConnections);
\r
68 private static void findConnectedComponents(
\r
69 ReadGraph graph, Resource connection, Variable configuration,
\r
70 ArrayList<ResourceWithContext> result,
\r
71 THashSet<Resource> visitedConnections) throws DatabaseException {
\r
72 if(visitedConnections.add(connection)) {
\r
73 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
74 Layer0 L0 = Layer0.getInstance(graph);
\r
76 // Browse related components
\r
77 for(Statement stat : graph.getStatements(connection, STR.Connects)) {
\r
78 Resource component = stat.getObject();
\r
79 Resource relation = graph.getInverse(stat.getPredicate());
\r
80 //System.out.println(NameUtils.getSafeName(graph, component) + "." + NameUtils.getSafeName(graph, relation));
\r
81 Resource boundConnection = graph.getPossibleObject(relation, STR.IsBoundBy);
\r
82 Resource type = graph.getPossibleObject(component, L0.InstanceOf);
\r
83 Resource def = type != null ? graph.getPossibleObject(type, STR.IsDefinedBy) : null;
\r
84 if(boundConnection != null && def != null) {
\r
85 // The connection point is bound in component type
\r
86 Variable newContext = configuration.browsePossible(graph, component);
\r
87 Resource newComposite = getCompositeOfConnection(graph, boundConnection);
\r
88 if(newContext != null && newComposite != null) {
\r
89 newContext = browse(graph, def, newContext, newComposite);
\r
90 if (newContext != null)
\r
91 findConnectedComponents(graph, boundConnection,
\r
93 result, visitedConnections);
\r
97 //System.out.println("added result");
\r
98 // A primitive connection point
\r
99 Variable context = configuration.browsePossible(graph, component);
\r
100 if (context != null)
\r
101 result.add(new ResourceWithContext(component, context));
\r
105 // Browse over connection joins
\r
106 for(Resource join : graph.getObjects(connection, STR.IsJoinedBy))
\r
107 for(Resource otherConnection : graph.getObjects(join, STR.Joins))
\r
108 if(!connection.equals(otherConnection)) {
\r
109 Resource sourceComposite = getCompositeOfConnection(graph, connection);
\r
110 Resource targetComposite = getCompositeOfConnection(graph, otherConnection);
\r
111 if (sourceComposite != null && targetComposite != null) {
\r
112 Variable sibling = browseSibling(graph,
\r
116 if (sibling != null)
\r
117 findConnectedComponents(graph, otherConnection,
\r
118 sibling, result, visitedConnections);
\r
122 // Browse to parents
\r
124 for(Resource relation : graph.getObjects(connection, STR.Binds)) {
\r
125 Resource composite = getCompositeOfConnection(graph, connection);
\r
126 if (composite == null)
\r
129 Variable curConfiguration = configuration;
\r
130 while(!graph.hasStatement(composite, STR.Defines)) {
\r
131 composite = graph.getSingleObject(composite, L0.PartOf);
\r
132 curConfiguration = curConfiguration.getParent(graph);
\r
134 Variable parent = curConfiguration.getParent(graph);
\r
135 Resource component = curConfiguration.getRepresents(graph);
\r
136 for(Resource c : graph.getObjects(component, relation))
\r
137 findConnectedComponents(graph, c,
\r
138 parent, result, visitedConnections);
\r
140 } catch(NoSingleResultException e) {
\r
141 } catch(MissingVariableException e) {
\r
142 } catch(MissingVariableValueException e) {
\r
147 public static Collection<VariableConnectionPointDescriptor> drill(ReadGraph graph, VariableConnectionPointDescriptor pair) throws DatabaseException {
\r
149 Collection<InterfaceResolution> interfaceDescription = pair.getInterfaceDescription(graph);
\r
150 if(interfaceDescription != null && interfaceDescription.size() > 0) {
\r
152 Variable cp = pair.getVariable(graph);
\r
153 Variable context = cp.getParent(graph);
\r
154 String cpName = cp.getName(graph);
\r
156 Collection<VariableConnectionPointDescriptor> result = new ArrayList<VariableConnectionPointDescriptor>();
\r
157 for(InterfaceResolution r : interfaceDescription) {
\r
158 if(r.interfaceName.equals(cpName)) {
\r
159 String path = Functions.resolveInterfacePath(graph, context, r.componentName, r.connectionPoint);
\r
160 result.add(new BrowseConnectionDescriptor(context, path));
\r
164 if(result.isEmpty()) return null;
\r
169 return Collections.singleton(pair);
\r
174 public static class JoinConnections extends ResourceRead<Collection<Resource>> {
\r
176 public JoinConnections(Resource join) {
\r
181 public Collection<Resource> perform(ReadGraph graph) throws DatabaseException {
\r
182 ConnectionSet cs = new ConnectionSet(graph);
\r
183 cs.addJoin(graph, resource);
\r
184 return cs.getConnections();
\r
190 public static final class VariableChildren extends TransientUnaryRead<Variable, Map<Resource,Variable>> {
\r
192 public VariableChildren(ReadGraph graph, Variable variable) throws DatabaseException {
\r
193 super(graph, variable);
\r
196 public VariableChildren(ReadGraph graph, QueryControl qc, Variable variable) throws DatabaseException {
\r
197 super(graph, qc, variable);
\r
201 public Map<Resource, Variable> perform(ReadGraph graph, Variable parameter) throws DatabaseException {
\r
202 CollectionSupport cs = graph.getService(CollectionSupport.class);
\r
203 Map<Resource,Variable> result = cs.createMap(Variable.class);
\r
204 for(Variable child : parameter.getChildren(graph)) {
\r
205 Resource represents = child.getPossibleRepresents(graph);
\r
206 if(represents != null) result.put(represents, child);
\r
213 static Variable resolve(ReadGraph graph, Variable base, Resource component) throws DatabaseException {
\r
214 Map<Resource,Variable> map = graph.syncRequest(new VariableChildren(graph, base), TransientCacheAsyncListener.<Map<Resource,Variable>>instance());
\r
215 Variable result = map.get(component);
\r
216 if(result != null) return result;
\r
218 Layer0 L0 = Layer0.getInstance(graph);
\r
219 Resource parent = graph.getPossibleObject(component, L0.PartOf);
\r
220 if(parent == null) return null;
\r
221 Variable v = resolve(graph, base, parent);
\r
222 if (v == null) return null;
\r
223 map = graph.syncRequest(new VariableChildren(graph, v), TransientCacheAsyncListener.<Map<Resource,Variable>>instance());
\r
224 return map.get(component);
\r
228 public static class ConnectionComponentsWithAncestor extends TransientUnaryRead<Resource, List<Resource>> {
\r
230 final private List<Resource> result;
\r
232 public ConnectionComponentsWithAncestor(ReadGraph graph, Resource conn) throws DatabaseException {
\r
233 this(graph, conn, null);
\r
236 public ConnectionComponentsWithAncestor(ReadGraph graph, QueryControl qc, Resource conn, List<Resource> result) throws DatabaseException {
\r
237 super(graph, qc, conn);
\r
238 this.result = result;
\r
241 public ConnectionComponentsWithAncestor(ReadGraph graph, Resource conn, List<Resource> result) throws DatabaseException {
\r
242 super(graph, conn);
\r
243 this.result = result;
\r
246 private ConnectionSet connSet(ReadGraph graph, Resource r ) throws DatabaseException {
\r
247 ConnectionSet cs = new ConnectionSet(graph);
\r
248 cs.addConnection(graph, r);
\r
253 public List<Resource> perform(ReadGraph graph, Resource resource) throws DatabaseException {
\r
255 if(result != null) return result;
\r
257 Layer0 L0 = Layer0.getInstance(graph);
\r
258 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
259 CollectionSupport colls = graph.getService(CollectionSupport.class);
\r
260 THashSet<Resource> ancestorGenerators = new THashSet<Resource>();
\r
261 Set<Resource> parts = colls.createSet();
\r
262 ConnectionSet cs = connSet(graph, resource);
\r
263 for(Resource connRes : cs.getConnections()) {
\r
264 for(Statement stm : graph.getStatements(connRes, STR.Connects)) {
\r
265 Resource component = stm.getObject();
\r
266 Resource parent = graph.getPossibleObject(component, L0.PartOf);
\r
267 if(parent != null && !graph.isInstanceOf(component, ModelingResources.getInstance(graph).ReferenceElement))
\r
268 ancestorGenerators.add(parent);
\r
270 parts.add(connRes);
\r
272 for (Resource join : cs.getJoins()) {
\r
274 for (Resource composite : graph.getObjects(join, STR.JoinsComposite))
\r
275 ancestorGenerators.add(composite);
\r
277 Resource ancestor = ancestorGenerators.size() == 1 ? ancestorGenerators.iterator().next() : CommonDBUtils.getNearestOwner(graph, ancestorGenerators);
\r
279 List<Resource> result = colls.createList();
\r
280 result.add(ancestor);
\r
281 result.addAll(colls.asSortedList(parts));
\r
283 if(parameter != WITH_PARENT) {
\r
284 for(int i=1;i<result.size();i++) {
\r
285 Resource r = result.get(i);
\r
287 if(!r.equals(resource))
\r
288 graph.syncRequest(new ConnectionComponentsWithAncestor(graph, r, result), TransientCacheAsyncListener.<List<Resource>>instance());
\r
298 public static Collection<VariableConnectionPointDescriptor> climb(ReadGraph graph, Variable child, Resource cp, String subPath_) throws DatabaseException {
\r
300 boolean isStructural = false;
\r
302 Variable curConfiguration = child.getParent(graph);
\r
306 Collection<InterfaceResolution> interfaceDescription = Functions.computeInterfacePaths(graph, curConfiguration);
\r
307 if(interfaceDescription != null) {
\r
308 isStructural = interfaceDescription != Functions.BUILTIN_STRUCTURAL_CPS;
\r
309 if(interfaceDescription.size() > 0) {
\r
311 if(subPath_ == null) {
\r
313 String childName = child.getName(graph);
\r
314 for(InterfaceResolution r : interfaceDescription) {
\r
315 if(r.componentName.equals(childName) && r.connectionPoint.equals(cp)) {
\r
316 Variable pConn = curConfiguration.getPossibleProperty(graph, r.interfaceName);
\r
317 if(pConn != null) {
\r
318 Resource cp2 = pConn.getPossiblePredicateResource(graph);
\r
319 Collection<VariableConnectionPointDescriptor> res = climb(graph, curConfiguration, cp2, null);
\r
320 if(res != null) return res;
\r
322 return Collections.emptyList();
\r
327 throw new UnsupportedOperationException("");
\r
334 if(child instanceof StandardProceduralChildVariable) {
\r
336 Variable conn = child.getPossibleProperty(graph, cp);
\r
337 FixedConnection fc = (FixedConnection)conn.getValue(graph);
\r
338 Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>(1+fc.cps.size());
\r
339 result.add(new ComponentConnectionDescriptor(child, cp));// (graph, STR, curConfiguration, "/" + c.name + "#" + conn.getName(graph)));
\r
340 for(Pair<String,Resource> cpzz : fc.cps) {
\r
341 if(cpzz.first == null) {
\r
342 throw new DatabaseException("Lifted connection was not resolved.");
\r
344 result.add(new PairConnectionDescriptor(curConfiguration, cpzz));
\r
351 Resource represents = child.getRepresents(graph);
\r
355 Collection<Resource> conns = graph.getObjects(represents, res);
\r
356 HashSet<VariableConnectionPointDescriptor> result = new HashSet<VariableConnectionPointDescriptor>();
\r
357 for(Resource c : conns) {
\r
358 List<Resource> rs = graph.syncRequest(new ConnectionComponentsWithAncestor(graph, c), TransientCacheAsyncListener.<List<Resource>>instance());
\r
359 result.addAll(graph.syncRequest(ConnectionVariables.forStructural(graph, curConfiguration, rs)));
\r
365 Resource connection = graph.getPossibleObject(represents, res);
\r
366 if(connection != null) {
\r
367 List<Resource> rs = graph.syncRequest(new ConnectionComponentsWithAncestor(graph, connection), TransientCacheAsyncListener.<List<Resource>>instance());
\r
368 return graph.syncRequest(ConnectionVariables.forConfiguration(graph, curConfiguration, rs));
\r
371 Collection<Resource> conns = graph.getObjects(represents, res);
\r
372 HashSet<VariableConnectionPointDescriptor> result = new HashSet<VariableConnectionPointDescriptor>();
\r
373 for(Resource c : conns) {
\r
374 List<Resource> rs = graph.syncRequest(new ConnectionComponentsWithAncestor(graph, c), TransientCacheAsyncListener.<List<Resource>>instance());
\r
375 result.addAll(graph.syncRequest(ConnectionVariables.forConfiguration(graph, curConfiguration, rs)));
\r
386 public static class ConnectionVariables extends BinaryRead<Variable, List<Resource>, Collection<VariableConnectionPointDescriptor>> {
\r
388 private ConnectionVariables(Variable parameter1, List<Resource> parameter2) {
\r
389 super(parameter1, parameter2);
\r
392 public static ConnectionVariables forConfiguration(ReadGraph graph, Variable configuration, List<Resource> rs) throws DatabaseException {
\r
393 return new ConnectionVariables(parent(graph, configuration, rs.get(0)), rs);
\r
396 public static ConnectionVariables forStructural(ReadGraph graph, Variable configuration, List<Resource> rs) throws DatabaseException {
\r
397 return new ConnectionVariables(configuration, rs);
\r
401 * Finds the parent variable of <code>configuration</code> that
\r
402 * represents <code>ancestor</code>.
\r
405 * @param configuration
\r
408 * @throws DatabaseException if no parent was found that represents ancestor
\r
410 private static Variable parent(ReadGraph graph, Variable configuration, Resource ancestor) throws DatabaseException {
\r
411 Variable v = configuration;
\r
412 Resource represents = v.getRepresents(graph);
\r
413 while(!represents.equals(ancestor)) {
\r
414 v = v.getParent(graph);
\r
416 throw new DatabaseException(
\r
417 "parent representing ancestor not found for variable, configuration="
\r
418 + safeURI(graph, configuration)
\r
420 + NameUtils.getURIOrSafeNameInternal(graph, ancestor));
\r
422 represents = v.getRepresents(graph);
\r
428 public Collection<VariableConnectionPointDescriptor> perform(ReadGraph graph) throws DatabaseException {
\r
429 if(parameter == null) return Collections.emptyList();
\r
430 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
431 ArrayList<VariableConnectionPointDescriptor> result = null;
\r
432 for(int i=1;i<parameter2.size();i++) {
\r
433 Resource connRes = parameter2.get(i);
\r
434 for(Statement stm : graph.getStatements(connRes, STR.Connects)) {
\r
435 Resource component = stm.getObject();
\r
436 Resource connectionPoint = graph.getInverse(stm.getPredicate());
\r
437 if(result == null) result = new ArrayList<VariableConnectionPointDescriptor>();
\r
438 result.add(new ActualConnectionDescriptor(parameter, component, connectionPoint));
\r
441 if(result == null) return Collections.emptyList();
\r
447 static class IsLeafType extends ResourceRead<Boolean> {
\r
449 protected IsLeafType(Resource type) {
\r
454 public Boolean perform(ReadGraph graph) throws DatabaseException {
\r
456 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
458 if(graph.isInstanceOf(resource, STR.ProceduralComponentType)) return false;
\r
459 if(graph.hasStatement(resource, STR.IsDefinedBy)) return false;
\r
467 static class ChildMapOfVariable extends VariableRead<Map<Resource,Variable>> {
\r
469 public ChildMapOfVariable(Variable variable) {
\r
474 public Map<Resource, Variable> perform(ReadGraph graph) throws DatabaseException {
\r
475 HashMap<Resource,Variable> result = new HashMap<Resource,Variable>();
\r
476 for(Variable child : variable.getChildren(graph)) {
\r
477 Resource represents = child.getPossibleRepresents(graph);
\r
478 if(represents != null) result.put(represents, child);
\r
486 * Given a root composite, related variable and some other component inside the composite,
\r
487 * finds the related variable for that component.
\r
489 public static Variable browse(ReadGraph graph, Resource root, Variable rootContext, Resource target) throws DatabaseException {
\r
490 if(target.equals(root))
\r
491 return rootContext;
\r
493 Layer0 L0 = Layer0.getInstance(graph);
\r
494 String name = (String)graph.getPossibleRelatedValue(target, L0.HasName, Bindings.STRING);
\r
495 Resource parent = graph.getPossibleObject(target, L0.PartOf);
\r
496 if(name == null || parent == null)
\r
498 Variable parentVariable = browse(graph, root, rootContext, parent);
\r
499 if(parentVariable == null)
\r
501 return parentVariable.getPossibleChild(graph, name);
\r
506 * Finds a variable whose location related to sourceContext is the same as
\r
507 * between target and source. In other words, the method solves {@code targetContext}
\r
508 * in the following equations:
\r
510 * URI(source) = resourceURIBase + sourceSuffix
\r
511 * URI(sourceContext) = variableURIBase + sourceSuffix
\r
512 * URI(target) = resourceURIBase + targetSuffix
\r
513 * URI(targetContext) = variableURIBase + targetSuffix
\r
516 public static Variable browseSibling(ReadGraph graph, Resource source, Variable sourceContext, Resource target) throws DatabaseException {
\r
517 Layer0 L0 = Layer0.getInstance(graph);
\r
518 THashMap<Resource, Variable> sourceMap = new THashMap<Resource, Variable>();
\r
519 while(source != null && sourceContext != null) {
\r
520 sourceMap.put(source, sourceContext);
\r
521 source = graph.getPossibleObject(source, L0.PartOf);
\r
522 sourceContext = sourceContext.getParent(graph);
\r
524 return browseSibling(graph, sourceMap, target);
\r
527 private static Variable browseSibling(ReadGraph graph, THashMap<Resource, Variable> sourceMap, Resource target) throws DatabaseException {
\r
528 Layer0 L0 = Layer0.getInstance(graph);
\r
529 Variable result = sourceMap.get(target);
\r
532 String name = (String)graph.getPossibleRelatedValue(target, L0.HasName, Bindings.STRING);
\r
533 Resource parent = graph.getPossibleObject(target, L0.PartOf);
\r
534 if(name == null || parent == null)
\r
536 Variable parentVariable = browseSibling(graph, sourceMap, parent);
\r
537 if(parentVariable == null)
\r
539 return parentVariable.getPossibleChild(graph, name);
\r
543 * Returns the composite where the connection given as a parameter resides.
\r
545 public static Resource getCompositeOfConnection(ReadGraph graph, Resource connection) throws DatabaseException {
\r
546 Layer0 L0 = Layer0.getInstance(graph);
\r
547 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
548 // First from connected components
\r
549 for(Resource component : graph.getObjects(connection, STR.Connects))
\r
550 for(Resource composite : graph.getObjects(component, L0.PartOf))
\r
552 // It could be that the connection is only supported by joins (input flag -> output flag) - use diagram info TODO!!
\r
553 Resource connToDiagramConn = graph.getPossibleResource("http://www.simantics.org/Modeling-1.2/ConnectionToDiagramConnection");
\r
554 if(connToDiagramConn != null) {
\r
555 Resource diagramConnection = graph.getPossibleObject(connection, connToDiagramConn);
\r
556 if(diagramConnection != null) {
\r
557 Resource diagram = graph.getPossibleObject(diagramConnection, L0.PartOf);
\r
558 if(diagram != null) {
\r
559 Resource diagramToComposite = graph.getPossibleResource("http://www.simantics.org/Modeling-1.2/DiagramToComposite");
\r
560 if(diagramToComposite != null) {
\r
561 return graph.getPossibleObject(diagram, diagramToComposite);
\r
569 static class Flatten extends BinaryRead<Variable,Resource,Collection<VariableConnectionPointDescriptor>> {
\r
571 public Flatten(Variable parameter1,
\r
572 Resource parameter2) {
\r
573 super(parameter1, parameter2);
\r
577 public Collection<VariableConnectionPointDescriptor> perform(ReadGraph graph)
\r
578 throws DatabaseException {
\r
579 return doFlatten(graph, parameter, parameter2, null);
\r
584 public static Collection<VariableConnectionPointDescriptor> flatten(ReadGraph graph, Variable child, Resource cp, Resource relationType) throws DatabaseException {
\r
586 if(relationType == null) return graph.syncRequest(new Flatten(child, cp));
\r
588 return doFlatten(graph, child, cp, relationType);
\r
592 public static Collection<VariableConnectionPointDescriptor> doFlatten(ReadGraph graph, Variable child, Resource cp, Resource relationType) throws DatabaseException {
\r
594 Collection<VariableConnectionPointDescriptor> climbed = climb(graph, child, cp, null);
\r
595 boolean needDrill = false;
\r
596 for(VariableConnectionPointDescriptor desc : climbed) {
\r
597 if(!desc.isLeaf(graph)) {
\r
604 if(relationType != null) {
\r
605 ArrayList<VariableConnectionPointDescriptor> filtered = new ArrayList<VariableConnectionPointDescriptor>(climbed.size());
\r
606 for(VariableConnectionPointDescriptor desc : climbed)
\r
607 if(filterByRelationType(graph, desc, relationType))
\r
608 filtered.add(desc);
\r
614 THashSet<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>(climbed.size());
\r
615 for(VariableConnectionPointDescriptor top : climbed) {
\r
616 Collection<VariableConnectionPointDescriptor> drilled = drill(graph, top);
\r
617 if(drilled != null) {
\r
618 for(VariableConnectionPointDescriptor drill : drilled) {
\r
619 if(relationType != null) {
\r
620 if(!filterByRelationType(graph, drill, relationType))
\r
631 private static boolean filterByRelationType(ReadGraph graph, VariableConnectionPointDescriptor desc, Resource relationType) throws DatabaseException {
\r
632 Resource predicateResource = desc.getConnectionPointResource(graph);
\r
633 return predicateResource != null && graph.isInstanceOf(predicateResource, relationType);
\r
636 private static String safeURI(ReadGraph graph, Variable v) {
\r
638 return "null variable";
\r
640 return v.getURI(graph);
\r
641 } catch (DatabaseException e) {
\r
642 return v.toString();
\r