-package org.simantics.db.common.utils.traverser;\r
-\r
-import java.util.Arrays;\r
-import java.util.HashSet;\r
-import java.util.LinkedList;\r
-import java.util.Set;\r
-\r
-import org.simantics.db.AsyncRequestProcessor;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.RequestProcessor;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.ServiceException;\r
-import org.simantics.db.procedure.AsyncListener;\r
-import org.simantics.db.procedure.AsyncProcedure;\r
-import org.simantics.db.procedure.Listener;\r
-import org.simantics.db.procedure.Procedure;\r
-import org.simantics.db.procedure.SyncListener;\r
-import org.simantics.db.procedure.SyncProcedure;\r
-import org.simantics.db.request.Read;\r
-import org.simantics.db.request.ReadInterface;\r
-\r
-/**\r
- * Traverse query is generic query that traverses accroding to given rules.\r
- * Use {@link TraverseQueryBuilder} to construct traverse query\r
- *\r
- * @author toni.kalajainen@semantum.fi\r
- */\r
-public class TraverseQuery implements Read<TraverseResult>, ReadInterface<TraverseResult> {\r
-\r
- // Start locations\r
- public final Resource[] startResources;\r
- // Instances of types to follow to\r
- public final Resource[] instancesOfTypesToFollowTo;\r
- // Instances of types to follow to\r
- public final Resource[] inheritedFromTypesToFollowTo;\r
- // Relations to traverse \r
- public final Resource[] relations;\r
- // Types to add to result\r
- public final Resource[] instancesOfTypesToAddToResult;\r
- // Types to add to result\r
- public final Resource[] inheritedFromTypesToAddToResult;\r
-\r
- private int hash;\r
- \r
- public TraverseQuery(\r
- Resource[] startResources, \r
- Resource[] instancesOfTypesToFollowTo, \r
- Resource[] relations, \r
- Resource[] instancesOfTypesToAddToResult,\r
- Resource[] inheritedFromTypesToFollowTo,\r
- Resource[] inheritedFromTypesToAddToResult\r
- )\r
- {\r
- this.startResources = startResources;\r
- this.relations = relations;\r
- this.instancesOfTypesToFollowTo = instancesOfTypesToFollowTo;\r
- this.instancesOfTypesToAddToResult = instancesOfTypesToAddToResult;\r
-\r
- this.inheritedFromTypesToFollowTo = inheritedFromTypesToFollowTo;\r
- this.inheritedFromTypesToAddToResult = inheritedFromTypesToAddToResult;\r
- \r
- int hash = 345436534;\r
- for (Resource r : startResources) hash = 13*hash + r.hashCode();\r
- for (Resource r : relations) hash = 7*hash + r.hashCode();\r
- for (Resource r : instancesOfTypesToFollowTo) hash = 3*hash + r.hashCode();\r
- for (Resource r : instancesOfTypesToAddToResult) hash = 11*hash + r.hashCode();\r
- for (Resource r : inheritedFromTypesToFollowTo) hash = 3*hash + r.hashCode();\r
- for (Resource r : inheritedFromTypesToAddToResult) hash = 11*hash + r.hashCode();\r
- }\r
- \r
- @Override\r
- public int hashCode() {\r
- return hash;\r
- }\r
-\r
- @Override\r
- public boolean equals(Object object) {\r
- if (this == object) return true;\r
- if ( object instanceof TraverseQuery == false ) return false;\r
- TraverseQuery other = (TraverseQuery) this;\r
- \r
- if (hash != other.hash) return false;\r
- \r
- // The order should not count - but who cares\r
- if (!Arrays.deepEquals(startResources, other.startResources)) return false;\r
- if (!Arrays.deepEquals(relations, other.relations)) return false;\r
- if (!Arrays.deepEquals(instancesOfTypesToFollowTo, other.instancesOfTypesToFollowTo)) return false;\r
- if (!Arrays.deepEquals(instancesOfTypesToAddToResult, other.instancesOfTypesToAddToResult)) return false;\r
- if (!Arrays.deepEquals(inheritedFromTypesToFollowTo, other.inheritedFromTypesToFollowTo)) return false;\r
- if (!Arrays.deepEquals(inheritedFromTypesToAddToResult, other.inheritedFromTypesToAddToResult)) return false;\r
-\r
- return true;\r
- }\r
-\r
- @Override\r
- public void request(AsyncRequestProcessor processor, AsyncProcedure<TraverseResult> procedure) {\r
- processor.asyncRequest(this, procedure);\r
- }\r
- \r
- @Override\r
- public void request(AsyncRequestProcessor processor, Procedure<TraverseResult> procedure) {\r
- processor.asyncRequest(this, procedure);\r
- }\r
- \r
- @Override\r
- public void request(AsyncRequestProcessor processor, SyncProcedure<TraverseResult> procedure) {\r
- processor.asyncRequest(this, procedure);\r
- }\r
-\r
- @Override\r
- public void request(AsyncRequestProcessor processor, AsyncListener<TraverseResult> procedure) {\r
- processor.asyncRequest(this, procedure);\r
- }\r
- \r
- @Override\r
- public void request(AsyncRequestProcessor processor, Listener<TraverseResult> procedure) {\r
- processor.asyncRequest(this, procedure);\r
- }\r
- \r
- @Override\r
- public void request(AsyncRequestProcessor processor, SyncListener<TraverseResult> procedure) {\r
- processor.asyncRequest(this, procedure);\r
- }\r
- \r
- @Override\r
- public TraverseResult request(RequestProcessor processor) throws DatabaseException {\r
- return processor.syncRequest(this);\r
- }\r
-\r
- @Override\r
- public TraverseResult perform(ReadGraph graph) throws DatabaseException {\r
- Traverser traverser = new Traverser();\r
- for (Resource r : startResources) traverser.toBeVisited.add(r);\r
- \r
- while ( !traverser.toBeVisited.isEmpty() ) {\r
- _doTraverse(graph, traverser);\r
- }\r
- \r
- return traverser.result;\r
- }\r
- \r
- void _doTraverse(ReadGraph graph, Traverser traverser) throws ServiceException {\r
- \r
- // Remove one resource\r
- while (!traverser.toBeVisited.isEmpty()) {\r
- Resource r = traverser.toBeVisited.removeFirst();\r
- if ( traverser.visited.contains(r) ) continue;\r
- \r
- // Get Objects\r
- for (Resource relation : relations) {\r
- nextObj:\r
- for (Resource obj : graph.getObjects(r, relation)) {\r
- if (traverser.visited.contains(obj)) continue nextObj;\r
- \r
- boolean isAcceptedObject = false;\r
- for (Resource acceptedType : instancesOfTypesToFollowTo) {\r
- isAcceptedObject |= graph.isInstanceOf(obj, acceptedType);\r
- if ( isAcceptedObject ) break;\r
- }\r
- if ( !isAcceptedObject ) {\r
- for (Resource acceptedType : inheritedFromTypesToFollowTo) {\r
- isAcceptedObject |= graph.isInheritedFrom(obj, acceptedType);\r
- if ( isAcceptedObject ) break;\r
- }\r
- }\r
- if ( !isAcceptedObject ) continue nextObj;\r
- \r
- traverser.toBeVisited.add(obj);\r
- }\r
- }\r
- \r
- // Add to result?\r
- boolean addToResult = false;\r
- for (Resource typeToAddToResult : instancesOfTypesToAddToResult) {\r
- addToResult |= graph.isInstanceOf(r, typeToAddToResult);\r
- if ( addToResult) break;\r
- }\r
- if (!addToResult)\r
- for (Resource typeToAddToResult : inheritedFromTypesToAddToResult) {\r
- addToResult |= graph.isInheritedFrom(r, typeToAddToResult);\r
- if ( addToResult) break;\r
- }\r
-\r
- if ( addToResult ) {\r
- traverser.result.result.add(r);\r
- }\r
- \r
- traverser.visited.add(r);\r
- }\r
- }\r
-\r
- class Traverser {\r
- \r
- TraverseResult result = new TraverseResult(); \r
-\r
- public Set<Resource> visited = new HashSet<Resource>();\r
- public LinkedList<Resource> toBeVisited = new LinkedList<Resource>();\r
- \r
- }\r
- \r
- \r
+package org.simantics.db.common.utils.traverser;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+
+import org.simantics.db.AsyncRequestProcessor;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.RequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ServiceException;
+import org.simantics.db.procedure.AsyncListener;
+import org.simantics.db.procedure.AsyncProcedure;
+import org.simantics.db.procedure.Listener;
+import org.simantics.db.procedure.Procedure;
+import org.simantics.db.procedure.SyncListener;
+import org.simantics.db.procedure.SyncProcedure;
+import org.simantics.db.request.Read;
+import org.simantics.db.request.ReadInterface;
+
+/**
+ * Traverse query is generic query that traverses accroding to given rules.
+ * Use {@link TraverseQueryBuilder} to construct traverse query
+ *
+ * @author toni.kalajainen@semantum.fi
+ */
+public class TraverseQuery implements Read<TraverseResult>, ReadInterface<TraverseResult> {
+
+ // Start locations
+ public final Resource[] startResources;
+ // Instances of types to follow to
+ public final Resource[] instancesOfTypesToFollowTo;
+ // Instances of types to follow to
+ public final Resource[] inheritedFromTypesToFollowTo;
+ // Relations to traverse
+ public final Resource[] relations;
+ // Types to add to result
+ public final Resource[] instancesOfTypesToAddToResult;
+ // Types to add to result
+ public final Resource[] inheritedFromTypesToAddToResult;
+
+ private int hash;
+
+ public TraverseQuery(
+ Resource[] startResources,
+ Resource[] instancesOfTypesToFollowTo,
+ Resource[] relations,
+ Resource[] instancesOfTypesToAddToResult,
+ Resource[] inheritedFromTypesToFollowTo,
+ Resource[] inheritedFromTypesToAddToResult
+ )
+ {
+ this.startResources = startResources;
+ this.relations = relations;
+ this.instancesOfTypesToFollowTo = instancesOfTypesToFollowTo;
+ this.instancesOfTypesToAddToResult = instancesOfTypesToAddToResult;
+
+ this.inheritedFromTypesToFollowTo = inheritedFromTypesToFollowTo;
+ this.inheritedFromTypesToAddToResult = inheritedFromTypesToAddToResult;
+
+ int hash = 345436534;
+ for (Resource r : startResources) hash = 13*hash + r.hashCode();
+ for (Resource r : relations) hash = 7*hash + r.hashCode();
+ for (Resource r : instancesOfTypesToFollowTo) hash = 3*hash + r.hashCode();
+ for (Resource r : instancesOfTypesToAddToResult) hash = 11*hash + r.hashCode();
+ for (Resource r : inheritedFromTypesToFollowTo) hash = 3*hash + r.hashCode();
+ for (Resource r : inheritedFromTypesToAddToResult) hash = 11*hash + r.hashCode();
+ }
+
+ @Override
+ public int hashCode() {
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) return true;
+ if ( object instanceof TraverseQuery == false ) return false;
+ TraverseQuery other = (TraverseQuery) this;
+
+ if (hash != other.hash) return false;
+
+ // The order should not count - but who cares
+ if (!Arrays.deepEquals(startResources, other.startResources)) return false;
+ if (!Arrays.deepEquals(relations, other.relations)) return false;
+ if (!Arrays.deepEquals(instancesOfTypesToFollowTo, other.instancesOfTypesToFollowTo)) return false;
+ if (!Arrays.deepEquals(instancesOfTypesToAddToResult, other.instancesOfTypesToAddToResult)) return false;
+ if (!Arrays.deepEquals(inheritedFromTypesToFollowTo, other.inheritedFromTypesToFollowTo)) return false;
+ if (!Arrays.deepEquals(inheritedFromTypesToAddToResult, other.inheritedFromTypesToAddToResult)) return false;
+
+ return true;
+ }
+
+ @Override
+ public void request(AsyncRequestProcessor processor, AsyncProcedure<TraverseResult> procedure) {
+ processor.asyncRequest(this, procedure);
+ }
+
+ @Override
+ public void request(AsyncRequestProcessor processor, Procedure<TraverseResult> procedure) {
+ processor.asyncRequest(this, procedure);
+ }
+
+ @Override
+ public void request(AsyncRequestProcessor processor, SyncProcedure<TraverseResult> procedure) {
+ processor.asyncRequest(this, procedure);
+ }
+
+ @Override
+ public void request(AsyncRequestProcessor processor, AsyncListener<TraverseResult> procedure) {
+ processor.asyncRequest(this, procedure);
+ }
+
+ @Override
+ public void request(AsyncRequestProcessor processor, Listener<TraverseResult> procedure) {
+ processor.asyncRequest(this, procedure);
+ }
+
+ @Override
+ public void request(AsyncRequestProcessor processor, SyncListener<TraverseResult> procedure) {
+ processor.asyncRequest(this, procedure);
+ }
+
+ @Override
+ public TraverseResult request(RequestProcessor processor) throws DatabaseException {
+ return processor.syncRequest(this);
+ }
+
+ @Override
+ public TraverseResult perform(ReadGraph graph) throws DatabaseException {
+ Traverser traverser = new Traverser();
+ for (Resource r : startResources) traverser.toBeVisited.add(r);
+
+ while ( !traverser.toBeVisited.isEmpty() ) {
+ _doTraverse(graph, traverser);
+ }
+
+ return traverser.result;
+ }
+
+ void _doTraverse(ReadGraph graph, Traverser traverser) throws ServiceException {
+
+ // Remove one resource
+ while (!traverser.toBeVisited.isEmpty()) {
+ Resource r = traverser.toBeVisited.removeFirst();
+ if ( traverser.visited.contains(r) ) continue;
+
+ // Get Objects
+ for (Resource relation : relations) {
+ nextObj:
+ for (Resource obj : graph.getObjects(r, relation)) {
+ if (traverser.visited.contains(obj)) continue nextObj;
+
+ boolean isAcceptedObject = false;
+ for (Resource acceptedType : instancesOfTypesToFollowTo) {
+ isAcceptedObject |= graph.isInstanceOf(obj, acceptedType);
+ if ( isAcceptedObject ) break;
+ }
+ if ( !isAcceptedObject ) {
+ for (Resource acceptedType : inheritedFromTypesToFollowTo) {
+ isAcceptedObject |= graph.isInheritedFrom(obj, acceptedType);
+ if ( isAcceptedObject ) break;
+ }
+ }
+ if ( !isAcceptedObject ) continue nextObj;
+
+ traverser.toBeVisited.add(obj);
+ }
+ }
+
+ // Add to result?
+ boolean addToResult = false;
+ for (Resource typeToAddToResult : instancesOfTypesToAddToResult) {
+ addToResult |= graph.isInstanceOf(r, typeToAddToResult);
+ if ( addToResult) break;
+ }
+ if (!addToResult)
+ for (Resource typeToAddToResult : inheritedFromTypesToAddToResult) {
+ addToResult |= graph.isInheritedFrom(r, typeToAddToResult);
+ if ( addToResult) break;
+ }
+
+ if ( addToResult ) {
+ traverser.result.result.add(r);
+ }
+
+ traverser.visited.add(r);
+ }
+ }
+
+ class Traverser {
+
+ TraverseResult result = new TraverseResult();
+
+ public Set<Resource> visited = new HashSet<Resource>();
+ public LinkedList<Resource> toBeVisited = new LinkedList<Resource>();
+
+ }
+
+
}
\ No newline at end of file