sclass TripleIndex extends VirtualNodeIndex { // TODO: do away with the main index? We have websByID and positionalIndices SyncListMultiMap index = symbolSyncListMultiMap(); SyncListMultiMap[] positionalIndices = new SyncListMultiMap[] { symbolSyncListMultiMap(), symbolSyncListMultiMap(), symbolSyncListMultiMap() }; new CompactHashSet websByID; bool activated; // are we the main index (see tripleIndex()) int size() { ret numWebs(); } int numWebs() { ret l(websByID); } int numTerms() { ret index.keysSize(); } Collection indexedTerms() { ret keys(index); } // query is shortened term L get(CharSequence _query) { Symbol query = symbol(_query); ret ai_triplesToWebNodes_lazyList(query, index.get(query)); } // query is shortened term L> getTripleRefs(Symbol query) { ret ai_triplesToTripleRefs_lazyList(query, index.get(query)); } L> getTripleRefs(Symbol query, int position) { ret ai_triplesToTripleRefs_lazyList(query, getTriples(query, position)); } // query is shortened term L getTriples(Symbol query) { ret index.get(query); } // query is shortened term L getTriples(Symbol query, int position) { ret positionalIndices[position].get(query); } bool hasShortTerm(Symbol s) { ret index.containsKey(s); } Web getWeb(GlobalID id) { ret webFromTriple(getTriple(id)); } TripleWeb getTriple(GlobalID id) { ret websByID.find(dummyTripleWebWithGlobalID(id)); } void addWeb(Web web) { if (web == null) ret; TripleWeb w = ai_webToTripleWeb(web); if (w == null) fail("Skipping non-tripelizable web: " + webToStringShort(web)); addTriple(w); } void addTriple(TripleWeb w) { if (w == null) ret; // XXX if (eqic(w.a, "Java")) print("adding " + w); synchronized(index) { for (Symbol s : sortedInPlace(ll(w.a, w.b, w.c))) index.put(s, w); positionalIndices[0].put(w.a, w); positionalIndices[1].put(w.b, w); positionalIndices[2].put(w.c, w); } websByID.add(w); } void removeWeb(Web web) { if (web != null) removeTriple(ai_webToTripleWeb(web)); } void removeTriples(Collection l) { new MultiMap mm; for (TripleWeb w : l) { mm.put(ai_shortenForIndex(w.a), w); mm.put(ai_shortenForIndex(w.b), w); mm.put(ai_shortenForIndex(w.c), w); } for (Symbol term : keys(mm)) { HashSet webs = asHashSet(mm.get(term)); indexRemoveMulti(index, term, webs);+ for i to 3: indexRemoveMulti(positionalIndices[i], term, webs); } } void removeTriple(TripleWeb w) { if (w == null) ret; GlobalID id = w.globalID(); websByID.remove(dummyTripleWebWithGlobalID(id)); indexRemove(0, ai_shortenForIndex(w.a), id); indexRemove(1, ai_shortenForIndex(w.b), id); indexRemove(2, ai_shortenForIndex(w.c), id); } // internal void indexRemove(int position, Symbol term, GlobalID globalID) { indexRemove2(index, term, globalID); indexRemove2(positionalIndices[position], term, globalID); } // remove from a single list void indexRemove2(MultiMap mm, Symbol term, GlobalID globalID) { L l = mm.get(term); for i over l: if (eq(l.get(i).globalID(), globalID)) { mm.remove(term, l.get(i)); ret; } } // internal void indexRemoveMulti(MultiMap mm, term, Set set) { L l = mm.get(term); synchronized(l) { removeSetFromListQuickly(l, set); } } void clear() { index.clear(); websByID.clear(); } void activate { if (!activated) { activated = true; ai_onNewOrRemovedWeb(func(Web web) { addWeb(web); false; }, func(Web web) { removeWeb(web); false; }); } } Collection allTriples() { ret websByID; } void trimToSize() { trimToSizeAll(index.allLists()); for i to 3: trimToSizeAll(positionalIndices[i].allLists()); } }