-package org.simantics.graph.query;\r
-\r
-import gnu.trove.list.array.TIntArrayList;\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-\r
-import org.simantics.databoard.adapter.AdaptException;\r
-import org.simantics.databoard.adapter.RuntimeAdaptException;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.graph.store.GraphStore;\r
-import org.simantics.graph.store.IdRes;\r
-import org.simantics.graph.store.IdentityStore;\r
-import org.simantics.graph.store.PathPattern;\r
-import org.simantics.graph.store.StatementStore;\r
-\r
-public class CompositeGraph implements IGraph {\r
-\r
- ArrayList<GraphStore> fragments = new ArrayList<GraphStore>();\r
- Paths paths;\r
- \r
- public CompositeGraph(Paths paths) {\r
- this.paths = paths;\r
- }\r
-\r
- public void addFragment(GraphStore fragment) {\r
- fragments.add(fragment);\r
- }\r
- \r
- public void undoAddFragment() {\r
- fragments.remove(fragments.size()-1);\r
- }\r
- \r
- public void addFragments(Collection<GraphStore> fragments) {\r
- fragments.addAll(fragments);\r
- }\r
- \r
- protected void rawGetObjects(GraphStore fragment, int subject, Res predicate, Collection<Res> result) {\r
- int predicateId;\r
- if(predicate instanceof Path) {\r
- predicateId = fragment.identities.pathToId((Path)predicate);\r
- if(predicateId < 0)\r
- return;\r
- } \r
- else {\r
- IdRes idPredicate = (IdRes)predicate;\r
- if(idPredicate.fragment != fragment)\r
- return;\r
- predicateId = idPredicate.id;\r
- }\r
- \r
- TIntArrayList objects = fragment.statements.getObjects(subject, predicateId);\r
- fragment.addIdsToResult(objects, result);\r
- }\r
- \r
- private void rawGetObjects(Res subject, Res predicate, Collection<Res> result) {\r
- if(subject instanceof Path) {\r
- Path path = (Path)subject;\r
- for(GraphStore fragment : fragments) {\r
- int id = fragment.identities.pathToId(path);\r
- if(id >= 0)\r
- rawGetObjects(fragment, id, predicate, result);\r
- }\r
- }\r
- else {\r
- IdRes idRes = (IdRes)subject; \r
- rawGetObjects(idRes.fragment, idRes.id, predicate, result);\r
- }\r
- }\r
- \r
- public boolean hasRawObjects(Res subject, Path predicate) {\r
- ArrayList<Res> result = new ArrayList<Res>();\r
- rawGetObjects(subject, predicate, result);\r
- return !result.isEmpty();\r
- }\r
- \r
- @Override\r
- public Collection<Res> rawGetObjects(Res subject, Res predicate) {\r
- ArrayList<Res> result = new ArrayList<Res>();\r
- rawGetObjects(subject, predicate, result);\r
- return result;\r
- }\r
- \r
- @Override\r
- public Res singleRawObject(Res subject, Res predicate) throws NoUniqueObjectException {\r
- ArrayList<Res> result = new ArrayList<Res>(1);\r
- rawGetObjects(subject, predicate, result);\r
- if(result.size() != 1)\r
- throw new NoUniqueObjectException("No unique objects (" + result.size()+ ") for " +\r
- subject + " -> " + predicate); \r
- return result.get(0);\r
- }\r
- \r
- @Override\r
- public Collection<Res> getTypes(Res subject) {\r
- THashSet<Res> result = new THashSet<Res>(); \r
- rawGetObjects(subject, paths.InstanceOf, result);\r
- for(Res type : result.toArray(new Res[result.size()]))\r
- collectSupertypes(type, result);\r
- return result;\r
- }\r
- \r
- public Collection<Res> getSupertypes(Res subject) {\r
- THashSet<Res> result = new THashSet<Res>(); \r
- result.add(subject); \r
- collectSupertypes(subject, result);\r
- return result;\r
- }\r
- \r
- private void collectSupertypes(Res type, THashSet<Res> result) {\r
- for(Res supertype : rawGetObjects(type, paths.Inherits))\r
- if(result.add(supertype))\r
- collectSupertypes(supertype, result); \r
- }\r
-\r
- @Override\r
- public Collection<Res> getObjects(Res subject, Res predicate) {\r
- ArrayList<Res> result = new ArrayList<Res>();\r
- rawGetObjects(subject, predicate, result);\r
- for(Res type : getTypes(subject)) \r
- for(Res assertion : rawGetObjects(type, paths.Asserts)) {\r
- Res pred = singleRawObject(assertion, paths.HasPredicate);\r
- if(equals(pred, predicate))\r
- result.add(singleRawObject(assertion, paths.HasObject));\r
- }\r
- return result;\r
- }\r
- \r
- public Collection<Res> getAssertedObjects(Res subject, Path predicate) {\r
- ArrayList<Res> result = new ArrayList<Res>();\r
- for(Res type : getSupertypes(subject)) \r
- for(Res assertion : rawGetObjects(type, paths.Asserts)) {\r
- Res pred = singleRawObject(assertion, paths.HasPredicate);\r
- if(equals(pred, predicate))\r
- result.add(singleRawObject(assertion, paths.HasObject));\r
- }\r
- return result;\r
- }\r
- \r
- private static boolean equals(Res r1, Res r2) {\r
- return r1.equals(r2);\r
- }\r
- \r
- interface ResourceProcedure {\r
- public void execute(GraphStore fragment, int id);\r
- }\r
- \r
- interface ResourceFunction<T> {\r
- public T execute(GraphStore fragment, int id);\r
- }\r
- \r
- public void forEachFragmentContaining(Res resource, ResourceProcedure proc) {\r
- if(resource instanceof Path) {\r
- Path path = (Path)resource;\r
- for(GraphStore fragment : fragments) {\r
- int id = fragment.identities.pathToId(path);\r
- if(id >= 0)\r
- proc.execute(fragment, id);\r
- }\r
- }\r
- else {\r
- IdRes res = (IdRes)resource;\r
- proc.execute(res.fragment, res.id);\r
- }\r
- }\r
- \r
- public <T> T apply(Res resource, ResourceFunction <T> func) {\r
- if(resource instanceof Path) {\r
- Path path = (Path)resource;\r
- for(GraphStore fragment : fragments) {\r
- int id = fragment.identities.pathToId(path);\r
- if(id >= 0) {\r
- T value = func.execute(fragment, id);\r
- if(value != null)\r
- return value;\r
- }\r
- }\r
- return null;\r
- }\r
- else {\r
- IdRes res = (IdRes)resource;\r
- return func.execute(res.fragment, res.id);\r
- }\r
- }\r
- \r
- private static ResourceFunction<Datatype> getDatatype = \r
- new ResourceFunction<Datatype>() {\r
- @Override\r
- public Datatype execute(GraphStore fragment, int id) {\r
- return fragment.values.getDatatypeValue(id);\r
- } \r
- };\r
- \r
- private static ResourceFunction<Variant> getValue = \r
- new ResourceFunction<Variant>() {\r
- @Override\r
- public Variant execute(GraphStore fragment, int id) {\r
- return fragment.values.getByteValue(id);\r
- } \r
- };\r
- \r
- THashMap<Res, Datatype> datatypeCache = new THashMap<Res, Datatype>();\r
- \r
- @Override\r
- public Datatype getDatatype(Res resource) {\r
- for(Res dt : getObjects(resource, paths.HasDatatype)) {\r
- Datatype type = datatypeCache.get(dt);\r
- if(type == null) {\r
- type = apply(dt, getDatatype);\r
- datatypeCache.put(dt, type);\r
- }\r
- return type;\r
- }\r
- return null;\r
- }\r
- \r
- @Override\r
- public Datatype getAssertedDatatype(Res resource) {\r
- for(Res dt : getAssertedObjects(resource, paths.HasDatatype)) {\r
- Datatype type = datatypeCache.get(dt);\r
- if(type == null) {\r
- type = apply(dt, getDatatype);\r
- datatypeCache.put(dt, type);\r
- }\r
- return type;\r
- }\r
- return null;\r
- }\r
- \r
- @Override\r
- public Variant getValue(Res resource) {\r
- return apply(resource, getValue);\r
- }\r
- \r
- @Override\r
- public Object getValue(Res resource, Binding binding) throws NoValueException {\r
- Variant value = getValue(resource);\r
- if(value == null)\r
- throw new NoValueException();\r
- try {\r
- return value.getValue(binding);\r
- } catch (AdaptException e) {\r
- throw new RuntimeAdaptException(e);\r
- }\r
- }\r
- \r
- @Override\r
- public void setValue(Res resource, Object value, Binding binding) {\r
- final Variant variant = new Variant(binding, value);\r
- apply(resource, new ResourceFunction<Object>() {\r
- @Override\r
- public Object execute(GraphStore fragment, int id) {\r
- fragment.values.setValue(id, variant);\r
- return null;\r
- } \r
- });\r
- }\r
- \r
- /**\r
- * Tells in how many fragments the resource occurs.\r
- */\r
- public int countOccurences(Res resource) {\r
- if(resource instanceof IdRes)\r
- return 1;\r
- else if(resource instanceof Path) {\r
- Path path = (Path)resource;\r
- int count = 0;\r
- for(GraphStore fragment : fragments)\r
- if(fragment.identities.contains(path))\r
- ++count;\r
- return count;\r
- }\r
- else\r
- return 0;\r
- }\r
- \r
- private void collectSubtypes(THashSet<Res> types, Res type) {\r
- if(types.add(type)) \r
- for(Res subtype : rawGetObjects(type, paths.SupertypeOf))\r
- collectSubtypes(types, subtype);\r
- }\r
- \r
- @Override\r
- public Collection<Res> getInstances(Res supertype) {\r
- THashSet<Res> types = new THashSet<Res>(); \r
- collectSubtypes(types, supertype);\r
- \r
- ArrayList<Res> result = new ArrayList<Res>();\r
- fragmentLoop:\r
- for(GraphStore fragment : fragments) {\r
- IdentityStore identities = fragment.identities;\r
- StatementStore statements = fragment.statements;\r
- \r
- TIntHashSet ids = new TIntHashSet(types.size());\r
- for(Res type : types) {\r
- if(type instanceof Path) {\r
- int id = identities.pathToId((Path)type);\r
- if(id >= 0)\r
- ids.add(id);\r
- }\r
- else {\r
- IdRes idRes = (IdRes)type;\r
- if(idRes.fragment == fragment)\r
- ids.add(idRes.id);\r
- }\r
- }\r
- if(ids.isEmpty())\r
- continue;\r
- \r
- int instanceOfId = identities.pathToId(paths.InstanceOf);\r
- if(instanceOfId < 0)\r
- continue;\r
- \r
- int resourceCount = identities.getResourceCount();\r
- nextResource:\r
- for(int i=0;i<resourceCount;++i)\r
- for(int typeId : statements.getObjects(i, instanceOfId).toArray())\r
- if(ids.contains(typeId)) {\r
- result.add(fragment.idToRes(i));\r
- continue nextResource;\r
- }\r
- }\r
- \r
- return result;\r
- }\r
-\r
- @Override\r
- public Collection<Res> getChildren(Res res) {\r
- if(res instanceof Path) {\r
- THashSet<Res> result = new THashSet<Res>();\r
- for(GraphStore store : fragments) {\r
- IdentityStore ids = store.identities;\r
- int id = ids.pathToId((Path)res);\r
- if(id >= 0) {\r
- for(int child : ids.getChildren(id))\r
- result.add(store.idToRes(child));\r
- }\r
- }\r
- return result;\r
- }\r
- else\r
- return Collections.<Res>emptyList();\r
- }\r
- \r
- public Collection<Path> searchByPattern(String pattern) {\r
- THashSet<Path> result = new THashSet<Path>();\r
- PathPattern pathPattern = PathPattern.compile(pattern);\r
- for(GraphStore store : fragments)\r
- pathPattern.search(store.identities, result);\r
- return result;\r
- }\r
- \r
- @Override\r
- public Paths getPaths() {\r
- return paths;\r
- }\r
-}\r
+package org.simantics.graph.query;
+
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.adapter.RuntimeAdaptException;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.graph.store.GraphStore;
+import org.simantics.graph.store.IdRes;
+import org.simantics.graph.store.IdentityStore;
+import org.simantics.graph.store.PathPattern;
+import org.simantics.graph.store.StatementStore;
+
+public class CompositeGraph implements IGraph {
+
+ ArrayList<GraphStore> fragments = new ArrayList<GraphStore>();
+ Paths paths;
+
+ public CompositeGraph(Paths paths) {
+ this.paths = paths;
+ }
+
+ public void addFragment(GraphStore fragment) {
+ fragments.add(fragment);
+ }
+
+ public void undoAddFragment() {
+ fragments.remove(fragments.size()-1);
+ }
+
+ public void addFragments(Collection<GraphStore> fragments) {
+ fragments.addAll(fragments);
+ }
+
+ protected void rawGetObjects(GraphStore fragment, int subject, Res predicate, Collection<Res> result) {
+ int predicateId;
+ if(predicate instanceof Path) {
+ predicateId = fragment.identities.pathToId((Path)predicate);
+ if(predicateId < 0)
+ return;
+ }
+ else {
+ IdRes idPredicate = (IdRes)predicate;
+ if(idPredicate.fragment != fragment)
+ return;
+ predicateId = idPredicate.id;
+ }
+
+ TIntArrayList objects = fragment.statements.getObjects(subject, predicateId);
+ fragment.addIdsToResult(objects, result);
+ }
+
+ private void rawGetObjects(Res subject, Res predicate, Collection<Res> result) {
+ if(subject instanceof Path) {
+ Path path = (Path)subject;
+ for(GraphStore fragment : fragments) {
+ int id = fragment.identities.pathToId(path);
+ if(id >= 0)
+ rawGetObjects(fragment, id, predicate, result);
+ }
+ }
+ else {
+ IdRes idRes = (IdRes)subject;
+ rawGetObjects(idRes.fragment, idRes.id, predicate, result);
+ }
+ }
+
+ public boolean hasRawObjects(Res subject, Path predicate) {
+ ArrayList<Res> result = new ArrayList<Res>();
+ rawGetObjects(subject, predicate, result);
+ return !result.isEmpty();
+ }
+
+ @Override
+ public Collection<Res> rawGetObjects(Res subject, Res predicate) {
+ ArrayList<Res> result = new ArrayList<Res>();
+ rawGetObjects(subject, predicate, result);
+ return result;
+ }
+
+ @Override
+ public Res singleRawObject(Res subject, Res predicate) throws NoUniqueObjectException {
+ ArrayList<Res> result = new ArrayList<Res>(1);
+ rawGetObjects(subject, predicate, result);
+ if(result.size() != 1)
+ throw new NoUniqueObjectException("No unique objects (" + result.size()+ ") for " +
+ subject + " -> " + predicate);
+ return result.get(0);
+ }
+
+ @Override
+ public Collection<Res> getTypes(Res subject) {
+ THashSet<Res> result = new THashSet<Res>();
+ rawGetObjects(subject, paths.InstanceOf, result);
+ for(Res type : result.toArray(new Res[result.size()]))
+ collectSupertypes(type, result);
+ return result;
+ }
+
+ public Collection<Res> getSupertypes(Res subject) {
+ THashSet<Res> result = new THashSet<Res>();
+ result.add(subject);
+ collectSupertypes(subject, result);
+ return result;
+ }
+
+ private void collectSupertypes(Res type, THashSet<Res> result) {
+ for(Res supertype : rawGetObjects(type, paths.Inherits))
+ if(result.add(supertype))
+ collectSupertypes(supertype, result);
+ }
+
+ @Override
+ public Collection<Res> getObjects(Res subject, Res predicate) {
+ ArrayList<Res> result = new ArrayList<Res>();
+ rawGetObjects(subject, predicate, result);
+ for(Res type : getTypes(subject))
+ for(Res assertion : rawGetObjects(type, paths.Asserts)) {
+ Res pred = singleRawObject(assertion, paths.HasPredicate);
+ if(equals(pred, predicate))
+ result.add(singleRawObject(assertion, paths.HasObject));
+ }
+ return result;
+ }
+
+ public Collection<Res> getAssertedObjects(Res subject, Path predicate) {
+ ArrayList<Res> result = new ArrayList<Res>();
+ for(Res type : getSupertypes(subject))
+ for(Res assertion : rawGetObjects(type, paths.Asserts)) {
+ Res pred = singleRawObject(assertion, paths.HasPredicate);
+ if(equals(pred, predicate))
+ result.add(singleRawObject(assertion, paths.HasObject));
+ }
+ return result;
+ }
+
+ private static boolean equals(Res r1, Res r2) {
+ return r1.equals(r2);
+ }
+
+ interface ResourceProcedure {
+ public void execute(GraphStore fragment, int id);
+ }
+
+ interface ResourceFunction<T> {
+ public T execute(GraphStore fragment, int id);
+ }
+
+ public void forEachFragmentContaining(Res resource, ResourceProcedure proc) {
+ if(resource instanceof Path) {
+ Path path = (Path)resource;
+ for(GraphStore fragment : fragments) {
+ int id = fragment.identities.pathToId(path);
+ if(id >= 0)
+ proc.execute(fragment, id);
+ }
+ }
+ else {
+ IdRes res = (IdRes)resource;
+ proc.execute(res.fragment, res.id);
+ }
+ }
+
+ public <T> T apply(Res resource, ResourceFunction <T> func) {
+ if(resource instanceof Path) {
+ Path path = (Path)resource;
+ for(GraphStore fragment : fragments) {
+ int id = fragment.identities.pathToId(path);
+ if(id >= 0) {
+ T value = func.execute(fragment, id);
+ if(value != null)
+ return value;
+ }
+ }
+ return null;
+ }
+ else {
+ IdRes res = (IdRes)resource;
+ return func.execute(res.fragment, res.id);
+ }
+ }
+
+ private static ResourceFunction<Datatype> getDatatype =
+ new ResourceFunction<Datatype>() {
+ @Override
+ public Datatype execute(GraphStore fragment, int id) {
+ return fragment.values.getDatatypeValue(id);
+ }
+ };
+
+ private static ResourceFunction<Variant> getValue =
+ new ResourceFunction<Variant>() {
+ @Override
+ public Variant execute(GraphStore fragment, int id) {
+ return fragment.values.getByteValue(id);
+ }
+ };
+
+ THashMap<Res, Datatype> datatypeCache = new THashMap<Res, Datatype>();
+
+ @Override
+ public Datatype getDatatype(Res resource) {
+ for(Res dt : getObjects(resource, paths.HasDatatype)) {
+ Datatype type = datatypeCache.get(dt);
+ if(type == null) {
+ type = apply(dt, getDatatype);
+ datatypeCache.put(dt, type);
+ }
+ return type;
+ }
+ return null;
+ }
+
+ @Override
+ public Datatype getAssertedDatatype(Res resource) {
+ for(Res dt : getAssertedObjects(resource, paths.HasDatatype)) {
+ Datatype type = datatypeCache.get(dt);
+ if(type == null) {
+ type = apply(dt, getDatatype);
+ datatypeCache.put(dt, type);
+ }
+ return type;
+ }
+ return null;
+ }
+
+ @Override
+ public Variant getValue(Res resource) {
+ return apply(resource, getValue);
+ }
+
+ @Override
+ public Object getValue(Res resource, Binding binding) throws NoValueException {
+ Variant value = getValue(resource);
+ if(value == null)
+ throw new NoValueException();
+ try {
+ return value.getValue(binding);
+ } catch (AdaptException e) {
+ throw new RuntimeAdaptException(e);
+ }
+ }
+
+ @Override
+ public void setValue(Res resource, Object value, Binding binding) {
+ final Variant variant = new Variant(binding, value);
+ apply(resource, new ResourceFunction<Object>() {
+ @Override
+ public Object execute(GraphStore fragment, int id) {
+ fragment.values.setValue(id, variant);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Tells in how many fragments the resource occurs.
+ */
+ public int countOccurences(Res resource) {
+ if(resource instanceof IdRes)
+ return 1;
+ else if(resource instanceof Path) {
+ Path path = (Path)resource;
+ int count = 0;
+ for(GraphStore fragment : fragments)
+ if(fragment.identities.contains(path))
+ ++count;
+ return count;
+ }
+ else
+ return 0;
+ }
+
+ private void collectSubtypes(THashSet<Res> types, Res type) {
+ if(types.add(type))
+ for(Res subtype : rawGetObjects(type, paths.SupertypeOf))
+ collectSubtypes(types, subtype);
+ }
+
+ @Override
+ public Collection<Res> getInstances(Res supertype) {
+ THashSet<Res> types = new THashSet<Res>();
+ collectSubtypes(types, supertype);
+
+ ArrayList<Res> result = new ArrayList<Res>();
+ fragmentLoop:
+ for(GraphStore fragment : fragments) {
+ IdentityStore identities = fragment.identities;
+ StatementStore statements = fragment.statements;
+
+ TIntHashSet ids = new TIntHashSet(types.size());
+ for(Res type : types) {
+ if(type instanceof Path) {
+ int id = identities.pathToId((Path)type);
+ if(id >= 0)
+ ids.add(id);
+ }
+ else {
+ IdRes idRes = (IdRes)type;
+ if(idRes.fragment == fragment)
+ ids.add(idRes.id);
+ }
+ }
+ if(ids.isEmpty())
+ continue;
+
+ int instanceOfId = identities.pathToId(paths.InstanceOf);
+ if(instanceOfId < 0)
+ continue;
+
+ int resourceCount = identities.getResourceCount();
+ nextResource:
+ for(int i=0;i<resourceCount;++i)
+ for(int typeId : statements.getObjects(i, instanceOfId).toArray())
+ if(ids.contains(typeId)) {
+ result.add(fragment.idToRes(i));
+ continue nextResource;
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public Collection<Res> getChildren(Res res) {
+ if(res instanceof Path) {
+ THashSet<Res> result = new THashSet<Res>();
+ for(GraphStore store : fragments) {
+ IdentityStore ids = store.identities;
+ int id = ids.pathToId((Path)res);
+ if(id >= 0) {
+ for(int child : ids.getChildren(id))
+ result.add(store.idToRes(child));
+ }
+ }
+ return result;
+ }
+ else
+ return Collections.<Res>emptyList();
+ }
+
+ public Collection<Path> searchByPattern(String pattern) {
+ THashSet<Path> result = new THashSet<Path>();
+ PathPattern pathPattern = PathPattern.compile(pattern);
+ for(GraphStore store : fragments)
+ pathPattern.search(store.identities, result);
+ return result;
+ }
+
+ @Override
+ public Paths getPaths() {
+ return paths;
+ }
+}