X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.db.common%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fcommon%2Futils%2Ftraverser%2FTraverseQuery.java;h=5b1f2ee0b4ef5dd7cfef0af6fee6076ca919dc63;hb=644b6dee7bb798f69a40a7c78142f9649f0d9b76;hp=8b5073a6c8e2558f66fdfdd78a8af6f78c816713;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/traverser/TraverseQuery.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/traverser/TraverseQuery.java index 8b5073a6c..5b1f2ee0b 100644 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/traverser/TraverseQuery.java +++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/traverser/TraverseQuery.java @@ -1,203 +1,203 @@ -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, ReadInterface { - - // 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 procedure) { - processor.asyncRequest(this, procedure); - } - - @Override - public void request(AsyncRequestProcessor processor, Procedure procedure) { - processor.asyncRequest(this, procedure); - } - - @Override - public void request(AsyncRequestProcessor processor, SyncProcedure procedure) { - processor.asyncRequest(this, procedure); - } - - @Override - public void request(AsyncRequestProcessor processor, AsyncListener procedure) { - processor.asyncRequest(this, procedure); - } - - @Override - public void request(AsyncRequestProcessor processor, Listener procedure) { - processor.asyncRequest(this, procedure); - } - - @Override - public void request(AsyncRequestProcessor processor, SyncListener 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 visited = new HashSet(); - public LinkedList toBeVisited = new LinkedList(); - - } - - +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, ReadInterface { + + // 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 procedure) { + processor.asyncRequest(this, procedure); + } + + @Override + public void request(AsyncRequestProcessor processor, Procedure procedure) { + processor.asyncRequest(this, procedure); + } + + @Override + public void request(AsyncRequestProcessor processor, SyncProcedure procedure) { + processor.asyncRequest(this, procedure); + } + + @Override + public void request(AsyncRequestProcessor processor, AsyncListener procedure) { + processor.asyncRequest(this, procedure); + } + + @Override + public void request(AsyncRequestProcessor processor, Listener procedure) { + processor.asyncRequest(this, procedure); + } + + @Override + public void request(AsyncRequestProcessor processor, SyncListener 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 visited = new HashSet(); + public LinkedList toBeVisited = new LinkedList(); + + } + + } \ No newline at end of file