package org.simantics.scl.runtime.minigraph; 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; 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; public class Minigraph { private static final int[] EMPTY_INT_ARRAY = new int[0]; TIntObjectHashMap predicatesPerSubject = new TIntObjectHashMap(); TLongObjectHashMap objectsPerSubjectPredicate = new TLongObjectHashMap(); TIntObjectHashMap idToUri = new TIntObjectHashMap(); TObjectIntHashMap uriToId = new TObjectIntHashMap(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, -1); TIntObjectHashMap values = new TIntObjectHashMap(); 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 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 map, int key, int value) { TIntHashSet set = map.get(key); if(set != null) set.remove(value); } private static void add(TLongObjectHashMap 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 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 getStatements(final int s) { TIntHashSet preds = predicatesPerSubject.get(s); if(preds == null) return Collections.emptyList(); final ArrayList statements = new ArrayList(); 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); } } }