Warning: session_start(): open(/var/lib/php/sessions/sess_l8i0qvdnb3fnketu6erqa6se8l, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
// DONE: prevent non-master users from setting createdBy field manually (at least through CRUD. Hopefully there is no other entry point.)
// If you ever move this class into loadableUtils, make sure to copy the definition of method db() to the subclass
mainPackage gazelle
mainClassName main
need latest startsWith.
set flag needToKnowMainLib.
!include early #1031277 // BEA general includes
!include once #1030833 // BEACalculations
//set flag defaultDefaultClassFinder_debug.
set flag CleanImports.
set flag DynModule.
set flag NoNanoHTTPD.
set flag AllPublic. // for dynamic BEA objects
rewrite BEA with BEAObject.
abstract static class GazelleBEA > DynGazelleRocks {
switchable bool mirrorBEAObjects; // don't do it for now
switchable bool enableAutoRuns = true;
switchable bool enableNewBEAObjectNotis = true;
switchable bool printAllConceptChanges;
switchable bool useShadowLogger = false;
switchable bool autoActivateDynamicObjects = true;
switchable bool reloadWhenMainLibUpdates;
switchable S baseSystemVersion = "1"; // increase this when all dynamic objects need a recompile
switchable int backupFrequency = 5; // make new backup file every x minutes
// proofOfStart
transient bool allObjectsActivated;
transient Throwable startError;
S activateOnlyTheseIDs;
S dontActivateTheseIDs;
transient ReliableSingleThread_Multi rstAutoRuns = dm_rstMulti(this, 1000, lambda1 performAutoRuns);
transient Q notificationQ;
transient ReliableSingleThread_Multi rstDistributeNewObject = dm_rstMulti(this, 1000, lambda1 distributeNewObject_impl);
transient Set newObjectsDistributed = weakSet();
transient ReliableSingleThread_Multi rstUpdateBEAMirrors = dm_rstMulti(this, 100, c -> c.updateMirrorPost());
transient ReliableSingleThread_Multi rstAutoActivateDynamicObjects = dm_rstMulti(this, 100, lambda1 autoActivateDynamicObject);
transient BEACalculations calculations = new(this);
transient BEACalculations calc = calculations;
transient int newFieldsToShow = 3;
transient bool allowAnonymousInputUpload = true; // TODO
switchable int maxInputLength = 50000;
switchable S mainDomainWithProtocol = "https://bea.gazelle.rocks";
switchable bool verboseQStartsAndStops;
transient ConceptClassesDependentValue inputsWithoutRewrites;
transient ConceptClassesDependentValue inputsWithoutMatches;
transient ConceptClassesDependentValue syntacticPatternsWithoutRewrites;
transient Set deadClassPaths = syncLinkedHashSet();
transient new x30_pkg.x30_util.BetterThreadLocal beaThreadOwner;
bool verboseClassLoading;
transient bool saveAllQsAsInput = true;
transient bool moveNavItemsToMisc = false;
transient bool additionalCommandsForObjects = true;
transient bool exportUsersInVM;
transient bool sourceIsPublic = true;
// create an anonymous user for each cookie unless user is logged in
transient bool makeAnonymousUsers = true;
// add more fields for GazelleBEA here
!include #1030883 // DB quickImport mix-in
void init :: after {
//set quickDBReloadEnabled;
botName = heading = adminName = "Gazelle";
favIconID = psI(#1102967);
set enableVars;
unset showTalkToBotLink;
unset phoneNumberSpecialInputField;
unset showMetaBotOnEveryPage;
set showCRUDToEveryone;
}
Class lookForClass(ClassLoader cl, S name) {
pcall {
// first thing - filter
if (!name.startsWith(DynClassName_mainPrefixForVM())) null;
if (verboseClassLoading) print("Looking for class " + name);
DynClassName dcn = DynClassName_parse(name);
if (dcn == null) dcn = DynClassName_parseOther(name);
if (dcn == null) {
vmBus_send lookingForClass_noDCNParse(name);
null;
}
S subPath = vmClassNameToSubPath(dcn.fullClassNameForVM());
File byteCode = dcn.byteCodeFile();
vmBus_send lookingForClass_haveByteCodeFile(byteCode);
// jar already added? done.
if (classLoaderContainsByteCodePath(cl, byteCode)) {
vmBus_send lookingForClass_haveByteCodePath(byteCode);
null;
}
// class file not found? bad.
bool exists = fileExistsInInDirOrZip(byteCode, subPath);
printVars(+exists, +subPath, +byteCode);
if (!exists) {
vmBus_send lookingForClass_subPathNotInByteCode(byteCode, subPath);
fail("Class not found: " + subPath + " in " + byteCode);
}
// register byte code path
addByteCodePathToClassLoader(cl, byteCode);
assertTrue("Byte code added", classLoaderContainsByteCodePath(cl, byteCode));
vmBus_send lookingForClass_byteCodePathAdded(byteCode);
ret (Class) call(cl, "super_findClass", name);
// null; // just let the class loader do its thing
// recursive call
//ctex { ret cl.loadClass(name); }
}
null;
}
// MUST be called outside of loadableUtils
void db {
main db();
}
void startDB {
ClassLoader cl = dm_moduleClassLoader();
setOpt(cl, verbose := verboseClassLoading);
setFieldToIF1Proxy(cl, findClass_extension := (IF1) name -> {
vmBus_send lookingForClass(cl, name);
Class c = lookForClass(cl, name);
vmBus_send lookingForClass_result(cl, name, c);
ret c;
});
O classFinder = _defaultClassFinder();
db_mainConcepts().classFinder = func(S name) -> Class enter {
print("Deserializing class " + name);
try {
S name2 = dropPrefix(mcName() + "$", name);
S mainPrefix = dotToDollar(DynClassName_mainPrefix());
//printVars(+mainPrefix, +name2);
if (name2.startsWith(mainPrefix)) {
S vmName = DynClassName_parse(name2).fullClassNameForVM();
if (verboseClassLoading) print("Loading dynamic class " + vmName);
Class c = classLoader_loadClass(module(), vmName);
//print(+c);
ret c;
}
Class c = cast callF(classFinder, name);
print(+c);
ret c;
} on fail e {
printStackTrace(e);
}
};
db();
Concepts concepts = db_mainConcepts();
concepts.useBackRefsForSearches = true;
concepts.newBackupEveryXMinutes = backupFrequency;
fixConceptIDs();
/*concepts.makeStructureData = () ->
concepts.finishStructureData(new structure_Data {
void writeObject(O o, S shortName, MapSO fv) {
if (o instanceof Concept && conceptID(o/Concept) == 136925)
print("writeProblemObject " + shortName + " " + fv);
super.writeObject(o, shortName, fv);
}
});*/
inputsWithoutRewrites = ConceptClassesDependentValue(litset(BEA), () -> countPred(beaList("Input"), c -> empty(beaBackRefs(c, "Rewrite"))));
inputsWithoutMatches = ConceptClassesDependentValue(litset(BEA), () -> countPred(beaList("Input"), c -> empty(beaBackRefs(c, "Match"))));
syntacticPatternsWithoutRewrites = ConceptClassesDependentValue(litset(BEA), () -> countPred(beaList("Syntactic Pattern"), c -> empty(beaBackRefs(c, "Rewrite"))));
if (useShadowLogger) {
ConceptsShadowLogger shadowLogger = new(db_mainConcepts());
shadowLogger.install();
//shadowLogger.writer = printWriter(deflaterOutputStream_syncFlush_append(programFile("shadow.log.deflated")));
shadowLogger.writer = filePrintWriter_append(programFile("shadow.log"));
dm_doEvery(10.0, r { shadowLogger.flush(); });
ownResource(shadowLogger);
}
if (printAllConceptChanges) printAllConceptChanges();
}
MapSO emergencyFlags() {
ret (Map) parseEqualsProperties(
joinNemptiesWithEmptyLines(
loadTextFile(programFile("gazelle-emergency-options.txt")),
loadTextFile(javaxDataDir("gazelle-emergency-options.txt")),
));
}
void start {
try {
start2();
} catch print e {
startError = e;
}
}
void start2 {
print("Module ID: " + dm_moduleID());
set !useBotNameAsModuleName;
setOptAllDyn_pcall(module(), pnl(+emergencyFlags()));
change();
S name = actualMCDollar() + "BEAObject";
print(+name);
assertEquals(BEAObject, callF(defaultDefaultClassFinder(), name));
assertEquals(ConceptWithGlobalID, callF(defaultDefaultClassFinder(), mcDollar() + "ConceptWithGlobalID"));
//seedDBFrom(#1030602);
set botDisabled;
set storeBaseClassesInStructure;
super.start();
assertSameVerbose("miscMap me", db_mainConcepts().miscMapGet(DynNewBot2), this);
assertSameVerbose("beaMod()", main beaMod(), this);
print("main concepts: " + db_mainConcepts() + ", count: " + db_mainConcepts().countConcepts());
print(renderConceptClassesWithCount(db_mainConcepts()));
print("Inputs: " + n2(beaCount("Input")));
//set showOnlySelectedObject;
// reload module when lib changes
dm_onSnippetTranspiled(mainLibID, r {
if (reloadWhenMainLibUpdates)
dm_reloadModule();
});
if (!enabled) ret;
if (exportUsersInVM) {
dm_vmBus_answerToMessage lookupGazelleUser(func(S name, S pw, S salt) {
if (!eq(salt, passwordSalt())) null;
User user = conceptWhereCI User(+name);
if (user == null) null;
if (!eq(getVar(user.passwordMD5), hashPW(pw))) null;
ret user;
});
}
// mirror all objects to be sure
rstUpdateBEAMirrors.addAll(list(BEAObject));
newObjectsDistributed.addAll(list(BEAObject));
/*onIndividualConceptChange_notOnAllChanged(BEAObject,
p -> { calculations.makeSyntacticPattern(p); });*/
onIndividualConceptChange_notOnAllChanged(BEAObject,
o -> {
if (enableAutoRuns) rstAutoRuns.add(o);
if (enableNewBEAObjectNotis && newObjectsDistributed.add(o))
rstDistributeNewObject.add(o);
});
notificationQ = dm_startQ();
// fix refs occasionally
dm_doEvery(5*60.0, r-enter {
print(ConceptsRefChecker(db_mainConcepts()).runAndFixAll());
});
// call _activate on all activatable objects (initial activations)
setField(activateOnlyTheseIDs := nemptyLinesLL(
loadTextFile(programDir("gazelle-activate-only")),
loadTextFile(javaxDataDir("gazelle-activate-only"))));
Set ids = activateOnlyTheseIDs();
Set antiIDs = dontActivateTheseIDs();
print("Object IDs to activate: " + (ids == null ? "ALL" : ids));
if (nempty(antiIDs)) print("Object IDs not to activate: " + (ids == null ? "ALL" : ids));
for (BEA bea)
if ((ids == null || contains(ids, bea.id)) && !contains(antiIDs, bea.id)) {
//print("Activating: " + bea);
callActivate(bea);
}
cleanReifiedWebSockets();
set allObjectsActivated; // proof of start
print("All objects activated");
}
void makeIndices :: after {
indexConceptClass(BSettings);
indexConceptFieldDesc(BEAObject, "_modified");
indexConceptFieldCIWithTopTen(BEAObject, "type");
indexConceptFieldIC(BEAObject, "text");
indexConceptFieldIC(BEAObject, "purpose");
}
bool isMaster(Req req) {
ret req?.masterAuthed;
}
@Override
L crudClasses(DynGazelleRocks.Req req) {
ret listPlus(super.crudClasses(req), BEAObject, AuthedDialogID, /*BEAPatternList*/);
}
Set hiddenCrudClasses() {
Set set = super.hiddenCrudClasses();
addAll(set, Conversation, ExecutedStep, InputHandled);
ret set;
}
S authFormHeading() {
ret h3(adminName);
}
swappable S authFormMoreContent() {
ret p(html_loggedIn(false)) + super.authFormMoreContent();
}
@Override
void makeFramer(DynGazelleRocks.Req req) {
super.makeFramer(req);
if (!allObjectsActivated)
req.framer.add(p("WARNING: Start failure"));
if (startError != null)
req.framer.add(pre_htmlEncode("WARNING: Start error\n\n" + renderStackTrace(startError)));
req.framer.addInHead(hjs_selectize());
req.framer.addInHead(hjs_selectizeClickable());
req.framer.addInHead(hjs_autoExpandingTextAreas());
}
@Override
HCRUD_Concepts crudData(Class c, DynGazelleRocks.Req _req) {
Req req = cast _req;
HCRUD_Concepts cc = super.crudData(c, req);
if (c == BEAObject) {
cc.lsMagic = true;
cc.humanizeFieldNames = false;
cc.convertConceptValuesToRefs = true;
cc.itemName = () -> "BEA Object";
cc.addRenderer("meta_code", new HCRUD_Data.AceEditor(80, 20));
cc.titleForObjectID = id -> beaHTML(beaGet(toLong(id)));
cc.isEditableValue = o ->
cc.isEditableValue_base(o)
&& !eq(shortClassName(o), "MultiSet");
cc.conceptClassForComboBoxSearch = (info, query) -> {
if (endsWith(info, "_nativeValue"))
ret Concept;
ret cc.conceptClassForComboBoxSearch_base(info, query);
};
cc.comboBoxSearchBaseItems = (info, query) -> {
new Matches m;
printVars comboBoxSearchBaseItems(+info);
if (jMatchStart("type=", info, m)) {
var l = beaList($1);
print("Got " + nItems(l));
ret cc.comboBoxItems(l);
}
ret cc.comboBoxSearchBaseItems_base(info, query);
};
// prevent non-master users from forging/changing createdBy
cc.massageItemMapForUpdate = (o, map) -> {
cc.massageItemMapForUpdate_base(o, map);
if (!isMaster(req)) {
O createdByOld = cget createdBy(o);
if (createdByOld != null || map.get("createdBy") != user(req))
map.remove("createdBy");
}
};
// probably already done by massageItemMapForUpdate
cc.onCreate.add(o ->
cset(o, createdBy := currentUser()));
cc.getObjectForDuplication = id -> {
BEA o = beaGet(toLong(id));
MapSO item = cc.getObjectForDuplication_base(id);
item.put(createdBy := req.auth.user!); // set default creator to current user
item.put(meta_createdFrom := o);
// call enhancer object
item = or((MapSO) pcallOpt(cget cleanObjectForDuplication(websiteEnhancersObject()), "cleanObjectForDuplication", o, item), item);
ret item;
};
cc.emptyObject = () -> {
MapSO item = cc.emptyObject_base();
item.put(type := "");
ret item;
};
Set deletableRefs = litciset("Match");
cc.objectCanBeDeleted = id -> {
BEA o = cast cc.conceptForID(id);
ret userCanEditObject(user(req), o)
&& all(findBackRefs(BEAObject, o), x -> contains(deletableRefs, x.type()));
};
cc.actuallyDeleteConcept = o -> {
deleteConcepts(filter(findBackRefs(BEAObject, o),
o2 -> contains(deletableRefs, o2.type())));
cdelete(o);
};
}
ret cc;
}
bool newLinkTargetBlank_base(Class c) {
ret super.newLinkTargetBlank_base(c) || c == BEA;
}
@Override
HCRUD makeCRUD(Class c, DynGazelleRocks.Req req, HTMLFramer1 framer) {
HCRUD crud = super.makeCRUD(c, req, framer);
HCRUD_Concepts data = cast crud.data;
crud.showOnlySelected = true;
crud.showSearchField = true;
if (data.customFilter == null)
crud.descending = true; // show latest objects first by default except when searching
crud.cleanItemIDs = true;
if (c == BEAObject) {
crud.allowFieldRenaming = true;
var renderValue_old = crud.renderValue;
crud.renderValue = (field, value) -> {
S html = crud.renderValue_fallback(renderValue_old, field, value);
ret addShowMoreButton(html);
};
crud.haveSelectizeClickable = true;
crud.cellColumnToolTips = true;
crud.unshownFields = litset("mirrorPost", "globalID");
crud.uneditableFields = litset("log");
crud.showTextFieldsAsAutoExpandingTextAreas = true;
crud.duplicateInNewTab = true;
crud.customizeACEEditor = ace -> {
ace.onKeyDown = "function(event) { " + jquery_submitFormOnCtrlEnter() + " }";
};
HCRUD_Concepts cc = cast crud.data;
S typeFilter = req.get("type");
if (nempty(typeFilter))
cc.addCIFilter(type := typeFilter);
crud.renderCmds = map -> {
BEA o = getConcept BEA(crud.itemIDAsLong(map));
if (o == null) ret "";
new LS cmds;
// ask the object itself for commands
addAll(cmds, allToString(optCast Cl(pcall(o, "cmds"))));
// special commands for BEA types or objects with certain fields
if (fileNotEmpty(javaSourceFileForObject(o)))
cmds.add(targetBlank(baseLink + "/javaSource?id=" + o.id, "Show Java source"));
for (S field : ll("text", "what", "type")) {
S text = getStringOpt(o, field);
if (nempty(text))
cmds.add(
targetBlank_noFollow(addParamsToURL(baseLink + "/query",
q := text, algorithm := "process input"),
"Use field " + quote(field) + " as query"));
}
if (o.typeIs("Input")) {
cmds.add(ahref(addParamsToURL(crudLink(BEAObject),
cmd := "new",
title := "Add Pattern For Input",
f_type := "Pattern",
f_text := getStringOpt text(o),
f_shouldMatch := o.id, metaInfo_shouldMatch := "concept",
), "Add pattern"));
cmds.add(ahref(appendParamsToURL(baseLink + "/query", q := o.text(), algorithm := "Apply all text functions"),
"Apply all text functions"));
}
if (o.typeIs("Pattern"))
cmds.add(ahref(appendParamsToURL(baseLink + "/query", q := o.id, algorithm := "Run pattern"),
"Try-run pattern against all inputs"));
if (o.typeIsOneOf("Pattern", "Syntactic Pattern")) {
cmds.add(ahref(appendParamsToURL(baseLink + "/reactAllInputsWithPattern", patternID := o.id),
"React pattern with all inputs"));
cmds.add(ahref(appendParamsToURL(baseLink + "/convertSyntacticToSemanticMatchesForWholePattern", patternID := o.id),
"Convert all syntactic matches to semantic matches"));
}
if (o.typeIs("Match")) {
cmds.add(ahref(appendParamsToURL(baseLink + "/query", q := o.id, algorithm := "Find rewrites for match"),
"Find rewrites"));
if (beaTypeIs(beaGet pattern(o), "Syntactic Pattern"))
cmds.add(ahref(appendParamsToURL(baseLink + "/convertSyntacticToSemanticMatches", matchID := o.id),
"Convert to semantic matches"));
}
cmds.add(
targetBlank(addParamsToURL(crudLink(BEA),
cmd := "new",
newField1_name := "inReferenceTo",
newField1_type := "BEAObject",
newField1_conceptValue := o.id),
"Reference this"));
cmds.add(
ahref(addParamsToURL(baseLink + "/markUseful",
redirect := beaShortURL(o),
objectID := o.id),
"Mark useful"));
cmds.add(
ahref(addParamsToURL(baseLink + "/markBad",
redirect := beaShortURL(o),
objectID := o.id),
"Mark bad"));
cmds.add(addCommentHTML(o));
if (o.typeIsOneOf("Script", "Step in script") || eqic(beforeVerticalBar(o.type()), "Instruction"))
cmds.add(
ahref(addParamsToURL(baseLink + "/runInstruction",
instruction := o.id),
"Run"));
if (o.typeIs("Function Result")) {
if (eqic(cget resultType(o), "string"))
cmds.add(
ahref(addParamsToURL(baseLink + "/convertResultToInput",
result := o.id),
"Convert to input"));
}
if (o.typeIs("Auto Run"))
cmds.add(
ahref(addParamsToURL(baseLink + "/performAutoRunOnAllObjects", autoRun := o.id), "Run on all objects"));
if (o.getClass() != BEA)
cmds.add(
ahref(addParamsToURL(baseLink + "/migrateToBase", id := o.id), "Migrate to BEAObject"));
cmds.add(
ahref(addParamsToURL(baseLink + "/performAutoRuns",
onObject := o.id),
"Perform auto runs on this object"));
framer.addInHead(hjs_copyToClipboard());
cmds.add(ahref_onClick(formatFunctionCall copyToClipboard(jsQuote(o.globalIDStr())), "Copy global ID [" + o.globalIDStr() + "]"));
LS items = llNempties(
crud.renderCmds_base(map),
!o.typeIsOneOf("Input", "Pattern", "Syntactic Pattern")
? null : addRewriteHTML(o),
!canAutoMigrate(o) ? null
: ahref(addParamsToURL(baseLink + "/autoMigrate", id := o.id), "Auto-migrate to " + shortClassName(defaultCustomClass(o))));
if (isObjectWithCode(o) && isMasterAuthed(req)) {
S link = baseLink + "/activateDynamicObject?id=" + o.id;
if (!codeHashUpToDate(o))
if (cget meta_codeHash(o) == null)
items.add(ahref(link, "Compile new code", title := "Object has not been compiled yet"));
else
items.add(ahref(link, "Compile changed code", title := "Code has changed afer last compilation"));
else if (compileErrorInObject(o))
items.add("Code error. " + ahref(link, "Compile again", title := "Object has code errors - maybe recompiling fixes them?"));
else if (o.customCodeLoaded())
items.add(ahref(link, "Compile again", title := "Custom code is loaded. Click if you want to recompile anyway"));
else
items.add(ahref(link, "Compile & load"));
}
if (additionalCommandsForObjects) {
if (hasMethodNamed(o, "html"))
items.add(targetBlank(beaMod().baseLink + "/beaHTML/" + o.id, "Show HTML"));
if (nempty(getStringOpt meta_code(o)))
items.add(targetBlank(addParamsToURL(beaMod().baseLink + "/get-field", obj := o.id, field := "meta_code"),
"Show code"));
S codeState = getStringOpt meta_codeState(o);
if (swic(codeState, "error"))
items.add(targetBlank(addParamsToURL(beaMod().baseLink + "/beaHTML/249697", obj := o.id, field := "meta_codeState"),
"Show compile error"));
bool master = beaMod().isMasterAuthed();
if (hasMethod(o, "_activate")) {
bool active = isTrue(pcallOpt(o, "_active"));
bool shouldActivate = isTrue(getOpt(o, "meta_shouldActivate"));
if (active != shouldActivate)
items.add("Warning: Object is semi-activated");
else if (active)
items.add("Object is active");
else
items.add("Object is inactive");
if (master) {
if (!active || !shouldActivate)
items.add(ahref(addParamsToURL(beaMod().baseLink + "/activateObject", id := o.id), "ACTIVATE"));
if (active || shouldActivate)
items.add(ahref(addParamsToURL(beaMod().baseLink + "/deactivateObject", id := o.id), "DEACTIVATE"));
}
}
if (master) {
new LS methodCalls;
for (Method method : methodsSortedByNameIC(allLiveMethodsBelowClass(o, BEA))) {
SS params = litorderedmap(id := o.id, name := method.getName());
bool incomplete = false, problem = false;
var types = method.getParameterTypes();
for (int i = 1; i <= l(types); i++) {
var argType = types[i-1];
set incomplete;
if (eq(argType, S))
params.put("arg" + i, "putArgHere");
else if (isSubclassOf(argType, BEA))
params.put("conceptArg" + i, "putArgHere");
else {
params.put("arg" + i, "missingConverterProblem");
set problem;
}
}
S url = addParamsToURL("/callAnyMethod", params);
S html = method.getName();
if (problem) html += appendBracketed("probably can't call, need converter");
else if (incomplete) html += appendBracketed("fill in parameters first");
methodCalls.add(targetBlank(url, html));
}
if (nempty(methodCalls)) items.add(hPopDownButtonWithText("Call a method", methodCalls));
}
}
// add more commands here
pcall { addAll(items, o.directCmds()); }
pcall {
addAll(items, (LS) callOpt(getWebsiteEnhancer("commandsForObject"), 'commandsFor, o));
}
items.add(hPopDownButton(cmds));
ret joinNemptiesWithVBar(items);
};
cc.massageItemMapForList = (item, map) -> {
BEAObject o = cast item;
if (o.typeIs("Input")) {
Cl matches = objectsWhereNotIC(objectsWhereCI(findBackRefs(o, BEAObject), type := "match"),
label := "bad");
map/Map.put("Best Matches", HTML(hparagraphs(
lmap matchDescHTML(takeFirst(3, matches)))));
}
S idField = crud.idField();
O id = map/Map.get(idField);
if (id instanceof S)
map/Map.put(idField, HTML(ahref(beaShortURL(o), id)));
if (o.typeIs("Function Result")) {
O value = o~.result;
map/Map.put("result", HTML(javaValueToHTML(value)));
}
if (o.typeIs("Match")) {
SS mapping = o.mapping();
if (mapping != null)
map/Map.put("mapping", HTML(
joinWithBR(map(mapping, (k, v) ->
htmlEncode2(k) + "=" + calculations.bestInputHTML(v)))));
}
if (o.getClass() != BEA)
map/Map.put("Java Class", dropPrefix(actualMCDollar(), className(o)));
if (eq(req.get("showSimpleObjectScore"), "1"))
map/Map.put("Simple object score" := calculations.simpleObjectScore(o));
o.massageItemMapForList(map/Map);
}; // end of massageItemMapForList
crud.massageFormMatrix = (map, matrix) -> {
for (int i = 1; i <= newFieldsToShow; i++) {
S nf = "newField" + i;
S key = "\*nf*/_conceptValue";
BEA refValue = beaGet(req.get(key));
S refSelector =
crud.renderInput(key,
cc.makeConceptsComboBox(key, BEAObject), refValue)
+ hjs([[$("[name=]] + key + [[]").hide()]]);
S nativeSelector =
crud.renderInput("\*nf*/_nativeValue",
cc.makeConceptsComboBox("\*nf*/_nativeValue", Concept), null)
+ hjs([[$("[name=]] + nf + [[_nativeValue]").hide()]]);
LS types = ll("String", "BEAObject", "Bool", "Native");
S toggleVis = [[
$("[name=]] + nf + [[_value]").toggle(value == "String" || value == "Bool");
$("#]] + nf + [[_refBox").toggle(value == "BEAObject");
$("#]] + nf + [[_nativeSel").toggle(value == "Native");
]];
S type = req.get("\*nf*/_type");
S typeSelector = hselect_list(types, type, name := "\*nf*/_type",
onchange := "var value = this.value;" + toggleVis);
if (nempty(type))
typeSelector += hscript("(function(value) {" + toggleVis + "})(" + jsQuote(type) + ")");
matrix.add(ll("Add field:
" + htextfield("\*nf*/_name", req.get("\*nf*/_name"), title := "New field name"),
htmlTable2_noHtmlEncode(ll(ll(
// string input
//htextfield("\*nf*/_value"),
crud.renderTextField("\*nf*/_value", "", 40)
/*htextarea("",
name := nf + "_value",
class := "auto-expand",
style := "width: 300px",
)*/ +
span(refSelector, id := "\*nf*/_refBox", style := "display: none"),
span(nativeSelector, id := "\*nf*/_nativeSel", style := "display: none"),
"Type", typeSelector
)),
noHeader := true,
tableParams := litobjectarray(style := "width: 100%"))));
}
};
crud.preprocessUpdateParams = params -> {
params = cloneMap(params);
// drop empty strings
//removeFromMapWhereValue(params, v -> eq(v, ""));
params = mapValues(params, v -> eq(v, "") ? null : v);
for (int i = 1; i <= max(newFieldsToShow, 10); i++) {
S nf = "newField" + i;
S name = trim(params.get("\*nf*/_name")),
type = params.get("\*nf*/_type"),
refValue = params.get("\*nf*/_conceptValue"),
nativeValue = params.get("\*nf*/_nativeValue"),
value = params.get("\*nf*/_value");
if (eqic(type, "BEAObject")) {
value = refValue;
params.put("metaInfo_" + name, "concept");
} else if (eqic(type, "Native")) {
value = nativeValue;
params.put("metaInfo_" + name, "concept");
} else if (eqic(type, "Bool"))
params.put("metaInfo_" + name, "bool");
if (eq(value, "")) value = null;
if (nempty(name) /*&& neqOneOf(value, null, "")*/)
params.put(crud.fieldPrefix + name, value);
}
ret params;
};
// regular users can only edit their own objects
if (!isMasterAuthed(req))
cc.objectCanBeEdited = id -> userCanEditObject(user(req), (BEA) cc.conceptForID(id));
} // end of CRUD customization for BEAObject
ret crud;
}
bool userCanEditObject(User user, BEA o) {
ret user != null && (user.isMaster || cget createdBy(o) == user);
}
@Override
O servePossiblyUserlessBotFunction(DynGazelleRocks.Req req, S function, Map data, User user) {
if (eq(function, "beaExport")) {
Cl ids = concatLists(
tok_integersAsLongs(urldecode(req.subURI)),
tok_integersAsLongs(req.get("ids")));
var objects = map beaGet(ids);
ret serveJSON_breakAtLevels(2, result := map(objects, obj ->
litorderedmap(id := obj.id,
gid := str(obj.globalID()),
struct := obj.structureString())));
}
ret super.servePossiblyUserlessBotFunction(req, function, data, user);
}
@Override
O serveBotFunction(DynGazelleRocks.Req req, S function, Map data, User user) {
if (eq(function, "beaList")) {
long changedAfter = toLong(data.get("changedAfter"));
double pollFor = min(bot_maxPollSeconds, toLong(data.get("pollFor"))); // how long to poll (seconds)
long startTime = sysNow();
// We're super-anal about catching all changes. This will probably never trigger
if (changedAfter > 0 && changedAfter == now()) sleep(1);
Cl objects;
while true {
objects = changedAfter == 0 ? list(BEAObject)
: conceptsWithFieldGreaterThan_sorted(BEAObject, _modified := changedAfter);
// return when there are results, no polling or poll expired
if (nempty(objects) || pollFor == 0 || elapsedSeconds_sysNow(startTime) >= pollFor)
ret serveJSON_breakAtLevels(2, result := map(objects, obj ->
litorderedmap(gid := str(obj.globalID()), struct := obj.structureString())
));
// sleep and try again
sleep(bot_pollInterval);
}
}
ret super.serveBotFunction(req, function, data, user);
}
@Override
O serveOtherPage2(DynGazelleRocks.Req req) { ret serveOtherPage2((Req) req); }
O serveOtherPage2(Req req) null {
//printVars_str serveOtherPage2(uri := req.uri);
try object super.serveOtherPage2(req);
S uri = dropTrailingSlashIfNemptyAfterwards(req.uri);
new Matches m;
if (swic_notSame(uri, "/beaCRUD/", m))
ret renderBEAObjectTable(req, urldecode(m.rest()));
if (eq(uri, "/inputs"))
ret renderBEAObjectTable(req, "input");
if (eq(uri, "/syntacticMatchesTable"))
ret hrefresh(baseLink + "/matchesTable?syntacticOnly=1");
if (eq(uri, "/matchesTable")) {
bool syntacticOnly = eq("1", req.get("syntacticOnly"));
new L list;
for (BEA match : beaList("Match")) {
BEA input = cgetOpt BEA(match, "input");
BEA pat = cgetOpt BEA(match, "pattern");
if (syntacticOnly && !calculations.isSyntacticPattern(pat)) continue;
continue if calculations.patternAlwaysMatches(pat);
SS mapping = match.mapping();
if (input == null || pat == null || mapping == null) continue;
list.add(match);
}
list = sortedByCalculatedFieldDesc(list,
match -> conceptID(cgetBEA input(match)));
new HTMLPaginator paginator;
paginator.processParams(req.params());
paginator.baseLink = addParamsToURL(baseLink,
filterKeys(req.params(), p -> eq(p, "syntacticOnly")));
paginator.max = l(list);
req.framer.add(divUnlessEmpty(paginator.renderNav()));
list = subList(list, paginator.visibleRange());
new L