+package org.simantics.graph.representation;
+
+import java.util.Comparator;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import gnu.trove.impl.Constants;
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TObjectProcedure;
+
+public class TransferableGraphQueries {
+
+ private static final int NOT_FOUND = TransferableGraphUtils.NOT_FOUND;
+
+ private final TransferableGraph1 tg;
+
+ private final TIntObjectHashMap<Identity> internalIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
+ private final TIntObjectHashMap<Identity> externalIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
+ private final TIntObjectHashMap<Identity> rootIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
+
+ private final TObjectIntHashMap<String> internalIdentitiesByURI = new TObjectIntHashMap<>();
+ private final TObjectIntHashMap<String> externalIdentitiesByURI = new TObjectIntHashMap<>();
+ private final TObjectIntHashMap<String> rootIdentitiesByURI = new TObjectIntHashMap<>();
+
+ private final TIntObjectHashMap<TIntArrayList> statementsCache = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
+
+ public TransferableGraphQueries(TransferableGraph1 graph) {
+ this.tg = graph;
+
+ // Calculate internals
+ initializeIdentities();
+ }
+
+ private void initializeIdentities() {
+ for (Identity identity : tg.identities) {
+ IdentityDefinition definition = identity.definition;
+ if (definition instanceof Internal) {
+ Internal internal = (Internal) definition;
+ internalIdentities.put(identity.resource, identity);
+ internalIdentitiesByURI.put(getURI(identity), identity.resource);
+ } else if (definition instanceof External) {
+ External external = (External) definition;
+ externalIdentities.put(identity.resource, identity);
+ externalIdentitiesByURI.put(getURI(identity), identity.resource);
+ } else if (definition instanceof Root) {
+ Root root = (Root) definition;
+ rootIdentities.put(identity.resource, identity);
+ rootIdentitiesByURI.put(getURI(identity), identity.resource);
+ }
+ }
+ }
+
+ public String getURI(Identity identity) {
+ IdentityDefinition definition = identity.definition;
+ if(definition instanceof External) {
+ External def = (External)definition;
+ if(def.parent == -1) return "http:/";
+ else return getURI(def.parent) + "/" + def.name;
+ } else if(definition instanceof Root) {
+ Root def = (Root)definition;
+ if(def.name.isEmpty()) return "http:/";
+ return def.name;
+ } else if (definition instanceof Internal) {
+ Internal def = (Internal)definition;
+ return getURI(def.parent) + "/" + def.name;
+ } else {
+ return "";
+ }
+ }
+
+ public String getURI(int id) {
+ Identity identity = getIdentity(id);
+ if (identity == null)
+ return "<internal reference " + id + ">:";
+ return getURI(identity);
+ }
+
+ private static final Comparator<Identity> IDENTITY_NAME_COMPARATOR = new Comparator<Identity>() {
+
+ @Override
+ public int compare(Identity o1, Identity o2) {
+ if (o1.definition instanceof Internal && o2.definition instanceof Internal) {
+ Internal i1 = (Internal) o1.definition;
+ Internal i2 = (Internal) o2.definition;
+ return i1.name.compareTo(i2.name);
+ } else if (o1.definition instanceof External && o2.definition instanceof External) {
+ External e1 = (External) o1.definition;
+ External e2 = (External) o2.definition;
+ return e1.name.compareTo(e2.name);
+ } else {
+ throw new IllegalArgumentException(o1 + " " + o2);
+ }
+ }
+ };
+
+ public Set<Identity> getChildren(Identity parent) {
+ TreeSet<Identity> children = new TreeSet<>(IDENTITY_NAME_COMPARATOR);
+ internalIdentities.forEachEntry((resource, identity) -> {
+ Internal internal = (Internal) identity.definition;
+ if (internal.parent == parent.resource)
+ children.add(identity);
+ return true;
+ });
+
+ return children;
+ }
+
+ public Identity findInternalByName(String name) {
+ int internal = internalIdentitiesByURI.get(name);
+ if (internal == NOT_FOUND)
+ return null;
+ return internalIdentities.get(internal);
+ }
+
+ private Identity findExternalByName(String name) {
+ int external = externalIdentitiesByURI.get(name);
+ if (external == NOT_FOUND)
+ return null;
+ return externalIdentities.get(external);
+ }
+
+ private Identity findExternalByNameAndParent(String name, int parent) {
+ Identity external = findExternalByName(name);
+ if (external.resource == parent)
+ return external;
+ return null;
+ }
+
+ public Identity findExternalByURI(String uri) {
+ int v = externalIdentitiesByURI.get(uri);
+ if (v == NOT_FOUND)
+ return null;
+ return externalIdentities.get(v);
+ }
+
+ public Identity findRootByName(String name) {
+ int root = rootIdentitiesByURI.get(name);
+ if (root == NOT_FOUND)
+ return null;
+ return rootIdentities.get(root);
+ }
+
+ public String getName(Identity identity) {
+ return TransferableGraphUtils.getName(identity);
+ }
+
+ public void forIdentities(TObjectProcedure<Identity> procedure) {
+ for (Identity identity : tg.identities) {
+ if (!procedure.execute(identity)) {
+ break;
+ }
+ }
+ }
+
+ public Identity getIdentity(int resource) {
+ Identity result = rootIdentities.get(resource);
+ if (result == null)
+ result = externalIdentities.get(resource);
+ if (result == null)
+ result = internalIdentities.get(resource);
+ return result;
+ }
+
+ public Value findValue(int object) {
+ return TransferableGraphUtils.findValue(tg, object);
+ }
+
+ public TreeMap<String, TreeSet<Integer>> sortByPredicateUniqueStatements(int resource) {
+ TreeMap<String, TreeSet<Integer>> results = new TreeMap<>();
+ TIntArrayList statements = getStatements(resource);
+ for (int i = 0; i < statements.size(); i += 2) {
+ int predicate = statements.get(i);
+ String predicateURI = getURI(predicate);
+ TreeSet<Integer> objects = results.get(predicateURI);
+ if (objects == null) {
+ objects = new TreeSet<>();
+ }
+ objects.add(statements.get(i + 1));
+ results.put(predicateURI, objects);
+ }
+ return results;
+ }
+
+ public TIntArrayList getStatements(int resource) {
+// System.out.println("getting statements with " + resource);
+ TIntArrayList statements = statementsCache.get(resource);
+ if (statements == null) {
+ statements = TransferableGraphUtils.getStatements(tg, resource);
+ statementsCache.put(resource, statements);
+ }
+ return statements;
+ }
+
+ public int getPossibleObject(int subject, Identity predicate) {
+ return TransferableGraphUtils.getPossibleObject2(tg, subject, predicate);
+ }
+
+ public TransferableGraph1 getGraph() {
+ return tg;
+ }
+
+}