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
// GazelleBEA - Base class of all Gazelle web servers
// About BEA objects with code: There is some confusion about the actions on them.
// There are:
// - compileAndLoadObject
// - activateDynamicObject
// - reactivateDynamicObject
// - deactivateObject
//
// It's not completely clear what each of these actions exactly does
// with respect to the at least 3 internal states of an object:
// - no custom code, or none compiled
// - custom code compiled (or imported from another object)
// - custom code loaded (actually migrated object to custom class)
// - object activated (activate listeners etc defined by the
// object in _activateImpl())
//
// Right now things seem to work, but we could really use some test cases related to this.
// Ways to put code into a BEA object:
//
// Way 1. Put the JavaX code directly in meta_code (string field).
// You can use an exports {} block to make things on the global level (e.g. static classes to export)
// You can use a special "extends" declaration (extends BBla from 123;) in meta_code to subclass a class defined in another object.
//
// Way 2. Point meta_prototype to another object with a custom class.
// This will use the same class for this object.
//
// Way 3. Set meta_useClass to something like "123.BBla" to use a class
// called BBla exported by object 123 for this object.
// Note about GazelleBEA:
// If you ever move this class into loadableUtils, make sure to copy the definition of method db() to the subclass
// and override uploadsBaseDir()
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
switchable S gazelleServerGlobalID = aGlobalID();
// 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;
transient bool showInputAndPatternNavItems = 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;
unset showDeliveredDomains;
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) {
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;
});
S mainPrefix = dotToDollar(DynClassName_mainPrefix());
O classFinder = _defaultClassFinder();
db_mainConcepts().classFinder = func(S name) -> Class enter {
print("Deserializing class " + name);
try {
S name2 = dropPrefix(mcName() + "$", name);
//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(BEA, 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(BEA));
newObjectsDistributed.addAll(list(BEA));
/*onIndividualConceptChange_notOnAllChanged(BEA,
p -> { calculations.makeSyntacticPattern(p); });*/
onIndividualConceptChange_notOnAllChanged(BEA,
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");
} // end of start2()
void makeIndices :: after {
indexConceptClass(BSettings);
indexConceptFieldDesc(BEA, "_modified");
indexConceptFieldCIWithTopTen(BEA, "type");
indexConceptFieldIC(BEA, "text");
indexConceptFieldIC(BEA, "purpose");
}
bool isMaster(Req req) {
ret req?.masterAuthed;
}
@Override
L crudClasses(DynGazelleRocks.Req req) {
var l = super.crudClasses(req);
l.add(BEA);
if (masterAuthed(req))
l.add(AuthedDialogID);
ret l;
}
Set hiddenCrudClasses() {
Set set = super.hiddenCrudClasses();
set.remove(UploadedSound);
addAll(set, Conversation, ExecutedStep, InputHandled);
ret set;
}
S authFormHeading() {
ret h3(adminName);
}
swappable S authFormMoreContent() {
S html = p(html_loggedIn(false));
new HTMLFramer1 framer;
if (anonymousUserWarning(currentReq(), framer))
html += lines(framer.contents);
ret html + super.authFormMoreContent();
}
HTMLFramer1 newFramerInstance() {
ret new BEAHTMLFramer;
}
@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 == UploadedSound || c == UploadedFile || c == UploadedImage) {
cc.onCreate.add(o -> cset(o, createdBy := currentUser());
cc.emptyConcept = () -> {
Concept ccc = cc.emptyConcept_base();
cset(ccc, isPublic := true);
ret (A) ccc;
};
}
if (c == BEA) {
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(BEA, o), x -> contains(deletableRefs, x.type()));
};
cc.actuallyDeleteConcept = o -> {
deleteConcepts(filter(findBackRefs(BEA, 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 == BEA) {
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", "meta_dependsOnCode");
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(BEA),
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_noFollow(addParamsToURL(baseLink + "/markUseful",
redirect := beaShortURL(o),
objectID := o.id),
"Mark useful"));
cmds.add(
ahref_noFollow(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_gen(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", enhance := "JavaX"),
"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) -> {
BEA o = cast item;
if (o.typeIs("Input")) {
Cl matches = objectsWhereNotIC(objectsWhereCI(findBackRefs(o, BEA), 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, BEA), 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(BEA)
: conceptsWithFieldGreaterThan_sorted(BEA, _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