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 internalIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND); private final TIntObjectHashMap externalIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND); private final TIntObjectHashMap rootIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND); private final TObjectIntHashMap internalIdentitiesByURI = new TObjectIntHashMap<>(); private final TObjectIntHashMap externalIdentitiesByURI = new TObjectIntHashMap<>(); private final TObjectIntHashMap rootIdentitiesByURI = new TObjectIntHashMap<>(); private final TIntObjectHashMap 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 ":"; return getURI(identity); } private static final Comparator IDENTITY_NAME_COMPARATOR = new Comparator() { @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 getChildren(Identity parent) { TreeSet 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 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> sortByPredicateUniqueStatements(int resource) { TreeMap> 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 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; } }