--- /dev/null
+package org.simantics.scl.runtime.minigraph;
+
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TLongObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.scl.runtime.tuple.Tuple0;
+
+public class Minigraph {
+
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
+
+ TIntObjectHashMap<TIntHashSet> predicatesPerSubject = new TIntObjectHashMap<TIntHashSet>();
+ TLongObjectHashMap<Object> objectsPerSubjectPredicate = new TLongObjectHashMap<Object>();
+
+ TIntObjectHashMap<String> idToUri = new TIntObjectHashMap<String>();
+ TObjectIntHashMap<String> uriToId = new TObjectIntHashMap<String>(Constants.DEFAULT_CAPACITY,
+ Constants.DEFAULT_LOAD_FACTOR, -1);
+ TIntObjectHashMap<String> values = new TIntObjectHashMap<String>();
+
+ int resourceCount = 0;
+ int InverseOf;
+
+ private static long combine(int a, int b) {
+ return (((long)a)<<32) | ((long)b);
+ }
+
+ private static int[] toArray(Object obj) {
+ if(obj == null)
+ return EMPTY_INT_ARRAY;
+ else if(obj instanceof Integer)
+ return new int[] { (Integer)obj };
+ else
+ return ((TIntHashSet)obj).toArray();
+ }
+
+ private static void add(TIntObjectHashMap<TIntHashSet> map, int key, int value) {
+ TIntHashSet set = map.get(key);
+ if(set == null) {
+ set = new TIntHashSet();
+ map.put(key, set);
+ }
+ set.add(value);
+ }
+
+ private static void remove(TIntObjectHashMap<TIntHashSet> map, int key, int value) {
+ TIntHashSet set = map.get(key);
+ if(set != null)
+ set.remove(value);
+ }
+
+ private static void add(TLongObjectHashMap<Object> map, long key, int value) {
+ Object obj = map.get(key);
+ if(obj == null)
+ map.put(key, Integer.valueOf(value));
+ else if(obj instanceof Integer) {
+ TIntHashSet set = new TIntHashSet();
+ set.add((Integer)obj);
+ set.add(value);
+ map.put(key, set);
+ }
+ else
+ ((TIntHashSet)obj).add(value);
+ }
+
+ private static boolean remove(TLongObjectHashMap<Object> map, long key, int value) {
+ Object obj = map.get(key);
+ if(obj == null)
+ return false;
+ else if(obj instanceof Integer) {
+ if(value != ((Integer)obj).intValue())
+ return false;
+ map.put(key, null);
+ return true;
+ }
+ else {
+ TIntHashSet set = (TIntHashSet)obj;
+ if(!set.remove(value))
+ return false;
+ if(set.size() == 1)
+ map.put(key, Integer.valueOf(set.iterator().next()));
+ return false;
+ }
+ }
+
+ public int blank() {
+ return resourceCount++;
+ }
+
+ public int getResource(String uri) {
+ int id = uriToId.get(uri);
+ if(id >= 0)
+ return id;
+ idToUri.put(resourceCount, uri);
+ uriToId.put(uri, resourceCount);
+ return resourceCount++;
+ }
+
+ public String getUri(int r) {
+ String uri = idToUri.get(r);
+ if(uri != null)
+ return uri;
+ else
+ return "#" + r;
+ }
+
+ public void rawClaim(int s, int p, int o) {
+ add(predicatesPerSubject, s, p);
+ add(objectsPerSubjectPredicate, combine(s, p), o);
+ }
+
+ public void claim(int s, int p, int o) {
+ rawClaim(s, p, o);
+ int inv = getPossibleObject(p, InverseOf);
+ if(inv >= 0)
+ rawClaim(o, inv, s);
+ }
+
+ public void rawDeny(int s, int p, int o) {
+ if(remove(objectsPerSubjectPredicate, combine(s, p), o))
+ remove(predicatesPerSubject, s, p);
+ }
+
+ public void deny(int s, int p, int o) {
+ rawDeny(s, p, o);
+ int inv = getPossibleObject(p, InverseOf);
+ if(inv >= 0)
+ rawDeny(o, inv, s);
+ }
+
+ public int[] getObjects(int s, int p) {
+ return toArray(objectsPerSubjectPredicate.get(combine(s, p)));
+ }
+
+ public int[] getSubjects(int o, int p) {
+ int inv = getPossibleObject(p, InverseOf);
+ if(inv >= 0)
+ return getObjects(o, inv);
+ else
+ return EMPTY_INT_ARRAY;
+ }
+
+ public int getPossibleObject(int s, int p) {
+ Object obj = objectsPerSubjectPredicate.get(combine(s, p));
+ if(obj instanceof Integer)
+ return ((Integer)obj).intValue();
+ else
+ return -1;
+ }
+
+ public boolean hasStatement(int s, int p, int o) {
+ Object obj = objectsPerSubjectPredicate.get(combine(s, p));
+ if(obj == null)
+ return false;
+ else if(obj instanceof Integer)
+ return o == ((Integer)obj).intValue();
+ else
+ return ((TIntHashSet)obj).contains(o);
+ }
+
+ public List<Statement> getStatements(final int s) {
+ TIntHashSet preds = predicatesPerSubject.get(s);
+ if(preds == null)
+ return Collections.<Statement>emptyList();
+
+ final ArrayList<Statement> statements = new ArrayList<Statement>();
+ preds.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(final int p) {
+ Object obj = objectsPerSubjectPredicate.get(combine(s, p));
+ if(obj instanceof Integer)
+ statements.add(new Statement(s, p, (Integer)obj));
+ else
+ ((TIntHashSet)obj).forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int o) {
+ statements.add(new Statement(s, p, o));
+ return true;
+ }
+ });
+ return true;
+ }
+ });
+ return statements;
+ }
+
+ public void setValue(int s, String value) {
+ values.put(s, value);
+ }
+
+ private void initializeLayer0() {
+ InverseOf = getResource("Layer0/InverseOf");
+ rawClaim(InverseOf, InverseOf, InverseOf);
+ }
+
+ public Minigraph() {
+ initializeLayer0();
+ }
+
+ public static void main(String[] args) {
+ Minigraph g = new Minigraph();
+ g.claim(10, g.InverseOf, 11);
+ g.claim(12, g.InverseOf, 13);
+ g.claim(1, 10, 2);
+ g.claim(1, 10, 3);
+ g.claim(1, 12, 4);
+ System.out.println(g.getStatements(2));
+ }
+
+ public static Object withGraph(Function f) {
+ Object oldGraph = SCLContext.getCurrent().put("graph", new Minigraph());
+ try {
+ return f.apply(Tuple0.INSTANCE);
+ } finally {
+ SCLContext.getCurrent().put("graph", oldGraph);
+ }
+ }
+}