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

199
LINES

< > BotCompany Repo | #1030775 // DynBEAReactor

JavaX fragment (include) [tags: use-pretranspiled]

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
    }
  }
}

Author comment

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: 253 / 516
Version history: 21 change(s)
Referenced in: #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674)