sclass WebRelation extends WebNode { WebNode a, b; public void _setField(S f, O x) { if (f.equals('a)) a = (WebNode) x; else if (f.equals('b)) b = (WebNode) x; else super._setField(f, x); } *() {} *(Web web, WebNode a, WebNode b) { super(web); this.a = a; this.b = b; } } sclass Web { new L nodes; // Relations are also nodes ifdef WebWithRelationsMap Map, WebRelation> relations = new Map; endifdef ifdef WebWithIndex MultiMap index; // label -> node endifdef ifndef WebWithIndex static final MultiMap index = null; endifndef //Map> pots = new Map; ifdef WebWithLock transient Lock lock = reentrantLock(true); endifdef //int size; //int flags; // TODO bool useCLParse = true; bool labelsToUpper; S title; O globalID = aGlobalIDObj(); S source; bool unverified; long created = nowUnlessLoading(); static new L onNewNode; // L static new L onNewLabel; // L static int F_useCLParse = 1; static int F_labelsToupper = 2; static int F_unverified = 3; /*bool potNotEmpty(S pot) { ret nempty(getPot(pot)); } L clearPot(S pot) { L l = getPot(pot); L l2 = cloneList(l); l.clear(); ret l2; }*/ /*L getPot(S pot) { L l = pots.get(pot); if (l == null) pots.put(pot, l = cloneList(nodes)); ret l; }*/ void relation(WebNode a, S arrow, WebNode b) { getRelation(a, b).addLabel(arrow); } Pair relation(S a, S arrow, S b) { ret relation(lisp(arrow, a, b)); } Pair relation(Lisp l) { if (l(l) == 1) { findNode(l.get(0)).addLabel(lisp("wvuyakuvuelmxpwp", l.head)); null; } else if (l(l) == 2) { S a = lisp2label(l.get(0)), b = lisp2label(l.get(1)); if (l.is("fgvvrzypbkqomktd")) { // X is Y. findNode(a).addLabel(b); findNode(b).addLabel(a); } WebNode na = findNode(a), nb = findNode(b); getRelation(na, nb).addLabel(l.head); ret pair(na, nb); } null; } void relations(L l) { for (Lisp li : l) relation(li); } WebRelation getRelation(S a, S b) { ret getRelation(findNode(a), findNode(b)); } WebRelation getRelation(WebNode a, WebNode b) { ret getRelation(pair(a, b)); } WebRelation relation(WebNode a, WebNode b) { ret getRelation(a, b); } WebRelation relation(Pair p) { ret getRelation(p); } WebRelation getRelationOpt(Pair p) { ret getRelationOpt(p.a, p.b); } WebRelation getRelationOpt(WebNode a, WebNode b) { ifdef WebWithRelationsMap if (relations != null) ret relations.get(pair(a, b)); endifdef for (WebNode n : nodes) if (n instanceof WebRelation) { WebRelation r = n/WebRelation; if (r.a == a && r.b == b) ret r; } null; } WebRelation getRelation(Pair p) { WebRelation r = getRelationOpt(p.a, p.b); if (r == null) { r = _newRelation(p.a, p.b); ifdef WebWithRelationsMap if (relations != null) relations.put(p, r); endifdef } ret r; } WebRelation _newRelation(WebNode a, WebNode b) { WebRelation r = new WebRelation(this, a, b); nodes.add(r); //for (L l : values(pots)) l.add(r); ret r; } WebNode newNode() { WebNode node = new WebNode(this); nodes.add(node); //for (L l : values(pots)) l.add(node); ret node; } WebNode newNode(S s) { WebNode node = newNode(); node.addLabel(parseLabel(s)); ret node; } WebNode node(S s) { ret findNode(s); } WebNode node(Lisp l) { ret findNode(l); } WebNode findNode(S s) { ret findNode(parseLabel(s)); } WebNode findNode(Lisp l) { WebNode n = findNodeOpt(l); ret n != null ? n : newNode(l); } WebNode findNodeOpt(Lisp l) { if (index != null) ret first(index.get(l)); for (WebNode n : nodes) if (n.hasLabel(l)) ret n; null; } WebNode newNode(S... labels) { WebNode n = newNode(); for (S label : labels) n.addLabel(label); ret n; } WebNode newNode(Lisp... labels) { WebNode n = newNode(); for (Lisp label : labels) n.addLabel(label); ret n; } toString { ret webToString(this); } void index(Lisp label, WebNode n) { if (index != null) index.put(label, n); fireNewLabel(n, label); } void clear { clearAll(nodes, index/*, pots*/); ifdef WebWithRelationsMap main clear(relations); endifdef } Lisp parseLabel(S s) { ifndef noCLParse if (useCLParse) ret clParse(s); endifndef ret lisp(labelsToUpper ? upper(s) : s); } S unparseLabel(Lisp l) { ifndef noCLParse if (useCLParse) ret clUnparse(l); endifndef ret lispHead(l); } L parseLabels(L l) { L x = new L(l(l)); for (S s : l) x.add(parseLabel(s)); ret x; } L unparseLabels(L l) { L x = new L(l(l)); for (Lisp lbl : l) x.add(unparseLabel(lbl)); ret x; } void fireNewNode(WebNode node) { for (O f : onNewNode) pcallF(f, node); } void fireNewLabel(WebNode node, Lisp label) { for (O f : onNewLabel) pcallF(f, node, label); } void removeNode(WebNode n) { if (n == null || !nodes.contains(n)) ret; n.web = null; ifdef WebWithRelationsMap // TODO L> relationsToDelete = pairList_lookupAnySide(keys(relations), n); endifdef if (index != null) for (Lisp label : n.labels()) index.remove(label, n); nodes.remove(n); ifdef WebWithRelationsMap for (Pair p : relationsToDelete) removeRelation(p.a, p.b); endifdef } void removeRelation(WebNode a, WebNode b) { Pair p = pair(a, b); WebNode r = getRelationOpt(p); if (r == null) ret; ifdef WebWithRelationsMap relations.remove(p); endifdef removeNode(r); } bool verified() { ret !unverified; } S globalID() { ret strOrNull(globalID); } GlobalID globalIDObj() { ret globalID instanceof S ? GlobalID((S) globalID) : (GlobalID) globalID; } void setGlobalID(S id) { globalID = asGlobalID(id); } public int hashCode() { ret globalIDObj().hashCode(); } public bool equals(O o) { ret o instanceof Web && eq(globalIDObj(), o/Web.globalIDObj()); } }