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

1639
LINES

< > BotCompany Repo | #1030602 // Gazelle BEA [backup before package change]

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 1951K of libraries. Compilation Failed (8718L/65K).

1  
!7
2  
3  
// TODO: prevent non-master users from setting createdBy field manually
4  
5  
!include early #1031277 // BEA general includes
6  
7  
!include once #1030833 // BEACalculations
8  
9  
set flag DynModule.
10  
set flag NoNanoHTTPD.
11  
rewrite BEA with BEAObject.
12  
13  
module GazelleBEA > DynGazelleRocks {
14  
  switchable bool mirrorBEAObjects; // don't do it for now
15  
  switchable bool enableAutoRuns = true;
16  
  switchable bool enableNewBEAObjectNotis = true;
17  
  switchable bool printAllConceptChanges;
18  
  switchable bool useShadowLogger = true;
19  
  switchable bool autoActivateDynamicObjects = true;
20  
  
21  
  transient ReliableSingleThread_Multi<BEAObject> rstAutoRuns = new(1000, lambda1 performAutoRuns);
22  
  transient Q notificationQ;
23  
  transient ReliableSingleThread_Multi<BEAObject> rstDistributeNewObject = new(1000, lambda1 distributeNewObject_impl);
24  
  transient Set<BEAObject> newObjectsDistributed = weakSet();
25  
26  
  transient ReliableSingleThread_Multi<BEAObject> rstUpdateBEAMirrors = new(100, c -> enter { c.updateMirrorPost(); });
27  
  
28  
  transient ReliableSingleThread_Multi<BEAObject> rstAutoActivateDynamicObjects = new(100, c -> enter { autoActivateDynamicObject(c); });
29  
30  
  transient BEACalculations calculations = new(this);
31  
  transient BEACalculations calc = calculations;
32  
  transient int newFieldsToShow = 3;
33  
  transient bool allowAnonymousInputUpload = true; // TODO
34  
  switchable int maxInputLength = 50000;
35  
  
36  
  transient ConceptClassesDependentValue<Int> inputsWithoutRewrites;
37  
  transient ConceptClassesDependentValue<Int> inputsWithoutMatches;
38  
  transient ConceptClassesDependentValue<Int> syntacticPatternsWithoutRewrites;
39  
40  
  // add more fields here
41  
  
42  
  !include #1030883 // DB quickImport mix-in
43  
  
44  
  void init {
45  
    super.init();
46  
    //set quickDBReloadEnabled;
47  
    botName = heading = adminName = "Gazelle BEA";
48  
    set enableVars;
49  
    unset showTalkToBotLink;
50  
    unset phoneNumberSpecialInputField;
51  
    unset showMetaBotOnEveryPage;
52  
  }
53  
54  
  void startDB {
55  
    db();
56  
    db_mainConcepts().useBackRefsForSearches = true;
57  
    inputsWithoutRewrites = ConceptClassesDependentValue(litset(BEA), () -> countPred(beaList("Input"), c -> empty(beaBackRefs(c, "Rewrite"))));
58  
    inputsWithoutMatches = ConceptClassesDependentValue(litset(BEA), () -> countPred(beaList("Input"), c -> empty(beaBackRefs(c, "Match"))));
59  
    syntacticPatternsWithoutRewrites = ConceptClassesDependentValue(litset(BEA), () -> countPred(beaList("Syntactic Pattern"), c -> empty(beaBackRefs(c, "Rewrite"))));
60  
    
61  
    if (useShadowLogger) {
62  
      ConceptsShadowLogger shadowLogger = new(db_mainConcepts());
63  
      shadowLogger.install();
64  
      //shadowLogger.writer = printWriter(deflaterOutputStream_syncFlush_append(programFile("shadow.log.deflated")));
65  
      shadowLogger.writer = filePrintWriter_append(programFile("shadow.log"));
66  
      dm_doEvery(10.0, r { shadowLogger.flush(); });
67  
      ownResource(shadowLogger);
68  
    }
69  
    
70  
    if (printAllConceptChanges) printAllConceptChanges();
71  
  }
72  
73  
  void start {
74  
    assertEquals(BEAObject, callF(defaultDefaultClassFinder(), "main$BEAObject"));
75  
    assertEquals(ConceptWithGlobalID, callF(defaultDefaultClassFinder(), "main$ConceptWithGlobalID"));
76  
    seedDBFrom(#1030602);
77  
    set botDisabled;
78  
    set storeBaseClassesInStructure;
79  
    super.start();
80  
    print("main concepts: " + db_mainConcepts() + ", count: " + db_mainConcepts().countConcepts());
81  
    print(renderConceptClassesWithCount(db_mainConcepts()));
82  
    print("Inputs: " + n2(beaCount("Input")));
83  
    set showCRUDToEveryone;
84  
    //set showOnlySelectedObject;
85  
    
86  
    // reload module when lib changes
87  
    dm_onSnippetTranspiled(voidfunc(S snippetID) {
88  
      if (sameSnippetID(snippetID, #1030952))
89  
        dm_reloadModule();
90  
    });
91  
92  
    if (!enabled) ret;
93  
94  
    // mirror all objects to be sure
95  
    rstUpdateBEAMirrors.addAll(list(BEAObject));
96  
    
97  
    newObjectsDistributed.addAll(list(BEAObject));
98  
    
99  
    /*onIndividualConceptChange_notOnAllChanged(BEAObject,
100  
      p -> { calculations.makeSyntacticPattern(p); });*/
101  
      
102  
    onIndividualConceptChange_notOnAllChanged(BEAObject,
103  
      o -> {
104  
        if (enableAutoRuns) rstAutoRuns.add(o);
105  
        if (enableNewBEAObjectNotis && newObjectsDistributed.add(o))
106  
          rstDistributeNewObject.add(o);
107  
      });
108  
      
109  
    notificationQ = dm_startQ();
110  
    
111  
    // fix refs occasionally
112  
    
113  
    dm_doEvery(5*60.0, r-enter {
114  
      print(ConceptsRefChecker(db_mainConcepts()).runAndFixAll());
115  
    });
116  
  }
117  
118  
  void makeIndices :: after {    
119  
    indexConceptFieldDesc(BEAObject, "_modified");
120  
    indexConceptFieldIC(BEAObject, "type");
121  
    indexConceptFieldIC(BEAObject, "text");
122  
  }
123  
  
124  
  L<Class> crudClasses(Req req) {
125  
    ret listPlus(super.crudClasses(req), BEAObject, /*BEAPatternList*/);
126  
  }
127  
  
128  
  Set<Class> hiddenCrudClasses() {
129  
    Set<Class> set = super.hiddenCrudClasses();
130  
    addAll(set, Conversation, ExecutedStep, InputHandled);
131  
    ret set;
132  
  }
133  
  
134  
  S authFormHeading() {
135  
    ret h3("Gazelle BEA");
136  
  }
137  
  
138  
  void makeFramer(Req req) {
139  
    super.makeFramer(req);
140  
    
141  
    req.framer.addInHead(hjs_autoExpandingTextAreas());
142  
  }
143  
144  
  <A extends Concept> HCRUD_Concepts<A> crudData(Class<A> c, Req req) {
145  
    HCRUD_Concepts<A> cc = super.crudData(c, req);
146  
    
147  
    if (c == BEAObject) {
148  
      cc.humanizeFieldNames = false;
149  
      cc.convertConceptValuesToRefs = true;
150  
      cc.itemName = () -> "BEA Object";
151  
      
152  
      cc.onCreate.add(o ->
153  
        cset(o, createdBy := currentUser()));
154  
      
155  
      cc.getObjectForDuplication = id -> {
156  
        MapSO item = cc.getObjectForDuplication_base(id);
157  
        item.put(createdBy := req.auth.user!); // set default creator to current user
158  
        item.put(createdFrom := getConcept(toLong(id)));
159  
        ret item;
160  
      };
161  
      
162  
      cc.emptyObject = () -> {
163  
        MapSO item = cc.emptyObject_base();
164  
        item.put(type := "");
165  
        ret item;
166  
      };
167  
      
168  
      Set<S> deletableRefs = litciset("Match");
169  
      
170  
      cc.objectCanBeDeleted = id -> {
171  
        BEA o = cast cc.conceptForID(id);
172  
        ret userCanEditObject(user(req), o)
173  
          && all(findBackRefs(BEAObject, o), x -> contains(deletableRefs, x.type()));
174  
      };
175  
176  
      cc.actuallyDeleteConcept = o -> {
177  
        deleteConcepts(filter(findBackRefs(BEAObject, o),
178  
          o2 -> contains(deletableRefs, o2.type())));
179  
        cdelete(o);
180  
      };
181  
    }
182  
183  
    ret cc;
184  
  }
185  
186  
  <A extends Concept> HCRUD makeCRUD(Class<A> c, Req req, HTMLFramer1 framer) {
187  
    HCRUD crud = super.makeCRUD(c, req, framer);
188  
    HCRUD_Concepts data = cast crud.data;
189  
    crud.showOnlySelected = true;
190  
    crud.showSearchField = true;
191  
    if (data.customFilter == null)
192  
      crud.descending = true; // show latest objects first by default except when searching
193  
    crud.cleanItemIDs = true;
194  
195  
    if (c == BEAObject) {
196  
      crud.cellColumnToolTips = true;
197  
      crud.unshownFields = litset("mirrorPost", "globalID");
198  
      crud.showTextFieldsAsAutoExpandingTextAreas = true;
199  
      HCRUD_Concepts cc = cast crud.data;
200  
      
201  
      S typeFilter = req.get("type");
202  
      if (nempty(typeFilter))
203  
        cc.addCIFilter(type := typeFilter);
204  
      
205  
      crud.renderCmds = map -> {
206  
        BEAObject o = getConcept BEAObject(crud.itemIDAsLong(map));
207  
        
208  
        new LS cmds;
209  
        
210  
        // special commands for BEA types or objects with certain fields
211  
        
212  
        if (nempty(o.text()))
213  
          cmds.add(
214  
            targetBlank(addParamsToURL(baseLink + "/query",
215  
              q := o.text(), algorithm := "process input"),
216  
              "Use text as query"));
217  
218  
        if (o.typeIs("Input")) {
219  
          cmds.add(ahref(addParamsToURL(crudLink(BEAObject),
220  
            cmd := "new",
221  
            title := "Add Pattern For Input",
222  
            f_type := "Pattern",
223  
            f_text := getStringOpt text(o),
224  
            f_shouldMatch := o.id, metaInfo_shouldMatch := "concept",
225  
          ), "Add pattern"));
226  
227  
          cmds.add(ahref(appendParamsToURL(baseLink + "/query", q := o.text(), algorithm := "Apply all text functions"),
228  
           "Apply all text functions"));
229  
        }
230  
231  
        if (o.typeIs("Pattern"))
232  
          cmds.add(ahref(appendParamsToURL(baseLink + "/query", q := o.id, algorithm := "Run pattern"),
233  
           "Try-run pattern against all inputs"));
234  
        
235  
        if (o.typeIsOneOf("Pattern", "Syntactic Pattern")) {
236  
          cmds.add(ahref(appendParamsToURL(baseLink + "/reactAllInputsWithPattern", patternID := o.id),
237  
           "React pattern with all inputs"));
238  
           
239  
          cmds.add(ahref(appendParamsToURL(baseLink + "/convertSyntacticToSemanticMatchesForWholePattern", patternID := o.id),
240  
            "Convert all syntactic matches to semantic matches"));
241  
        }
242  
243  
        if (o.typeIs("Match")) {
244  
          cmds.add(ahref(appendParamsToURL(baseLink + "/query", q := o.id, algorithm := "Find rewrites for match"),
245  
           "Find rewrites"));
246  
          if (beaTypeIs(beaGet pattern(o), "Syntactic Pattern"))
247  
            cmds.add(ahref(appendParamsToURL(baseLink + "/convertSyntacticToSemanticMatches", matchID := o.id),
248  
            "Convert to semantic matches"));
249  
        }
250  
251  
        cmds.add(
252  
          ahref(addParamsToURL(baseLink + "/markUseful",
253  
            redirect := beaShortURL(o),
254  
            objectID := o.id),
255  
            "Mark useful"));
256  
        
257  
        cmds.add(
258  
          ahref(addParamsToURL(baseLink + "/markBad",
259  
            redirect := beaShortURL(o),
260  
            objectID := o.id),
261  
            "Mark bad"));
262  
        
263  
        cmds.add(addCommentHTML(o));
264  
          
265  
        if (o.typeIsOneOf("Script", "Step in script") || eqic(beforeVerticalBar(o.type()), "Instruction"))
266  
          cmds.add(
267  
            ahref(addParamsToURL(baseLink + "/runInstruction",
268  
              instruction := o.id),
269  
              "Run"));
270  
              
271  
        if (o.typeIs("Function Result")) {
272  
          if (eqic(cget resultType(o), "string"))
273  
            cmds.add(
274  
              ahref(addParamsToURL(baseLink + "/convertResultToInput",
275  
                result := o.id),
276  
                "Convert to input"));
277  
        }
278  
        
279  
        if (o.typeIs("Auto Run"))
280  
          cmds.add(
281  
            ahref(addParamsToURL(baseLink + "/performAutoRunOnAllObjects", autoRun := o.id), "Run on all objects"));
282  
283  
        if (o.getClass() != BEA)
284  
          cmds.add(
285  
            ahref(addParamsToURL(baseLink + "/migrateToBase", id := o.id), "Migrate to BEAObject"));
286  
            
287  
        cmds.add(
288  
          ahref(addParamsToURL(baseLink + "/performAutoRuns",
289  
            onObject := o.id),
290  
            "Perform auto runs on this object"));
291  
            
292  
        framer.addInHead(hjs_copyToClipboard());
293  
        
294  
        cmds.add(ahref_onClick(formatFunctionCall copyToClipboard(jsQuote(o.globalIDStr())), "Copy global ID [" + o.globalIDStr() + "]"));
295  
        
296  
        LS items = llNempties(
297  
          crud.renderCmds_base(map),
298  
          !o.typeIsOneOf("Input", "Pattern", "Syntactic Pattern")
299  
            ? null : addRewriteHTML(o),
300  
          !canAutoMigrate(o) ? null 
301  
            : ahref(addParamsToURL(baseLink + "/autoMigrate", id := o.id), "Auto-migrate to " + shortClassName(defaultCustomClass(o))));
302  
303  
        if (isObjectWithCode(o) && isMasterAuthed(req))
304  
          items.add(ahref(baseLink + "/activateDynamicObject?id=" + o.id, "Activate custom code"));
305  
306  
        if (fileNotEmpty(javaSourceFileForObject(o)))
307  
          cmds.add(ahref(baseLink + "/javaSource?id=" + o.id, "Show Java source"));
308  
        
309  
        // add more commands here
310  
        
311  
        addAll(items, o.directCmds());
312  
        items.add(hPopDownButton(cmds));
313  
        
314  
        ret joinNemptiesWithVBar(items);
315  
      };
316  
      
317  
      cc.massageItemMapForList = (item, map) -> {
318  
        BEAObject o = cast item;
319  
        
320  
        if (o.typeIs("Input")) {
321  
          Cl<BEAObject> matches = objectsWhereNotIC(objectsWhereCI(findBackRefs(o, BEAObject), type := "match"),
322  
            label := "bad");
323  
          map/Map.put("Best Matches", HTML(hparagraphs(
324  
            lmap matchDescHTML(takeFirst(3, matches)))));
325  
        }
326  
        S idField = crud.idField();
327  
        O id = map/Map.get(idField);
328  
        if (id instanceof S)
329  
          map/Map.put(idField, HTML(ahref(beaShortURL(o), id)));
330  
        if (o.typeIs("Function Result")) {
331  
          O value = o~.result;
332  
          map/Map.put("result", HTML(javaValueToHTML(value)));
333  
        }
334  
        
335  
        if (o.typeIs("Match")) {
336  
          SS mapping = o.mapping();
337  
          if (mapping != null)
338  
          map/Map.put("mapping", HTML(
339  
            joinWithBR(map(mapping, (k, v) ->
340  
              htmlEncode2(k) + "=" + calculations.bestInputHTML(v)))));
341  
        }
342  
      
343  
        if (o.getClass() != BEA)
344  
          map/Map.put("Java Class", shortClassName(o));
345  
          
346  
        if (eq(req.get("showSimpleObjectScore"), "1"))
347  
          map/Map.put("Simple object score" := calculations.simpleObjectScore(o));
348  
      }; // end of massageItemMapForList
349  
      
350  
      crud.massageFormMatrix = (map, matrix) -> {
351  
        for (int i = 1; i <= newFieldsToShow; i++) {
352  
          S nf = "newField" + i;
353  
          
354  
          S refSelector =
355  
            crud.renderInput("\*nf*/_conceptValue",
356  
              cc.makeConceptsComboBox("\*nf*/_conceptValue", BEAObject), null)
357  
            + hjs([[$("[name=]] + nf + [[_conceptValue]").hide()]]);
358  
              
359  
          S userSelector =
360  
            crud.renderInput("\*nf*/_userValue",
361  
              cc.makeConceptsComboBox("\*nf*/_userValue", User), null)
362  
            + hjs([[$("[name=]] + nf + [[_userValue]").hide()]]);
363  
              
364  
          LS types = ll("String", "BEAObject", "Bool", "User");
365  
              
366  
          S typeSelector = hselect_list(types, name := "\*nf*/_type",
367  
              onchange := [[
368  
                var value = this.value;
369  
                $("[name=]] + nf + [[_value]").toggle(value == "String" || value == "Bool");
370  
                $("#]] + nf + [[_refBox").toggle(value == "BEAObject");
371  
                $("#]] + nf + [[_userSel").toggle(value == "User");
372  
              ]]);
373  
          
374  
          matrix.add(ll("Add field:<br>" + htextfield("\*nf*/_name", title := "New field name"),
375  
            htmlTable2_noHtmlEncode(ll(ll(
376  
              // string input
377  
              //htextfield("\*nf*/_value"),
378  
              htextarea("",
379  
                name := "\*nf*/_value", 
380  
                class := "auto-expand",
381  
                style := "max-height: 10em; width: 300px; vertical-align: top",
382  
              ) +
383  
              span(refSelector, id := "\*nf*/_refBox", style := "display: none"),
384  
              span(userSelector, id := "\*nf*/_userSel", style := "display: none"),
385  
            "Type", typeSelector
386  
            )),
387  
            noHeader := true,
388  
            tableParams := litobjectarray(style := "width: 100%"))));
389  
          }
390  
        };
391  
      
392  
      crud.preprocessUpdateParams = params -> {
393  
        params = cloneMap(params);
394  
395  
        // drop empty strings
396  
        //removeFromMapWhereValue(params, v -> eq(v, ""));
397  
        params = mapValues(params, v -> eq(v, "") ? null : v);
398  
        
399  
        for (int i = 1; i <= max(newFieldsToShow, 10); i++) {
400  
          S nf = "newField" + i;
401  
          S name = params.get("\*nf*/_name"),
402  
            type = params.get("\*nf*/_type"),
403  
            refValue = params.get("\*nf*/_conceptValue"),
404  
            userValue = params.get("\*nf*/_userValue"),
405  
            value = params.get("\*nf*/_value");
406  
  
407  
          if (eqic(type, "BEAObject")) {
408  
            value = refValue;
409  
            params.put("metaInfo_" + name, "concept");
410  
          } else if (eqic(type, "User")) {
411  
            value = userValue;
412  
            params.put("metaInfo_" + name, "concept");
413  
          } else if (eqic(type, "Bool"))
414  
            params.put("metaInfo_" + name, "bool");
415  
          
416  
          if (eq(value, "")) value = null;
417  
            
418  
          if (nempty(name) /*&& neqOneOf(value, null, "")*/)
419  
            params.put(crud.fieldPrefix + name, value);
420  
        }
421  
        
422  
        ret params;
423  
      };
424  
425  
      // regular users can only edit their own objects
426  
      if (!isMasterAuthed(req))
427  
        cc.objectCanBeEdited = id -> userCanEditObject(user(req), (BEA) cc.conceptForID(id));
428  
    } // end of CRUD customization for BEAObject
429  
    
430  
    ret crud;
431  
  }
432  
433  
  bool userCanEditObject(User user, BEA o) {
434  
    ret cget createdBy(o) == user;
435  
  }
436  
  
437  
  O serveBotFunction(Req req, S function, Map data, User user) {
438  
    if (eq(function, "beaList")) {
439  
      long changedAfter = toLong(data.get("changedAfter"));
440  
      double pollFor = min(bot_maxPollSeconds, toLong(data.get("pollFor"))); // how long to poll (seconds)
441  
      long startTime = sysNow();
442  
443  
      // We're super-anal about catching all changes. This will probably never trigger
444  
      if (changedAfter > 0 && changedAfter == now()) sleep(1);
445  
      
446  
      Cl<BEAObject> objects;
447  
      while true {
448  
        objects = changedAfter == 0 ? list(BEAObject)
449  
          : conceptsWithFieldGreaterThan_sorted(BEAObject, _modified := changedAfter);
450  
451  
        // return when there are results, no polling or poll expired
452  
        if (nempty(objects) || pollFor == 0 || elapsedSeconds_sysNow(startTime) >= pollFor)
453  
          ret serveJSON_breakAtLevels(2, result := map(objects, obj ->
454  
            litorderedmap(gid := str(obj.globalID()), struct := obj.structureString())
455  
          ));
456  
457  
        // sleep and try again
458  
        sleep(bot_pollInterval);
459  
      }
460  
    }
461  
    
462  
    ret super.serveBotFunction(req, function, data, user);
463  
  }
464  
465  
  O serveOtherPage2(Req req) null {
466  
    printVars_str serveOtherPage2(uri := req.uri);
467  
    try object super.serveOtherPage2(req);
468  
    
469  
    S uri = dropTrailingSlashIfNemptyAfterwards(req.uri);
470  
    new Matches m;
471  
    
472  
    if (swic_notSame(uri, "/beaCRUD/", m))
473  
      ret renderBEAObjectTable(req, urldecode(m.rest()));
474  
    
475  
    if (eq(uri, "/inputs"))
476  
      ret renderBEAObjectTable(req, "input");
477  
      
478  
    if (eq(uri, "/syntacticMatchesTable"))
479  
      ret hrefresh(baseLink + "/matchesTable?syntacticOnly=1");
480  
      
481  
    if (eq(uri, "/matchesTable")) {
482  
      bool syntacticOnly = eq("1", req.get("syntacticOnly"));
483  
484  
      new L<BEA> list;
485  
      for (BEA match : beaList("Match")) {
486  
        BEA input = cgetOpt BEA(match, "input");
487  
        BEA pat = cgetOpt BEA(match, "pattern");
488  
        if (syntacticOnly && !calculations.isSyntacticPattern(pat)) continue;
489  
        continue if calculations.patternAlwaysMatches(pat);
490  
491  
        SS mapping = match.mapping();
492  
        if (input == null || pat == null || mapping == null) continue;
493  
        list.add(match);
494  
      }
495  
      list = sortedByCalculatedFieldDesc(list,
496  
        match -> conceptID(cgetBEA input(match)));
497  
      
498  
      new HTMLPaginator paginator;
499  
      paginator.processParams(req.params());
500  
      paginator.baseLink = addParamsToURL(baseLink,
501  
        filterKeys(req.params(), p -> eq(p, "syntacticOnly")));
502  
      paginator.max = l(list);
503  
      req.framer.add(divUnlessEmpty(paginator.renderNav()));
504  
      list = subList(list, paginator.visibleRange());
505  
      
506  
      new L<Map> data;
507  
      for (BEA match : list) {
508  
        BEA input = cgetOpt BEA(match, "input");
509  
        BEA pat = cgetOpt BEA(match, "pattern");
510  
        SS mapping = match.mapping();
511  
        S patText = calculations.patternTextWithAngleBracketVars(pat);
512  
        LS tok = javaTokWithAngleBrackets(patText);
513  
        new BitSet bs;
514  
        tok = replaceAngleBracketVars(tok, mapping, bs);
515  
        for (IntRange r, bool b : unpair bitSetStreaksAndNonStreaks(bs, l(tok))) {
516  
          S t = joinSubList(tok, r);
517  
          replaceTokens(tok, r, b
518  
            ? formatSubInput(input, t, "obj" + match.id)
519  
            : htmlEncode2(t));
520  
        }
521  
        S boldenedInput = join(tok);
522  
        
523  
        data.add(litorderedmap(
524  
          "Input" := aname("obj" + match.id, joinWithBR(
525  
            ahref(beaURL(input), htmlEncode2_str(input~.text())),
526  
            boldenedInput)),
527  
          "Pattern" := ahref(beaURL(pat), htmlEncode2(pat.text())), // beaHTML(pat),
528  
          //"Sub-Inputs" := htmlEncode2_str(mapping),
529  
          "DB object" := beaHTML_justID(match),
530  
          "Feedback" := joinNemptiesWithSpace(calculations.feedbackHTML(match),
531  
            addCommentHTML(match, defaultComment := "good match", redirectAfterSave := req.uriWithParams(),
532  
            text := "+")),
533  
        ));
534  
      }
535  
        
536  
      req.framer.title = syntacticOnly ? "Syntactic matches table" : "Matches table";
537  
      req.framer.add(p());
538  
      req.framer.add(htmlTable2_noHtmlEncode(data));
539  
      ret completeFrame(req);
540  
    }
541  
            
542  
    if (eq(uri, "/rewritesTable")) {
543  
      new L<Map> data;
544  
      for (BEA input : beaList("Input"))
545  
        for (BEA r : beaBackRefs(input, "Rewrite"))
546  
          data.add(litorderedmap(
547  
            "Input" := input.text(),
548  
            "Rewrite" := tok_dropCurlyBrackets(r.text()),
549  
            "Rewrite Type" := r~.rewriteType));
550  
            
551  
      req.framer.title = "Rewrites table";
552  
      req.framer.add(p());
553  
      req.framer.add(htmlTable2(data));
554  
      ret completeFrame(req);
555  
    }
556  
557  
    if (eq(uri, "/patternRewritesTable")) {
558  
      new L<Map> data;
559  
      for (BEA pat : beaListAny("Pattern", "Syntactic Pattern"))
560  
        for (BEA r : beaBackRefs(pat, "Rewrite"))
561  
          if (cget isRewriteOf(r) == pat) {
562  
            PairS example = calculations.exampleForPatternRewrite(pat, r);
563  
            data.add(litorderedmap(
564  
              "Pattern" := ahref(beaURL(pat), htmlEncode2(pat.text())),
565  
              "Rewrite" := ahref(beaURL(r), htmlEncode2(tok_dropCurlyBrackets(r.text()))),
566  
              "Example" := joinWithBR(htmlEncode2(example.a), htmlEncode2("=> " + example.b)),
567  
              "Rewrite Type" := htmlEncode2_str(r~.rewriteType),
568  
              "Cmds" := hPopDownButton(
569  
                targetBlank(conceptEditLink(r), "Edit"),
570  
              )));
571  
          }
572  
            
573  
      req.framer.title = "Pattern rewrites table";
574  
      req.framer.add(p());
575  
      req.framer.add(htmlTable2_noHtmlEncode(data));
576  
      ret completeFrame(req);
577  
    }
578  
579  
    if (eq(uri, "/syntacticPatternsWithoutRewrites")) {
580  
      HCRUD crud = makeBEAObjectCRUD(req, "Syntactic Pattern");
581  
      HCRUD_Concepts<BEAObject> data = cast crud.data;
582  
      
583  
      IF1 prev = data.customFilter;
584  
      data.customFilter = list -> {
585  
        list = filter(list, c -> empty(beaBackRefs(c, "Rewrite")));
586  
        ret postProcess(prev, list);
587  
      };
588  
      crud.customTitle = "Syntactic patterns without rewrites";
589  
      ret serveCRUD(req, BEAObject, crud);
590  
    }
591  
      
592  
    if (eq(uri, "/inputsWithoutRewrites")) {
593  
      HCRUD crud = makeBEAObjectCRUD(req, "input");
594  
      HCRUD_Concepts<BEAObject> data = cast crud.data;
595  
      
596  
      IF1 prev = data.customFilter;
597  
      data.customFilter = list -> {
598  
        list = filter(list, c -> empty(beaBackRefs(c, "Rewrite")));
599  
        ret postProcess(prev, list);
600  
      };
601  
      crud.customTitle = "Inputs without rewrites";
602  
      ret serveCRUD(req, BEAObject, crud);
603  
    }
604  
      
605  
    if (eq(uri, "/inputsWithRewrites")) {
606  
      HCRUD crud = makeBEAObjectCRUD(req, "input");
607  
      HCRUD_Concepts<BEAObject> data = cast crud.data;
608  
      
609  
      IF1 prev = data.customFilter;
610  
      data.customFilter = list -> {
611  
        list = filter(list, c -> nempty(beaBackRefs(c, "Rewrite")));
612  
        ret postProcess(prev, list);
613  
      };
614  
      crud.customTitle = "Inputs with rewrites";
615  
      ret serveCRUD(req, BEAObject, crud);
616  
    }
617  
      
618  
    if (eq(uri, "/inputsWithoutMatches")) {
619  
      HCRUD crud = makeBEAObjectCRUD(req, "input");
620  
      HCRUD_Concepts<BEAObject> data = cast crud.data;
621  
      
622  
      IF1 prev = data.customFilter;
623  
      data.customFilter = list -> {
624  
        list = filter(list, c -> empty(beaBackRefs(c, "Match")));
625  
        ret postProcess(prev, list);
626  
      };
627  
      crud.customTitle = "Inputs without matches";
628  
      ret serveCRUD(req, BEAObject, crud);
629  
    }
630  
      
631  
    if (eq(uri, "/patterns"))
632  
      ret renderBEAObjectTable(req, "pattern");
633  
634  
    if (eq(uri, "/syntacticPatterns"))
635  
      ret renderBEAObjectTable(req, "Syntactic Pattern");
636  
637  
    if (eq(uri, "/matches"))
638  
      ret renderBEAObjectTable(req, "match");
639  
640  
    if (eq(uri, "/rewrites"))
641  
      ret renderBEAObjectTable(req, "rewrite");
642  
643  
    if (eq(uri, "/aiTasks"))
644  
      ret renderBEAObjectTable(req, "AI Task");
645  
646  
    if (eq(uri, "/query"))
647  
      ret calculations.serveQueryPage(req);
648  
      
649  
    if (eq(uri, "/saveInput")) {
650  
      S text = trim(req.get("text"));
651  
      S info = trim(req.get("info"));
652  
      if (empty(text)) ret subBot_serve500("Input empty");
653  
      if (l(text) > maxInputLength) ret subBot_serve500("Input too long");
654  
      BEAObject input = uniqCI BEAObject(type := "Input", +text, createdBy := user(req));
655  
      saveUserAgent(input);
656  
      if (nempty(info))
657  
        uniqCI BEAObject(type := "Input Source", +input, source := info);
658  
      ret hrefresh(or2(req.get("redirect"), baseLink + "/"));
659  
    }
660  
      
661  
    if (eq(uri, "/markUseful")) {
662  
      BEA o = beaGet objectID(req);
663  
      if (o == null) ret subBot_serve500("Object not found");
664  
      uniqCI BEA(type := "Useful", object := o, createdBy := user(req));
665  
      ret hrefresh(or2(req.get("redirect"), baseLink + "/"));
666  
    }
667  
      
668  
    if (eq(uri, "/markBad")) {
669  
      BEA o = beaGet objectID(req);
670  
      if (o == null) ret subBot_serve500("Object not found");
671  
      uniqCI BEA(type := "Bad", object := o, createdBy := user(req));
672  
      ret hrefresh(or2(req.get("redirect"), baseLink + "/"));
673  
    }
674  
      
675  
    if (eq(uri, "/saveAnswer")) {
676  
      S text = trim(req.get("text"));
677  
      S rewriteType = or2(trim(req.get("rewriteType")), "Suggested Answer");
678  
      long inputID = toLong(req.get("inputID"));
679  
      BEAObject input = beaGet(inputID);
680  
      if (input == null) ret subBot_serve500("Input not found");
681  
      if (empty(text)) ret subBot_serve500("Text empty");
682  
      if (l(text) > maxInputLength) ret subBot_serve500("Text too long");
683  
      uniqCI BEAObject(type := "Rewrite", +text, isRewriteOf := input, +rewriteType, createdBy := user(req));
684  
      ret hrefresh(or2(req.get("redirect"), baseLink + "/"));
685  
    }
686  
687  
    if (eq(uri, "/javaSource")) {
688  
      BEA o = beaGet id(req);
689  
      ret serveText(loadTextFile(javaSourceFileForObject(o)));
690  
    }
691  
      
692  
    // add more public URLs here
693  
      
694  
    if (!inMasterMode(req)) null;
695  
    
696  
    if (eq(uri, "/uploadInputs"))
697  
      ret serveUploadTexts(req, "Input");
698  
    
699  
    if (eq(uri, "/uploadPatterns"))
700  
      ret serveUploadTexts(req, "Pattern");
701  
      
702  
    if (eq(uri, "/analyzeInput"))
703  
      ret calculations.serveAnalyzeInput(req);
704  
      
705  
    if (eq(uri, "/allBEATypes")) {
706  
      ret h2_title("All object types")
707  
        + ul(renderObjectTypes());
708  
    }
709  
    
710  
    if (eq(uri, "/storeMatch")) {
711  
      BEAObject pattern = beaGet(req.get("pattern"));
712  
      BEAObject input = beaGet(req.get("input"));
713  
      S label = req.get("label");
714  
      BEAObject match = calculations.reactInputWithPattern(input, pattern);
715  
      if (match == null) ret "Couldn't match";
716  
      cset(match, +label);
717  
      ret hrefresh(or2(req.get("redirect"), beaObjectURL(match)));
718  
    }
719  
    
720  
    if (eq(uri, "/saveSyntacticPattern") || eq(uri, "/savePattern")) {
721  
      S type = cic(uri, "syntactic") ? "Syntactic Pattern" : "Pattern";
722  
      S text = req.get("text");
723  
      BEAObject fromInput = beaGet(req.get("fromInput"));
724  
      BEAObject pat = uniqCI BEAObject(+type, +text, createdBy := user(req));
725  
      csetIfUnset(pat, +fromInput);
726  
      if (fromInput != null)
727  
        calculations.reactInputWithPattern(fromInput, pat);
728  
      ret hrefresh(or2(req.get("redirect"), baseLink + "/"));
729  
    }
730  
    
731  
    if (eq(uri, "/runInstruction")) {
732  
      BEAObject o = beaGet(req.get("instruction"));
733  
      runInstruction(o);
734  
      ret hrefresh(beaObjectURL(o));
735  
    }
736  
    
737  
    if (eq(uri, "/convertResultToInput")) {
738  
      BEAObject result = beaGet(req.get("result"));
739  
      if (result == null) ret subBot_serve500("Object not found");
740  
      S text = unquote(getString result(result));
741  
      if (l(text) > maxInputLength) ret subBot_serve500("Input too long");
742  
      BEAObject input = uniqCI BEAObject(type := "Input", +text);
743  
      uniqCI BEAObject(type := "Input Source", +input, source := result);
744  
      ret hrefresh(beaShortURL(input));
745  
    }
746  
    
747  
    /*if (eq(uri, "/pipeStringListIntoPattern")) {
748  
      BEA r = beaGet(req.get("resultID"));
749  
      BEa pat = beaGet(req.get("patternID"));
750  
      if (r == null || pat == null) ret "Object not found";
751  
      LS result = assertStringList(cget result(r));
752  
      for (S s : result)
753  
        uniq BEA(type := "Statement", );
754  
    }*/
755  
    
756  
    if (eq(uri, "/setWordType")) {
757  
      BEA r = beaGet(req.get("resultID"));
758  
      S wordType = assertNempty(req.get("wordType"));
759  
      LS result = assertStringList(cget result(r));
760  
      for (S s : result)
761  
        uniqCI BEA(type := "Word type", word := s, +wordType);
762  
      ret "OK";
763  
    }
764  
    
765  
    if (eq(uri, "/reload")) {
766  
      dm_reloadModuleIn(3);
767  
      ret "Reloading module in 3";
768  
    }
769  
    
770  
    if (eq(uri, "/performAutoRuns")) {
771  
      BEA o = beaGet(req.get("onObject"));
772  
      if (o == null) ret "Object not found";
773  
      rstAutoRuns.add(o);
774  
      ret hrefresh(beaURL(o));
775  
    }
776  
    
777  
    if (eq(uri, "/reactAllInputsWithAllSyntacticPatterns")) {
778  
      ret str(returnTimed(r { calculations.reactAllInputsWithAllSyntacticPatterns(); }));
779  
    }
780  
    
781  
    if (eq(uri, "/reactAllInputsWithPattern")) {
782  
      BEA pat = beaGet(req.get("patternID"));
783  
      if (pat == null) ret "Pattern not found";
784  
      ret str(returnTimed(r { calculations.reactAllInputsWithPattern(pat); }));
785  
    }
786  
    
787  
    if (eq(uri, "/storeSubInput")) {
788  
      BEA input = beaGet(req.get("input"));
789  
      if (input == null) ret "Input not found";
790  
      S text = req.get("text");
791  
      S type = eqic(req.get("label"), "good") ? "Sub-Input" : "Bad Sub-Input";
792  
      BEA o = uniqCI BEA(
793  
        +type,
794  
        +input,
795  
        +text,
796  
        createdBy := currentUser());
797  
      ret hrefresh(or2(req.get("redirect"), beaURL(o)));
798  
    }
799  
    
800  
    if (eq(uri, "/performAutoRunOnAllObjects")) {
801  
      BEA autoRun = beaGet autoRun(req);
802  
      performAutoRunOnAllObjects(autoRun);
803  
      ret "OK";
804  
    }
805  
    
806  
    if (eq(uri, "/autoMigrate")) {
807  
      BEA o = beaGet id(req);
808  
      if (o == null) ret "Object not found";
809  
      S url = beaURL(o);
810  
      ret hsansserif() + "Migrated " + beaHTML(o) + " to " + className(autoMigrateToCustomClass(o))
811  
        + hrefresh(1.0, url);
812  
    }
813  
      
814  
    if (eq(uri, "/migrateToBase")) {
815  
      BEA o = beaGet id(req);
816  
      if (o == null) ret "Object not found";
817  
      S url = beaURL(o);
818  
      ret hsansserif() + "Migrated " + beaHTML(o) + " to " + className(autoMigrateToBase(o))
819  
        + hrefresh(1.0, url);
820  
    }
821  
      
822  
    if (eq(uri, "/convertSyntacticToSemanticMatches")) {
823  
      BEA match = beaGet matchID(req);
824  
      if (match == null) ret "Match not found";
825  
      ret ul_htmlEncode2(calculations.convertSyntacticToSemanticMatches(match));
826  
    }
827  
    
828  
    if (eq(uri, "/convertSyntacticToSemanticMatchesForWholePattern")) {
829  
      BEA pat = beaGet patternID(req);
830  
      if (pat == null) ret "Pattern not found";
831  
      ret ul_htmlEncode2(calculations.convertSyntacticToSemanticMatchesForWholePattern(pat));
832  
    }
833  
    
834  
    if (eq(uri, "/createPatternListFromUsefulSyntacticPatterns"))
835  
      ret hrefresh(beaURL(calc.createPatternListFromUsefulSyntacticPatterns()));
836  
      
837  
    if (eq(uri, "/createConceptShadows"))
838  
      ret createConceptShadows();
839  
840  
    if (eq(uri, "/compareConceptShadows")) {
841  
      if (conceptShadows == null) ret createConceptShadows();
842  
      L<ConceptShadow> newShadows = allConceptShadows();
843  
      L<CreatedDeletedChanged<ConceptShadow>> diff
844  
        = diffConceptShadows(conceptShadows, newShadows);
845  
      ret subBot_serveText(nDiffs(diff) + ":\n\n"
846  
        + pnlToString(diff));
847  
    }
848  
849  
    if (eq(uri, "/includeScript")) {
850  
      S snippetID = req.get("id");
851  
      O wired = hotwire(snippetID);
852  
      ret "Wired: " + wired;
853  
    }
854  
    
855  
    if (eq(uri, "/activateDynamicObject")) {
856  
      BEA o = beaGet id(req);
857  
      if (o == null) ret "Object not found";
858  
      activateDynamicObject(o);
859  
      o = beaGet id(req);
860  
      S url = beaURL(o);
861  
      ret hsansserif() + "Migrated " + beaHTML(o) + " to " + className(o)
862  
        + hrefresh(3.0, url);
863  
    }
864  
    
865  
    if (eq(uri, "/callAnyMethod")) {
866  
      BEA o = beaGet id(req);
867  
      if (o == null) ret "Object not found";
868  
      S name = req.get("name");
869  
870  
      new L args;
871  
      for (S key, val : req.params()) {
872  
        int idx = parseIntOpt(regexpExtractGroup("^conceptArg(\\d+)$", key));
873  
        if (idx > 0)
874  
          listSet(args, idx-1, getConcept(parseLong(val)));
875  
      }
876  
      
877  
      O result = call(o, name, toObjectArray(args));
878  
      ret serveText("Result of " + o.id + "." + name + "(" + joinWithComma(args) + "):\n" + result);
879  
    }
880  
    
881  
    // add more master-mode URLs here
882  
  } // end of serveOtherPage2
883  
  
884  
  transient L<ConceptShadow> conceptShadows;
885  
886  
  O createConceptShadows() {  
887  
    time "Make shadows" {
888  
      S profile = profileThisThreadToString(r {
889  
        conceptShadows = allConceptShadows();
890  
      });
891  
    }
892  
    ret subBot_serveText(n2(conceptShadows, "shadow") + " made in " + lastTiming_formatted() + "\n\n" + profile);
893  
  }
894  
  
895  
  HCRUD makeBEAObjectCRUD(Req req, S type) {
896  
    HCRUD crud = makeCRUD(BEAObject, req);
897  
    crud.baseLink = req.uri();
898  
    HCRUD_Concepts data = cast crud.data;
899  
    data.itemName = () -> firstToUpper(type);
900  
    data.addCIFilter(type := eqic(type, "(no type)") ? null : type);
901  
    
902  
    if (eqicOneOf(type, "Input", "Pattern", "AI Task")) {
903  
      IF0<MapSO> prev = data.emptyObject;
904  
      data.emptyObject = () -> {
905  
        MapSO item = data.emptyObject_fallback(prev);
906  
        item.put(text := ""); // show text field when creating new objects
907  
        ret item;
908  
      };
909  
    }
910  
    ret crud;
911  
  }
912  
  
913  
  O renderBEAObjectTable(Req req, S type) {
914  
    HCRUD crud = makeBEAObjectCRUD(req, type);
915  
    ret serveCRUD(req, BEAObject, crud);
916  
  }
917  
  
918  
  O serveUploadTexts(Req req, S type) {
919  
    S inputs = req.get("text");
920  
    
921  
    new LS output;
922  
    
923  
    if (nempty(inputs)) {
924  
      for (S text : tlft(inputs)) {
925  
        Pair<BEAObject, Bool> p = uniqCI2_sync BEAObject(+type, +text);
926  
        if (cget uploadedBy(p.a) == null)
927  
          cset(p.a, uploadedBy := req.auth.user);
928  
        output.add(type + " " + (p.b ? "added" : "exists")
929  
          + " (ID " + p.a.id + "): " + text);
930  
      }
931  
    }
932  
    
933  
    ret h2("Upload " + plural(type))
934  
      + hpostform(
935  
          p(plural(type) + " (one per line):")
936  
        + p(htextarea(inputs, name := "text"))
937  
        + pIfNempty(htmlEncode_nlToBR(lines(output)))
938  
        + hsubmit("Upload " + plural(type)));
939  
  }
940  
  
941  
  Cl<BEAObject> beaObjectsOfType(S type) {
942  
    ret conceptsWhereCI BEAObject(+type);
943  
  }
944  
  
945  
  void reactAllInputsWithSomePatterns {
946  
    calculations.reactAllInputsWithSomePatterns();
947  
  }
948  
  
949  
  S navDiv() {
950  
    HCRUD crud = makeCRUD(BEAObject, currentReq!);
951  
952  
    long time = sysNow();
953  
    int inputsWithoutRewrites = this.inputsWithoutRewrites!;
954  
    int inputsWithoutMatches = this.inputsWithoutMatches!;
955  
    int syntacticPatternsWithoutRewrites = this.syntacticPatternsWithoutRewrites!;
956  
    /*int inputsWithoutRewrites = 0;
957  
    int inputsWithoutMatches = 0;
958  
    int syntacticPatternsWithoutRewrites = 0;*/
959  
    done2_always("Count Things", time);
960  
    
961  
    ret joinNemptiesWithVBar(
962  
      ahref(baseLink + "/query", "Query"),
963  
      beaNavLink("Input", crud),
964  
      beaNavLink("Pattern", crud),
965  
      beaNavLink("Syntactic Pattern", crud),
966  
      ahref(baseLink + "/syntacticPatternsWithoutRewrites", n2(syntacticPatternsWithoutRewrites) + " Syntactic patterns w/o rewrites"),
967  
      beaNavLink("Match", crud),
968  
      beaNavLink("Rewrite", crud),
969  
      beaNavLink("AI Task", crud),
970  
      ahref(baseLink + "/inputsWithoutMatches", n2(inputsWithoutMatches) + " Inputs w/o matches"),
971  
      ahref(baseLink + "/inputsWithoutRewrites", n2(inputsWithoutRewrites) + " Inputs w/o rewrites"),
972  
      hPopDownButtonWithText("Bot Forum", navLinks(flat := true, withStats := false)),
973  
      HTMLPopDownButton(
974  
        ahref(baseLink + "/allBEATypes", "All object types")
975  
          + " " + hPopDownButton(renderObjectTypes()),
976  
        ahref(baseLink + "/stats", "Stats"),
977  
        !inMasterMode(currentReq!) ? null : ahref(baseLink + "/refchecker", "Reference checker"),
978  
        ahref(baseLink + "/inputsWithRewrites", "Inputs with rewrites"),
979  
        ahref(baseLink + "/rewritesTable", "Rewrites table"),
980  
        ahref(baseLink + "/patternRewritesTable", "Pattern rewrites table"),
981  
        ahref(baseLink + "/matchesTable", "Matches table"),
982  
        ahref(baseLink + "/matchesTable?syntacticOnly=1", "Syntactic matches table"),
983  
        ahref("https://gazelle.rocks/htmlBot/238410", "Classic Gazelle"),
984  
      ).width(350).height(500).html());
985  
  }
986  
  
987  
  // crud is just the cached BEAObject crud to check for creation rights
988  
  S beaNavLink(S type, HCRUD crud, int count default beaCount(type)) {
989  
    S plural = firstToLower(plural(type));
990  
    S link = baseLink + "/" + camelCase(plural);
991  
    
992  
    ret ahref(link, n2(count) + " " + firstToUpper(plural)) + (!crud.actuallyAllowCreate() ? "" : " " + ahref(addParamToURL(link, cmd := "new"), "+"));
993  
  }
994  
  
995  
  S beaObjectURL(BEAObject o) {
996  
    ret conceptLink(o, currentReq!);
997  
    /*ret o == null ?:
998  
      addParamsToURL(baseLink + "/crud/BEAObject",
999  
        selectObj := o.id) + "#" + o.id;*/
1000  
  }
1001  
  
1002  
  S matchDescHTML(BEAObject m) {
1003  
    pcall {
1004  
      BEAObject pat = cget pattern(m);
1005  
      SS mapping = cast cget mapping(m);
1006  
      ret ahref_undecorated(crudLink(m), htmlEncode2(quote(getString text(pat)))
1007  
        + "<br>&nbsp; with " + renderEqualsCommaProperties(mapping));
1008  
    }
1009  
    ret htmlEncode2(str(m));
1010  
  }
1011  
  
1012  
  int beaCount(S type) {
1013  
    ret countConceptsWhereCI BEAObject(+type);
1014  
  }
1015  
  
1016  
  Cl<BEAObject> beaList(S type, O... params) {
1017  
    ret conceptsWhereCI BEAObject(paramsPlus_inFront(params, +type));
1018  
  }
1019  
  
1020  
  Cl<BEAObject> beaListAny(S... types) {
1021  
    ret concatLists(lmap beaList(litciset(types)));
1022  
  }
1023  
  
1024  
  BEA beaGet(long id) {
1025  
    ret getConceptOpt BEAObject(id);
1026  
  }
1027  
  
1028  
  BEA beaGet(S id) {
1029  
    ret beaGet(parseFirstLong(id));
1030  
  }
1031  
  
1032  
  // first param can be type
1033  
  BEA beaNew(O... _) {
1034  
    _ = prependParamIfOddCount("type", _);
1035  
    ret cnew BEA(_);
1036  
  }
1037  
  
1038  
  bool beaTypeIs(BEA o, S type) {
1039  
    ret o != null && o.typeIs(type);
1040  
  }
1041  
  
1042  
  BEA mapMethodLike beaGet(S key, Req req) {
1043  
    ret beaGet(req.get(key));
1044  
  }
1045  
1046  
  BEA mapMethodLike cgetBEA aka beaGet(S field, BEA o) {
1047  
    ret (BEA) cget(field, o);
1048  
  }
1049  
  
1050  
  BEAObject cgetBEA aka beaGet(BEAObject o, S field) {
1051  
    ret cgetBEA(field, o);
1052  
  }
1053  
1054  
  S beaLinkHTML aka beaToHTML aka beaHTML(BEAObject o) {  
1055  
    ret o == null ?: ahref(conceptLink(o), htmlEncode2_nlToBr(str(o)));
1056  
  }
1057  
  
1058  
  S beaHTML_justID(BEA o) { ret o == null ?: ahref(beaShortURL(o), o.id); }
1059  
  
1060  
  S beaShortURL aka beaURL(BEAObject o) {
1061  
    ret o == null ?: baseLink + "/" + o.id;
1062  
  }
1063  
1064  
  Cl<BEAObject> beaBackRefs(BEAObject o, S type) {
1065  
    ret objectsWhereCI(findBackRefs BEAObject(o), +type);
1066  
  }
1067  
  
1068  
  Cl<BEAObject> beaBackRefs(BEAObject o) {
1069  
    ret findBackRefs BEAObject(o);
1070  
  }
1071  
  
1072  
  O serveDefaultPage(Req req) {
1073  
    HTMLFramer1 framer = req.framer;
1074  
    framer.add(hcenter3(hsnippetimg_scaleToWidth(200, #1102967, 200, 110, title := "Gazelle"), style := "margin-top: 100px"));
1075  
    ret completeFrame(req);
1076  
  }
1077  
  
1078  
  S html_loggedIn() {
1079  
    User user = user(currentReq!);
1080  
    ret user == null
1081  
      ? /*"Not logged in"*/ ahref(baseLink + "/", "Log in")
1082  
      : "Logged in as " + htmlEncode2(user.name);
1083  
  }
1084  
  
1085  
  void distributeNewObject_impl(BEAObject o) {
1086  
    if (o.typeIs("Match")) ret;
1087  
    distributeNotification("New object: " + o);
1088  
  }
1089  
  
1090  
  void performAutoRuns(BEAObject o) enter {
1091  
    print("performAutoRuns", o);
1092  
    
1093  
    for (BEAObject autoRun : beaList("Auto Run")) {
1094  
      if (!isTrue(getOpt enabled(autoRun)))
1095  
        continue with print("Not enabled: " + autoRun);
1096  
      performAutoRunOnObject(autoRun, o);
1097  
    }
1098  
  }
1099  
  
1100  
  void performAutoRunOnAllObjects(BEA autoRun) {
1101  
    for (BEA o : list(BEA))
1102  
      performAutoRunOnObject(autoRun, o);
1103  
  }
1104  
  
1105  
  void performAutoRunOnObject(BEA autoRun, BEA o) {
1106  
    ping();
1107  
    S type = getString onChangedObjectOfType(autoRun);
1108  
    if (!o.typeIs(type)) ret with print("Wrong type: " + type);
1109  
    
1110  
    print("Running " + autoRun);
1111  
    BEAObject procedure = cast cget procedure(autoRun);
1112  
    
1113  
    S internalCode = getString internalCode(procedure);
1114  
    printVars_str(+internalCode, +o);
1115  
    
1116  
    if (eqic(internalCode, "convertInputToPattern")) {
1117  
      S text = o.text();
1118  
      if (!containsAngleBracketVars(text)) ret with print("No angle bracket vars");
1119  
      BEAObject p = uniqCI_returnIfNew BEAObject(type := "Pattern", +text);
1120  
      cset(p, fromInput := o, byProcedure := procedure, byAutoRun := autoRun);
1121  
      print(+p);
1122  
    } else if (eqic(internalCode, "convertInputToSyntacticPattern")) {
1123  
      S text = o.text();
1124  
      if (!containsStars(text)) ret with print("No stars");
1125  
      BEAObject p = uniqCI_returnIfNew BEAObject(type := "Syntactic Pattern", +text);
1126  
      cset(p, fromInput := o, byProcedure := procedure, byAutoRun := autoRun);
1127  
      print(+p);
1128  
    } else if (eqic(internalCode, "dropPunctuationFromPattern")) {
1129  
      S text = o.text();
1130  
      S text2 = dropPunctuation(text);
1131  
      if (eq(text, text2)) ret;
1132  
      
1133  
      BEAObject p = uniqCI BEA(
1134  
        type := o.type(),
1135  
        text := text2);
1136  
      cset(o, withoutPunctuation := p);
1137  
    } else if (eqic(internalCode, "makeSyntacticPattern")) {
1138  
      print(sp := calculations.makeSyntacticPattern(o));
1139  
    } else if (eqic(internalCode, "runFunctionOnInput")) {
1140  
      print("runFunctionOnInput");
1141  
      BEA function = beaGet(o, "function");
1142  
      BEA input = beaGet(o, "input");
1143  
      if (function == null || input == null) ret with print("Missing parameters");
1144  
      if (cget result(o) != null) ret with print("Has result");
1145  
1146  
      BEA result = calculations.reactFunctionWithInput(calculations.new BackEndAlgorithm, function, input);
1147  
      print(+result);
1148  
      if (result != null) {
1149  
        cset(result, request := o);
1150  
        cset(o, +result);
1151  
      }
1152  
    } else
1153  
      print("Unknown internal code");
1154  
  }
1155  
1156  
  BEAObject findInput(S text) {
1157  
    ret conceptWhereIC(BEAObject, type := "Input", +text);
1158  
  }
1159  
  
1160  
  S addRewriteHTML(BEAObject o) {
1161  
    ret ahref(addParamsToURL(crudLink(BEAObject),
1162  
      cmd := "new",
1163  
      title := "Add Rewrite",
1164  
      f_type := "Rewrite",
1165  
      f_text := getStringOpt text(o),
1166  
      f_isRewriteOf := o.id, metaInfo_isRewriteOf := "concept",
1167  
    ), "Add Rewrite");
1168  
  }
1169  
  
1170  
  O serveIntegerLink(Req req, long id) {
1171  
    BEAObject o = getConceptOpt BEAObject(id);
1172  
    if (o != null)
1173  
      ret htitle(str(o)) + hrefresh(conceptLink(o));
1174  
    ret super.serveIntegerLink(req, id);
1175  
  }
1176  
  
1177  
  void distributeTestNotification() {
1178  
    distributeNotification("It is " + localTimeWithSeconds());
1179  
  }
1180  
  
1181  
  void distributeNotification(S text) {
1182  
    notificationQ.add(r {
1183  
      /*for (User user)
1184  
        if (nemptyAfterTrim(user.notificationSetting))
1185  
          sendNotification(text);*/
1186  
          
1187  
      for (Pair<virtual WebSocket, WebSocketInfo> p : syncMapToPairs(webSockets)) {
1188  
        // TODO: check user
1189  
        S jsCode =
1190  
          "window.createNotification({ theme: 'success', showDuration: 3000 })("
1191  
          + jsonEncodeMap(message := text) + ");";
1192  
        call(p.a, "send", jsonEncodeMap(eval := jsCode));
1193  
      }
1194  
    });
1195  
  }
1196  
  
1197  
  void runInstruction(BEAObject o) {
1198  
    if (o == null) ret;
1199  
    try {
1200  
      BEAObject instruction = o;
1201  
      if (o.typeIs("Step in script"))
1202  
        instruction = (BEAObject) cget(o, "instruction");
1203  
      
1204  
      if (instruction.typeIs("Instruction | List objects by type")) {
1205  
        saveInstructionResult(o, beaList(getString typeToList(instruction)));
1206  
        ret;
1207  
      }
1208  
      
1209  
      if (instruction.typeIs("Instruction | List object types"))
1210  
        ret with saveInstructionResult(o, distinctCIFieldValuesOfConcepts(BEAObject, "type"));
1211  
1212  
      if (instruction.typeIs("Instruction | Filter list by text starting with")) {
1213  
        // find list made before
1214  
        BEAObject scriptRun = cgetBEA scriptRun(o);
1215  
        if (scriptRun == null) fail("Need to be run as part of script");
1216  
        L<BEAObject> steps = scriptRunSteps(scriptRun);
1217  
        int idx = indexOf(steps, o);
1218  
        if (idx < 0) fail("Step not found in script run");
1219  
        
1220  
        L<BEAObject> list = firstNotNull(map(reversed(takeFirst(steps, idx)),
1221  
          step -> optCast L(cget data(cgetBEA result(step)))));
1222  
         
1223  
        S prefix = getString prefix(instruction);
1224  
        L<BEAObject> filtered = filter(list, obj -> swic(obj.text(), prefix));
1225  
        saveInstructionResult(o, filtered);
1226  
        ret;
1227  
      }
1228  
      
1229  
      if (instruction.typeIs("Script")) {
1230  
        BEAObject script = instruction;
1231  
        BEAObject scriptRun = cnew BEAObject(type := "Script Run", +script);
1232  
        
1233  
        // Make an instance of all the instructions
1234  
        
1235  
        int i = 0;
1236  
        new L<BEAObject> steps;
1237  
        while not null (instruction = (BEAObject) cget(instruction, "step" + (++i))) {
1238  
          BEAObject step = cnew(BEAObject, type := "Step in script", step := i, +scriptRun, +instruction);
1239  
          steps.add(step);
1240  
        }
1241  
        
1242  
        cset(scriptRun, +steps);
1243  
        
1244  
        // TODO: run steps?
1245  
1246  
        ret;
1247  
      }
1248  
      
1249  
      cnew BEAObject(type := "Instruction Error", instruction := o, error := "Unknown instruction type");
1250  
    } catch e {
1251  
      cnew BEAObject(type := "Instruction Error", instruction := o, error := getStackTrace(e));
1252  
    }
1253  
  }
1254  
1255  
  BEAObject saveInstructionResult(BEAObject instruction, O data) {
1256  
    BEAObject result = cnew BEAObject(type := "Instruction Result",
1257  
      +instruction, +data);
1258  
    cset(instruction, +result);
1259  
    ret result;
1260  
  }
1261  
  
1262  
  L<BEAObject> scriptRunSteps(BEAObject scriptRun) {
1263  
    ret (L) cget steps(scriptRun);
1264  
  }
1265  
  
1266  
  S addCommentHTML(BEA o, O... _) {
1267  
    optPar S redirectAfterSave;
1268  
    optPar S defaultComment;
1269  
    optPar S text = "Add comment";
1270  
    
1271  
    ret ahref(addParamsToURL(crudLink(BEAObject),
1272  
      cmd := "new",
1273  
      title := "Add Comment",
1274  
      f_type := "Comment",
1275  
      f_on := o.id,
1276  
      f_text := unnull(defaultComment),
1277  
      +redirectAfterSave,
1278  
      autofocus := "f_text",
1279  
      metaInfo_on := "concept"), text);
1280  
  }
1281  
  
1282  
  S formatSubInput(BEA input, S text, S anchor) {
1283  
    S redirect = addAnchorToURL(currentReq->uriWithParams(), anchor);
1284  
    int goodCount = countConceptsCI BEA(type := "Sub-Input", +input, +text);
1285  
    int badCount = countConceptsCI BEA(type := "Bad Sub-Input", +input, +text);
1286  
    ret calculations.bestInputHTML(text)
1287  
      + " " + small(joinNemptiesWithSpace(
1288  
        ahref(addParamsToURL(
1289  
          baseLink + "/storeSubInput", 
1290  
          label := "good",
1291  
          +text,
1292  
          input := input.id,
1293  
          +redirect),
1294  
        unicode_thumbsUp()),
1295  
        goodCount == 0 ? "" : n2(goodCount),
1296  
        ahref(addParamsToURL(
1297  
          baseLink + "/storeSubInput", 
1298  
          label := "bad",
1299  
          +text,
1300  
          input := input.id,
1301  
          +redirect),
1302  
        unicode_thumbsDown()),
1303  
        badCount == 0 ? "" : n2(badCount)
1304  
      ));
1305  
  }
1306  
1307  
  LS renderObjectTypes() {
1308  
    MultiSet<S> ms = distinctCIFieldValuesOfConcepts_multiSet(BEAObject, "type");
1309  
    ret mapPairs(multiSetToPairsByPopularity(ms),
1310  
      (type, count) -> {
1311  
        S _type = or2(type, "(no type)");
1312  
        ret n2(count) + " " + ahref(baseLink + "/beaCRUD/" + urlencode(_type), htmlEncode2(_type));
1313  
      });
1314  
  }
1315  
  
1316  
  BEA autoMigrateToBase(BEA o) {
1317  
    ret autoMigrateToClass(o, BEA);
1318  
  }
1319  
  
1320  
  BEA autoMigrateToCustomClass(BEA o) {
1321  
    ret autoMigrateToClass(o, defaultCustomClass(o));
1322  
  }
1323  
  
1324  
  BEA autoMigrateToClass(BEA o, Class<? extends BEAObject> targetClass) {
1325  
    pcall {
1326  
      if (o == null || o._concepts != db_mainConcepts()) null;
1327  
      if (targetClass != null && targetClass != _getClass(o))
1328  
        ret replaceConceptAndUpdateRefs(o, unlistedCopyToClass(targetClass, o));
1329  
    }
1330  
    ret o;
1331  
  }
1332  
1333  
  void setCodeState(BEA o, long timestamp, S codeHash, O state) {
1334  
    if (empty(state)) state = null; else
1335  
      state = "[" + formatGMTWithMilliseconds_24(timestamp) + "] "
1336  
        + (empty(codeHash) ? "" : "Code hash: " + codeHash + ". ")
1337  
        + state;
1338  
    cset(o, meta_codeState := state);
1339  
  }
1340  
1341  
  S codeForObject(BEA o) {
1342  
    S code = getString meta_code(o);
1343  
    BEA prototype = beaGet meta_prototype(o);
1344  
    if (prototype != null)
1345  
      code = getString meta_code(o);
1346  
    ret code;
1347  
  }
1348  
  
1349  
  void activateDynamicObject(BEA o) ctex {
1350  
    ClassLoader cl = getClassLoader(module());
1351  
    print(+cl);
1352  
1353  
    long timestamp = now();
1354  
    setCodeState(o, timestamp, null, "Compiling");
1355  
1356  
    S codeHash = null;
1357  
    transpileAndCompileForHotwiring_src.set(null);
1358  
1359  
    // TODO: there is still a slight possibility that erroneous code will be compiled again and again
1360  
1361  
    try {
1362  
      // Check meta_code and meta_prototype (latter overwrites the former)
1363  
      S code = codeForObject(o);
1364  
      codeHash = empty(code) ? null : md5(code);
1365  
      cset(o, meta_codeHash := codeHash);
1366  
  
1367  
      if (empty(code)) { // Nothing to activate - migrate back to base
1368  
        o = autoMigrateToBase(o);
1369  
        setCodeState(o, timestamp, null, null);
1370  
        ret;
1371  
      }
1372  
1373  
      // safety check for reference
1374  
      cset(o, meta_codeSafety := codeSafetyCheckResult(code));
1375  
1376  
      S id = aGlobalID();
1377  
      S mcName = "main_" + id;
1378  
      
1379  
      S prelude = "!include early #1031282\n\n";
1380  
      S src = prelude
1381  
        + "mainClassName " + mcName + "\n"
1382  
        + "concept " + id + " extends main.BEAObject {\n" + code + "\n}";
1383  
      
1384  
      print("SRC> ", src);
1385  
      javaCompileToJar_localLibraries.set(filesFromClassLoader(cl));
1386  
      dm_mediumRefreshTranspiler();
1387  
      File bytecode = transpileAndCompileForHotwiring(src);
1388  
      copyFile(bytecode, byteCodeFileForObject(o));
1389  
      dm_addByteCodePathToModuleClassLoader(bytecode);
1390  
      S fullName = mcName + "$" + id;
1391  
      
1392  
      //Class targetClass = _getClass(fullName);
1393  
      Class targetClass = cl.loadClass(fullName);
1394  
      print(+targetClass);
1395  
      assertNotNull("Class not found: " + fullName, targetClass);
1396  
      o = autoMigrateToClass(o, targetClass);
1397  
1398  
      setCodeState(o, timestamp, codeHash, "Custom code loaded");
1399  
    } catch print e {
1400  
      setCodeState(o, timestamp, codeHash, exceptionToStringShort(e));
1401  
    }
1402  
    saveTextFile(javaSourceFileForObject(o), transpileAndCompileForHotwiring_src!);
1403  
  }
1404  
1405  
  File javaSourceFileForObject(BEA o) {
1406  
    ret programFile("BEA Java Sources/" + o.id + ".java");
1407  
  }
1408  
  
1409  
  File byteCodeFileForObject(BEA o) {
1410  
    ret programFile("Object ByteCode/" + o.id + ".jar");
1411  
  }
1412  
  
1413  
  BEA autoMigrateUnlistedOrKeep(BEA o) {
1414  
    ret canAutoMigrate(o) ? unlistedCopyToClass(defaultCustomClass(o), o) : o;
1415  
  }
1416  
  
1417  
  bool canAutoMigrate(BEA o) {
1418  
    ret o != null && !eqOneOf(defaultCustomClass(o), _getClass(o), null);
1419  
  }
1420  
  
1421  
  Class<? extends BEA> defaultCustomClass(BEA o) {
1422  
    if (o == null) null;
1423  
    BEA entry = conceptWhereCI BEA(type := "Auto Custom Class", forType := o.type());
1424  
    //printVars_str defaultCustomClass(+o, +entry);
1425  
    if (entry == null) null;
1426  
    S className = getString toClassName(entry);
1427  
    //printVars_str defaultCustomClass(+className);
1428  
    Class c = findClassThroughDefaultClassFinder(className);
1429  
    //printVars_str defaultCustomClass(+c);
1430  
    ret c;
1431  
  }
1432  
  
1433  
  S queryLink(S algorithm, S q) {
1434  
    ret addParamsToURL(baseLink + "/query", +algorithm, +q);
1435  
  }
1436  
1437  
  S currentUserAgent() {  
1438  
    Req req = currentReq!;
1439  
    if (req == null) null;
1440  
    ret mapGet(req.webRequest.headers(), "user-agent");
1441  
  }
1442  
1443  
  void saveUserAgent(BEA input) {  
1444  
    S userAgent = currentUserAgent();
1445  
    if (nempty(userAgent))
1446  
      uniqCI2 BEA(type := "Input Source",  +input, +userAgent);
1447  
  }
1448  
1449  
  bool isObjectWithCode(BEA o) {
1450  
    ret o != null && (cget meta_code(o) != null || cget meta_prototype(o) != null);
1451  
  }
1452  
1453  
  bool createdByMasterUser(BEA o) {
1454  
    User user = optCast User(cget createdBy(o));
1455  
    ret user != null && user.isMaster;
1456  
  }
1457  
1458  
  void autoActivateDynamicObject(BEA o) {
1459  
    if (!autoActivateDynamicObjects) ret;
1460  
    if (!createdByMasterUser(o)) ret;
1461  
    S codeState = getString meta_codeState(o);
1462  
    S time = leadingAngleBracketStuff(codeState);
1463  
    long timestamp = empty(time) ? 0 : parseDateWithMillisecondsGMT(time);
1464  
    if (o._modified <= timestamp) ret;
1465  
    //S hash = regexpExtractIC("code hash: (\\w+)?", codeState);
1466  
    S hash = getString meta_codeHash(o);
1467  
    if (eq(hash, md5(codeForObject(o))))
1468  
      ret; // Code unchanged
1469  
    print("Auto-activating dynamic object: " + o);
1470  
    activateDynamicObject(o);
1471  
    sleepSeconds(1); // safety sleep
1472  
  }
1473  
} // end of module
1474  
1475  
extend User {
1476  
  S notificationSetting;
1477  
}
1478  
1479  
concept BEAObject > ConceptWithGlobalID {
1480  
  // optional new Ref<UserPost> mirrorPost;
1481  
  UserPost mirrorPost() { ret (UserPost) cget mirrorPost(this); }
1482  
1483  
  void change :: after {
1484  
    var mod = beaMod();
1485  
    mod.rstUpdateBEAMirrors.add(this);
1486  
    if (mod.autoActivateDynamicObjects)
1487  
      mod.rstAutoActivateDynamicObjects.add(this);
1488  
  }
1489  
1490  
  void delete :: before {
1491  
    cdelete(mirrorPost());
1492  
  }
1493  
  
1494  
  void updateMirrorPost {
1495  
    GazelleBEA mod = beaMod();
1496  
    if (isDeleted() || !mod.mirrorBEAObjects) ret;
1497  
1498  
    if (mirrorPost() == null)
1499  
      cset(this, mirrorPost := cnew UserPost(
1500  
        type := "BEA Object",
1501  
        creator := mod.internalUser(),
1502  
        botInfo := "BEA Mirror Bot"));
1503  
1504  
    S text = structureString();
1505  
1506  
    cset(mirrorPost(), 
1507  
      title := str(this),
1508  
      +text);
1509  
  }
1510  
1511  
  S structureString() {
1512  
    S text = "Error";
1513  
    pcall {
1514  
      structure_Data data = new {
1515  
        structure_ClassInfo newClass(Class c) {
1516  
          structure_ClassInfo info = super.newClass(c);
1517  
          if (c == Concept.Ref.class) {
1518  
            info.special = true;
1519  
            info.serializeObject = o -> {
1520  
              Concept cc = cast deref((Concept.Ref) o);
1521  
              //append("cu CRef " + (cc != null ? str(cc.id) : "null"), 3);
1522  
              if (cc cast BEAObject)
1523  
                append("CRef(gid=" + quote(cc.globalID()) + ")", 6);
1524  
              else if (cc != null)
1525  
                append("CRef(id=" + cc.id + ")", 6);
1526  
              else
1527  
                append("CRef", 1);
1528  
            };
1529  
          }
1530  
          ret info;
1531  
        }
1532  
1533  
        void setFields(structure_ClassInfo info, L<Field> fields) {
1534  
          if (isSubclassOf(info.c, BEAObject)) {
1535  
            // Don't serialize "refs" and "backRefs" fields
1536  
            removeAll(fields,
1537  
              getField(BEAObject, "refs"),
1538  
              getField(BEAObject, "backRefs"));
1539  
          }
1540  
          super.setFields(info, fields);
1541  
        }
1542  
      };
1543  
      
1544  
      S struct = structure(this, data);
1545  
      struct = dropLoadableUtilsPackageFromStruct(struct);
1546  
      text = indentStructureString_firstLevels(1, struct);
1547  
    }
1548  
1549  
    ret text;
1550  
  }
1551  
      
1552  
  toString {
1553  
    ret shorten(toString_long());
1554  
  }
1555  
  
1556  
  S toString_long() {
1557  
    S type = strOrNull(cget type(this));
1558  
    S s = super.toString();
1559  
    
1560  
    if (nempty(type)) {
1561  
      s = type + " " + id;
1562  
      
1563  
      s += appendBracketed(strOrNull(this~.label));
1564  
1565  
      if (eqic(type, "Match"))
1566  
        s += " " + this.~mapping
1567  
          /*+ appendBracketed(this.~input + " + " + this~.pattern)*/;
1568  
    }
1569  
    
1570  
    bool enabled = eq(true, getOpt enabled(this));
1571  
    if (enabled) s += " [enabled]";
1572  
    
1573  
    S text = or2(text(),
1574  
      getStringOpt name(this),
1575  
      getStringOpt internalCode(this));
1576  
    if (text != null)
1577  
      s += " " + quote(text);
1578  
      
1579  
    O fc = this~.functionCalled;
1580  
    if (fc != null) s += " " + fc;
1581  
      
1582  
    O result = this~.result;
1583  
    if (result != null) s += " = " + shorten_str(result);
1584  
      
1585  
    ret s;
1586  
  }
1587  
1588  
  !include #1031300 // BEAObject methods
1589  
1590  
} // end of BEAObject
1591  
1592  
beaConcept BEARegExp {
1593  
  S text;
1594  
  bool caseInsensitive = true;
1595  
  
1596  
  bool valid() { ret nempty(text); }
1597  
  
1598  
  java.util.regex.Pattern compile() {
1599  
    ret compileRegexpPossiblyIC_unicodeCase(text, caseInsensitive);
1600  
  }
1601  
}
1602  
1603  
beaConcept BEARegExpReplacement > BEARegExp {
1604  
  S replacement;
1605  
1606  
  S apply(S text) {
1607  
    try {
1608  
      ret regexpReplace_directWithRefs(compile().matcher(text), unnull(replacement));
1609  
    } catch e {
1610  
      fail(format_quoted("Was searching * in * ", this.text, text));
1611  
    }
1612  
  }
1613  
  
1614  
  LS directCmds() {
1615  
    ret listPlus(super.directCmds(),
1616  
      !valid() ? "Note: not valid"
1617  
      : targetBlank(beaMod().queryLink("Apply regular expression replacement to all inputs", str(id)), "Apply to all inputs"));
1618  
  }
1619  
}
1620  
1621  
beaConcept BEAPatternList {
1622  
  new RefL<BEA> patterns;
1623  
  
1624  
  toString {
1625  
    ret super.toString() + ": " + nPatterns(patterns);
1626  
  }
1627  
}
1628  
1629  
static GazelleBEA beaMod() {
1630  
  ret (GazelleBEA) botMod();
1631  
}
1632  
1633  
set flag hotwire_here.
1634  
1635  
// share ISpec interface with sub-modules
1636  
static JavaXClassLoader hotwire_makeClassLoader(L<File> files) {
1637  
  ClassLoader cl = myClassLoader();
1638  
   ret new JavaXClassLoaderWithParent2(null, files, cl, ll(/*TODO*/));
1639  
}

Author comment

Began life as a copy of #1030422

download  show line numbers  debug dex  old transpilations   

Travelled to 5 computer(s): bhatertpkbcr, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, vouqrxazstgt

No comments. add comment

Snippet ID: #1030602
Snippet name: Gazelle BEA [backup before package change]
Eternal ID of this version: #1030602/644
Text MD5: e284f6e01cc1ed51cda07d921c4dcb6f
Transpilation MD5: e006f069d3e0587910c4cb4e18c0ad1a
Author: stefan
Category: javax
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-06-05 03:37:12
Source code size: 58237 bytes / 1639 lines
Pitched / IR pitched: No / No
Views / Downloads: 1902 / 9946
Version history: 643 change(s)
Referenced in: [show references]