Libraryless. Click here for Pure Java version (27227L/191K).
sinterface IBEAReactor {
BEAObject uniqResult(Class<? extends BEAObject> c, O... params);
}
extend BEAObject {
bool canReactWith(BEAObject o) {
ret isInstanceOfAny(o, (Cl) reactableWithClasses());
}
Cl<Class<? extends BEAObject>> reactableWithClasses() {
ret (Cl) collectFirstMethodArguments(findMethodsNamed_nonSynthetic(this, "reactWith"));
}
}
beaConcept BReactor {}
concept Reactable {
BEAObject a, b;
}
asclass DynBEAReactor > DynCRUD_v2<BEAObject> {
S input, output;
switchable int maxObjects = 1000;
transient new BEAUtils beaUtils;
transient new Concepts reactableConcepts;
transient ReliableSingleThread rstUpdateReactables = dm_rstWithDelay(this, 100, r updateReactables);
transient JTabbedPane bottomTabs;
{ tableFontSize = 15; }
start {
ensureConceptClassIsIndexed(BEAObject);
crud.humanizeFieldNames = false;
crud.showBackRefs = true;
crud.specialFieldsForItem = a -> {
MapSO map = litorderedmap(crud.hID, str(a.id));
S j = crud.javaClassDescForItem(a);
mapPut(map, "Class/Type", joinUniqueNemptiesCI("/", j, a.type()));
ret map;
};
crud.itemToMap_inner = a -> {
MapSO map = crud.itemToMap_inner_base(a);
map.remove("type");
ret map;
};
onConceptChangesAndNow(rstUpdateReactables);
thread {
createInitialObjects();
}
}
void createInitialObjects {}
visualize {
JConceptsTable<Reactable> tblReactables = new(reactableConcepts, Reactable);
JComponent c = jvsplit(0.75, 100,
jCenteredSection("Objects", super.visualize()),
bottomTabs = jtabs("Reactables",
withRightAlignedButtons(
tblReactables,
"React all", rThreadEnter reactAll,
"React until output", rThreadEnter reactUntilOutput,
jPopDownButton_noText("Update reactables", rstUpdateReactables))));
tablePopupMenuFirst(tblReactables.table(), (menu, row) -> {
Reactable r = tblReactables.getItem(row);
printVars_str(+row, +r);
ret if r == null;
addMenuItem(menu, "React", rThreadEnter {
BEAReactor reactor = new("Manually triggered reaction");
reactor.react(r.a, r.b);
});
});
tablePopupMenuFirst(table(), (menu, row) -> {
BEAObject o = getItem(row);
print("Item: " + o);
if (o == null) ret;
pcall {
L<BEAObject> partners = filter(list(BEAObject),
partner -> o.canReactWith(partner));
if (nempty(partners))
addScrollingSubMenu(menu, "React with", menu2 -> {
for (BEAObject p : partners)
addMenuItem(menu2, str(p), rThread {
new BEAReactor("User reacts " + o + " with " + p).react(o, p);
});
});
}
});
addButton("Delete reactors", rThreadEnter deleteReactors);
addButton(jPopDownButton_noText(popDownButtonEntries()));
ret c;
} // end of visualize
O[] popDownButtonEntries() {
ret litobjectarray(
"Export all objects", rThreadEnter exportAllObjects,
"Import objects [TODO]", rThread importObjects,
);
}
void exportAllObjects {
S text = indentStructureString(dm_mainConceptsStructWithExplicitMarkers());
//dm_showExtraFrame("Export all objects", withCenteredButtons(jTextArea_wordWrap(text)));
dm_showTextInCodeEditor(text);
}
void importObjects {
dm_showExtraFrame("Import objects",
withCenteredButtons(jTextArea_wordWrap()));
}
class BEAReactor {
BReactor reactorConcept;
*(S purpose) {
reactorConcept = cnew BReactor(+purpose);
}
void react(BEAObject a, BEAObject b) {
call(a, 'reactWith, b, new IBEAReactor {
public BEAObject uniqResult(Class<? extends BEAObject> c, O... params) {
BEAObject product = cnew(c, paramsPlus(params,
_fromReaction := ll(a, b),
_reactor := reactorConcept));
product = beaUtils.autoMigrate(product);
BEAObject existing = findExisting(product);
print("Existing for " + product + ": " + existing);
if (existing != null) {
cdelete(product);
ret existing;
} else {
onReactionProduct(product);
ret product;
}
}
});
}
}
// find an existing reactor-made object with the same values
BEAObject findExisting(BEAObject o) {
MapSO map = allConceptFieldsAsMap(o);
removeAll(map, "_reactor", "globalID");
//print(+map);
ret firstThat(conceptsWhere(o.getClass(), mapToParams(map)),
a -> a.getClass() == o.getClass() && a != o && cget _reactor(a) != null);
}
void onReactionProduct(BEAObject a) pcall {
if (a.typeIs("output"))
setField(output := getStringOpt text(a));
}
void deleteReactors {
deleteConcepts(BEAObject,
o -> cget _reactor(o) != null || o.typeIs("reactor"));
}
void updateReactables {
deleteConcepts(reactableConcepts);
L<BEAObject> objects = list(BEAObject);
for (BEAObject a : objects)
for (BEAObject b : filter(objects, b -> a.canReactWith(b)))
cnew(reactableConcepts, Reactable, +a, +b);
}
BEAReactor reactAll() {
Cl<Reactable> l = list(reactableConcepts, Reactable);
if (empty(l)) null;
BEAReactor reactor = new("User clicked \"react all\"");
for (Reactable r : l) pcall {
reactor.react(r.a, r.b);
}
ret reactor;
}
bool hasOutput() { false; }
void reactUntilOutput {
while (!hasOutput() && countConcepts(BEAObject) < maxObjects) {
rstUpdateReactables.waitUntilDone();
int count = countConcepts(BEAObject);
BEAReactor reactor = reactAll();
if (countConcepts(BEAObject) <= count+oneIf(reactor != null)) break; // +1 because of reactor
}
}
}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: | 501 / 807 |
| Version history: | 21 change(s) |
| Referenced in: | [show references] |