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

1414
LINES

< > BotCompany Repo | #1031031 // Gazelle BEA fast DB load test, dev.

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

Uses 1951K of libraries. Click here for Pure Java version (6676L/52K).

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

Author comment

Began life as a copy of #1030602

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1031031
Snippet name: Gazelle BEA fast DB load test, dev.
Eternal ID of this version: #1031031/4
Text MD5: de8239a6dd3aabb8619f15f0a1f7874e
Transpilation MD5: 6dbd6b9b1914664f79a3a162216d9a2d
Author: stefan
Category: javax
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-04-24 06:18:25
Source code size: 50053 bytes / 1414 lines
Pitched / IR pitched: No / No
Views / Downloads: 107 / 214
Version history: 3 change(s)
Referenced in: [show references]