Libraryless. Click here for Pure Java version (27227L/191K).
1 | sinterface IBEAReactor { |
2 | BEAObject uniqResult(Class<? extends BEAObject> c, O... params); |
3 | } |
4 | |
5 | extend BEAObject { |
6 | bool canReactWith(BEAObject o) { |
7 | ret isInstanceOfAny(o, (Cl) reactableWithClasses()); |
8 | } |
9 | |
10 | Cl<Class<? extends BEAObject>> reactableWithClasses() { |
11 | ret (Cl) collectFirstMethodArguments(findMethodsNamed_nonSynthetic(this, "reactWith")); |
12 | } |
13 | } |
14 | |
15 | beaConcept BReactor {} |
16 | |
17 | concept Reactable { |
18 | BEAObject a, b; |
19 | } |
20 | |
21 | asclass DynBEAReactor > DynCRUD_v2<BEAObject> { |
22 | S input, output; |
23 | switchable int maxObjects = 1000; |
24 | |
25 | transient new BEAUtils beaUtils; |
26 | transient new Concepts reactableConcepts; |
27 | transient ReliableSingleThread rstUpdateReactables = dm_rstWithDelay(this, 100, r updateReactables); |
28 | transient JTabbedPane bottomTabs; |
29 | |
30 | { tableFontSize = 15; } |
31 | |
32 | start { |
33 | ensureConceptClassIsIndexed(BEAObject); |
34 | crud.humanizeFieldNames = false; |
35 | crud.showBackRefs = true; |
36 | crud.specialFieldsForItem = a -> { |
37 | MapSO map = litorderedmap(crud.hID, str(a.id)); |
38 | S j = crud.javaClassDescForItem(a); |
39 | mapPut(map, "Class/Type", joinUniqueNemptiesCI("/", j, a.type())); |
40 | ret map; |
41 | }; |
42 | crud.itemToMap_inner = a -> { |
43 | MapSO map = crud.itemToMap_inner_base(a); |
44 | map.remove("type"); |
45 | ret map; |
46 | }; |
47 | |
48 | onConceptChangesAndNow(rstUpdateReactables); |
49 | |
50 | thread { |
51 | createInitialObjects(); |
52 | } |
53 | } |
54 | |
55 | void createInitialObjects {} |
56 | |
57 | visualize { |
58 | JConceptsTable<Reactable> tblReactables = new(reactableConcepts, Reactable); |
59 | JComponent c = jvsplit(0.75, 100, |
60 | jCenteredSection("Objects", super.visualize()), |
61 | bottomTabs = jtabs("Reactables", |
62 | withRightAlignedButtons( |
63 | tblReactables, |
64 | "React all", rThreadEnter reactAll, |
65 | "React until output", rThreadEnter reactUntilOutput, |
66 | jPopDownButton_noText("Update reactables", rstUpdateReactables)))); |
67 | |
68 | tablePopupMenuFirst(tblReactables.table(), (menu, row) -> { |
69 | Reactable r = tblReactables.getItem(row); |
70 | printVars_str(+row, +r); |
71 | ret if r == null; |
72 | addMenuItem(menu, "React", rThreadEnter { |
73 | BEAReactor reactor = new("Manually triggered reaction"); |
74 | reactor.react(r.a, r.b); |
75 | }); |
76 | }); |
77 | |
78 | tablePopupMenuFirst(table(), (menu, row) -> { |
79 | BEAObject o = getItem(row); |
80 | print("Item: " + o); |
81 | if (o == null) ret; |
82 | |
83 | pcall { |
84 | L<BEAObject> partners = filter(list(BEAObject), |
85 | partner -> o.canReactWith(partner)); |
86 | if (nempty(partners)) |
87 | addScrollingSubMenu(menu, "React with", menu2 -> { |
88 | for (BEAObject p : partners) |
89 | addMenuItem(menu2, str(p), rThread { |
90 | new BEAReactor("User reacts " + o + " with " + p).react(o, p); |
91 | }); |
92 | }); |
93 | } |
94 | }); |
95 | |
96 | addButton("Delete reactors", rThreadEnter deleteReactors); |
97 | |
98 | addButton(jPopDownButton_noText(popDownButtonEntries())); |
99 | |
100 | ret c; |
101 | } // end of visualize |
102 | |
103 | O[] popDownButtonEntries() { |
104 | ret litobjectarray( |
105 | "Export all objects", rThreadEnter exportAllObjects, |
106 | "Import objects [TODO]", rThread importObjects, |
107 | ); |
108 | } |
109 | |
110 | void exportAllObjects { |
111 | S text = indentStructureString(dm_mainConceptsStructWithExplicitMarkers()); |
112 | //dm_showExtraFrame("Export all objects", withCenteredButtons(jTextArea_wordWrap(text))); |
113 | dm_showTextInCodeEditor(text); |
114 | } |
115 | |
116 | void importObjects { |
117 | dm_showExtraFrame("Import objects", |
118 | withCenteredButtons(jTextArea_wordWrap())); |
119 | } |
120 | |
121 | class BEAReactor { |
122 | BReactor reactorConcept; |
123 | |
124 | *(S purpose) { |
125 | reactorConcept = cnew BReactor(+purpose); |
126 | } |
127 | |
128 | void react(BEAObject a, BEAObject b) { |
129 | call(a, 'reactWith, b, new IBEAReactor { |
130 | public BEAObject uniqResult(Class<? extends BEAObject> c, O... params) { |
131 | BEAObject product = cnew(c, paramsPlus(params, |
132 | _fromReaction := ll(a, b), |
133 | _reactor := reactorConcept)); |
134 | product = beaUtils.autoMigrate(product); |
135 | BEAObject existing = findExisting(product); |
136 | print("Existing for " + product + ": " + existing); |
137 | if (existing != null) { |
138 | cdelete(product); |
139 | ret existing; |
140 | } else { |
141 | onReactionProduct(product); |
142 | ret product; |
143 | } |
144 | } |
145 | }); |
146 | } |
147 | } |
148 | |
149 | // find an existing reactor-made object with the same values |
150 | BEAObject findExisting(BEAObject o) { |
151 | MapSO map = allConceptFieldsAsMap(o); |
152 | removeAll(map, "_reactor", "globalID"); |
153 | //print(+map); |
154 | ret firstThat(conceptsWhere(o.getClass(), mapToParams(map)), |
155 | a -> a.getClass() == o.getClass() && a != o && cget _reactor(a) != null); |
156 | } |
157 | |
158 | void onReactionProduct(BEAObject a) pcall { |
159 | if (a.typeIs("output")) |
160 | setField(output := getStringOpt text(a)); |
161 | } |
162 | |
163 | void deleteReactors { |
164 | deleteConcepts(BEAObject, |
165 | o -> cget _reactor(o) != null || o.typeIs("reactor")); |
166 | } |
167 | |
168 | void updateReactables { |
169 | deleteConcepts(reactableConcepts); |
170 | L<BEAObject> objects = list(BEAObject); |
171 | for (BEAObject a : objects) |
172 | for (BEAObject b : filter(objects, b -> a.canReactWith(b))) |
173 | cnew(reactableConcepts, Reactable, +a, +b); |
174 | } |
175 | |
176 | BEAReactor reactAll() { |
177 | Cl<Reactable> l = list(reactableConcepts, Reactable); |
178 | if (empty(l)) null; |
179 | |
180 | BEAReactor reactor = new("User clicked \"react all\""); |
181 | |
182 | for (Reactable r : l) pcall { |
183 | reactor.react(r.a, r.b); |
184 | } |
185 | |
186 | ret reactor; |
187 | } |
188 | |
189 | bool hasOutput() { false; } |
190 | |
191 | void reactUntilOutput { |
192 | while (!hasOutput() && countConcepts(BEAObject) < maxObjects) { |
193 | rstUpdateReactables.waitUntilDone(); |
194 | int count = countConcepts(BEAObject); |
195 | BEAReactor reactor = reactAll(); |
196 | if (countConcepts(BEAObject) <= count+oneIf(reactor != null)) break; // +1 because of reactor |
197 | } |
198 | } |
199 | } |
Began life as a copy of #1030774
download show line numbers debug dex old transpilations
Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt
No comments. add comment
Snippet ID: | #1030775 |
Snippet name: | DynBEAReactor |
Eternal ID of this version: | #1030775/22 |
Text MD5: | 6264c8c98c4a951ccf6f9a07e2bcd2bd |
Transpilation MD5: | d6b251f5a3f0541e2dd1fdff40ac5558 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-03-31 15:04:25 |
Source code size: | 6079 bytes / 199 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 252 / 516 |
Version history: | 21 change(s) |
Referenced in: | [show references] |