Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

594
LINES

< > BotCompany Repo | #1004681 // OLD Concepts (include)

JavaX fragment (include)

1  
// A concept should be an object, not just a string.
2  
3  
// Functions that should always be there for child processes:
4  
please include function dbLock.
5  
6  
static interface Derefable {
7  
  Concept get();
8  
}
9  
  
10  
sclass Concept extends DynamicObject {
11  
  long id;
12  
  //double energy;
13  
  //bool defunct;
14  
  long created;
15  
  
16  
  // used only internally (cnew)
17  
  *(S className) {
18  
    super(className);
19  
    _created();
20  
  }
21  
  
22  
  *() {
23  
    className = shortClassName(this);
24  
    if (!DynamicObject_loading) {
25  
      //print("New concept of type " + className);
26  
      _created();
27  
    }
28  
  }
29  
  
30  
  new L<Ref> refs;
31  
  new L<Ref> backRefs;
32  
33  
  void _created() {  
34  
    created = now();
35  
    if (!isTrue(_unlisted.get())) register();
36  
  }
37  
  
38  
  void put(S field, O value) {
39  
    fieldValues.put(field, value);
40  
    change();
41  
  }
42  
  
43  
  O get(S field) {
44  
    ret fieldValues.get(field);
45  
  }
46  
  
47  
  class Ref<A extends Concept> implements Derefable {
48  
    A value;
49  
    
50  
    *() {
51  
      if (!DynamicObject_loading) refs.add(this);
52  
    }
53  
    
54  
    *(A *value) {
55  
      refs.add(this);
56  
      index();
57  
    }
58  
    
59  
    // get owning concept (source)
60  
    Concept concept() { ret Concept.this; }
61  
    
62  
    // get target
63  
    public A get() { ret value; }
64  
    
65  
    bool has() { ret value != null; }
66  
    bool empty() { ret value == null; }
67  
    
68  
    void set(A a) {
69  
      if (a == value) ret;
70  
      unindex();
71  
      value = a;
72  
      index();
73  
    }
74  
    
75  
    void set(Ref<A> ref) { set(ref.get()); }
76  
    
77  
    void clear() { set((A) null); }
78  
    
79  
    void index() { 
80  
      if (value != null)
81  
        value.backRefs.add(this);
82  
      change();
83  
    }
84  
    
85  
    void unindex() {
86  
      if (value != null)
87  
        value.backRefs.remove(this);
88  
    }
89  
    
90  
    public S toString() {
91  
      ret str(get());
92  
    }
93  
  }
94  
  
95  
  class RefL<A extends Concept> extends AbstractList<A> {
96  
    new L<Ref<A>> l;
97  
    
98  
    public A set(int i, A o) {
99  
      A prev = l.get(i).get();
100  
      l.get(i).set(o);
101  
      change();
102  
      ret prev;
103  
    }
104  
    
105  
    public void add(int i, A o) {
106  
      l.add(i, new Ref(o));
107  
      change();
108  
    }
109  
    
110  
    public A get(int i) {
111  
      ret l.get(i).get();
112  
    }
113  
    
114  
    public A remove(int i) {
115  
      A a = l.remove(i).get();
116  
      change();
117  
      ret a;
118  
    }
119  
    
120  
    public int size() {
121  
      ret l.size();
122  
    }
123  
    
124  
    // derefs
125  
    void addAll_(L l) {
126  
      for (O x : l) add_(x);
127  
    }
128  
    
129  
    // derefs
130  
    void add_(O o) {
131  
      add((A) deref(o));
132  
    }
133  
  }
134  
  
135  
  void delete() {
136  
    if (id == 0) ret;
137  
    concepts.remove(id);
138  
    conceptsByClass.get(getClass()).remove(id);
139  
    id = 0;
140  
    //name = "[defunct " + name + "]";
141  
    //defunct = true;
142  
    //energy = 0;
143  
    for (Ref r : refs)
144  
      r.unindex();
145  
    refs.clear();
146  
    change();
147  
  }
148  
  
149  
  // register a previously unlisted concept
150  
  void register() {
151  
    if (id != 0) ret; // already registered
152  
    id = newID();
153  
    concepts.put(id, this);
154  
    _addToClassMap();
155  
    change();
156  
  }
157  
  
158  
  void _addToClassMap() {
159  
    Class c = getClass();
160  
    Map<Long, Concept> map = conceptsByClass.get(c);
161  
    if (map == null) {
162  
      // we're the first object, register this class
163  
      Class superclass = c.getSuperclass();
164  
      if (superclass != Concept)
165  
        subclasses.put(superclass, c);
166  
      conceptsByClass.put(c, map = new TreeMap);
167  
    }
168  
    map.put(id, this);
169  
  }
170  
} // class Concept
171  
172  
// for inter-process communication
173  
// prepared for string ids if we do them later
174  
sclass PassRef {
175  
  S id;
176  
  
177  
  *() {} // make serialisation happy
178  
  *(long id) { this.id = str(id); }
179  
  *(Concept c) { this(c.id); }
180  
  long longID() { ret parseLong(id); }
181  
  
182  
  public S toString() {
183  
    ret id;
184  
  }
185  
}
186  
187  
sclass Event extends Concept {}
188  
189  
// This can be set by client
190  
static bool concepts_quietSave;
191  
192  
static Map<Long, Concept> concepts = synchroTreeMap();
193  
static Map<Class, Map<Long, Concept>> conceptsByClass = synchroHashMap();
194  
static new MultiMap<Class, Class> subclasses;
195  
196  
static long idCounter;
197  
static volatile long changes = 1, changesWritten;
198  
static volatile java.util.Timer autoSaver;
199  
static volatile bool savingConcepts;
200  
static new ThreadLocal<Bool> _unlisted;
201  
static bool concepts_saveOneMore;
202  
static S conceptsLoadedFrom;
203  
static int concepts_internStringsLongerThan = 10;
204  
static int concepts_autoSaveInterval = 1000;
205  
206  
static long newID() {
207  
  do {
208  
    ++idCounter;
209  
  } while (hasConcept(idCounter));
210  
  ret idCounter;
211  
}
212  
213  
ssvoid loadConceptsFrom(S programID) {
214  
  conceptsLoadedFrom = programID;
215  
  clearConcepts();
216  
  DynamicObject_loading = true;
217  
  try {
218  
    structure_internStringsLongerThan = concepts_internStringsLongerThan;
219  
    readLocally(programID, "concepts");
220  
    readLocally(programID, "idCounter");
221  
    assignConceptsToUs();
222  
  } finally {
223  
    DynamicObject_loading = false;
224  
  }
225  
}
226  
227  
svoid assignConceptsToUs() {
228  
  for (Concept c : values(concepts)) {
229  
    c._addToClassMap();
230  
    callOpt(c, "_doneLoading2");
231  
  }
232  
}
233  
234  
ssvoid loadConcepts() {
235  
  loadConceptsFrom(programID());
236  
}
237  
238  
static Concept getConcept(S id) {
239  
  ret empty(id) ? null : getConcept(parseLong(id));
240  
}
241  
242  
static Concept getConcept(long id) {
243  
  ret (Concept) concepts.get((long) id);
244  
}
245  
246  
static Concept getConcept(PassRef ref) {
247  
  ret ref == null ? null : getConcept(ref.longID());
248  
}
249  
250  
static bool hasConcept(long id) {
251  
  ret concepts.containsKey((long) id);
252  
}
253  
254  
static bool hasConcept(Class c, O... params) {
255  
  ret conceptWhere(c, params) != null;
256  
}
257  
258  
static Concept deleteConcept(long id) {
259  
  Concept c = getConcept(id);
260  
  if (c == null)
261  
    print("Concept " + id + " not found");
262  
  else
263  
    c.delete();
264  
  ret c;
265  
}
266  
267  
// call in only one thread
268  
static void saveConceptsIfDirty() {
269  
  saveConceptsIfDirty(programID());
270  
}
271  
272  
static void saveConceptsIfDirty(S programID) {
273  
  savingConcepts = true;
274  
  try {
275  
    S s;
276  
    synchronized(main.class) {
277  
      bool change = changes != changesWritten;
278  
      if (!change && !concepts_saveOneMore) ret;
279  
      changesWritten = changes;
280  
      concepts_saveOneMore = change;
281  
      save(programID, "idCounter");
282  
      s = structure(cloneMap(concepts));
283  
    }
284  
    if (!concepts_quietSave)
285  
      print("Saving " + l(s) + " chars (" + changesWritten + ")");
286  
    saveTextFile(getProgramFile(programID, "concepts.structure"), s);
287  
    copyFile(getProgramFile(programID, "concepts.structure"), getProgramFile(programID, "concepts.structure.backup" + ymd() + "-" + formatInt(hours(), 2)));
288  
  } finally {
289  
    savingConcepts = false;
290  
  }
291  
}
292  
293  
static void saveConcepts() {
294  
  saveConceptsIfDirty();
295  
}
296  
297  
static void saveConceptsTo(S programID) {
298  
  saveConceptsIfDirty(programID);
299  
}
300  
301  
static void clearConcepts() {
302  
  concepts.clear();
303  
  conceptsByClass.clear();
304  
  subclasses.clear();
305  
  change();
306  
}
307  
308  
static synchronized void change() {
309  
  ++changes;
310  
}
311  
312  
// auto-save every second if dirty
313  
static synchronized void autoSaveConcepts() {
314  
  if (autoSaver == null)
315  
    autoSaver = doEvery(concepts_autoSaveInterval, r { saveConcepts(); });
316  
}
317  
318  
static void cleanMeUp() {
319  
  if (autoSaver != null) {
320  
    autoSaver.cancel();
321  
    autoSaver = null;
322  
  }
323  
  while (savingConcepts) sleep(10);
324  
  saveConceptsIfDirty();
325  
}
326  
327  
static Map<Long, S> getIDsAndNames() {
328  
  new Map<Long, S> map;
329  
  Map<Long, Concept> cloned = cloneMap(concepts);
330  
  for (long id : keys(cloned)) 
331  
    map.put(id, cloned.get(id).className);
332  
  ret map;
333  
}
334  
335  
static <A extends Concept> A findBackRef(Concept c, Class<A> type) {
336  
  ret findBackRefOfType(c, type);
337  
}
338  
339  
static <A extends Concept> A findBackRefOfType(Concept c, Class<A> type) {
340  
  for (Concept.Ref r : c.backRefs)
341  
    if (instanceOf(r.concept(), type))
342  
      ret (A) r.concept();
343  
  null;
344  
}
345  
346  
static <A extends Concept> L<A> findBackRefs(Concept c, Class<A> type) {
347  
  new L<A> l;
348  
  for (Concept.Ref r : c.backRefs)
349  
    if (instanceOf(r.concept(), type))
350  
      l.add((A) r.concept());
351  
  ret l;
352  
}
353  
354  
static <A extends Concept> A conceptOfType(Class<A> type) {
355  
  ret firstOfType(allConcepts(), type);
356  
}
357  
358  
static <A extends Concept> L<A> conceptsOfType(Class<A> type) {
359  
  //ret filterByType(allConcepts(), type);
360  
  new L<A> l;
361  
  _collectInstances(type, l);
362  
  ret l;
363  
}
364  
365  
svoid _collectInstances(Class c, L l) {
366  
  l.addAll(values(conceptsByClass.get(c)));
367  
  for (Class sub : subclasses.get(c))
368  
    _collectInstances(sub, l);
369  
}
370  
371  
static <A extends Concept> L<A> listConcepts(Class<A> type) {
372  
  ret conceptsOfType(type);
373  
}
374  
375  
static L<Concept> list(S type, O... params) {
376  
  ret empty(params) ? conceptsOfType(type)
377  
    : conceptsWhere(type, params);
378  
}
379  
380  
static <A extends Concept> L<A> list(Class<A> type, O... params) {
381  
  ret empty(params) ? conceptsOfType(type)
382  
    : conceptsWhere(type, params);
383  
}
384  
385  
static L<Concept> conceptsOfType(S type) {
386  
  ret filterByDynamicType(allConcepts(), "main$" + type);
387  
}
388  
389  
static bool hasConceptOfType(Class<? extends Concept> type) {
390  
  ret hasType(allConcepts(), type);
391  
}
392  
393  
static void persistConcepts() {
394  
  concepts_quietSave = true;
395  
  loadConcepts();
396  
  autoSaveConcepts();
397  
}
398  
399  
static void loadAndAutoSaveConcepts() {
400  
  persistConcepts();
401  
}
402  
403  
// We love synonyms
404  
static void conceptPersistence() {
405  
  persistConcepts();
406  
}
407  
  
408  
// Runs r if there is no concept of that type
409  
static <A extends Concept> A ensureHas(Class<A> c, Runnable r) {
410  
  A a = conceptOfType(c);
411  
  if (a == null) {
412  
    r.run();
413  
    a = conceptOfType(c);
414  
    if (a == null)
415  
      fail("Concept not made by " + r + ": " + shortClassName(c));
416  
  }
417  
  ret a;
418  
}
419  
420  
// Ensures that every concept of type c1 is ref'd by a concept of
421  
// type c2.
422  
// Type of func: voidfunc(concept)
423  
static void ensureHas(Class<? extends Concept> c1, Class<? extends Concept> c2, O func) {
424  
  for (Concept a : conceptsOfType(c1)) {
425  
    Concept b = findBackRef(a, c2);
426  
    if (b == null) {
427  
      callF(func, a);
428  
      b = findBackRef(a, c2);
429  
      if (b == null)
430  
        fail("Concept not made by " + func + ": " + shortClassName(c2));
431  
    }
432  
  }
433  
}
434  
435  
// Type of func: voidfunc(concept)
436  
static void forEvery(Class<? extends Concept> type, O func) {
437  
  for (Concept c : conceptsOfType(type))
438  
    callF(func, c);
439  
}
440  
441  
static int deleteAll(Class<? extends Concept> type) {
442  
  L<Concept> l = (L) conceptsOfType(type);
443  
  for (Concept c : l) c.delete();
444  
  ret l(l);
445  
}
446  
447  
static Collection<Concept> allConcepts() {
448  
  synchronized(concepts) {
449  
    ret new L(values(concepts));
450  
  }
451  
}
452  
453  
static Concept cnew(S name, O... values) {
454  
  Class<? extends Concept> cc = findClass(name);
455  
  Concept c = cc != null ? nuObject(cc) : new Concept(name);
456  
  csetAll(c, values);
457  
  ret c;
458  
}
459  
460  
static <A extends Concept> A cnew(Class<A> cc, O... values) {
461  
  A c = nuObject(cc);
462  
  csetAll(c, values);
463  
  ret c;
464  
}
465  
466  
static void csetAll(Concept c, O... values) {
467  
  cset(c, values);
468  
}
469  
470  
static void cset(Concept c, O... values) ctex {
471  
  values = expandParams(c.getClass(), values);
472  
  warnIfOddCount(values);
473  
  for (int i = 0; i+1 < l(values); i += 2) {
474  
    S field = (S) values[i];
475  
    O value = values[i+1];
476  
    Field f = setOpt_findField(c.getClass(), field);
477  
    //print("cset: " + c.id + " " + field + " " + struct(value) + " " + f);
478  
    if (value instanceof PassRef) value = getConcept((PassRef) value);
479  
    value = deref(value);
480  
    
481  
    if (value instanceof S && l((S) value) >= concepts_internStringsLongerThan) value = ((S) value).intern();
482  
    
483  
    if (f == null)
484  
      c.fieldValues.put(field, value instanceof Concept ? c.new Ref((Concept) value) : value);
485  
    else if (isSubtypeOf(f.getType(), Concept.Ref.class))
486  
      ((Concept.Ref) f.get(c)).set((Concept) value);
487  
    else
488  
      f.set(c, value);
489  
  }
490  
  change();
491  
}
492  
493  
static O cget(Concept c, S field) {
494  
  O o = getOptDyn(c, field);
495  
  if (o instanceof Concept.Ref) ret ((Concept.Ref) o).get();
496  
  ret o;
497  
}
498  
499  
static PassRef toPassRef(Concept c) {
500  
  ret new PassRef(c);
501  
}
502  
503  
// inter-process methods
504  
505  
static PassRef xnew(S name, O... values) {
506  
  ret new PassRef(cnew(name, values));
507  
}
508  
509  
static void xset(long id, S field, O value) {
510  
  xset(new PassRef(id), field, value);
511  
}
512  
513  
static void xset(PassRef c, S field, O value) {
514  
  if (value instanceof PassRef)
515  
    value = getConcept((PassRef) value);
516  
  cset(getConcept(c), field, value);
517  
}
518  
519  
// get class name of concept
520  
static O xclass(PassRef id) {
521  
  Concept c = getConcept(id);
522  
  ret c == null ? null : c.className;
523  
}
524  
525  
static O xget(long id, S field) {
526  
  ret xget(new PassRef(id), field);
527  
}
528  
529  
static O xget(PassRef c, S field) {
530  
  ret export(cget(getConcept(c), field));
531  
}
532  
533  
static void xdelete(long id) {
534  
  xdelete(new PassRef(id));
535  
}
536  
537  
static void xdelete(PassRef c) {
538  
  getConcept(c).delete();
539  
}
540  
541  
static L<PassRef> xlist() {
542  
  ret map("toPassRef", allConcepts());
543  
}
544  
545  
static L<PassRef> xlist(S className) {
546  
  ret map("toPassRef", conceptsOfType(className));
547  
}
548  
549  
// end of IPC methods
550  
551  
// make concept instance that is not connected to DB
552  
static <A extends Concept> A unlisted(Class<A> c) {
553  
  _unlisted.set(true);
554  
  try {
555  
    ret nuObject(c);
556  
  } finally {
557  
    _unlisted.set(null);
558  
  }
559  
}
560  
561  
static <A extends Concept> A unary(Class<A> c) {
562  
  A a = conceptOfType(c);
563  
  if (a == null)
564  
    a = nuObject(c);
565  
  ret a;
566  
}
567  
568  
static Android3 makeDBBot(S name) {
569  
  ret makeBot(name, makeDBResponder());
570  
}
571  
572  
static L<S> exposedDBMethods = ll("xlist", "xnew", "xset", "xdelete", "xget", "xclass");
573  
574  
static O makeDBResponder() {
575  
  ret new O {
576  
    S answer(S s) {
577  
      ret exposeMethods(s, exposedDBMethods);
578  
    }
579  
  };
580  
}
581  
582  
static O export(O o) {
583  
  if (o instanceof Concept)
584  
    ret new PassRef(((Concept) o).id);
585  
  ret o;
586  
}
587  
588  
ssvoid saveConceptsBack() {
589  
  saveConceptsTo(assertNotNull(conceptsLoadedFrom));
590  
}
591  
592  
static bool eq(O a, O b) {
593  
  ret _eq(deref(a), deref(b));
594  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, ddnzoavkxhuk, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1004681
Snippet name: OLD Concepts (include)
Eternal ID of this version: #1004681/3
Text MD5: 6d12e262917c4a94929783915cae1ab2
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2017-08-16 19:38:25
Source code size: 13914 bytes / 594 lines
Pitched / IR pitched: No / No
Views / Downloads: 1051 / 4462
Version history: 2 change(s)
Referenced in: [show references]