import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.table.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.imageio.*; import java.math.*; import x30_pkg.x30_util; import static x30_pkg.x30_util.VF1; import static x30_pkg.x30_util.l; import static x30_pkg.x30_util.fail; import static x30_pkg.x30_util.indexOf; import static x30_pkg.x30_util.getOpt; import static x30_pkg.x30_util.setOpt; import static x30_pkg.x30_util.callOpt; import static x30_pkg.x30_util.newWeakHashMap; import static x30_pkg.x30_util.newDangerousWeakHashMap; import static x30_pkg.x30_util.get; import static x30_pkg.x30_util.get_raw; import static x30_pkg.x30_util.assertTrue; import static x30_pkg.x30_util.isHeadless; import static x30_pkg.x30_util.isAndroid; import static x30_pkg.x30_util.isTrue; import x30_pkg.x30_util.DynamicObject; import loadableUtils.utils; import static loadableUtils.utils._threadInfo; import static loadableUtils.utils._threadInheritInfo; import static loadableUtils.utils._threadInfo_addMakerAndRetriever; import static loadableUtils.utils.dm_currentModule; import static loadableUtils.utils.dm_current_mandatory; import static loadableUtils.utils.match; import static loadableUtils.utils.getOpt_raw; import static loadableUtils.utils.setOpt_raw; import static loadableUtils.utils.getField; import static loadableUtils.utils.fieldType; import static loadableUtils.utils.format3; import static loadableUtils.utils.vm_generalIdentityHashSet; import static loadableUtils.utils.vm_generalHashMap; import static loadableUtils.utils.vm_generalWeakSubMap; import static loadableUtils.utils.bindToComponent; import static loadableUtils.utils.struct; import static loadableUtils.utils.structure; import static loadableUtils.utils.loadPage; import static loadableUtils.utils.loadPage_utf8; import static loadableUtils.utils.loadPageSilentlyWithTimeout; import static loadableUtils.utils.loadPageSilently; import static loadableUtils.utils.loadSnippet; import static loadableUtils.utils.loadSnippetQuietly; import static loadableUtils.utils.sendToLocalBot; import static loadableUtils.utils.sendToLocalBotOpt; import static loadableUtils.utils.sendToLocalBotQuietly; import static loadableUtils.utils.componentPopupMenu; import static loadableUtils.utils.componentPopupMenu_top; import static loadableUtils.utils.componentPopupMenu_initForComponent; import static loadableUtils.utils.componentPopupMenu_getEvent; import static loadableUtils.utils.listPopupMenu; import static loadableUtils.utils.tablePopupMenu; import static loadableUtils.utils.tablePopupMenuFirst; import static loadableUtils.utils.rowSorter_setComparators; import static loadableUtils.utils.sexyTableWithoutDrag; import static loadableUtils.utils.dm_current_generic; import static loadableUtils.utils.dm_current_mandatory_generic; import static loadableUtils.utils.cset; import static loadableUtils.utils.DynamicObject_loading; import static loadableUtils.utils.concepts_unlisted; import static loadableUtils.utils.makePopupMenuConditional; import static loadableUtils.utils.makeConceptsTable_idWidth; import static loadableUtils.utils.showConceptsTable_afterUpdate; import static loadableUtils.utils.dynamicObjectIsLoading; import static loadableUtils.utils.rethrow; import static loadableUtils.utils.hasBot; import static loadableUtils.utils.concepts_internStringsLongerThan; import static loadableUtils.utils.concepts_setUnlistedByDefault; import static loadableUtils.utils.realMC_tl; import loadableUtils.utils.F0; import loadableUtils.utils.F1; import loadableUtils.utils.IF0; import loadableUtils.utils.IF1; import loadableUtils.utils.IVF1; import loadableUtils.utils.IVF2; import loadableUtils.utils.Matches; import loadableUtils.utils.BetterLabel; import loadableUtils.utils.SingleComponentPanel; import loadableUtils.utils.Snippet; import loadableUtils.utils.Q; import loadableUtils.utils.ImageSurface; import loadableUtils.utils.structure_Data; import loadableUtils.utils.structure_ClassInfo; import loadableUtils.utils.RGBImage; import loadableUtils.utils.RGB; import loadableUtils.utils.BWImage; import loadableUtils.utils.MakesBufferedImage; import loadableUtils.utils.MultiSet; import loadableUtils.utils.Concept; import loadableUtils.utils.Concepts; import loadableUtils.utils.RC; import loadableUtils.utils.IConceptIndex; import loadableUtils.utils.IConceptCounter; import loadableUtils.utils.IFieldIndex; import loadableUtils.utils.Derefable; import loadableUtils.utils.ImageSurfaceSelector; import loadableUtils.utils.SimpleCRUD; import loadableUtils.utils.PersistableThrowable; import loadableUtils.utils.DynModule; import loadableUtils.utils.DynPrintLog; import loadableUtils.utils.DynObjectTable; import loadableUtils.utils.DynImageSurface; import loadableUtils.utils.DynCalculatedList; import loadableUtils.utils.GlobalID; import loadableUtils.utils.Rect; import loadableUtils.utils.Pt; import loadableUtils.utils.SynchronizedArrayList; import loadableUtils.utils.SecretValue; import loadableUtils.utils.HCRUD; import loadableUtils.utils.HCRUD_Data; import loadableUtils.utils.HCRUD_Concepts; import loadableUtils.utils.ValueConverterForField; import loadableUtils.utils.DefaultValueConverterForField; import loadableUtils.utils.OrError; import loadableUtils.utils.HTML; import java.text.*; import java.awt.datatransfer.StringSelection; import java.text.NumberFormat; import java.nio.charset.Charset; import java.util.TimeZone; import java.text.SimpleDateFormat; import javax.imageio.metadata.*; import javax.imageio.stream.*; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import javax.swing.undo.UndoManager; import java.nio.file.Files; import java.nio.file.Path; import java.awt.geom.*; class main { static public class BEACalculations { public GazelleBEA mod; public BEACalculations(GazelleBEA mod) { this.mod = mod; } transient public int liveOutputDelay = 1000; transient public double algoTimeout = 30.0; public void reactAllInputsWithSomePatterns() { for (BEAObject input : mod.beaObjectsOfType("input")) { ReactInputWithSomePatterns r = new ReactInputWithSomePatterns(); r.input = input; r.ccOut = db_mainConcepts(); r.max = 10; r.start(); stepAllWithTimeout(10.0, r); } } public class ReactInputWithSomePatterns implements Steppable { public BEAObject input; public Concepts ccOut; public int max = 3, n; public Iterator patterns; public void start() { n = countConceptsWhereIC(ccOut, BEAObject.class, "input", input, "type", "match"); patterns = iterator(sortByConceptID(conceptsWhereIC(BEAObject.class, "type", "Pattern"))); } public boolean step() { if (n >= max) return false; if (!patterns.hasNext()) return false; if (reactInputWithPattern(input, patterns.next(), ccOut) != null) ++n; return true; } } public Map matchInputWithPattern(BEAObject input, BEAObject pattern) { String text = getString("text", input); return matchInputWithPattern(text, pattern); } public Map matchInputWithPattern(String text, BEAObject pattern) { String pat = getString("text", pattern); boolean punctuationOnly = isTrue_getOpt("punctuationOnly", pattern); if (pattern.typeIs("Syntactic Pattern")) return matchInputWithSyntacticPattern(text, pat, punctuationOnly); else if (eqic_gen(getOpt("subType", pattern), "PhraseCache")) return phraseCache(pat, text) ? litmap() : null; else return matchInputWithPattern(text, pat, punctuationOnly); } public Map matchInputWithSyntacticPattern(String text, String pat) { return matchInputWithSyntacticPattern(text, pat, false); } public Map matchInputWithSyntacticPattern(String text, String pat, boolean punctuationOnly) { pat = starsToAngleBracketedNumbers(pat); return matchInputWithPattern(text, pat, punctuationOnly); } public Map matchInputWithPattern(String text, String pat) { return matchInputWithPattern(text, pat, false); } public Map matchInputWithPattern(String text, String pat, boolean punctuationOnly) { Map mapping = flexMatchAngleBracketVarsIC_honorPunctuation_first(pat, text); if (mapping != null || punctuationOnly) return mapping; return flexMatchAngleBracketVarsIC_first(pat, text); } public BEAObject reactInputWithPattern(BEAObject input, BEAObject pattern) { return reactInputWithPattern(input, pattern, db_mainConcepts()); } public BEAObject reactInputWithPattern(BEAObject input, BEAObject pattern, Concepts ccOut) { if (input == null || pattern == null) return null; Map mapping = matchInputWithPattern(input, pattern); if (mapping == null) return null; return cnew(ccOut, BEAObject.class, "type", "Match", "input", input, "pattern", pattern, "mapping", mapping); } public Object serveAnalyzeInput(GazelleBEA.Req req) { Concepts ccOut = new Concepts(); BEAObject input = getConcept(BEAObject.class, parseLong(req.get("id"))); if (input == null) input = cnew(ccOut, BEAObject.class, "type", "Input", "text", req.get("q")); String text = getString("text", input); ReactInputWithSomePatterns r = new ReactInputWithSomePatterns(); r.input = input; r.ccOut = ccOut; r.max = 1000; r.start(); stepAllWithTimeout(10.0, r); List matches = conceptsWhereIC(ccOut, BEAObject.class, "type", "Match"); return h1_title("Analyze Input") + p("Input: " + b(htmlEncode(text))) + p(empty(matches) ? "No matches" : "Matches") + ul_htmlEncode(matches); } public Object serveQueryPage(GazelleBEA.Req req) { String q = req.get("q"), algorithm = req.get("algorithm"); boolean dontRun = eq(req.get("dontRun"), "1"); boolean liveOutput = eq(req.get("liveOutput"), "1"); if (liveOutput) req.noSpam(); if (eqic(algorithm, "process input")) algorithm = "Process new input v3"; Map> algorithms = litorderedmap("Process new input v3", (IF0) () -> new ProcessNewInput_v3(), "Process new input v2", (IF0) () -> new ProcessNewInput_v2(), "Process new input", (IF0) () -> new ProcessNewInput(), "Run pattern", (IF0) () -> new RunPattern(), "Find rewrites for match", (IF0) () -> new FindRewrites(), "Reverse input (test algorithm)", (IF0) () -> new ReverseInput(), "Timeout test", (IF0) () -> new TimeoutTest(), "Syntactic pattern from input", (IF0) () -> new SyntacticPatternFromInput(), "Apply all text functions", (IF0) () -> new ApplyTextFunctions(), "Find Path", (IF0) () -> new FindPath(), "Execute text query", (IF0) () -> new ExecuteTextQuery(), "Make syntactic patterns for all patterns in DB", (IF0) () -> new MakeSyntacticPatterns()); String output = empty(algorithm) || dontRun ? null : doAlgorithm(algorithms, algorithm, q, liveOutput); if (liveOutput) return jsonEncode(litorderedmap("answer", output)); String right = mod.html_loggedIn(); String centered = htitle_h2(ahref(mod.baseLink + "/", "Gazelle BEA") + " Query") + hscript(replaceVars("\n var sugLoading = false, sugTriggerAgain = false;\n\n function sugTrigger() {\n console.log(\"sugTrigger\");\n if (sugLoading) { sugTriggerAgain = true; return; }\n\n // get form data as JSON\n \n var data = {\n \"liveOutput\" : \"1\",\n \"q\": $(\"textarea[name=q]\").val(),\n \"algorithm\": $(\"select[name=algorithm]\").val()\n };\n \n const url = \"/query\";\n console.log(\"Loading \" + url + \" with \" + data);\n sugLoading = true;\n $.post(url, data,\n function(result) {\n console.log(\"Suggestor result: \" + result);\n const answer = !result ? \"\" : JSON.parse(result).answer;\n if (answer) {\n $(\"#liveResult .sectionContents\").html(answer);\n $(\"#liveResult\").show();\n } else\n $(\"#liveResult\").hide();\n //$(\"#suggestorResult\").html(answer ? \"Suggestor says: \" + answer : \"\");\n }\n ).always(function() {\n console.log(\"sug loading done\");\n setTimeout(function() {\n sugLoading = false;\n if (sugTriggerAgain) { sugTriggerAgain = false; sugTrigger(); }\n }, liveOutputDelay);\n });\n }\n\n $(document).ready(function() {\n $(\"textarea[name=q], input[name=q], select[name=algorithm]\").on('input propertychange change', sugTrigger);\n sugTrigger();\n });\n ", "liveOutputDelay", liveOutputDelay)) + hform(p("Query (Ctrl+Enter): " + htextarea(q, "id", "mainInput", "name", "q", "class", "auto-expand", "style", "max-height: 10em; width: 300px; vertical-align: top", "onkeydown", "\n if ((event.keyCode == 10 || event.keyCode == 13) && event.ctrlKey) $(this).closest('form').submit();\n ") + hjs("$(document).ready(function() {\n autoExpandTextArea(document.getElementById(\"mainInput\"));\n });") + "   Algorithm: " + hselect_list(keys(algorithms), algorithm, "name", "algorithm") + "   " + hbutton("Go"))); return hhtml(hhead(hmobilefix() + hsansserif() + loadJQuery2() + hjs_autoExpandingTextAreas() + mod.webSocketHeadStuff(req) + hNotificationPopups()) + hbody(div_alignRight(right) + div_center(centered) + htitledSectionWithDiv("Live Result", "", "id", "liveResult", "style", "display: none", "innerDivStyle", "max-height: 150px; overflow: auto") + (output == null ? "" : h3(algorithm) + output))); } public String doAlgorithm(Map> algorithms, String algorithm, String q, boolean liveMode) { GazelleBEA.Req req = mod.currentReq.get(); StringBufferWithMaxSize out = new StringBufferWithMaxSize(1000000); IF0 algo = lookupPossiblyCI(algorithms, algorithm); if (algo == null) out.append("Algorithm not found: " + algorithm); else { if (isB(evalWithTimeout(algoTimeout, new Runnable() { public void run() { try { AutoCloseable __3 = mod.enter(); try { AutoCloseable __4 = tempSetTL(mod.currentReq, req); try { Algorithm alg = algo.get(); alg.liveMode = liveMode; alg.q = q; alg.out = out; alg.runIt(); } finally { _close(__4); } } finally { _close(__3); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp mod.enter();\n temp tempSetTL(mod.currentReq, req);\n Algori..."; } }))) out.append("\n[algorithm timeout]"); } return str(out); } abstract public class Algorithm implements Runnable { public String q; public Appendable out; public boolean liveMode = false; public Concepts localConcepts; public List nonMatches; public void runLiveMode() { } public void appendHTML(String html) { appendHTML(this.out, html); } public void appendHTML(Appendable out, String html) { try { if (empty(html)) return; html = wrapInDiv(html, "style", "margin-top: 0.5em"); out.append(html).append("\n"); } catch (Exception __e) { throw rethrow(__e); } } public void appendText(String text) { appendText(this.out, text); } public void appendText(Appendable out, String text) { try { if (empty(text)) return; out.append(hpre_htmlencode(rtrim(text))); } catch (Exception __e) { throw rethrow(__e); } } public void appendTextBold(String text) { appendTextBold(this.out, text); } public void appendTextBold(Appendable out, String text) { try { if (empty(text)) return; out.append(b(hpre_htmlencode(rtrim(text)))); } catch (Exception __e) { throw rethrow(__e); } } public void allowSuggestingAnswer(BEAObject input) { if (input == null) return; String text = input.text(); String url = mod.baseLink + "/saveAnswer"; appendHTML(hpostform("Suggest an answer to " + htmlEncode_quote(text) + ": " + htextarea(text, "id", "suggestAnswer", "name", "text", "class", "auto-expand", "style", "max-height: 10em; width: 300px; vertical-align: top") + hhidden("inputID", input.id) + hhidden("redirect", "") + " " + hsubmit("Save answer") + " [Optional rewrite type: " + hinputfield("rewriteType", "style", "width: 100px") + " ]", "action", url, "onsubmit", js_setRedirect())); } public void saveInput(String q) { Pair p = uniqCI2(BEAObject.class, "type", "Input", "text", q); if (p.b) { csetIfUnset(p.a, "createdBy", mod.user(mod.currentReq.get())); appendHTML("Input saved"); } } public void runNonMatches() { if (nempty(nonMatches)) { appendHTML(hr()); callFAll(nonMatches); } } public void runIt() { if (liveMode) runLiveMode(); else run(); runNonMatches(); } } public class ReverseInput extends Algorithm { public void run() { appendText(reversed(q)); } public void runLiveMode() { run(); } } public class TimeoutTest extends Algorithm { public void run() { sleepSeconds(120); } } public class RunPattern extends Algorithm { public void run() { BEAObject pattern = mod.beaGet(parseFirstLong(q)); if (pattern == null) { appendText("Pattern not found"); return; } appendText("Pattern: " + pattern); for (BEAObject input : mod.beaList("Input")) { String text = input.text(); Map mapping = matchInputWithPattern(input, pattern); if (mapping == null) nonMatches.add(new Runnable() { public void run() { try { appendText("Checking Input: " + input + " - No match"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "appendText(\"Checking Input: \" + input + \" - No match\");"; } }); else { String result = "\n" + indent(formatDoubleArrowMap_horizontallyAligned(mapping)); appendText("Checking Input: " + input + result); allowStoringMatch(this, input, pattern, mapping); } } } } public class FindRewrites extends Algorithm { public void run() { BEAObject match = mod.beaGet(parseFirstLong(q)); if (match == null || !match.typeIs("Match")) { appendText("Match not found"); return; } BEAObject pattern = (BEAObject) (cget("pattern", match)); BEAObject input = (BEAObject) (cget("input", match)); Map mapping = (Map) (get("mapping", match)); appendText("Match: " + match); appendText("Input: " + input); appendText("Pattern: " + pattern); appendText("Mapping:\n" + indent(formatDoubleArrowMap_horizontallyAligned(mapping))); appendRewrites(this, input, input.text(), pattern, match, mapping); } } public List appendRewrites(Algorithm algo, BEAObject input, String inputText, BEAObject pattern, BEAObject match, Map mapping) { Collection rewrites = mod.beaBackRefs(pattern, "Rewrite"); List texts = new ArrayList(); for (BEAObject r : rewrites) { String text = r.text(); String textWithVars = text; if (pattern.typeIs("Syntactic pattern")) textWithVars = starsToAngleBracketedNumbers(text); String text2 = replaceAngleBracketVars_curly(textWithVars, mapping); algo.appendText(" Using pattern rewrite: " + text); algo.appendTextBold(" " + inputText + "\n" + " => " + text2); texts.add(text2); BEAObject existing = match == null || input == null ? null : conceptWhereIC(BEAObject.class, "type", "Rewrite", "input", input, "text", text2, "match", match, "patternRewrite", r, "label", "good"); if (existing != null) algo.appendHTML("Rewrite exists: " + mod.beaLinkHTML(existing)); else if (match != null && input != null) algo.appendHTML(hinlinepostform(hhiddenMulti("action", "create", "f_type", "Rewrite", "f_text", text2, "f_input", input.id, "metaInfo_input", "concept", "f_match", match.id, "metaInfo_match", "concept", "f_patternRewrite", r.id, "metaInfo_patternRewrite", "concept", "f_label", "good") + hbutton("Good rewrite"), "target", "_blank", "action", mod.crudLink(BEAObject.class))); } return texts; } public class ProcessNewInput extends Algorithm { public void run() { q = trim(q); BEAObject input = handleInput(this, q, false); for (BEAObject pattern : mod.beaListAny("Pattern", "Syntactic Pattern")) { Map mapping = matchInputWithPattern(q, pattern); if (mapping == null) nonMatches.add(new Runnable() { public void run() { try { appendText("Checking Pattern: " + pattern + " - No match"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "appendText(\"Checking Pattern: \" + pattern + \" - No match\");"; } }); else { String result = "\n" + indent(formatDoubleArrowMap_horizontallyAligned(mapping)); appendText("Checking Pattern: " + pattern + result); if (input == null) { } else allowStoringMatch(this, input, pattern, mapping); appendRewrites(this, input, q, pattern, null, mapping); } } } } public class ProcessNewInput_v2 extends Algorithm { public void run() { q = trim(q); saveInput(q); BEAObject input = handleInput(this, q, false); if (input != null) { Collection rewrites = mod.beaBackRefs(input, "Rewrite"); BEAObject rewrite = random(rewrites); if (rewrite != null) appendHTML("My answer: " + b(htmlEncode2(rewrite.text())) + " " + ahref(mod.beaShortURL(rewrite), "[source]")); } allowSuggestingAnswer(input); for (BEAObject pattern : syntacticPatternsSortedBySpecificityDesc()) { { if (isTrue_getOpt("alwaysMatches", pattern)) continue; } Map mapping = matchInputWithPattern(q, pattern); if (mapping == null) { if (nonMatches != null) nonMatches.add(new Runnable() { public void run() { try { appendHTML("Checking Syntactic Pattern: " + mod.beaLinkHTML(pattern) + " - No match"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "appendHTML(\"Checking Syntactic Pattern: \" + mod.beaLinkHTML(pattern) + \" - No..."; } }); } else { String result = "Grouped as: " + replaceAngleBracketVars_curly(starsToAngleBracketedNumbers(pattern.text()), mapping) + "\n" + indent(formatDoubleArrowMap_horizontallyAligned(mapping)); appendHTML(hr()); appendHTML("Checking Syntactic Pattern: " + mod.beaLinkHTML(pattern)); appendText(result); BEAObject match = null; if (input == null) { } else match = allowStoringMatch(this, input, pattern, mapping); MultiMap subInputRewrites = ciMultiMap(); for (String subInput : uniquifyCI(values(mapping))) if (!eqic(subInput, q)) { BEAObject subInputObj = handleInput(this, subInput, "Sub-Input", true); if (subInputObj != null) { List subRewrites = concatLists(conceptsWhereCI(BEAObject.class, "type", "Rewrite", "input", subInputObj), conceptsWhereCI(BEAObject.class, "type", "Rewrite", "isRewriteOf", subInputObj)); for (BEAObject r : subRewrites) appendHTML("  Sub-Rewrite found: " + r); subInputRewrites.putAll(subInput, subRewrites); } } appendRewrites(this, input, q, pattern, match, mapping); Map rewrittenMapping = mapValues(mapping, s -> { BEAObject rewrite = random(subInputRewrites.get(s)); return rewrite == null ? s : uncurly(rewrite.text()); }); String randomRewrite = replaceAngleBracketVars_curly(starsToAngleBracketedNumbers(pattern.text()), rewrittenMapping); if (neq(randomRewrite, q)) appendText("Random rewrite from sub-inputs: " + randomRewrite); } } } } public class ProcessNewInput_v3 extends Algorithm { public void run() { q = trim(q); saveInput(q); BEAObject input = handleInput(this, q, false); HTMLTabs tabs = new HTMLTabs(); { StringBuffer toTab = new StringBuffer(); Algorithm alg = new ProcessNewInput_v2(); alg.q = q; alg.out = toTab; alg.runIt(); tabs.add("Match input with patterns", toTab); } { StringBuffer toTab = new StringBuffer(); Algorithm alg = new SyntacticPatternFromInput(); alg.q = q; alg.out = toTab; alg.runIt(); tabs.add("Make syntactic pattern", toTab); } appendHTML(tabs.html()); } } public BEAObject allowStoringMatch(Algorithm algo, BEAObject input, BEAObject pattern, Map mapping) { BEAObject match = conceptWhereCI(BEAObject.class, "type", "Match", "pattern", pattern, "input", input, "mapping", mapping); if (match != null) { algo.appendHTML("Match exists: " + mod.beaLinkHTML(match)); return match; } algo.appendHTML(joinWithSpace(storeMatchForm(input, pattern, "good"), storeMatchForm(input, pattern, "bad"))); return null; } public String storeMatchForm(BEAObject input, BEAObject pattern, String label) { return hinlinepostform(hhiddenMulti("pattern", pattern.id, "input", input.id, "label", label, "redirect", "") + hbutton(firstToUpper(label) + " match"), "action", mod.baseLink + "/storeMatch", "onsubmit", js_setRedirect()); } public class MakeSyntacticPatterns extends Algorithm implements Runnable { public void run() { for (BEAObject p : mod.beaList("Pattern")) { appendText(p + " => " + makeSyntacticPattern(p)); } } } public String syntacticPatternText(BEAObject p) { return simpleSpacesTrim_javaTok(angleBracketVarsToStars(p.text())); } public BEAObject makeSyntacticPattern(BEAObject p) { if (p == null || !p.typeIs("Pattern") || empty(p.text())) return null; print("makeSyntacticPattern", p); String text = syntacticPatternText(p); BEAObject sp = uniqCI(BEAObject.class, "type", "Syntactic Pattern", "text", text); cset(p, "syntacticPattern", sp); return sp; } public BEAObject handleInput(Algorithm algo, String q, boolean showProcessLink) { return handleInput(algo, q, "Input", showProcessLink); } public BEAObject handleInput(Algorithm algo, String q, String desc, boolean showProcessLink) { algo.appendHTML((desc + ": ") + tt(htmlEncode(q)) + (!showProcessLink ? "" : " " + targetBlank(addParamsToURL(mod.baseLink + "/query", "q", q, "algorithm", "process input"), "Process"))); BEAObject input = mod.findInput(q); algo.appendHTML(inputHTML(input, desc, q)); return input; } public String inputHTML(BEAObject input, String q) { return inputHTML(input, "Input", q); } public String inputHTML(BEAObject input, String desc, String q) { return input != null ? (desc + " exists: ") + mod.beaLinkHTML(input) : !mod.requestAuthed() && !mod.allowAnonymousInputUpload ? null : hinlinepostform(hhiddenMulti("text", q, "redirect", "") + hbutton(("Save " + desc)), "action", mod.baseLink + "/saveInput", "onsubmit", js_setRedirect()); } public String syntacticPatternLinkHTML(BEAObject obj, String text) { return syntacticPatternLinkHTML(obj, text, null); } public String syntacticPatternLinkHTML(BEAObject obj, String text, BEAObject fromInput) { String desc = "Syntactic pattern"; return obj != null ? mod.beaLinkHTML(obj) : !mod.requestAuthed() ? null : hinlinepostform(hhiddenMulti("text", text, "fromInput", conceptIDOrNull(fromInput), "redirect", "") + hbutton(("Save " + (firstToLower(desc)))), "action", mod.baseLink + "/saveSyntacticPattern", "onsubmit", js_setRedirect()); } public class SyntacticPatternFromInput extends Algorithm implements Runnable { public void run() { BEAObject input = handleInput(this, q, false); if (countTokens(q) > 10) { appendText("Input too long to extract syntactic patterns"); return; } String q2 = dropPunctuation(q); List data = new ArrayList(); for (String pat : sortedIC(gazelle_allSyntacticPatternsFromInput(q))) { Map mapping = matchInputWithSyntacticPattern(q2, pat); BEAObject obj = conceptWhereIC(BEAObject.class, "type", "Syntactic Pattern", "text", pat); Map row = litorderedmap("Syntactic Pattern", htmlEncode2(pat), "In database", syntacticPatternLinkHTML(obj, pat, input)); for (Map.Entry __1 : _entrySet(mapping)) { String key = __1.getKey(); String val = __1.getValue(); row.put("Argument " + key, htmlEncode2(val)); } data.add(row); } appendHTML(print(htmlTable2_noHtmlEncode(data))); } } public class ApplyTextFunctions extends Algorithm { public void run() { q = trim(q); saveInput(q); BEAObject input = handleInput(this, q, false); localConcepts = db_mainConcepts(); LinkedHashSet objectsMade = new LinkedHashSet(); for (BEAObject f : mod.beaList("JavaX Standard Function")) { try { String fName = getString("name", f); if (!isIdentifier(fName)) continue; if (!isSafeStandardFunction(fName)) { { if (nonMatches != null) nonMatches.add(new Runnable() { public void run() { try { appendText("Function " + fName + " not safe"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "appendText(\"Function \" + fName + \" not safe\");"; } }); } continue; } BEAObject o = cnew(localConcepts, BEAObject.class, "type", "Function Result", "function", f, "functionCalled", fName, "input", input, "calculating", true); objectsMade.add(o); try { Object holder = loadFunction_cached(fName); Object result = evalWithTimeoutOrFail(10.0, () -> call(holder, fName, q)); if (!(result instanceof List) && isStringCollection(result)) result = asList((Collection) result); if (result == null) cset(o, "resultType", "null"); else if (result instanceof String) cset(o, "resultType", "string", "result", result); else if (isStringList(result)) cset(o, "resultType", "list of strings", "result", result); else cset(o, "result", "other" + appendRoundBracketed(className(result)), "result", shorten(1000, str(result))); } catch (Throwable e) { cset(o, "resultType", "error", "error", getStackTrace(e)); } cset(o, "calculating", null); } catch (Throwable __e) { _handleException(__e); } } appendHTML(h3("Results of function calls")); HCRUD crud = mod.makeCRUD(BEAObject.class, mod.currentReq.get()); HCRUD_Concepts crudData = (HCRUD_Concepts) (crud.data); crudData.listConcepts_firstStep = () -> objectsMade; appendHTML(crud.renderTable(true)); } } public class FindPath extends Algorithm { public BreadthFirstPathFinder_withLinkType pathFinder = new BreadthFirstPathFinder_withLinkType(); public BEAObject start, dest; public void run() { start = mod.beaGet(parseFirstLong(q)); dest = mod.beaGet(parseSecondLong(q)); if (start == null || dest == null) { appendText("Please supply object IDs of start and end"); return; } appendHTML("Looking for path from " + mod.beaToHTML(start) + " to " + mod.beaToHTML(dest)); pathFinder.getChildren = o -> cForwardAndBackRefsWithFieldIndicator(BEAObject.class, o); pathFinder.add(start); while (!pathFinder.nodeReached(dest) && pathFinder.step()) { } List> path = pathFinder.examplePathWithTypes(start, dest); if (path == null) appendText("No path found!"); else { appendHTML(b("Path found!")); appendHTML(ol(map(path, p -> { String html = mod.beaHTML(p.a); if (p.b == null) return html; String arrow = ifThenElse(p.b.forward, ">>", "<<"); return html + " " + htmlEncode2(joinNemptiesWithSpace(arrow, p.b.field, arrow)); }))); } } } public class ExecuteTextQuery extends Algorithm { public void run() { saveInput(q = trim(q)); appendHTML(h3("Result")); appendHTML(htmlEncode2(strOrEmpty(executeTextQuery(q)))); } } public int patternSpecificity(BEAObject pattern) { return countWordsWithoutAngleBracketedAndStars(pattern.text()); } public List syntacticPatternsSortedBySpecificityDesc() { return sortedByCalculatedFieldDesc(__45 -> patternSpecificity(__45), mod.beaList("Syntactic Pattern")); } public Object executeTextQuery(String s) { Matches m = new Matches(); if (match3_withIntsAndIDs("all references in field of object ", s, m)) { Object value = cget(mod.beaGet(m.unq(1)), m.unq(0)); return value instanceof Collection ? instancesOf(BEAObject.class, (Collection) value) : value instanceof BEAObject ? ll((BEAObject) value) : ll(); } return new QueryNotUnderstood(s); } static public class QueryNotUnderstood implements IFieldsToList { public String s; public QueryNotUnderstood() { } public QueryNotUnderstood(String s) { this.s = s; } public String toString() { return shortClassName(this) + "(" + s + ")"; } public boolean equals(Object o) { if (!(o instanceof QueryNotUnderstood)) return false; QueryNotUnderstood __5 = (QueryNotUnderstood) o; return eq(s, __5.s); } public int hashCode() { int h = 1528655894; h = boostHashCombine(h, _hashCode(s)); return h; } public Object[] _fieldsToList() { return new Object[] { s }; } } } static public class GazelleBEA extends DynGazelleRocks { static public boolean _switchableField_mirrorBEAObjects = true; public boolean mirrorBEAObjects = false; static public boolean _switchableField_enableAutoRuns = true; public boolean enableAutoRuns = true; static public boolean _switchableField_enableNewBEAObjectNotis = true; public boolean enableNewBEAObjectNotis = true; transient public ReliableSingleThread_Multi rstAutoRuns = new ReliableSingleThread_Multi<>(1000, __18 -> performAutoRuns(__18)); transient public Q notificationQ; transient public ReliableSingleThread_Multi rstDistributeNewObject = new ReliableSingleThread_Multi<>(1000, __19 -> distributeNewObject_impl(__19)); transient public Set newObjectsDistributed = weakSet(); transient public BEACalculations calculations = new BEACalculations(this); transient public int newFieldsToShow = 3; transient public boolean allowAnonymousInputUpload = true; static public boolean _switchableField_maxInputLength = true; public int maxInputLength = 50000; public void init() { super.init(); botName = heading = adminName = "Gazelle BEA"; enableVars = true; showTalkToBotLink = true; phoneNumberSpecialInputField = false; } public void start() { storeBaseClassesInStructure = true; super.start(); showCRUDToEveryone = true; if (!enabled) return; rstUpdateBEAMirrors.addAll(list(BEAObject.class)); newObjectsDistributed.addAll(list(BEAObject.class)); onIndividualConceptChange_notOnAllChanged(BEAObject.class, o -> { if (enableAutoRuns) rstAutoRuns.add(o); if (enableNewBEAObjectNotis && newObjectsDistributed.add(o)) rstDistributeNewObject.add(o); }); notificationQ = dm_startQ(); dm_doEvery(30.0, new Runnable() { public void run() { try { print(new ConceptsRefChecker(db_mainConcepts()).runAndFixAll()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "print(ConceptsRefChecker(db_mainConcepts()).runAndFixAll());"; } }); } public void makeIndices() { super.makeIndices(); indexConceptFieldDesc(BEAObject.class, "_modified"); indexConceptFieldIC(BEAObject.class, "type"); indexConceptField(BEAObject.class, "input"); } public List crudClasses(Req req) { return listPlus(super.crudClasses(req), BEAObject.class); } public String authFormHeading() { return h3("Gazelle BEA"); } public void makeFramer(Req req) { super.makeFramer(req); req.framer.renderTitle = () -> h1(ahref(baseLink + "/", "Gazelle BEA") + " " + htmlEncode2(req.framer.title)); req.framer.addInHead(hjs_autoExpandingTextAreas()); } public HCRUD_Concepts crudData(Class c, Req req) { HCRUD_Concepts cc = super.crudData(c, req); if (c == BEAObject.class) { cc.humanizeFieldNames = false; cc.convertConceptValuesToRefs = true; cc.itemName = () -> "BEA Object"; cc.onCreate.add(o -> cset(o, "createdBy", currentUser())); cc.getObjectForDuplication = id -> { Map item = cc.getObjectForDuplication_base(id); item.put("creator", req.auth.user.get()); item.put("createdFrom", getConcept(toLong(id))); return item; }; cc.emptyObject = () -> { Map item = cc.emptyObject_base(); item.put("type", ""); return item; }; Set deletableRefs = litciset("Match"); cc.objectCanBeDeleted = id -> all(findBackRefs(BEAObject.class, cc.conceptForID(id)), o -> contains(deletableRefs, o.type())); cc.actuallyDeleteConcept = o -> { deleteConcepts(filter(findBackRefs(BEAObject.class, o), o2 -> contains(deletableRefs, o2.type()))); cdelete(o); }; } return cc; } public HCRUD makeCRUD(Class c, Req req, HTMLFramer1 framer) { HCRUD crud = super.makeCRUD(c, req, framer); HCRUD_Concepts data = (HCRUD_Concepts) (crud.data); crud.showOnlySelected = true; crud.showSearchField = true; if (data.customFilter == null) crud.descending = true; crud.cleanItemIDs = true; if (c == BEAObject.class) { crud.cellColumnToolTips = true; crud.unshownFields = litset("mirrorPost", "globalID"); crud.showTextFieldsAsAutoExpandingTextAreas = true; HCRUD_Concepts cc = (HCRUD_Concepts) (crud.data); String typeFilter = req.get("type"); if (nempty(typeFilter)) cc.addCIFilter("type", typeFilter); crud.renderCmds = map -> { BEAObject o = getConcept(BEAObject.class, crud.itemIDAsLong(map)); List cmds = new ArrayList(); if (nempty(o.text())) cmds.add(targetBlank(addParamsToURL(baseLink + "/query", "q", o.text(), "algorithm", "process input"), "Use text as query")); if (o.typeIs("Input")) { cmds.add(ahref(addParamsToURL(crudLink(BEAObject.class), "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"), "Run pattern against all inputs")); if (o.typeIs("Match")) cmds.add(ahref(appendParamsToURL(baseLink + "/query", "q", o.id, "algorithm", "Find rewrites for match"), "Find rewrites")); cmds.add(ahref(addParamsToURL(baseLink + "/markUseful", "redirect", beaShortURL(o), "objectID", o.id), "Mark useful")); cmds.add(ahref(addParamsToURL(crudLink(BEAObject.class), "cmd", "new", "title", "Add Comment", "f_type", "Comment", "f_on", o.id, "f_text", "", "metaInfo_on", "concept"), "Add comment")); 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") && eqic(cget("resultType", o), "string")) cmds.add(ahref(addParamsToURL(baseLink + "/convertResultToInput", "result", o.id), "Convert to input")); framer.addInHead(hjs_copyToClipboard()); cmds.add(ahref_onClick(formatFunctionCall("copyToClipboard", jsQuote(o.globalIDStr())), "Copy global ID [" + o.globalIDStr() + "]")); return joinNemptiesWithVBar(crud.renderCmds_base(map), !o.typeIsOneOf("Input", "Pattern", "Syntactic Pattern") ? null : addRewriteHTML(o), hPopDownButton(cmds)); }; cc.massageItemMapForList = (item, map) -> { BEAObject o = (BEAObject) item; if (o.typeIs("Input")) { Collection matches = objectsWhereCI(findBackRefs(o, BEAObject.class), "type", "match"); ((Map) map).put("Best Matches", new HTML(hparagraphs(lmap(__46 -> matchDescHTML(__46), takeFirst(3, matches))))); } String idField = crud.idField(); Object id = ((Map) map).get(idField); if (id instanceof String) ((Map) map).put(idField, new HTML(ahref(beaShortURL(o), id))); if (o.typeIs("Function Result")) { Object value = getOpt("result", o); ((Map) map).put("result", new HTML(javaValueToHTML(value))); } }; crud.massageFormMatrix = (map, matrix) -> { for (int i = 1; i <= newFieldsToShow; i++) { String nf = "newField" + i; String refSelector = crud.renderInput((nf + "_conceptValue"), cc.makeConceptsComboBox((nf + "_conceptValue"), BEAObject.class), null) + hjs("$(\"[name=" + nf + "_conceptValue]\").hide()"); List types = ll("String", "BEAObject", "Bool"); String typeSelector = hselect_list(types, "name", (nf + "_type"), "onchange", "\r\n var value = this.value;\r\n $(\"[name=" + nf + "_value]\").toggle(value != \"BEAObject\");\r\n $(\"#" + nf + "_refBox\").toggle(value == \"BEAObject\");\r\n "); matrix.add(ll("Add field:
" + htextfield((nf + "_name"), "title", "New field name"), htmlTable2_noHtmlEncode(ll(ll(htextfield((nf + "_value")), span(refSelector, "id", (nf + "_refBox"), "style", "display: none"), "Type", typeSelector)), "noHeader", true, "tableParams", litobjectarray("style", "width: 100%")))); } }; crud.preprocessUpdateParams = params -> { params = cloneMap(params); params = mapValues(params, v -> eq(v, "") ? null : v); for (int i = 1; i <= max(newFieldsToShow, 10); i++) { String nf = "newField" + i; String name = params.get((nf + "_name")), type = params.get((nf + "_type")), refValue = params.get((nf + "_conceptValue")), value = params.get((nf + "_value")); if (eqic(type, "BEAObject")) { value = refValue; params.put("metaInfo_" + name, "concept"); } else if (eqic(type, "Bool")) params.put("metaInfo_" + name, "bool"); if (eq(value, "")) value = null; if (nempty(name)) params.put(crud.fieldPrefix + name, value); } return params; }; } return crud; } public Object serveBotFunction(Req req, String function, Map data, User user) { if (eq(function, "beaList")) { long changedAfter = toLong(data.get("changedAfter")); double pollFor = min(bot_maxPollSeconds, toLong(data.get("pollFor"))); long startTime = sysNow(); if (changedAfter > 0 && changedAfter == now()) sleep(1); Collection objects; while (true) { objects = changedAfter == 0 ? list(BEAObject.class) : conceptsWithFieldGreaterThan_sorted(BEAObject.class, "_modified", changedAfter); if (nempty(objects) || pollFor == 0 || elapsedSeconds_sysNow(startTime) >= pollFor) return serveJSON_breakAtLevels(2, "result", map(objects, obj -> litorderedmap("gid", str(obj.globalID()), "struct", obj.structureString()))); sleep(bot_pollInterval); } } return super.serveBotFunction(req, function, data, user); } transient public ReliableSingleThread_Multi rstUpdateBEAMirrors = new ReliableSingleThread_Multi<>(100, c -> c.updateMirrorPost()); public Object serveOtherPage2(Req req) { printVars_str("serveOtherPage2", "uri", req.uri); { Object __17 = super.serveOtherPage2(req); if (__17 != null) return __17; } String uri = dropTrailingSlashIfNemptyAfterwards(req.uri); Matches m = new Matches(); if (swic_notSame(uri, "/beaCRUD/", m)) return renderBEAObjectTable(req, urldecode(m.rest())); if (eq(uri, "/inputs")) return renderBEAObjectTable(req, "input"); if (eq(uri, "/syntacticPatternsWithoutRewrites")) { HCRUD crud = makeBEAObjectCRUD(req, "Syntactic Pattern"); HCRUD_Concepts data = (HCRUD_Concepts) (crud.data); IF1 prev = data.customFilter; data.customFilter = list -> { list = filter(list, c -> empty(beaBackRefs(c, "Rewrite"))); return postProcess(prev, list); }; crud.customTitle = "Syntactic patterns without rewrites"; return serveCRUD(req, BEAObject.class, crud); } if (eq(uri, "/inputsWithoutRewrites")) { HCRUD crud = makeBEAObjectCRUD(req, "input"); HCRUD_Concepts data = (HCRUD_Concepts) (crud.data); IF1 prev = data.customFilter; data.customFilter = list -> { list = filter(list, c -> empty(beaBackRefs(c, "Rewrite"))); return postProcess(prev, list); }; crud.customTitle = "Inputs without rewrites"; return serveCRUD(req, BEAObject.class, crud); } if (eq(uri, "/inputsWithoutMatches")) { HCRUD crud = makeBEAObjectCRUD(req, "input"); HCRUD_Concepts data = (HCRUD_Concepts) (crud.data); IF1 prev = data.customFilter; data.customFilter = list -> { list = filter(list, c -> empty(beaBackRefs(c, "Match"))); return postProcess(prev, list); }; crud.customTitle = "Inputs without matches"; return serveCRUD(req, BEAObject.class, crud); } if (eq(uri, "/patterns")) return renderBEAObjectTable(req, "pattern"); if (eq(uri, "/syntacticPatterns")) return renderBEAObjectTable(req, "Syntactic Pattern"); if (eq(uri, "/matches")) return renderBEAObjectTable(req, "match"); if (eq(uri, "/rewrites")) return renderBEAObjectTable(req, "rewrite"); if (eq(uri, "/aiTasks")) return renderBEAObjectTable(req, "AI Task"); if (eq(uri, "/query")) return calculations.serveQueryPage(req); if (eq(uri, "/saveInput")) { String text = trim(req.get("text")); String info = trim(req.get("info")); if (empty(text)) return subBot_serve500("Input empty"); if (l(text) > maxInputLength) return subBot_serve500("Input too long"); BEAObject input = uniqCI(BEAObject.class, "type", "Input", "text", text, "createdBy", user(req)); if (nempty(info)) uniqCI(BEAObject.class, "type", "Input Source", "input", input, "source", info); return hrefresh(or2(req.get("redirect"), baseLink + "/")); } if (eq(uri, "/markUseful")) { BEAObject o = beaGet(req.get("objectID")); if (o == null) return subBot_serve500("Object not found"); uniqCI(BEAObject.class, "type", "Useful", "object", o, "createdBy", user(req)); return hrefresh(or2(req.get("redirect"), baseLink + "/")); } if (eq(uri, "/saveAnswer")) { String text = trim(req.get("text")); String rewriteType = or2(trim(req.get("rewriteType")), "Suggested Answer"); long inputID = toLong(req.get("inputID")); BEAObject input = beaGet(inputID); if (input == null) return subBot_serve500("Input not found"); if (empty(text)) return subBot_serve500("Text empty"); if (l(text) > maxInputLength) return subBot_serve500("Text too long"); uniqCI(BEAObject.class, "type", "Rewrite", "text", text, "isRewriteOf", input, "rewriteType", rewriteType, "createdBy", user(req)); return hrefresh(or2(req.get("redirect"), baseLink + "/")); } if (!inMasterMode(req)) return null; if (eq(uri, "/uploadInputs")) return serveUploadTexts(req, "Input"); if (eq(uri, "/uploadPatterns")) return serveUploadTexts(req, "Pattern"); if (eq(uri, "/analyzeInput")) return calculations.serveAnalyzeInput(req); if (eq(uri, "/allBEATypes")) { MultiSet ms = asCIMultiSet(collect("type", list(BEAObject.class))); return h2_title("All BEA object types") + ul(mapPairs(multiSetToPairsByPopularity(ms), (type, count) -> { String _type = or2(type, "(no type)"); return count + " " + ahref(baseLink + "/beaCRUD/" + urlencode(_type), htmlEncode2(_type)); })); } if (eq(uri, "/storeMatch")) { BEAObject pattern = beaGet(req.get("pattern")); BEAObject input = beaGet(req.get("input")); String label = req.get("label"); BEAObject match = calculations.reactInputWithPattern(input, pattern); if (match == null) return "Couldn't match"; cset(match, "label", label); return hrefresh(or2(req.get("redirect"), beaObjectURL(match))); } if (eq(uri, "/saveSyntacticPattern")) { String text = req.get("text"); BEAObject fromInput = beaGet(req.get("fromInput")); BEAObject pat = uniqCI(BEAObject.class, "type", "Syntactic Pattern", "text", text, "createdBy", user(req)); csetIfUnset(pat, "fromInput", fromInput); if (fromInput != null) calculations.reactInputWithPattern(fromInput, pat); return hrefresh(or2(req.get("redirect"), baseLink + "/")); } if (eq(uri, "/runInstruction")) { BEAObject o = beaGet(req.get("instruction")); runInstruction(o); return hrefresh(beaObjectURL(o)); } if (eq(uri, "/convertResultToInput")) { BEAObject result = beaGet(req.get("result")); if (result == null) return subBot_serve500("Object not found"); String text = unquote(getString("result", result)); if (l(text) > maxInputLength) return subBot_serve500("Input too long"); BEAObject input = uniqCI(BEAObject.class, "type", "Input", "text", text); uniqCI(BEAObject.class, "type", "Input Source", "input", input, "source", result); return hrefresh(beaShortURL(input)); } return null; } public HCRUD makeBEAObjectCRUD(Req req, String type) { HCRUD crud = makeCRUD(BEAObject.class, req); crud.baseLink = req.uri(); HCRUD_Concepts data = (HCRUD_Concepts) (crud.data); data.itemName = () -> firstToUpper(type); data.addCIFilter("type", eqic(type, "(no type)") ? null : type); if (eqicOneOf(type, "Input", "Pattern", "AI Task")) { IF0> prev = data.emptyObject; data.emptyObject = () -> { Map item = data.emptyObject_fallback(prev); item.put("text", ""); return item; }; } return crud; } public Object renderBEAObjectTable(Req req, String type) { HCRUD crud = makeBEAObjectCRUD(req, type); return serveCRUD(req, BEAObject.class, crud); } public Object serveUploadTexts(Req req, String type) { String inputs = req.get("text"); List output = new ArrayList(); if (nempty(inputs)) { for (String text : tlft(inputs)) { Pair p = uniqCI2_sync(BEAObject.class, "type", type, "text", text); if (cget("uploadedBy", p.a) == null) cset(p.a, "uploadedBy", req.auth.user); output.add(type + " " + (p.b ? "added" : "exists") + " (ID " + p.a.id + "): " + text); } } return h2("Upload " + plural(type)) + hpostform(p(plural(type) + " (one per line):") + p(htextarea(inputs, "name", "text")) + pIfNempty(htmlEncode_nlToBR(lines(output))) + hsubmit("Upload " + plural(type))); } public Collection beaObjectsOfType(String type) { return conceptsWhereCI(BEAObject.class, "type", type); } public void reactAllInputsWithSomePatterns() { calculations.reactAllInputsWithSomePatterns(); } public String navDiv() { HCRUD crud = makeCRUD(BEAObject.class, currentReq.get()); int inputsWithoutRewrites = countPred(beaList("Input"), c -> empty(beaBackRefs(c, "Rewrite"))); int inputsWithoutMatches = countPred(beaList("Input"), c -> empty(beaBackRefs(c, "Match"))); int syntacticPatternsWithoutRewrites = countPred(beaList("Syntactic Pattern"), c -> empty(beaBackRefs(c, "Rewrite"))); return joinNemptiesWithVBar(beaNavLink("Input", crud), beaNavLink("Pattern", crud), beaNavLink("Syntactic Pattern", crud), ahref(baseLink + "/syntacticPatternsWithoutRewrites", n2(syntacticPatternsWithoutRewrites) + " Syntactic patterns w/o rewrites"), beaNavLink("Match", crud), beaNavLink("Rewrite", crud), beaNavLink("AI Task", crud), ahref(baseLink + "/query", "Query"), ahref(baseLink + "/inputsWithoutMatches", n2(inputsWithoutMatches) + " Inputs w/o matches"), ahref(baseLink + "/inputsWithoutRewrites", n2(inputsWithoutRewrites) + " Inputs w/o rewrites"), hPopDownButtonWithText("Bot Forum", navLinks("flat", true, "withStats", false)), hPopDownButton(ahref(baseLink + "/allBEATypes", "All object types"), ahref(baseLink + "/stats", "Stats"), !inMasterMode(currentReq.get()) ? null : ahref(baseLink + "/refchecker", "Reference checker"))); } public String beaNavLink(String type, HCRUD crud) { return beaNavLink(type, crud, beaCount(type)); } public String beaNavLink(String type, HCRUD crud, int count) { String plural = firstToLower(plural(type)); String link = baseLink + "/" + camelCase(plural); return ahref(link, count + " " + firstToUpper(plural)) + (!crud.actuallyAllowCreate() ? "" : " " + ahref(addParamToURL(link, "cmd", "new"), "+")); } public String beaObjectURL(BEAObject o) { return conceptLink(o, currentReq.get()); } public String matchDescHTML(BEAObject m) { try { BEAObject pat = cget("pattern", m); Map mapping = (Map) (cget("mapping", m)); return ahref_undecorated(crudLink(m), htmlEncode2(quote(getString("text", pat))) + "
  with " + renderEqualsCommaProperties(mapping)); } catch (Throwable __e) { _handleException(__e); } return htmlEncode2(str(m)); } public int beaCount(String type) { return countConceptsWhereCI(BEAObject.class, "type", type); } public Collection beaList(String type) { return conceptsWhereCI(BEAObject.class, "type", type); } public Collection beaListAny(String... types) { return concatLists(lmap(__47 -> beaList(__47), litciset(types))); } public BEAObject beaGet(long id) { return getConceptOpt(BEAObject.class, id); } public BEAObject beaGet(String id) { return beaGet(parseFirstLong(id)); } public BEAObject cgetBEA(String field, BEAObject o) { return (BEAObject) cget(field, o); } public String beaLinkHTML(BEAObject o) { return o == null ? null : ahref(conceptLink(o), htmlEncode2_nlToBr(str(o))); } public String beaToHTML(BEAObject o) { return beaLinkHTML(o); } public String beaHTML(BEAObject o) { return beaLinkHTML(o); } public String beaShortURL(BEAObject o) { return o == null ? null : baseLink + "/" + o.id; } public Collection beaBackRefs(BEAObject o, String type) { return objectsWhereCI(findBackRefs(BEAObject.class, o), "type", type); } public Object serveDefaultPage(Req req) { HTMLFramer1 framer = req.framer; framer.add(hcenter3(hsnippetimg_scaleToWidth(200, "#1102967", 200, 110, "title", "Gazelle"), "style", "margin-top: 100px")); return completeFrame(req); } public String html_loggedIn() { User user = user(currentReq.get()); return user == null ? ahref(baseLink + "/", "Log in") : "Logged in as " + htmlEncode2(user.name); } public void distributeNewObject_impl(BEAObject o) { if (o.typeIs("Match")) return; distributeNotification("New object: " + o); } public void performAutoRuns(BEAObject o) { print("performAutoRuns", o); for (BEAObject autoRun : beaList("Auto Run")) { if (!isTrue(getOpt("enabled", autoRun))) { print("Not enabled: " + autoRun); continue; } String type = getString("onChangedObjectOfType", autoRun); if (!o.typeIs(type)) { print("Wrong type: " + type); continue; } print("Running " + autoRun); BEAObject procedure = (BEAObject) (cget("procedure", autoRun)); String internalCode = getString("internalCode", procedure); print("internalCode", internalCode); if (eqic(internalCode, "convertInputToPattern")) { String text = o.text(); if (!containsAngleBracketVars(text)) { print("No angle bracket vars"); continue; } BEAObject p = uniqCI_returnIfNew(BEAObject.class, "type", "Pattern", "text", text); cset(p, "fromInput", o, "byProcedure", procedure, "byAutoRun", autoRun); print("p", p); } else if (eqic(internalCode, "makeSyntacticPattern")) { print("sp", calculations.makeSyntacticPattern(o)); } else print("Unknown internal code"); } } public BEAObject findInput(String text) { return conceptWhereIC(BEAObject.class, "type", "Input", "text", text); } public String addRewriteHTML(BEAObject o) { return ahref(addParamsToURL(crudLink(BEAObject.class), "cmd", "new", "title", "Add Rewrite", "f_type", "Rewrite", "f_text", getStringOpt("text", o), "f_isRewriteOf", o.id, "metaInfo_isRewriteOf", "concept"), "Add Rewrite"); } public Object serveIntegerLink(Req req, long id) { BEAObject o = getConceptOpt(BEAObject.class, id); if (o != null) return htitle(str(o)) + hrefresh(conceptLink(o)); return super.serveIntegerLink(req, id); } public void distributeTestNotification() { distributeNotification("It is " + localTimeWithSeconds()); } public void distributeNotification(String text) { notificationQ.add(new Runnable() { public void run() { try { for (Pair p : syncMapToPairs(webSockets)) { String jsCode = "window.createNotification({ theme: 'success', showDuration: 3000 })(" + jsonEncodeMap("message", text) + ");"; call(p.a, "send", jsonEncodeMap("eval", jsCode)); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "/*for (User user)\r\n if (nemptyAfterTrim(user.notificationSetting))\r\n ..."; } }); } public void runInstruction(BEAObject o) { if (o == null) return; try { BEAObject instruction = o; if (o.typeIs("Step in script")) instruction = (BEAObject) cget(o, "instruction"); if (instruction.typeIs("Instruction | List objects by type")) { saveInstructionResult(o, beaList(getString("typeToList", instruction))); return; } if (instruction.typeIs("Instruction | List object types")) { saveInstructionResult(o, distinctCIFieldValuesOfConcepts(BEAObject.class, "type")); return; } if (instruction.typeIs("Instruction | Filter list by text starting with")) { BEAObject scriptRun = cgetBEA("scriptRun", o); if (scriptRun == null) throw fail("Need to be run as part of script"); List steps = scriptRunSteps(scriptRun); int idx = indexOf(steps, o); if (idx < 0) throw fail("Step not found in script run"); List list = firstNotNull(map(reversed(takeFirst(steps, idx)), step -> optCast(List.class, cget("data", cgetBEA("result", step))))); String prefix = getString("prefix", instruction); List filtered = filter(list, obj -> swic(obj.text(), prefix)); saveInstructionResult(o, filtered); return; } if (instruction.typeIs("Script")) { BEAObject script = instruction; BEAObject scriptRun = cnew(BEAObject.class, "type", "Script Run", "script", script); int i = 0; List steps = new ArrayList(); while ((instruction = (BEAObject) cget(instruction, "step" + (++i))) != null) { BEAObject step = cnew(BEAObject.class, "type", "Step in script", "step", i, "scriptRun", scriptRun, "instruction", instruction); steps.add(step); } cset(scriptRun, "steps", steps); return; } cnew(BEAObject.class, "type", "Instruction Error", "instruction", o, "error", "Unknown instruction type"); } catch (Throwable e) { cnew(BEAObject.class, "type", "Instruction Error", "instruction", o, "error", getStackTrace(e)); } } public BEAObject saveInstructionResult(BEAObject instruction, Object data) { BEAObject result = cnew(BEAObject.class, "type", "Instruction Result", "instruction", instruction, "data", data); cset(instruction, "result", result); return result; } public List scriptRunSteps(BEAObject scriptRun) { return (List) cget("steps", scriptRun); } } static public boolean _moduleClass_GazelleBEA = true; static public class BEAObject extends ConceptWithGlobalID { public Ref mirrorPost = new Ref(); public void change() { super.change(); ((GazelleBEA) botMod()).rstUpdateBEAMirrors.add(this); } public void delete() { cdelete(mirrorPost.get()); super.delete(); } public void updateMirrorPost() { GazelleBEA mod = (GazelleBEA) (botMod()); if (isDeleted() || !mod.mirrorBEAObjects) return; if (!mirrorPost.has()) cset(this, "mirrorPost", cnew(UserPost.class, "type", "BEA Object", "creator", mod.internalUser(), "botInfo", "BEA Mirror Bot")); String text = structureString(); cset(mirrorPost.get(), "title", str(this), "text", text); } public String structureString() { String text = "Error"; try { structure_Data data = new structure_Data() { public structure_ClassInfo newClass(Class c) { structure_ClassInfo info = super.newClass(c); if (c == Concept.Ref.class) { info.special = true; info.serializeObject = o -> { Concept cc = (Concept) (deref((Concept.Ref) o)); if (cc instanceof BEAObject) append("CRef(gid=" + quote(((BEAObject) cc).globalID()) + ")", 6); else if (cc != null) append("CRef(id=" + cc.id + ")", 6); else append("CRef", 1); }; } return info; } public void setFields(structure_ClassInfo info, List fields) { if (isSubclassOf(info.c, BEAObject.class)) { removeAll(fields, getField(BEAObject.class, "refs"), getField(BEAObject.class, "backRefs")); } super.setFields(info, fields); } }; String struct = structure(this, data); struct = dropLoadableUtilsPackageFromStruct(struct); text = indentStructureString_firstLevels(1, struct); } catch (Throwable __e) { _handleException(__e); } return text; } public String toString() { String type = strOrNull(cget("type", this)); String s = super.toString(); if (nempty(type)) { s = type + " " + id; if (eqic(type, "Match")) s += appendBracketed(strOrNull(getOpt("label", this))) + " " + getOpt("mapping", this) + appendBracketed(getOpt("input", this) + " + " + getOpt("pattern", this)); } boolean enabled = eq(true, getOpt("enabled", this)); if (enabled) s += " [enabled]"; String text = or2(text(), getStringOpt("name", this)); if (text != null) s += " " + quote(text); Object fc = getOpt("functionCalled", this); if (fc != null) s += " " + fc; return s; } public String type() { return getStringOpt("type", this); } public boolean typeIs(String type) { return eqic(type(), type); } public boolean typeIsOneOf(String... types) { return eqicOneOf(type(), types); } public String text() { return getStringOpt("text", this); } } static public String programID; static public void _onLoad_initUtils() { utils.__javax = javax(); } static public void _onLoad_defaultClassFinder() { setDefaultClassFinder(new F1() { public Class get(String name) { Class c = findClass_fullName(name); if (c != null) return c; if (name.startsWith("main$")) return loadableUtils.utils.findClass_fullName("loadableUtils.utils" + name.substring(4)); return null; } }); } static public ThreadLocal dynamicObjectIsLoading_threadLocal() { return DynamicObject_loading; } static volatile public Concepts mainConcepts; static public Concepts db_mainConcepts() { if (mainConcepts == null) mainConcepts = newConceptsWithClassFinder(getDBProgramID()); return mainConcepts; } static public void cleanMeUp_concepts() { if (db_mainConcepts() != null) db_mainConcepts().cleanMeUp(); } static public void stepAllWithTimeout(double timeout, Steppable s) { if (s == null) return; long endTime = sysNow() + toMS(timeout); do { ping(); } while (s.step() && sysNow() < endTime); } static public
int countConceptsWhereIC(Concepts cc, Class c, Object... params) { return countConceptsCI(cc, c, params); } static public int countConceptsWhereIC(Class c, Object... params) { return countConceptsCI(c, params); } static public Iterator iterator(Iterable c) { return c == null ? emptyIterator() : c.iterator(); } static public List sortByConceptID(Collection l) { return sortConceptsByID(l); } static public List conceptsWhereIC(Class c, Object... params) { return conceptsWhereIC(db_mainConcepts(), c, params); } static public List conceptsWhereIC(String c, Object... params) { return conceptsWhereIC(db_mainConcepts(), c, params); } static public List conceptsWhereIC(Concepts concepts, Class c, Object... params) { params = expandParams(c, params); return filterConceptsIC(concepts.list(c), params); } static public List conceptsWhereIC(Concepts concepts, String c, Object... params) { return filterConceptsIC(concepts.list(c), params); } static public String getString(Map map, Object key) { return map == null ? null : (String) map.get(key); } static public String getString(List l, int idx) { return (String) get(l, idx); } static public String getString(Object o, Object key) { if (o instanceof Map) return getString((Map) o, key); if (key instanceof String) return (String) getOpt(o, (String) key); throw fail("Not a string key: " + getClassName(key)); } static public String getString(String key, Object o) { return getString(o, (Object) key); } static public boolean isTrue_getOpt(String field, Object o) { return isTrue(getOpt(field, o)); } static public boolean eqic_gen(Object a, Object b) { return a instanceof String && b instanceof String && eqic((String) a, (String) b); } static public boolean phraseCache(String pattern, String s) { return mmo2_match(pattern, s); } static public boolean phraseCache(MMOPattern pattern, String s) { return mmo2_match(pattern, s); } static public IF1 phraseCache(String pattern) { return phraseCache(mmo2_parsePattern(pattern)); } static public IF1 phraseCache(MMOPattern pattern) { return s -> phraseCache(pattern, s); } static public HashMap litmap(Object... x) { HashMap map = new HashMap(); litmap_impl(map, x); return map; } static public void litmap_impl(Map map, Object... x) { if (x != null) for (int i = 0; i < x.length - 1; i += 2) if (x[i + 1] != null) map.put(x[i], x[i + 1]); } static public String starsToAngleBracketedNumbers(String s) { List tok = javaTokWithAngleBrackets(s); int count = 0; for (int idx : indicesOf(tok, "*")) tok.set(idx, angleBracketed(str(++count))); return join(tok); } static public Map flexMatchAngleBracketVarsIC_honorPunctuation_first(String pat, String input) { return grabValueAndCancel(new VF1>>() { public void get(VF1> onMatch) { try { flexMatchAngleBracketVarsIC_honorPunctuation_iterate(pat, input, onMatch); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "flexMatchAngleBracketVarsIC_honorPunctuation_iterate(pat, input, onMatch);"; } }); } static public Map flexMatchAngleBracketVarsIC_first(String pat, String input) { return grabValueAndCancel(new VF1>>() { public void get(VF1> onMatch) { try { flexMatchAngleBracketVarsIC_iterate(pat, input, onMatch); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "flexMatchAngleBracketVarsIC_iterate(pat, input, onMatch);"; } }); } static public Concept cnew(String name, Object... values) { return cnew(db_mainConcepts(), name, values); } static public Concept cnew(Concepts concepts, String name, Object... values) { Class cc = findClass(name); concepts_unlisted.set(true); Concept c; try { c = cc != null ? nuObject(cc) : new Concept(name); } finally { concepts_unlisted.set(null); } concepts.register(c); csetAll(c, values); return c; } static public A cnew(Class cc, Object... values) { return cnew(db_mainConcepts(), cc, values); } static public A cnew(Concepts concepts, Class cc, Object... values) { concepts_unlisted.set(true); A c; try { c = nuObject(cc); } finally { concepts_unlisted.set(null); } concepts.register(c); csetAll(c, values); return c; } static public Concept getConcept(long id) { return db_mainConcepts().getConcept(id); } static public Concept getConcept(Concepts concepts, long id) { return concepts.getConcept(id); } static public A getConcept(Class cc, long id) { return getConcept(db_mainConcepts(), cc, id); } static public A getConcept(Concepts concepts, Class cc, long id) { Concept c = concepts.getConcept(id); if (c == null) return null; if (!isInstance(cc, c)) throw fail("Can't convert concept: " + getClassName(c) + " -> " + getClassName(cc) + " (" + id + ")"); return (A) c; } static public long parseLong(String s) { if (empty(s)) return 0; return Long.parseLong(dropSuffix("L", s)); } static public long parseLong(Object s) { return Long.parseLong((String) s); } static public String h1_title(String s) { return htitle_h1(s); } static public String p(Object contents, Object... params) { return hfulltag("p", contents, params) + "\n"; } static public String b(Object contents, Object... params) { return tag("b", contents, params); } static public String htmlEncode(String s) { return htmlencode(s); } static public boolean empty(Collection c) { return c == null || c.isEmpty(); } static public boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); } static public boolean empty(CharSequence s) { return s == null || s.length() == 0; } static public boolean empty(Map map) { return map == null || map.isEmpty(); } static public boolean empty(Object[] o) { return o == null || o.length == 0; } static public boolean empty(Object o) { if (o instanceof Collection) return empty((Collection) o); if (o instanceof String) return empty((String) o); if (o instanceof Map) return empty((Map) o); if (o instanceof Object[]) return empty((Object[]) o); if (o instanceof byte[]) return empty((byte[]) o); if (o == null) return true; throw fail("unknown type for 'empty': " + getType(o)); } static public boolean empty(Iterator i) { return i == null || !i.hasNext(); } static public boolean empty(double[] a) { return a == null || a.length == 0; } static public boolean empty(float[] a) { return a == null || a.length == 0; } static public boolean empty(int[] a) { return a == null || a.length == 0; } static public boolean empty(long[] a) { return a == null || a.length == 0; } static public boolean empty(byte[] a) { return a == null || a.length == 0; } static public boolean empty(short[] a) { return a == null || a.length == 0; } static public boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); } static public boolean empty(MultiMap mm) { return mm == null || mm.isEmpty(); } static public boolean empty(File f) { return getFileSize(f) == 0; } static public boolean empty(IntRange r) { return r == null || r.empty(); } static public boolean empty(Chain c) { return c == null; } static public String ul_htmlEncode(String... list) { return ul_htmlEncode(asList(list)); } static public String ul_htmlEncode(Collection list, Object... params) { return ul(map("htmlEncode2", allToString(list)), params); } static public boolean eq(Object a, Object b) { return a == b || a != null && b != null && a.equals(b); } static public boolean eqic(String a, String b) { if ((a == null) != (b == null)) return false; if (a == null) return true; return a.equalsIgnoreCase(b); } static public boolean eqic(char a, char b) { if (a == b) return true; char u1 = Character.toUpperCase(a); char u2 = Character.toUpperCase(b); if (u1 == u2) return true; return Character.toLowerCase(u1) == Character.toLowerCase(u2); } static public LinkedHashMap litorderedmap(Object... x) { LinkedHashMap map = new LinkedHashMap(); litmap_impl(map, x); return map; } static public String jsonEncode(Object o) { StringBuilder buf = new StringBuilder(); jsonEncode(o, buf); return str(buf); } static public void jsonEncode(Object o, StringBuilder buf) { if (o == null) buf.append("null"); else if (o instanceof String) buf.append(quote((String) o)); else if (o instanceof Number || o instanceof Boolean) buf.append(o); else if (o instanceof Map) { Map map = (Map) o; buf.append("{"); boolean first = true; for (Object key : keys(map)) { if (first) first = false; else buf.append(","); buf.append(quote((String) key)); buf.append(":"); jsonEncode(map.get(key), buf); } buf.append("}"); } else if (o instanceof Collection) { Collection l = (Collection) o; buf.append("["); boolean first = true; for (Object element : l) { if (first) first = false; else buf.append(","); jsonEncode(element, buf); } buf.append("]"); } else throw fail("Unknown object for JSON encoding: " + className(o)); } static public String htitle_h2(String s) { return htitle_noEncode(dropTags(s)) + h2(s); } static public String ahref(String link, Object contents, Object... params) { return link == null ? str(contents) : href(link, contents, params); } static public String hscript(String script) { return hjavascript(script); } static public String replaceVars(String s, Map map) { return empty(map) ? s : join(replaceVars(javaTok(s), map)); } static public List replaceVars(List tok, Map map) { if (empty(map)) return tok; tok = cloneList(tok); for (Map.Entry __0 : _entrySet(map)) { String var = __0.getKey(); Object val = __0.getValue(); jreplace(tok, var, str(val)); } return tok; } static public String replaceVars(String s, Object... params) { return replaceVars(s, paramsToMap(params)); } static public String hform(Object contents, Object... params) { return htag("form", contents, params); } static public String htextarea(String text, Object... params) { params = html_massageAutofocusParam(params); return hopeningTag("textarea", params) + htmlencode2(text) + ""; } static public String hjs(String script) { return hjavascript(script); } static public String hselect_list(Collection entries, Object... params) { StringBuilder buf = new StringBuilder(); String selected = null; if (odd(l(params))) { selected = str(first(params)); params = dropFirst(params); } int i = indexOf(params, "allowEmpty"); if (even(i)) { buf.append("\n"); params[i] = params[i + 1] = null; } if (nempty(entries)) for (String k : entries) { String value = k; boolean isSelected = eq(selected, k); buf.append(hfulltag("option", htmlencode(str(or(value, ""))), "value", k, "selected", isSelected ? html_valueLessParam() : null)).append("\n"); } return tag("select", buf, params) + "\n"; } static public Set keys(Map map) { return map == null ? new HashSet() : map.keySet(); } static public Set keys(Object map) { return keys((Map) map); } static public Set keys(MultiSet ms) { return ms.keySet(); } static public Set keys(MultiMap mm) { return mm.keySet(); } static public Set keys(MultiSetMap mm) { return mm.keySet(); } static public String hbutton(String text, Object... params) { return hfulltag("button", text, params); } static public String hhtml(Object contents) { return containerTag("html", contents); } static public String hhead(Object contents) { return tag("head", contents); } static public String hmobilefix() { return ""; } static public String hmobilefix(String html) { return hAddToHead(html, hmobilefix()); } static public String hsansserif() { return hcss("body { font-family: Sans-Serif; }"); } static public String loadJQuery2() { return ""; } static public String hjs_autoExpandingTextAreas() { return hcss("\r\n textarea.auto-expand {\r\n max-height: 10em; vertical-align: top;\r\n }\r\n ") + hjs("\r\n var autoExpandTextArea = function (field) {\r\n field.style.height = \"1px\";\r\n \r\n // Get the computed styles for the element\r\n var computed = window.getComputedStyle(field);\r\n \r\n var h = field.scrollHeight\r\n + parseInt(computed.getPropertyValue('border-top-width'))\r\n + parseInt(computed.getPropertyValue('border-bottom-width'));\r\n \r\n field.style.height = h + 'px';\r\n };\r\n \r\n document.addEventListener('input', function (event) {\r\n if (event.target.tagName.toLowerCase() !== 'textarea') return;\r\n if (!event.target.classList.contains(\"auto-expand\")) return;\r\n autoExpandTextArea(event.target);\r\n }, false);\r\n \r\n $(document).ready(function() {\r\n $(\"textarea.auto-expand\").each(function() { autoExpandTextArea(this); });\r\n });\r\n "); } static public String hNotificationPopups() { return hStylesheetSnippet_maxCache("#1029723") + hjssnippet_maxCache("#1029726") + hjs("\r\n function successNotification(text) {\r\n window.createNotification({ theme: 'success', showDuration: 3000 })({ message: text });\r\n }\r\n \r\n function errorNotification(text) {\r\n window.createNotification({ theme: 'error', showDuration: 3000 })({ message: text });\r\n }\r\n "); } static public String hbody(Object contents, Object... params) { return tag("body", contents, params); } static public String div_alignRight(Object contents, Object... params) { return div(contents, params_stylePlus(params, "text-align: right")); } static public String div_center(Object contents, Object... __) { return hcenter3(contents, __); } static public String htitledSectionWithDiv(String title, Object contents, Object... params) { String backgroundColor = "#fff"; String labelStyle = "width: auto; float: top; position: relative; top: -.6em; left:15px; background-color: " + backgroundColor; String innerDivStyle = stringPar("innerDivStyle", params); params = dropParam("innerDivStyle", params); return div(htag("label", b(" " + title + " "), "style", labelStyle) + div(contents, "style", joinNemptiesWithSemicolon(innerDivStyle, "padding-left: 15px"), "class", "sectionContents"), params_stylePlus("border: 2px solid", params)); } static public String h3(String s, Object... params) { return tag("h3", s, params) + "\n"; } static public List lookupPossiblyCI(MultiMap map, String key) { return lookupPossiblyIgnoreCase(map, key); } static public A lookupPossiblyCI(Map map, String key) { return lookupPossiblyIgnoreCase(map, key); } static public boolean isB(Either e) { return eitherIsB(e); } static public Set evalWithTimeout_inTime = synchroSet(); static public Set evalWithTimeout_allThreads = newWeakHashSet(); static public ThreadLocal evalWithTimeout_threadName = new ThreadLocal(); static public Either evalWithTimeout(int timeoutMS, final Object r) { final Flag done = new Flag(); final Flag doneWaiting = new Flag(); final Var var = new Var(); final Var error = new Var(); Thread t = newThread(getAndClearThreadLocal(evalWithTimeout_threadName), new Runnable() { public void run() { try { try { try { var.set(callF(r)); } finally { evalWithTimeout_allThreads.remove(currentThread()); } } catch (Throwable e) { error.set(e); if (doneWaiting.isUp()) printStackTrace(e); } finally { done.raise(); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "try {\r\n try {\r\n var.set(callF(r));\r\n } finally {\r\n ev..."; } }); beforeDelegatingToThread(t); try { startThread(t); evalWithTimeout_inTime.add(t); evalWithTimeout_allThreads.add(t); try { done.waitUntilUp(timeoutMS); doneWaiting.raise(); } finally { evalWithTimeout_inTime.remove(t); } if (!done.isUp()) { print("Cancelling thread (timeout)"); cancelAndInterruptThread(t); return either2(t); } if (error.get() != null) rethrow(error.get()); return either1(var.get()); } finally { afterDelegatingToThread(t); } } static public Either evalWithTimeout(double timeoutSeconds, final Object r) { return evalWithTimeout(toMS_int(timeoutSeconds), r); } static public AutoCloseable tempSetTL(ThreadLocal tl, A a) { return tempSetThreadLocal(tl, a); } static public void _close(AutoCloseable c) { if (c != null) try { c.close(); } catch (Throwable e) { if (c instanceof javax.imageio.stream.ImageOutputStream) return; else throw rethrow(e); } } static public String str(Object o) { return o == null ? "null" : o.toString(); } static public String str(char[] c) { return new String(c); } static public String wrapInDiv(String html, Object... __) { String tag = getTag(firstToken(htmlTok(html))); return eqicOneOf(tag, "div", "p") ? html : div(html, __); } static public String hpre_htmlencode(Object contents, Object... params) { return pre_htmlencode(contents, params); } public static String rtrim(String s) { if (s == null) return null; int i = s.length(); while (i > 0 && " \t\r\n".indexOf(s.charAt(i - 1)) >= 0) --i; return i < s.length() ? s.substring(0, i) : s; } static public String hpostform(Object contents, Object... params) { return tag("form", contents, concatArrays(new Object[] { "method", "POST" }, params)); } static public String htmlEncode_quote(Object o) { return htmlEncode2(quote(o)); } static public String hhidden(String name, Object value, Object... params) { return tag("input", "", concatArrays(new Object[] { "type", "hidden", "name", name, "value", value }, params)); } static public String hsubmit(String text, Object... params) { return tag("input", "", concatArrays(new Object[] { "type", "submit", "value", text }, params)); } static public String hsubmit() { return hsubmit("Submit"); } static public String hinputfield(String name, Object... params) { return htextinput(name, params); } static public String js_setRedirect() { return "$('input[name=redirect]').val(window.location.toString());"; } static public Pair uniqCI2(Class c, Object... params) { return uniqCI2(db_mainConcepts(), c, params); } static public Pair uniqCI2(Concepts cc, Class c, Object... params) { params = expandParams(c, params); A x = findConceptWhereCI(cc, c, params); if (x == null) { x = unlisted(c); csetAll(x, params); cc.register(x); return pair(x, true); } return pair(x, false); } static public void csetIfUnset(Concept c, String field, Object value) { if (cget(c, field) == null) cset(c, field, value); } static public boolean nempty(Collection c) { return !empty(c); } static public boolean nempty(CharSequence s) { return !empty(s); } static public boolean nempty(Object[] o) { return !empty(o); } static public boolean nempty(byte[] o) { return !empty(o); } static public boolean nempty(int[] o) { return !empty(o); } static public boolean nempty(Map m) { return !empty(m); } static public boolean nempty(Iterator i) { return i != null && i.hasNext(); } static public boolean nempty(Object o) { return !empty(o); } static public boolean nempty(IntRange r) { return !empty(r); } static public String hr() { return tag("hr"); } static public List callFAll(Collection l, Object... args) { return callF_all(l, args); } static public Class run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static public List reversed(Iterable l) { return reversedList(l); } static public List reversed(A[] l) { return reversedList(asList(l)); } static public String reversed(String s) { return reversedString(s); } static public void sleepSeconds(double s) { if (s > 0) sleep(round(s * 1000)); } static public long parseFirstLong(String s) { return parseLong(jextract("", s)); } static public int indent_default = 2; static public String indent(int indent) { return repeat(' ', indent); } static public String indent(int indent, String s) { return indent(repeat(' ', indent), s); } static public String indent(String indent, String s) { return indent + s.replace("\n", "\n" + indent); } static public String indent(String s) { return indent(indent_default, s); } static public List indent(String indent, List lines) { List l = new ArrayList(); if (lines != null) for (String s : lines) l.add(indent + s); return l; } static public String formatDoubleArrowMap_horizontallyAligned(Map map) { return formatDoubleArrowPairs_horizontallyAligned(mapToPairs(map)); } static public A cget(Object c, String field) { Object o = getOpt(c, field); if (o instanceof Concept.Ref) return (A) ((Concept.Ref) o).get(); return (A) o; } static public A cget(String field, Object c) { return cget(c, field); } static public String replaceAngleBracketVars_curly(String s, Map map) { return replaceAngleBracketVars(s, mapValues(__48 -> curly(__48), map)); } static public List replaceAngleBracketVars_curly(List tok, Map map) { return replaceAngleBracketVars(tok, mapValues(__49 -> curly(__49), map)); } static public String replaceAngleBracketVars_curly(String s, Object... params) { return replaceAngleBracketVars_curly(s, paramsToMap(params)); } static public A conceptWhereIC(Class c, Object... params) { return findConceptWhereCI(c, params); } static public Concept conceptWhereIC(String c, Object... params) { return findConceptWhereCI(db_mainConcepts(), c, params); } static public A conceptWhereIC(Concepts concepts, Class c, Object... params) { return findConceptWhereCI(concepts, c, params); } static public Concept conceptWhereIC(Concepts concepts, String c, Object... params) { return findConceptWhereCI(concepts, c, params); } static public String hinlinepostform(Object contents, Object... __) { return hpostform(contents, params_stylePlus(__, "display: inline")); } static public String hhiddenMulti(Object... params) { return mapPairsToLines(paramsToPairs(params), (k, v) -> hhidden(str(k), v)); } static public String trim(String s) { return s == null ? null : s.trim(); } static public String trim(StringBuilder buf) { return buf.toString().trim(); } static public String trim(StringBuffer buf) { return buf.toString().trim(); } static public Random random_random = new Random(); static public int random(int n) { return random(random_random, n); } static public int random(int n, Random r) { return random(r, n); } static public int random(Random r, int n) { return n <= 0 ? 0 : r.nextInt(n); } static public double random(double max) { return random() * max; } static public double random() { return random_random.nextInt(100001) / 100000.0; } static public double random(double min, double max) { return min + random() * (max - min); } static public int random(int min, int max) { return min + random(max - min); } static public int random(int min, int max, Random r) { return random(r, min, max); } static public int random(Random r, int min, int max) { return min + random(r, max - min); } static public A random(List l) { return oneOf(l); } static public A random(Collection c) { if (c instanceof List) return random((List) c); int i = random(l(c)); return collectionGet(c, i); } static public int random(IntRange r) { return random(r.start, r.end); } static public String htmlEncode2(String s) { return htmlencode_noQuotes(s); } static public MultiMap ciMultiMap() { return caseInsensitiveMultiMap(); } static public List uniquifyCI(Collection l) { TreeSet set = ciSet(); List out = new ArrayList(); for (String a : unnull(l)) if (set.add(a)) out.add(a); return out; } static public Collection values(Map map) { return map == null ? emptyList() : map.values(); } static public Collection values(Object map) { return values((Map) map); } static public Collection values(MultiMap mm) { return mm == null ? emptyList() : concatLists(values(mm.data)); } static public List concatLists(Iterable... lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) addAll(l, list); return l; } static public List concatLists(Collection> lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) addAll(l, list); return l; } static public Collection conceptsWhereCI(Class c, Object... params) { return findConceptsWhereCI(c, params); } static public Collection conceptsWhereCI(String c, Object... params) { return findConceptsWhereCI(c, params); } static public Collection conceptsWhereCI(Concepts concepts, Class c, Object... params) { return findConceptsWhereCI(concepts, c, params); } static public List conceptsWhereCI(Concepts concepts, String c, Object... params) { return findConceptsWhereCI(concepts, c, params); } static public Map mapValues(Object func, Map map) { Map m = similarEmptyMap(map); for (Object key : keys(map)) m.put(key, callF(func, map.get(key))); return m; } static public Map mapValues(Map map, IF1 f) { return mapValues(f, map); } static public Map mapValues(IF1 f, Map map) { return mapValues((Object) f, map); } static public Map mapValues(Map map, Object func) { return mapValues(func, map); } static public String uncurly(String s) { return tok_unCurlyBracket(s); } static public boolean neq(Object a, Object b) { return !eq(a, b); } static public A conceptWhereCI(Class c, Object... params) { return findConceptWhereCI(c, params); } static public Concept conceptWhereCI(String c, Object... params) { return findConceptWhereCI(db_mainConcepts(), c, params); } static public A conceptWhereCI(Concepts concepts, Class c, Object... params) { return findConceptWhereCI(concepts, c, params); } static public Concept conceptWhereCI(Concepts concepts, String c, Object... params) { return findConceptWhereCI(concepts, c, params); } static public String joinWithSpace(Iterable c) { return join(" ", c); } static public String joinWithSpace(String... c) { return join(" ", c); } static public String firstToUpper(String s) { if (empty(s)) return s; return Character.toUpperCase(s.charAt(0)) + s.substring(1); } static public String simpleSpacesTrim_javaTok(String s) { return trim(simpleSpaces_javaTok(s)); } static public String angleBracketVarsToStars(String s) { return angleBracketVarsToStars(s, null); } static public String angleBracketVarsToStars(String s, List varNames_out) { List tok = javaTokWithAngleBrackets(s); for (int idx : indicesOfAngleBracketVars(tok)) { { if (varNames_out != null) varNames_out.add(deAngleBracket(tok.get(idx))); } tok.set(idx, "*"); } return join(tok); } static volatile public StringBuffer local_log = new StringBuffer(); static volatile public Appendable print_log = local_log; static volatile public int print_log_max = 1024 * 1024; static volatile public int local_log_max = 100 * 1024; static public boolean print_silent = false; static public Object print_byThread_lock = new Object(); static volatile public ThreadLocal print_byThread; static volatile public Object print_allThreads; static volatile public Object print_preprocess; static public void print() { print(""); } static public A print(String s, A o) { print((endsWithLetterOrDigit(s) ? s + ": " : s) + o); return o; } static public A print(A o) { ping_okInCleanUp(); if (print_silent) return o; String s = o + "\n"; print_noNewLine(s); return o; } static public void print_noNewLine(String s) { try { Object f = getThreadLocal(print_byThread_dontCreate()); if (f == null) f = print_allThreads; if (f != null) if (isFalse(f instanceof F1 ? ((F1) f).get(s) : callF(f, s))) return; } catch (Throwable e) { System.out.println(getStackTrace(e)); } print_raw(s); } static public void print_raw(String s) { if (print_preprocess != null) s = (String) callF(print_preprocess, s); s = fixNewLines(s); Appendable loc = local_log; Appendable buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); System.out.print(s); vmBus_send("printed", mc(), s); } static public void print_autoRotate() { } static public A uniqCI(Class c, Object... params) { return uniqueConcept(db_mainConcepts(), c, params); } static public A uniqCI(Concepts cc, Class c, Object... params) { AutoCloseable __1 = tempDBLock(cc); try { params = expandParams(c, params); A x = findConceptWhereCI(cc, c, params); if (x == null) { x = unlisted(c); csetAll(x, params); cc.register(x); } return x; } finally { _close(__1); } } static public void tt() { typeWriterConsole(); } static public String tt(Object contents, Object... params) { return tag("tt", contents, params); } static public String targetBlank(String link, Object contents, Object... params) { return hrefBlank(link, contents, params); } static public String addParamsToURL(String url, Map params) { return appendQueryToURL(url, params); } static public String addParamsToURL(String url, Object... data) { return appendQueryToURL(url, data); } static public Long conceptIDOrNull(Concept c) { return c == null ? null : c.id; } static public String firstToLower(String s) { if (empty(s)) return s; return Character.toLowerCase(s.charAt(0)) + s.substring(1); } static public int countTokens(String s) { return l(javaTokC(s)); } static public int countTokens(List tok) { return l(tok) / 2; } static public List dropPunctuation_keep = ll("*", "<", ">"); static public List dropPunctuation(List tok) { tok = new ArrayList(tok); for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (t.length() == 1 && !Character.isLetter(t.charAt(0)) && !Character.isDigit(t.charAt(0)) && !dropPunctuation_keep.contains(t)) { tok.set(i - 1, tok.get(i - 1) + tok.get(i + 1)); tok.remove(i); tok.remove(i); i -= 2; } } return tok; } static public String dropPunctuation(String s) { return join(dropPunctuation(nlTok(s))); } static public List sortedIC(Collection l) { return sortedIgnoreCase(l); } static public Set gazelle_allSyntacticPatternsFromInput(String input) { Chain tokens = toChain(javaTokC(input)); LinkedHashSet out = new LinkedHashSet(); gazelle_allSyntacticPatternsFromInput_collect(null, tokens, out); return out; } static public void gazelle_allSyntacticPatternsFromInput_collect(ReverseChain prefix, Chain tokens, Set out) { ping(); if (empty(tokens)) { out.add(joinWithSpace(asList(prefix))); return; } gazelle_allSyntacticPatternsFromInput_collect(chainPlus(prefix, first(tokens)), dropFirst(tokens), out); if (!eq(last(prefix), "*")) { ReverseChain prefix2 = chainPlus(prefix, "*"); Chain tokens2 = tokens; while (!empty(tokens2)) { tokens2 = dropFirst(tokens2); gazelle_allSyntacticPatternsFromInput_collect(prefix2, tokens2, out); } } } static public Set> _entrySet(Map map) { return map == null ? Collections.EMPTY_SET : map.entrySet(); } static public String htmlTable2_noHtmlEncode(Object data, Object... __) { return htmlTable2(data, paramsPlus(__, "htmlEncode", false)); } static public boolean isIdentifier(String s) { return isJavaIdentifier(s); } static public boolean isSafeStandardFunction(String name) { return isCodeSafe(formatFunctionCall(name)); } static public Class loadFunction_cached(String function) { return loadFunctions_cached(function); } static public A evalWithTimeoutOrFail(int timeoutMS, F0 f) { return evalWithTimeoutOrException(timeoutMS, f); } static public A evalWithTimeoutOrFail(double timeoutSeconds, F0 f) { return evalWithTimeoutOrException(timeoutSeconds, f); } static public A evalWithTimeoutOrFail(int timeoutMS, IF0 f) { return evalWithTimeoutOrException(timeoutMS, f); } static public A evalWithTimeoutOrFail(double timeoutSeconds, IF0 f) { return evalWithTimeoutOrException(timeoutSeconds, f); } static public void evalWithTimeoutOrFail(int timeoutMS, Runnable r) { evalWithTimeoutOrException(timeoutMS, runnableToF0(r)); } static public void evalWithTimeoutOrFail(double timeoutSeconds, Runnable r) { evalWithTimeoutOrException(timeoutSeconds, runnableToF0(r)); } static public Object callF(Object f, Object... args) { try { if (f instanceof String) return callMC((String) f, args); return x30_util.callF(f, args); } catch (Exception __e) { throw rethrow(__e); } } static public A callF(F0 f) { return f == null ? null : f.get(); } static public A callF(IF0 f) { return f == null ? null : f.get(); } static public B callF(F1 f, A a) { return f == null ? null : f.get(a); } static public B callF(IF1 f, A a) { return f == null ? null : f.get(a); } static public C callF(F2 f, A a, B b) { return f == null ? null : f.get(a, b); } static public void callF(VF1 f, A a) { if (f != null) f.get(a); } static public Object callMC(String method, Object... args) { return call(mc(), method, args); } static public Object call(Object o) { return callF(o); } static public Object call(Object o, String method, Object... args) { return call_withVarargs(o, method, args); } static public boolean isStringCollection(Object o) { if (!(o instanceof Collection)) return false; Collection l = (Collection) o; for (Object x : l) if (!(x instanceof String)) return false; return true; } static public ArrayList asList(A[] a) { return a == null ? new ArrayList() : new ArrayList(Arrays.asList(a)); } static public ArrayList asList(int[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (int i : a) l.add(i); return l; } static public ArrayList asList(long[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (long i : a) l.add(i); return l; } static public ArrayList asList(float[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (float i : a) l.add(i); return l; } static public ArrayList asList(double[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (double i : a) l.add(i); return l; } static public ArrayList asList(Iterable s) { if (s instanceof ArrayList) return (ArrayList) s; ArrayList l = new ArrayList(); if (s != null) for (A a : s) l.add(a); return l; } static public ArrayList asList(Producer p) { ArrayList l = new ArrayList(); A a; if (p != null) while ((a = p.next()) != null) l.add(a); return l; } static public ArrayList asList(Enumeration e) { ArrayList l = new ArrayList(); if (e != null) while (e.hasMoreElements()) l.add(e.nextElement()); return l; } static public ArrayList asList(ReverseChain c) { return c == null ? emptyList() : c.toList(); } static public boolean isStringList(Object o) { if (!(o instanceof List)) return false; List l = (List) o; for (Object x : l) if (!(x instanceof String)) return false; return true; } static public String appendRoundBracketed(String b) { return empty(b) ? "" : "" + " (" + b + ")"; } static public String appendRoundBracketed(String a, String b) { return empty(b) ? a : a + appendRoundBracketed(b); } static public String className(Object o) { return getClassName(o); } static public int shorten_default = 100; static public String shorten(CharSequence s) { return shorten(s, shorten_default); } static public String shorten(CharSequence s, int max) { return shorten(s, max, "..."); } static public String shorten(CharSequence s, int max, String shortener) { if (s == null) return ""; if (max < 0) return str(s); return s.length() <= max ? str(s) : subCharSequence(s, 0, min(s.length(), max - l(shortener))) + shortener; } static public String shorten(int max, CharSequence s) { return shorten(s, max); } static public String getStackTrace(Throwable throwable) { lastException(throwable); return getStackTrace_noRecord(throwable); } static public String getStackTrace_noRecord(Throwable throwable) { StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer)); return hideCredentials(writer.toString()); } static public String getStackTrace() { return getStackTrace_noRecord(new Throwable()); } static volatile public PersistableThrowable _handleException_lastException; static public List _handleException_onException = synchroList(ll("printStackTrace2")); static public void _handleException(Throwable e) { _handleException_lastException = persistableThrowable(e); Throwable e2 = innerException(e); if (e2.getClass() == RuntimeException.class && eq(e2.getMessage(), "Thread cancelled.") || e2 instanceof InterruptedException) return; for (Object f : cloneList(_handleException_onException)) try { callF(f, e); } catch (Throwable e3) { try { printStackTrace2(e3); } catch (Throwable e4) { System.out.println(getStackTrace(e3)); System.out.println(getStackTrace(e4)); } } } static public long parseSecondLong(String s) { List tok = javaTokC(s); int i = 0; while (i < l(tok) && !isInteger(tok.get(i))) ++i; ++i; while (i < l(tok) && !isInteger(tok.get(i))) ++i; if (i < l(tok)) return parseLong(tok.get(i)); return 0; } static public Collection> cForwardAndBackRefsWithFieldIndicator(Concept c, Class type) { return concatLists_conservative(mapPairsB(cForwardRefsWithFieldNames(c, type), f -> new FieldIndicator(f, true)), mapPairsB(findBackRefsWithFieldNames(c, type), f -> new FieldIndicator(f, false))); } static public Collection> cForwardAndBackRefsWithFieldIndicator(Class type, Concept c) { return cForwardAndBackRefsWithFieldIndicator(c, type); } static public String ol(String... list) { return ol(asList(list)); } static public String ol(List list, Object... params) { StringBuilder buf = new StringBuilder(); int i = indexOf(params, null); if (i == -1) i = l(params); for (String s : withoutNulls(list)) buf.append(tag("li", s, subArray(params, i + 1))).append("\n"); return containerTag("ol", buf, subArray(params, 0, i)) + "\n"; } static public List map(Iterable l, Object f) { return map(f, l); } static public List map(Object f, Iterable l) { List x = emptyList(l); if (l != null) for (Object o : l) x.add(callF(f, o)); return x; } static public List map(Iterable l, F1 f) { return map(f, l); } static public List map(F1 f, Iterable l) { List x = emptyList(l); if (l != null) for (A o : l) x.add(callF(f, o)); return x; } static public List map(IF1 f, Iterable l) { return map(l, f); } static public List map(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) x.add(f.get(o)); return x; } static public List map(IF1 f, A[] l) { return map(l, f); } static public List map(A[] l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) x.add(f.get(o)); return x; } static public List map(Object f, Object[] l) { return map(f, asList(l)); } static public List map(Object[] l, Object f) { return map(f, l); } static public List map(Object f, Map map) { return map(map, f); } static public List map(Map map, Object f) { List x = new ArrayList(); if (map != null) for (Object _e : map.entrySet()) { Map.Entry e = (Map.Entry) _e; x.add(callF(f, e.getKey(), e.getValue())); } return x; } static public List map(Map map, IF2 f) { return map(map, (Object) f); } static public A ifThenElse(boolean b, A trueValue, A falseValue) { return b ? trueValue : falseValue; } static public String joinNemptiesWithSpace(String... strings) { return joinNempties(" ", strings); } static public String joinNemptiesWithSpace(Collection strings) { return joinNempties(" ", strings); } static public String strOrEmpty(Object o) { return o == null ? "" : str(o); } static public int countWordsWithoutAngleBracketedAndStars(String s) { int n = 0; for (String t : javaTokWithAllPlusAngleBracketsC(s)) if (!isAngleBracketed(t) && !eq(t, "*")) ++n; return n; } static public List sortedByCalculatedFieldDesc(Collection c, final Object f) { return sortByCalculatedFieldDesc(c, f); } static public List sortedByCalculatedFieldDesc(Object f, Collection c) { return sortByCalculatedFieldDesc(f, c); } static public List sortedByCalculatedFieldDesc(Iterable c, IF1 f) { return sortByCalculatedFieldDesc(c, f); } static public List sortedByCalculatedFieldDesc(IF1 f, Iterable c) { return sortByCalculatedFieldDesc(f, c); } static public boolean match3_withIntsAndIDs(String pat, String s) { return match3_withIntsAndIDs(pat, s, null); } static public boolean match3_withIntsAndIDs(String pat, String s, Matches m) { List tokPat = javaTokWithAllPlusAngleBrackets(pat); String pat2 = joinMap(tokPat, t -> eqOneOf(t, "", "") ? "*" : t); Matches m2 = m == null ? new Matches() : m; if (!match3(pat2, s, m2)) return false; List vars = filter(codeTokens(tokPat), t -> eqOneOf(t, "", "", "*")); for (int i = 0; i < l(vars); i++) { if (eq(vars.get(i), "") && !isInteger(m2.get(i)) || eq(vars.get(i), "") && !isIdentifier(m2.get(i))) return false; } return true; } static public List instancesOf(Iterable i, Class c) { return collectInstances(i, c); } static public List instancesOf(Class c, Iterable i) { return collectInstances(c, i); } static public List ll(A... a) { ArrayList l = new ArrayList(a.length); if (a != null) for (A x : a) l.add(x); return l; } static public String shortClassName(Object o) { if (o == null) return null; Class c = o instanceof Class ? (Class) o : o.getClass(); String name = c.getName(); return shortenClassName(name); } static public int boostHashCombine(int a, int b) { return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2)); } static public int _hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static public Set weakSet() { return synchroWeakHashSet(); } static public List list(Class type) { return db_mainConcepts().list(type); } static public List list(Concepts concepts, Class type) { return concepts.list(type); } static public List list(String type) { return db_mainConcepts().list(type); } static public List list(Concepts concepts, String type) { return concepts.list(type); } static public void onIndividualConceptChange_notOnAllChanged(Class type, IVF1 r) { onIndividualConceptChange_notOnAllChanged(db_mainConcepts(), type, r); } static public void onIndividualConceptChange_notOnAllChanged(Concepts cc, Class type, IVF1 r) { if (r != null) { if (cc != null) cc.addConceptIndex(new IConceptIndex() { public void update(Concept c) { if (instanceOf(c, type)) r.get((A) c); } public void remove(Concept c) { } }); } } static public Q dm_startQ() { return dm_ownQ(startQ()); } static public Q dm_startQ(String name) { return dm_ownQ(startQ(name)); } static public FixedRateTimer dm_doEvery(long delay, final Object r) { return dm_ownTimer(doEvery(delay, delay, r)); } static public FixedRateTimer dm_doEvery(long delay, long firstDelay, final Object r) { return dm_ownTimer(doEvery(delay, firstDelay, r)); } static public FixedRateTimer dm_doEvery(double initialSeconds, double delaySeconds, final Object r) { return dm_ownTimer(doEvery(initialSeconds, delaySeconds, r)); } static public FixedRateTimer dm_doEvery(double delaySeconds, final Object r) { return dm_ownTimer(doEvery(delaySeconds, r)); } static public void indexConceptFieldDesc(Class c, String field) { indexConceptFieldDesc(db_mainConcepts(), c, field); } static public void indexConceptFieldDesc(Concepts concepts, Class c, String field) { if (!isConceptFieldIndexed(concepts, c, field)) new ConceptFieldIndexDesc(concepts, c, field); } static public ConceptFieldIndexCI indexConceptFieldIC(Class c, String field) { return indexConceptFieldCI(c, field); } static public ConceptFieldIndexCI indexConceptFieldIC(Concepts concepts, Class c, String field) { return indexConceptFieldCI(concepts, c, field); } static public void indexConceptField(Class c, String field) { indexConceptField(db_mainConcepts(), c, field); } static public void indexConceptField(Concepts concepts, Class c, String field) { if (!isConceptFieldIndexed(concepts, c, field)) new ConceptFieldIndex(concepts, c, field); } static public List listPlus(Collection l, A... more) { return concatLists(l, asList(more)); } static public String h1(String s, Object... params) { return hfulltag("h1", s, params); } static public long toLong(Object o) { if (o instanceof Number) return ((Number) o).longValue(); if (o instanceof String) return parseLong((String) o); return 0; } static public TreeSet litciset(String... items) { TreeSet set = caseInsensitiveSet(); for (String a : items) set.add(a); return set; } static public boolean all(Object pred, Iterable l) { if (l != null) for (Object o : l) if (!isTrue(callF(pred, o))) return false; return true; } static public boolean all(Iterable l, IF1 f) { if (l != null) for (A a : l) if (!f.get(a)) return false; return true; } static public boolean all(IF1 f, Iterable l) { return all(l, f); } static public List findBackRefs(Collection concepts, Class type) { IdentityHashMap l = new IdentityHashMap(); for (Concept c : concepts) if (c.backRefs != null) for (Concept.Ref r : c.backRefs) if (instanceOf(r.concept(), type)) l.put((A) r.concept(), true); return asList(keys(l)); } static public List findBackRefs(Concept c, Class type) { IdentityHashMap l = new IdentityHashMap(); if (c != null && c.backRefs != null) for (Concept.Ref r : c.backRefs) if (instanceOf(r.concept(), type)) l.put((A) r.concept(), true); return asList(keys(l)); } static public List findBackRefs(Class type, Concept c) { return findBackRefs(c, type); } static public Collection findBackRefs(Concept c) { return findBackRefs(c, Concept.class); } static public boolean contains(Collection c, Object o) { return c != null && c.contains(o); } static public boolean contains(Object[] x, Object o) { if (x != null) for (Object a : x) if (eq(a, o)) return true; return false; } static public boolean contains(String s, char c) { return s != null && s.indexOf(c) >= 0; } static public boolean contains(String s, String b) { return s != null && s.indexOf(b) >= 0; } static public boolean contains(BitSet bs, int i) { return bs != null && bs.get(i); } static public boolean contains(Producer p, A a) { if (p != null && a != null) while (true) { A x = p.next(); if (x == null) break; if (eq(x, a)) return true; } return false; } static public void deleteConcepts(Collection conceptsOrIDs) { db_mainConcepts().deleteConcepts(asList(conceptsOrIDs)); } static public List deleteConcepts(Class c, Object... params) { return deleteConcepts(db_mainConcepts(), c, params); } static public List deleteConcepts(Concepts cc, Class c, Object... params) { List l = asList(findConceptsWhere(cc, c, params)); deleteConcepts(l); return l; } static public void deleteConcepts(Class c, IF1 pred) { deleteConcepts(db_mainConcepts(), c, pred); } static public void deleteConcepts(Concepts cc, Class c, IF1 pred) { deleteConcepts(filter(list(cc, c), pred)); } static public List deleteConcepts(Concepts cc) { return deleteConcepts(cc, Concept.class); } static public List filter(Iterable c, Object pred) { if (pred instanceof F1) return filter(c, (F1) pred); List x = new ArrayList(); if (c != null) for (Object o : c) if (isTrue(callF(pred, o))) x.add(o); return x; } static public List filter(Object pred, Iterable c) { return filter(c, pred); } static public List filter(Iterable c, F1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(F1 pred, Iterable c) { return filter(c, pred); } static public List filter(Iterable c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(B[] c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(IF1 pred, Iterable c) { return filter(c, pred); } static public List cdelete(Class c, Object... params) { return deleteConcepts(c, params); } static public void cdelete(Concept c) { deleteConcept(c); } static public void cdelete(Collection c) { for (A a : cloneList(c)) cdelete(a); } static public HashSet litset(A... items) { return lithashset(items); } static public String getStringOpt(Map map, Object key) { return map == null ? null : optCast(String.class, map.get(key)); } static public String getStringOpt(List l, int idx) { return optCast(String.class, get(l, idx)); } static public String getStringOpt(Object o, Object key) { if (o instanceof Map) return getStringOpt((Map) o, key); if (key instanceof String) return optCast(String.class, getOpt(o, (String) key)); throw fail("Not a string key: " + getClassName(key)); } static public String getStringOpt(String key, Object o) { return getStringOpt(o, (Object) key); } static public String appendParamsToURL(String url, Map params) { return appendQueryToURL(url, params); } static public String appendParamsToURL(String url, Object... data) { return appendQueryToURL(url, data); } static public String beforeVerticalBar(String s) { return trimSubstring(s, 0, smartIndexOf(s, '|')); } static public JavaScript hjs_copyToClipboard() { return new JavaScript("\r\n const copyToClipboard = str => {\r\n const el = document.createElement('textarea');\r\n el.value = str;\r\n el.setAttribute('readonly', '');\r\n el.style.position = 'absolute';\r\n el.style.left = '-9999px';\r\n document.body.appendChild(el);\r\n const selected =\r\n document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;\r\n el.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(el);\r\n if (selected) {\r\n document.getSelection().removeAllRanges();\r\n document.getSelection().addRange(selected);\r\n }\r\n };\r\n "); } static public String ahref_onClick(String js, Object contents, Object... params) { return ahref_js(js, contents, params); } static public String formatFunctionCall(String fname, Object... args) { return fname + "(" + joinWithComma(allToString(args)) + ")"; } static public String copyToClipboard(String text) { return copyTextToClipboard(text); } static public A copyToClipboard(A image) { copyImageToClipboard(image); return image; } static public File copyToClipboard(File f) { return copyFileToClipboard(f); } static public String jsQuote(String s) { return javascriptQuote(s); } static public String joinNemptiesWithVBar(String... strings) { return joinNempties(" | ", strings); } static public String joinNemptiesWithVBar(Collection strings) { return joinNempties(" | ", strings); } static public String hPopDownButton(String... entries) { String id = "dropdown-" + aGlobalID(), outerID = "outer-" + id; return hstyle(replaceDollarVars("\r\n #$id ul {\r\n list-style-type: none;\r\n margin: 0;\r\n padding: 0;\r\n width: 200px;\r\n background-color: #f1f1f1;\r\n }\r\n \r\n #$id {\r\n position: absolute;\r\n display:none;\r\n background-color: #f9f9f9;\r\n width:auto;\r\n height:200px;\r\n overflow: auto;\r\n \r\n min-width: 160px;\r\n box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);\r\n \r\n z-index: 99;\r\n \r\n }\r\n \r\n #$id li a {\r\n display: block;\r\n border-bottom: 1px solid #555;\r\n color: #000;\r\n padding: 8px 16px;\r\n text-decoration: none;\r\n }\r\n \r\n #$id li a:hover {\r\n background-color: #3399ff;\r\n color: white;\r\n } \r\n ", "$id", id)) + hdiv(htmlEncode2(unicode_smallDownPointingTriangle()) + hdiv(ul(entries), "id", id), "style", "position: relative; display: inline-block; cursor: context-menu", "onclick", replaceDollarVars("\r\n var x = document.getElementById($id);\r\n x.style.display = window.getComputedStyle(x).display === \"none\" ? \"block\" : \"none\";\r\n ", "$id", jsQuote(id)), "id", outerID) + hscript(replaceDollarVars("\r\n if (typeof $ !== 'undefined')\r\n $('body').click(function(e) {\r\n if (!$(e.target).closest('#$outerID').length) {\r\n $(\"#$id\").hide();\r\n }\r\n });\r\n ", "id", id, "outerID", outerID)); } static public String hPopDownButton(Collection entries) { return hPopDownButton(toStringArray(entries)); } static public List objectsWhereCI(Collection c, Object... data) { return objectsWhereIC(c, data); } static public String hparagraphs(Collection l) { return lines(lambdaMap(__50 -> p(__50), l)); } static public List lmap(IF1 f, Iterable l) { return lambdaMap(f, l); } static public List lmap(IF1 f, A[] l) { return lambdaMap(f, l); } static public List takeFirst(List l, int n) { return l(l) <= n ? l : newSubListOrSame(l, 0, n); } static public List takeFirst(int n, List l) { return takeFirst(l, n); } static public String takeFirst(int n, String s) { return substring(s, 0, n); } static public String takeFirst(String s, int n) { return substring(s, 0, n); } static public CharSequence takeFirst(int n, CharSequence s) { return subCharSequence(s, 0, n); } static public List takeFirst(int n, Iterable i) { if (i == null) return null; List l = new ArrayList(); Iterator it = i.iterator(); for (int _repeat_0 = 0; _repeat_0 < n; _repeat_0++) { if (it.hasNext()) l.add(it.next()); else break; } return l; } static public int[] takeFirst(int n, int[] a) { return takeFirstOfIntArray(n, a); } static public String javaValueToHTML(Object value) { return javaValueToHTML(value, identityHashSet()); } static public String javaValueToHTML(Object value, Set seen) { if (!seen.add(value)) return "see above"; if (value instanceof String) return htmlEncode_quote(((String) value)); else if (value instanceof List) return ol(map(((List) value), v -> javaValueToHTML(v, seen))); else return htmlEncode(shorten(str(value))); } static public String htextfield(String name, Object... params) { return htextinput(name, params); } static public String span(Object contents, Object... params) { return hfulltag("span", contents, params); } static public String span() { return span(""); } static public Object[] litobjectarray(Object... l) { return litObjectArray(l); } static public Map cloneMap(Map map) { if (map == null) return new HashMap(); synchronized (map) { return map instanceof TreeMap ? new TreeMap((TreeMap) map) : map instanceof LinkedHashMap ? new LinkedHashMap(map) : new HashMap(map); } } static public List cloneMap(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : cloneList(l)) x.add(f.get(o)); return x; } static public int max(int a, int b) { return Math.max(a, b); } static public int max(int a, int b, int c) { return max(max(a, b), c); } static public long max(int a, long b) { return Math.max((long) a, b); } static public long max(long a, long b) { return Math.max(a, b); } static public double max(int a, double b) { return Math.max((double) a, b); } static public float max(float a, float b) { return Math.max(a, b); } static public double max(double a, double b) { return Math.max(a, b); } static public int max(Collection c) { int x = Integer.MIN_VALUE; for (int i : c) x = max(x, i); return x; } static public double max(double[] c) { if (c.length == 0) return Double.MIN_VALUE; double x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static public float max(float[] c) { if (c.length == 0) return Float.MAX_VALUE; float x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static public byte max(byte[] c) { byte x = -128; for (byte d : c) if (d > x) x = d; return x; } static public short max(short[] c) { short x = -0x8000; for (short d : c) if (d > x) x = d; return x; } static public int max(int[] c) { int x = Integer.MIN_VALUE; for (int d : c) if (d > x) x = d; return x; } static public int min(int a, int b) { return Math.min(a, b); } static public long min(long a, long b) { return Math.min(a, b); } static public float min(float a, float b) { return Math.min(a, b); } static public float min(float a, float b, float c) { return min(min(a, b), c); } static public double min(double a, double b) { return Math.min(a, b); } static public double min(double[] c) { double x = Double.MAX_VALUE; for (double d : c) x = Math.min(x, d); return x; } static public float min(float[] c) { float x = Float.MAX_VALUE; for (float d : c) x = Math.min(x, d); return x; } static public byte min(byte[] c) { byte x = 127; for (byte d : c) if (d < x) x = d; return x; } static public short min(short[] c) { short x = 0x7FFF; for (short d : c) if (d < x) x = d; return x; } static public int min(int[] c) { int x = Integer.MAX_VALUE; for (int d : c) if (d < x) x = d; return x; } static public long sysNow() { ping(); return System.nanoTime() / 1000000; } static public long now_virtualTime; static public long now() { return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis(); } static volatile public boolean sleep_noSleep = false; static public void sleep(long ms) { ping(); if (ms < 0) return; if (isAWTThread() && ms > 100) throw fail("Should not sleep on AWT thread"); try { Thread.sleep(ms); } catch (Exception e) { throw new RuntimeException(e); } } static public void sleep() { try { if (sleep_noSleep) throw fail("nosleep"); print("Sleeping."); sleepQuietly(); } catch (Exception __e) { throw rethrow(__e); } } static public boolean conceptsWithFieldGreaterThan_sorted_verbose = false; static public Collection conceptsWithFieldGreaterThan_sorted(Class c, String field, Object value) { return conceptsWithFieldGreaterThan_sorted(db_mainConcepts(), c, field, value); } static public Collection conceptsWithFieldGreaterThan_sorted(Concepts concepts, Class c, String field, Object value) { IFieldIndex index = concepts.getFieldIndex(c, field); if (index instanceof ConceptFieldIndexDesc) return reverseInPlace(((ConceptFieldIndexDesc) index).objectsWithValueGreaterThan(value)); if (conceptsWithFieldGreaterThan_sorted_verbose) print("conceptsWithFieldGreaterThan: table scan of " + c + " for field " + field); return sortByFieldInPlace(field, objectsWhereFieldGreaterThan(concepts.list(c), field, value)); } static public double elapsedSeconds_sysNow(long time) { return elapsedSeconds(time); } static public Object serveJSON_breakAtLevels(int levels, Object... data) { return serveText(jsonEncode_breakAtLevels(levels, jsonPrepareData(data))); } static public void printVars_str(Object... params) { String s = ""; if (odd(l(params))) { s = str(first(params)); if (endsWithLetterOrDigit(s)) s += ": "; params = dropFirst(params); } print(s + renderVars_str(params)); } static public String dropTrailingSlashIfNemptyAfterwards(String s) { return l(s) > 1 ? dropSuffix("/", s) : s; } static public boolean swic_notSame(String a, String b) { return swic_notSame(a, b, null); } static public boolean swic_notSame(String a, String b, Matches m) { return l(a) > l(b) && swic(a, b, m); } static public String urldecode(String x) { try { return URLDecoder.decode(unnull(x), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } static public A postProcess(Object f, A a) { return callPostProcessor(f, a); } static public A postProcess(IF1 f, A a) { return callPostProcessor(f, a); } static public Object subBot_serve500() { return call(getMainBot(), "serve500"); } static public Object subBot_serve500(String msg) { return call(getMainBot(), "serve500", msg); } static public String hrefresh(String target) { return hrefresh(0, target); } static public String hrefresh(double seconds) { return hrefresh(seconds, ""); } static public String hrefresh(double seconds, String target) { return tag("meta", "", "http-equiv", "refresh", "content", iceil(seconds) + (nempty(target) ? "; url=" + target : "")); } static public String or2(String a, String b) { return nempty(a) ? a : b; } static public String or2(String a, String b, String c) { return or2(or2(a, b), c); } static public MultiSet asCIMultiSet(Iterable l) { MultiSet ms = new MultiSet(); ms.map = ciMap(); ms.addAll(l); return ms; } static public List collect(Iterable c, String field) { return collectField(c, field); } static public List collect(String field, Iterable c) { return collectField(c, field); } static public String h2_title(String s) { return htitle_h2(s); } static public String ul(String... list) { return ul(asList(list)); } static public String ul(Collection list, Object... params) { StringBuilder buf = new StringBuilder(); int i = indexOf(params, null); if (i == -1) i = l(params); for (Object s : withoutNulls(list)) buf.append(tag("li", s, subArray(params, i + 1))).append("\n"); return containerTag("ul", buf, subArray(params, 0, i)) + "\n"; } static public IterableIterator> mapPairs(Map map) { final Iterator> it = map.entrySet().iterator(); return iteratorFromFunction(new F0>() { public Pair get() { try { if (it.hasNext()) { Map.Entry entry = it.next(); return pair(entry.getKey(), entry.getValue()); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (it.hasNext()) {\r\n Map.Entry entry = it.next();\r\n ret pair..."; } }); } static public List mapPairs(Iterable> l, IF2 f) { return mapPairsToList(l, f); } static public List> multiSetToPairsByPopularity(MultiSet ms) { List> l = new ArrayList(); if (ms != null) for (A a : ms.highestFirst()) l.add(pair(a, ms.get(a))); return l; } static public String urlencode(String x) { try { return URLEncoder.encode(unnull(x), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } static public String unquote(String s) { if (s == null) return null; if (startsWith(s, '[')) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i + 1, s.length() - i - 1); } } if (s.length() > 1) { char c = s.charAt(0); if (c == '\"' || c == '\'') { int l = endsWith(s, c) ? s.length() - 1 : s.length(); StringBuilder sb = new StringBuilder(l - 1); for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } sb.append((char) Integer.parseInt(code, 8)); continue; } switch(nextChar) { case '\"': ch = '\"'; break; case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\'': ch = '\''; break; case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt("" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); sb.append(Character.toChars(code)); i += 5; continue; default: ch = nextChar; } i++; } sb.append(ch); } return sb.toString(); } } return s; } static public boolean eqicOneOf(String s, String... l) { for (String x : l) if (eqic(s, x)) return true; return false; } static public List tlft(String s) { return toLinesFullTrim(s); } static public List tlft(File f) { return toLinesFullTrim(f); } static public Pair uniqCI2_sync(Class c, final Object... params) { return uniqCI2_sync(db_mainConcepts(), c, params); } static public Pair uniqCI2_sync(Concepts cc, Class c, final Object... params) { return withDBLock(cc, new F0>() { public Pair get() { try { return uniqCI2(cc, c, params); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret uniqCI2(cc, c, params);"; } }); } static public String h2(String s, Object... params) { return tag("h2", s, params); } static public String plural(String s) { return getPlural(s); } static public String pIfNempty(String contents, Object... params) { return nempty(contents) ? p(contents, params) : ""; } static public String htmlEncode_nlToBR(String s) { return htmlEncode_nlToBr(s); } static public String lines(Iterable lines) { return fromLines(lines); } static public String lines(Object[] lines) { return fromLines(asList(lines)); } static public List lines(String s) { return toLines(s); } static public int countPred(Iterable c, Object pred) { return nfilter(c, pred); } static public int countPred(Object pred, Iterable c) { return nfilter(pred, c); } static public int countPred(Iterable c, IF1 pred) { return nfilter(c, pred); } static public String n2(long l) { return formatWithThousands(l); } static public String n2(Collection l) { return n2(l(l)); } static public String n2(Map map) { return n2(l(map)); } static public String n2(double l, String singular) { return n2(l, singular, singular + "s"); } static public String n2(double l, String singular, String plural) { if (fraction(l) == 0) return n2((long) l, singular, plural); else return l + " " + plural; } static public String n2(long l, String singular, String plural) { return n_fancy2(l, singular, plural); } static public String n2(long l, String singular) { return n_fancy2(l, singular, singular + "s"); } static public String n2(Collection l, String singular) { return n2(l(l), singular); } static public String n2(Collection l, String singular, String plural) { return n_fancy2(l, singular, plural); } static public String n2(Map m, String singular, String plural) { return n_fancy2(m, singular, plural); } static public String n2(Map m, String singular) { return n2(l(m), singular); } static public String n2(Object[] a, String singular) { return n2(l(a), singular); } static public String n2(Object[] a, String singular, String plural) { return n_fancy2(a, singular, plural); } static public String n2(MultiSet ms, String singular, String plural) { return n_fancy2(ms, singular, plural); } static public String hPopDownButtonWithText(String text, String... entries) { return (empty(text) ? "" : text + " ") + hPopDownButton(entries); } static public String hPopDownButtonWithText(String text, Collection entries) { return hPopDownButtonWithText(text, asStringArray(entries)); } static public String camelCase(List words) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < l(words); i++) { String word = words.get(i); word = toLower(word); buf.append(i == 0 ? word : firstToUpper(word)); } return str(buf); } static public String camelCase(String words) { return camelCase(words(words)); } static public String addParamToURL(String url, Map params) { return appendQueryToURL(url, params); } static public String addParamToURL(String url, Object... data) { return appendQueryToURL(url, data); } static public String ahref_undecorated(String link, Object contents, Object... params) { return ahref_unstyled(link, contents, params); } static public String quote(Object o) { if (o == null) return "null"; return quote(str(o)); } static public String quote(String s) { if (s == null) return "null"; StringBuilder out = new StringBuilder((int) (l(s) * 1.5 + 2)); quote_impl(s, out); return out.toString(); } static public void quote_impl(String s, StringBuilder out) { out.append('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') out.append('\\').append(c); else if (c == '\r') out.append("\\r"); else if (c == '\n') out.append("\\n"); else if (c == '\t') out.append("\\t"); else if (c == '\0') out.append("\\0"); else out.append(c); } out.append('"'); } static public String renderEqualsCommaProperties(Map map) { return joinWithComma(map(map, (key, value) -> key + "=" + value)); } static public int countConceptsWhereCI(Concepts cc, Class c, Object... params) { return countConceptsCI(cc, c, params); } static public int countConceptsWhereCI(Class c, Object... params) { return countConceptsCI(c, params); } static public A getConceptOpt(Class cc, long id) { return getConceptOpt(db_mainConcepts(), cc, id); } static public A getConceptOpt(Concepts concepts, Class cc, long id) { return concepts == null ? null : optCast(cc, concepts.getConcept(id)); } static public String htmlEncode2_nlToBr(String s) { return htmlEncode_nlToBr(s); } static public String hcenter3(Object contents, Object... __) { return tag("div", contents, params_stylePlus(__, "width: 100%; text-align: center")); } static public String hsnippetimg_scaleToWidth(int width, String imageID, int originalWidth, int originalHeight, Object... params) { return hsnippetimg(imageID, paramsPlus(params, "width", width, "height", calcHeight(originalWidth, originalHeight, width))); } static public boolean containsAngleBracketVars(String s) { List tok = javaTokWithAngleBrackets(s); return nempty(indicesOfAngleBracketVars(tok)); } static public A uniqCI_returnIfNew(Class c, Object... params) { Pair p = uniqCI2(c, params); return p.b ? p.a : null; } static public A uniqCI_returnIfNew(Concepts cc, Class c, Object... params) { Pair p = uniqCI2(cc, c, params); return p.b ? p.a : null; } static public String htitle(String title) { return hfulltag("title", htmlencode_noQuotes(title)); } static public String localTimeWithSeconds(long time) { return simpleDateFormat_local("HH:mm:ss").format(time); } static public String localTimeWithSeconds() { return localTimeWithSeconds(now()); } static public List> syncMapToPairs(Map map) { if (map == null) return new ArrayList(); synchronized (collectionMutex(map)) { return mapToPairs(map); } } static public String jsonEncodeMap(Object... __) { return jsonEncode(paramsToMap(__)); } static public Collection distinctCIFieldValuesOfConcepts(Class c, String field) { return distinctCIFieldValuesOfConcepts(db_mainConcepts(), c, field); } static public Collection distinctCIFieldValuesOfConcepts(Concepts concepts, Class c, String field) { IFieldIndex index = concepts.getCIFieldIndex(c, field); if (index != null) return index.allValues(); Set set = ciSet(); for (A x : concepts.list(c)) set.add((String) getOpt(x, field)); return set; } static public A firstNotNull(Iterable c) { Iterator it = c.iterator(); while (it.hasNext()) { A a = it.next(); if (a != null) return a; } return null; } static public A optCast(Class c, Object o) { return isInstance(c, o) ? (A) o : null; } static public boolean swic(String a, String b) { return startsWithIgnoreCase(a, b); } static public boolean swic(String a, String b, Matches m) { if (!swic(a, b)) return false; m.m = new String[] { substring(a, l(b)) }; return true; } static public Object deref(Object o) { if (o instanceof Derefable) o = ((Derefable) o).get(); return o; } static public boolean isSubclassOf(Class a, Class b) { return isSubclass(a, b); } static public void removeAll(Collection a, Collection b) { if (a != null && b != null) a.removeAll(b); } static public void removeAll(Map a, Collection b) { if (a != null && b != null) for (A x : b) a.remove(x); } static public boolean removeAll(Collection c, B... b) { return c != null && b != null && c.removeAll(Arrays.asList(b)); } static public void removeAll(Map a, A... b) { if (a != null && b != null) for (A x : b) a.remove(x); } static public String dropLoadableUtilsPackageFromStruct(String s) { String prefix = "loadableUtils.utils$"; if (!contains(s, "loadableUtils.utils$")) return s; List tok = javaTokForStructure(s); for (int i = 5; i < l(tok); i += 2) if (eqGet(tok, i - 4, "loadableUtils") && eqGet(tok, i - 2, ".")) replaceTokens(tok, i - 4, i + 1, dropPrefix("utils$", tok.get(i))); return join(tok); } static public String indentStructureString_firstLevels(int levelsToIndent, String s) { if (s == null) return null; List tok = javaTokForStructure(s); StringBuilder buf = new StringBuilder(); int level = 0; for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (isOpeningBracket(t)) { int j = i + 5; if (containsClosingBracket(subList(tok, i + 2, i + 5))) { buf.append(joinSubList(tok, i, j)); i = j - 1; } else { buf.append(t); ++level; if (level <= levelsToIndent) buf.append("\n").append(spaces(level * 2)); } } else if (isClosingBracket(t)) { if (level-- <= levelsToIndent) buf.append("\n").append(spaces(level * 2)); buf.append(t); } else if (eq(t, ",")) { buf.append(t); if (level <= levelsToIndent) buf.append("\n").append(spaces(level * 2)); i++; } else buf.append(t); } return str(buf); } static public String strOrNull(Object o) { return o == null ? null : str(o); } static public String appendBracketed(Object o) { String b = strOrNull(o); return empty(b) ? "" : "" + " (" + b + ")"; } static public String appendBracketed(String a, String b) { return a + appendBracketed(b); } static public Class javax() { return getJavaX(); } static public void setDefaultClassFinder(Object cf) { _defaultClassFinder_value = cf; } static public HashMap findClass_fullName_cache = new HashMap(); static public Class findClass_fullName(String name) { synchronized (findClass_fullName_cache) { if (findClass_fullName_cache.containsKey(name)) return findClass_fullName_cache.get(name); Class c; try { c = Class.forName(name); } catch (ClassNotFoundException e) { c = null; } findClass_fullName_cache.put(name, c); return c; } } static public AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) { return print_byThread().get() == null ? tempInterceptPrint(f) : null; } static public Throwable printStackTrace2(Throwable e) { print(getStackTrace2(e)); return e; } static public void printStackTrace2() { printStackTrace2(new Throwable()); } static public void printStackTrace2(String msg) { printStackTrace2(new Throwable(msg)); } static public Object _defaultClassFinder_value = defaultDefaultClassFinder(); static public Object _defaultClassFinder() { return _defaultClassFinder_value; } static public Concepts newConceptsWithClassFinder(String progID) { Concepts cc = new Concepts(progID); cc.classFinder = _defaultClassFinder(); return cc; } static public String getDBProgramID_id; static public String getDBProgramID() { return nempty(getDBProgramID_id) ? getDBProgramID_id : programIDWithCase(); } static public long toMS(double seconds) { return (long) (seconds * 1000); } static volatile public boolean ping_pauseAll = false; static public int ping_sleep = 100; static volatile public boolean ping_anyActions = false; static public Map ping_actions = newWeakHashMap(); static public ThreadLocal ping_isCleanUpThread = new ThreadLocal(); static public boolean ping() { if (ping_pauseAll || ping_anyActions) ping_impl(true); return true; } static public boolean ping_impl(boolean okInCleanUp) { try { if (ping_pauseAll && !isAWTThread()) { do Thread.sleep(ping_sleep); while (ping_pauseAll); return true; } if (ping_anyActions) { if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get())) failIfUnlicensed(); Object action = null; synchronized (ping_actions) { if (!ping_actions.isEmpty()) { action = ping_actions.get(currentThread()); if (action instanceof Runnable) ping_actions.remove(currentThread()); if (ping_actions.isEmpty()) ping_anyActions = false; } } if (action instanceof Runnable) ((Runnable) action).run(); else if (eq(action, "cancelled")) throw fail("Thread cancelled."); } return false; } catch (Exception __e) { throw rethrow(__e); } } static public int countConceptsCI(Concepts cc, Class c, Object... params) { if (empty(params)) return countConcepts(cc, c); return l(conceptsWhereCI(cc, c, params)); } static public int countConceptsCI(Class c, Object... params) { return countConceptsCI(db_mainConcepts(), c, params); } static public Iterator emptyIterator() { return Collections.emptyIterator(); } static public List sortConceptsByID(Collection l) { return sortedByCalculatedField(l, c -> c.id); } static public Object[] expandParams(Class c, Object[] params) { if (l(params) == 1) params = new Object[] { singleFieldName(c), params[0] }; else warnIfOddCount(params); return params; } static public List filterConceptsIC(Collection list, Object... params) { List l = new ArrayList(); if (list != null) for (A x : list) if (checkConceptFieldsIC(x, params)) l.add(x); return l; } static public String getClassName(Object o) { return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName(); } static public boolean mmo2_match(MMOPattern pattern, String s) { return mmo2_match(pattern, s, false, false); } static public boolean mmo2_match(MMOPattern pattern, String s, boolean startOfLine, boolean endOfLine) { if (pattern == null) return false; String s2 = trim(s); if (pattern instanceof MMOPattern.StartOfLine) return mmo2_match(((MMOPattern.StartOfLine) pattern).p, s2, true, endOfLine); if (pattern instanceof MMOPattern.EndOfLine) return mmo2_match(((MMOPattern.EndOfLine) pattern).p, s2, startOfLine, true); if (pattern instanceof MMOPattern.Phrase) { String p = ((MMOPattern.Phrase) pattern).phrase; if (((MMOPattern.Phrase) pattern).quoted) return cicWithSmartWordBoundary(s2, p); if (startsWith(p, "#")) return eqic(p, s2); return match3_startOrEndOfLine(p, s2, startOfLine, endOfLine); } if (pattern instanceof MMOPattern.And) return all(((MMOPattern.And) pattern).l, pat -> mmo2_match(pat, s2, startOfLine, endOfLine)); if (pattern instanceof MMOPattern.Or) return any(((MMOPattern.Or) pattern).l, pat -> mmo2_match(pat, s2, startOfLine, endOfLine)); if (pattern instanceof MMOPattern.Not) return !mmo2_match(((MMOPattern.Not) pattern).p, s2, startOfLine, endOfLine); throw fail("what. " + pattern); } static public boolean mmo2_match(String pattern, String s) { return mmo2_match(mmo2_parsePattern(pattern), s); } static public MMOPattern mmo2_parsePattern(String s) { s = trim(tok_deRoundBracket(trim(s))); List tok = javaTokWithBrackets(s); List l = tok_splitAtComma(tok); if (l(l) > 1) return new MMOPattern.Or(lambdaMap(__51 -> mmo2_parsePattern(__51), l)); l = tok_splitAtPlus(tok); if (l(l) > 1) return new MMOPattern.And(lambdaMap(__52 -> mmo2_parsePattern(__52), l)); if (startsWith(s, "!")) return new MMOPattern.Not(mmo2_parsePattern(dropFirst(s))); if (startsWith(s, "^")) return new MMOPattern.StartOfLine(mmo2_parsePattern(dropFirst(s))); if (endsWith(s, "$")) return new MMOPattern.EndOfLine(mmo2_parsePattern(dropLast(s))); l = tok_splitAtAsterisk(tok); if (l(l) == 2) return new MMOPattern.Weighted(parseDouble(second(l)), mmo2_parsePattern(first(l))); return new MMOPattern.Phrase(unquote(s), isQuoted(s)); } static public List javaTokWithAngleBrackets(String s) { return tok_combineAngleBrackets_keep(javaTok(s)); } static public List indicesOf(List l, A a) { if (l == null) return null; if (l instanceof IContentsIndexedList) return intArrayToList(((IContentsIndexedList) l).indicesOf(a)); if (l instanceof IContentsIndexedList2) return map(h -> ((HasIndex) h).idx, ((IContentsIndexedList2) l).indicesOf_treeSetOfHasIndex(a)); List x = new ArrayList(); for (int i = 0; i < l(l); i++) if (eq(l.get(i), a)) x.add(i); return x; } static public List indicesOf(String s, String x) { int i = -1; List out = new ArrayList(); while ((i = indexOf(s, x, i + 1)) >= 0) out.add(i); return out; } static public String angleBracketed(String s) { return angleBracket(s); } public static String join(String glue, Iterable strings) { if (strings == null) return ""; if (strings instanceof Collection) { if (((Collection) strings).size() == 1) return str(first(((Collection) strings))); } StringBuilder buf = new StringBuilder(); Iterator i = strings.iterator(); if (i.hasNext()) { buf.append(i.next()); while (i.hasNext()) buf.append(glue).append(i.next()); } return buf.toString(); } public static String join(String glue, String... strings) { return join(glue, Arrays.asList(strings)); } static public String join(Iterable strings) { return join("", strings); } static public String join(Iterable strings, String glue) { return join(glue, strings); } public static String join(String[] strings) { return join("", strings); } static public String join(String glue, Pair p) { return p == null ? "" : str(p.a) + glue + str(p.b); } static public A grabValueAndCancel(VF1> r) { Var var = new Var(); withCancelPoint(new VF1() { public void get(CancelPoint cp) { try { callF(r, new VF1() { public void get(A a) { try { var.set(a); cancelTo(cp); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "var.set(a); cancelTo(cp)"; } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r, voidfunc(A a) { var.set(a); cancelTo(cp) });"; } }); return var.get(); } static public void flexMatchAngleBracketVarsIC_honorPunctuation_iterate(String pat, String input, VF1> onMatch) { List vars = new ArrayList(); String starsPat = angleBracketVarsToStars(pat, vars); flexMatchIC_iterate(starsPat, javaTokWithBrackets(starsPat), javaTokWithBrackets(input), new VF1() { public void get(Matches m) { try { Map map = matchesToMapUsingVarList_ciMap(m, vars); if (map != null) callF(onMatch, map); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "SS map = matchesToMapUsingVarList_ciMap(m, vars);\r\n if (map != null) callF..."; } }); } static public void flexMatchAngleBracketVarsIC_iterate(String pat, String input, VF1> onMatch) { List vars = new ArrayList(); String starsPat = angleBracketVarsToStars(pat, vars); flexMatchIC_iterate(starsPat, input, new VF1() { public void get(Matches m) { try { Map map = matchesToMapUsingVarList_ciMap(m, vars); if (map != null) callF(onMatch, map); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "SS map = matchesToMapUsingVarList_ciMap(m, vars);\r\n if (map != null) callF..."; } }); } static public HashMap findClass_cache = new HashMap(); static public Class findClass(String name) { synchronized (findClass_cache) { if (findClass_cache.containsKey(name)) return findClass_cache.get(name); if (!isJavaIdentifier(name)) return null; Class c; try { c = Class.forName("main$" + name); } catch (ClassNotFoundException e) { c = null; } findClass_cache.put(name, c); return c; } } static public Object nuObject(String className, Object... args) { try { return nuObject(classForName(className), args); } catch (Exception __e) { throw rethrow(__e); } } static public A nuObject(Class c, Object... args) { try { if (args.length == 0) return nuObjectWithoutArguments(c); Constructor m = nuObject_findConstructor(c, args); makeAccessible(m); return (A) m.newInstance(args); } catch (Exception __e) { throw rethrow(__e); } } static public Constructor nuObject_findConstructor(Class c, Object... args) { for (Constructor m : c.getDeclaredConstructors()) { if (!nuObject_checkArgs(m.getParameterTypes(), args, false)) continue; return m; } throw fail("Constructor " + c.getName() + getClasses(args) + " not found" + (args.length == 0 && (c.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0 ? " - hint: it's a non-static class!" : "")); } static public boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) { if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static public int csetAll(Concept c, Object... values) { return cset(c, values); } static public int csetAll(Iterable l, Object... values) { int n = 0; for (Concept c : unnull(l)) n += cset(c, values); return n; } static public boolean isInstance(Class type, Object arg) { return type.isInstance(arg); } static public String dropSuffix(String suffix, String s) { return s.endsWith(suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static public String htitle_h1(String s) { return htitle_noEncode(dropTags(s)) + h1(s); } static public String hfulltag(String tag) { return hfulltag(tag, ""); } static public String hfulltag(String tag, Object contents, Object... params) { return hopeningTag(tag, params) + str(contents) + ""; } static public String tag(String tag) { return htag(tag); } static public String tag(String tag, Object contents, Object... params) { return htag(tag, str(contents), params); } static public String tag(String tag, StringBuilder contents, Object... params) { return htag(tag, contents, params); } static public String tag(String tag, StringBuffer contents, Object... params) { return htag(tag, contents, params); } static public String htmlencode(Object o) { return htmlencode(str(o)); } static public String htmlencode(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { int cp = s.codePointAt(i); out.append("&#x"); out.append(intToHex_flexLength(cp)); out.append(';'); i += Character.charCount(cp) - 1; } else out.append(c); } return out.toString(); } static public String getType(Object o) { return getClassName(o); } static public long getFileSize(String path) { return path == null ? 0 : new File(path).length(); } static public long getFileSize(File f) { return f == null ? 0 : f.length(); } static public List allToString(Iterable c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static public List allToString(Object[] c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static public String asString(Object o) { return o == null ? null : o.toString(); } static public String htitle_noEncode(String title) { return tag("title", title); } static public String dropTags(String html) { return dropAllTags(html); } static public List dropTags(List tok) { return dropAllTags(tok); } static public String href(String link, Object contents, Object... params) { if (link == null) return str(contents); return tag("a", contents, arrayPlus(params, "href", link)); } static public String hjavascript(String script) { return tag("script", script, "type", "text/javascript"); } static public int javaTok_n, javaTok_elements; static public boolean javaTok_opt = false; static public List javaTok(String s) { ++javaTok_n; ArrayList tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0; while (i < l) { int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !regionMatches(s, j, "*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(javaTok_substringN(s, i, j)); i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' && Character.isJavaIdentifierStart(d) && i + 2 < l && "'\\".indexOf(s.charAt(i + 2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { int c2 = s.charAt(j); if (c2 == opener || c2 == '\n' && opener == '\'') { ++j; break; } else if (c2 == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j < l && !regionMatches(s, j, "]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !regionMatches(s, j, "]=]")); j = Math.min(j + 3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static public List javaTok(List tok) { return javaTokWithExisting(join(tok), tok); } static public ArrayList cloneList(Iterable l) { return l instanceof Collection ? cloneList((Collection) l) : asList(l); } static public ArrayList cloneList(Collection l) { if (l == null) return new ArrayList(); synchronized (collectionMutex(l)) { return new ArrayList(l); } } static public String jreplace(String s, String in, String out) { return jreplace(s, in, out, null); } static public String jreplace(String s, String in, String out, Object condition) { List tok = javaTok(s); return jreplace(tok, in, out, condition) ? join(tok) : s; } static public boolean jreplace(List tok, String in, String out) { return jreplace(tok, in, out, false, true, null); } static public boolean jreplace(List tok, String in, String out, Object condition) { return jreplace(tok, in, out, false, true, condition); } static public boolean jreplace(List tok, String in, String out, IF2, Integer, Boolean> condition) { return jreplace(tok, in, out, (Object) condition); } static public boolean jreplace(List tok, String in, String out, boolean ignoreCase, boolean reTok, Object condition) { String[] toks = javaTokForJFind_array(in); int lTokin = toks.length * 2 + 1; boolean anyChange = false; int i = -1; for (int n = 0; n < 10000; n++) { i = findCodeTokens(tok, i + 1, ignoreCase, toks, condition); if (i < 0) return anyChange; List subList = tok.subList(i - 1, i + lTokin - 1); String expansion = jreplaceExpandRefs(out, subList); int end = i + lTokin - 2; clearAllTokens(tok, i, end); tok.set(i, expansion); if (reTok) reTok(tok, i, end); i = end; anyChange = true; } throw fail("woot? 10000! " + quote(in) + " => " + quote(out)); } static public boolean jreplace_debug = false; static public Map paramsToMap(Object... params) { int n = l(params); if (l(params) == 1 && params[0] instanceof Map) return (Map) params[0]; LinkedHashMap map = new LinkedHashMap(); for (int i = 0; i + 1 < n; i += 2) mapPut(map, params[i], params[i + 1]); return map; } static public String htag(String tag) { return htag(tag, ""); } static public String htag(String tag, Object contents, Object... params) { String openingTag = hopeningTag(tag, params); String s = str(contents); if (empty(s) && neqic(tag, "script")) return dropLast(openingTag) + "/>"; return openingTag + s + ""; } static public Object[] html_massageAutofocusParam(Object[] params) { Object autofocus = optPar("autofocus", params); return changeParam(params, "autofocus", eqOneOf(autofocus, true, 1, "1", "autofocus") ? html_valueLessParam() : null); } static public String hopeningTag(String tag, Map params) { return hopeningTag(tag, mapToParams(params)); } static public String hopeningTag(String tag, Object... params) { StringBuilder buf = new StringBuilder(); buf.append("<" + tag); params = unrollParams(params); for (int i = 0; i < l(params); i += 2) { String name = (String) get(params, i); Object val = get(params, i + 1); if (nempty(name) && val != null) { if (val == html_valueLessParam()) buf.append(" " + name); else { String s = str(val); if (!empty(s)) buf.append(" " + name + "=" + htmlQuote(s)); } } } buf.append(">"); return str(buf); } static public String htmlencode2(String s) { return htmlencode_noQuotes(s); } static public boolean odd(int i) { return (i & 1) != 0; } static public boolean odd(long i) { return (i & 1) != 0; } static public boolean odd(BigInteger i) { return odd(toInt(i)); } static public Object first(Object list) { return first((Iterable) list); } static public A first(List list) { return empty(list) ? null : list.get(0); } static public A first(A[] bla) { return bla == null || bla.length == 0 ? null : bla[0]; } static public A first(IterableIterator i) { return first((Iterator) i); } static public A first(Iterator i) { return i == null || !i.hasNext() ? null : i.next(); } static public A first(Iterable i) { if (i == null) return null; Iterator it = i.iterator(); return it.hasNext() ? it.next() : null; } static public Character first(String s) { return empty(s) ? null : s.charAt(0); } static public Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); } static public A first(Pair p) { return p == null ? null : p.a; } static public Byte first(byte[] l) { return empty(l) ? null : l[0]; } static public String[] dropFirst(int n, String[] a) { return drop(n, a); } static public String[] dropFirst(String[] a) { return drop(1, a); } static public Object[] dropFirst(Object[] a) { return drop(1, a); } static public List dropFirst(List l) { return dropFirst(1, l); } static public List dropFirst(int n, Iterable i) { return dropFirst(n, toList(i)); } static public List dropFirst(Iterable i) { return dropFirst(toList(i)); } static public List dropFirst(int n, List l) { return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size())); } static public List dropFirst(List l, int n) { return dropFirst(n, l); } static public String dropFirst(int n, String s) { return substring(s, n); } static public String dropFirst(String s, int n) { return substring(s, n); } static public String dropFirst(String s) { return substring(s, 1); } static public Chain dropFirst(Chain c) { return c == null ? null : c.next; } static public boolean even(int i) { return (i & 1) == 0; } static public boolean even(long i) { return (i & 1) == 0; } static public boolean even(BigInteger n) { return even(n.intValue()); } static public A or(A a, A b) { return a != null ? a : b; } static public Object html_valueLessParam_cache; static public Object html_valueLessParam() { if (html_valueLessParam_cache == null) html_valueLessParam_cache = html_valueLessParam_load(); return html_valueLessParam_cache; } static public Object html_valueLessParam_load() { return new Object(); } static public String containerTag(String tag) { return containerTag(tag, ""); } static public String containerTag(String tag, Object contents, Object... params) { String openingTag = hopeningTag(tag, params); String s = str(contents); return openingTag + s + ""; } static public String hAddToHead(String html, String tag) { List tok = htmlTok(html); List head = first(findContainerTag(tok, "head")); if (head == null) return tag + html; head.set(2, addLineBreak(tag) + head.get(2)); return join(tok); } static public String hcss(Object contents) { return htag("style", contents); } static public String hStylesheetSnippet_maxCache(String snippetID) { return tag("link", "", "rel", "stylesheet", "type", "text/css", "href", snippetRawURL_maxCache(snippetID, "text/css")); } static public String hjssnippet_maxCache(String snippetID) { return hfulltag("script", "", "src", snippetRawURL_maxCache(snippetID, "text/javascript")); } static public String div(Object contents, Object... params) { return hfulltag("div", contents, params); } static public String div() { return div(""); } static public BigInteger div(BigInteger a, BigInteger b) { return a.divide(b); } static public BigInteger div(BigInteger a, int b) { return a.divide(bigint(b)); } static public Object[] params_stylePlus(Object[] params, String style) { return paramsPlus(params, "style", joinNemptiesWithSemicolon(stringPar("style", params), style)); } static public Object[] params_stylePlus(String style, Object[] params) { return params_stylePlus(params, style); } static public String stringPar(Object[] params, String name) { return stringOptPar(params, name); } static public String stringPar(String name, Object[] params) { return stringOptPar(params, name); } static public String stringPar(String name, Map params) { return (String) optPar(name, params); } static public String stringPar(String name, Object[] params, String defaultValue) { return optPar(name, params, defaultValue); } static public Object[] dropParam(Object key, Object[] params) { return paramsWithout(params, key); } static public String joinNemptiesWithSemicolon(String... strings) { return joinNempties("; ", strings); } static public String joinNemptiesWithSemicolon(Collection strings) { return joinNempties("; ", strings); } static public List lookupPossiblyIgnoreCase(MultiMap map, String key) { if (map == null) return null; List value = map.get(key); return !value.isEmpty() ? value : lookupIgnoreCase(map, key); } static public A lookupPossiblyIgnoreCase(Map map, String key) { if (map == null) return null; A value = map.get(key); return value != null ? value : lookupIgnoreCase(map, key); } static public boolean eitherIsB(Either e) { return e != null && e.isB(); } static public Set synchroSet() { return synchroHashSet(); } static public Set synchroSet(Set set) { return Collections.synchronizedSet(set); } static public Set newWeakHashSet() { return synchroWeakHashSet(); } static public Thread newThread(Object runnable) { return new Thread(_topLevelErrorHandling(toRunnable(runnable))); } static public Thread newThread(Object runnable, String name) { if (name == null) name = defaultThreadName(); return new Thread(_topLevelErrorHandling(toRunnable(runnable)), name); } static public Thread newThread(String name, Object runnable) { return newThread(runnable, name); } static public A getAndClearThreadLocal(ThreadLocal tl) { A a = tl.get(); tl.set(null); return a; } static public Thread currentThread() { return Thread.currentThread(); } static public A printStackTrace(A e) { print(getStackTrace(e)); return e; } static public void printStackTrace() { printStackTrace(new Throwable()); } static public void printStackTrace(String msg) { printStackTrace(new Throwable(msg)); } static public void printStackTrace(String msg, Throwable e) { printStackTrace(new Throwable(msg, e)); } static public List beforeDelegatingToThread_operations = synchroList(); static public void beforeDelegatingToThread(Thread t) { for (Object op : cloneList(beforeDelegatingToThread_operations)) pcallF(op, t); } static public void beforeDelegatingToThread_do(Object f) { setAdd(beforeDelegatingToThread_operations, f); } static public Thread startThread(Object runnable) { return startThread(defaultThreadName(), runnable); } static public Thread startThread(String name, Object runnable) { runnable = wrapAsActivity(runnable); return startThread(newThread(toRunnable(runnable), name)); } static public Thread startThread(Thread t) { _registerThread(t); t.start(); return t; } static public void cancelAndInterruptThread(Thread t) { if (t == null) return; cancelThread(t); t.interrupt(); } static public Either either2(B b) { return new Either(2, b); } static public Either either1(A a) { return new Either(1, a); } static public List afterDelegatingToThread_operations = synchroList(); static public void afterDelegatingToThread(Thread t) { for (Object op : cloneList(afterDelegatingToThread_operations)) pcallF(op, t); } static public void afterDelegatingToThread_do(Object f) { setAdd(afterDelegatingToThread_operations, f); } static public int toMS_int(double seconds) { return toInt_checked((long) (seconds * 1000)); } static public AutoCloseable tempSetThreadLocal(final ThreadLocal tl, A a) { if (tl == null) return null; final A prev = setThreadLocal(tl, a); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); } }; } static public String getTag(String s) { if (!startsWith(s, "<")) return null; int i = 1; if (charAt(s, i) == '/') ++i; while (" \t>/\0".indexOf(charAt(s, i)) < 0) ++i; return substring(s, 1, i); } static public String firstToken(String s) { return firstJavaToken(s); } static public String firstToken(List tok) { return get(tok, 1); } static public List htmlTok(String s) { return htmlcoarsetok(s); } static public String pre_htmlencode(Object contents, Object... params) { return pre(htmlencode_noQuotes(str(contents)), params); } static public Object[] concatArrays(Object[]... arrays) { int l = 0; for (Object[] a : arrays) l += l(a); Object[] x = new Object[l]; int i = 0; for (Object[] a : arrays) if (a != null) { System.arraycopy(a, 0, x, i, l(a)); i += l(a); } return x; } static public String htextinput(String name, Object... params) { Object value = ""; if (odd(l(params))) { value = params[0]; params = dropFirst(params); } params = html_massageAutofocusParam(params); return tag("input", "", concatArrays(new Object[] { "type", "text", "name", name, "value", value }, params)); } static public String htextinput(String name) { return htextinput(name, ""); } static public A findConceptWhereCI(Class c, Object... params) { return findConceptWhereCI(db_mainConcepts(), c, params); } static public A findConceptWhereCI(Concepts concepts, Class c, Object... params) { params = expandParams(c, params); if (concepts.ciFieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getCIFieldIndex(c, (String) params[i]); if (index != null) { for (A x : index.getAll(params[i + 1])) if (checkConceptFieldsIC(x, params)) return x; return null; } } for (A x : concepts.list(c)) if (checkConceptFieldsIC(x, params)) return x; return null; } static public Concept findConceptWhereCI(Concepts concepts, String c, Object... params) { for (Concept x : concepts.list(c)) if (checkConceptFieldsIC(x, params)) return x; return null; } static public A unlisted(Class c, Object... args) { concepts_unlisted.set(true); try { return nuObject(c, args); } finally { concepts_unlisted.set(null); } } static public Concept unlisted(String name, Object... args) { Class cc = findClass(name); concepts_unlisted.set(true); try { return cc != null ? nuObject(cc) : new Concept(name); } finally { concepts_unlisted.set(null); } } static public Pair pair(A a, B b) { return new Pair(a, b); } static public Pair pair(A a) { return new Pair(a, a); } static public List callF_all(Collection l, Object... args) { return map(l, f -> callF(f, args)); } static public Class hotwire(String src) { assertFalse(_inCore()); Class j = getJavaX(); if (isAndroid()) { synchronized (j) { List libraries = new ArrayList(); File srcDir = (File) call(j, "transpileMain", src, libraries); if (srcDir == null) throw fail("transpileMain returned null (src=" + quote(src) + ")"); Object androidContext = get(j, "androidContext"); return (Class) call(j, "loadx2android", srcDir, src); } } else { Class c = (Class) (call(j, "hotwire", src)); hotwire_copyOver(c); return c; } } static public A callMain(A c, String... args) { callOpt(c, "main", new Object[] { args }); return c; } static public void callMain() { callMain(mc()); } static public List reversedList(Iterable l) { List x = cloneList(l); Collections.reverse(x); return x; } static public String reversedString(String s) { return reverseString(s); } static public long round(double d) { return Math.round(d); } static public String round(String s) { return roundBracket(s); } static public String jextract(String pat, String s) { return jextract(pat, javaTok(s)); } static public String jextract(String pat, List tok) { List tokpat = javaTok(pat); jfind_preprocess(tokpat); int i = jfind(tok, tokpat); if (i < 0) return null; int j = i + l(tokpat) - 2; return joinSubList(tok, i, j); } static public String repeat(char c, int n) { n = Math.max(n, 0); char[] chars = new char[n]; for (int i = 0; i < n; i++) chars[i] = c; return new String(chars); } static public List repeat(A a, int n) { n = Math.max(n, 0); List l = new ArrayList(n); for (int i = 0; i < n; i++) l.add(a); return l; } static public List repeat(int n, A a) { return repeat(a, n); } static public String formatDoubleArrowPairs_horizontallyAligned(List> l) { return asciiSideBySideWithSeparator(" => ", ll(lines(pairsA(l)), lines(pairsB(l)))); } static public List> mapToPairs(Map map) { List> l = new ArrayList(); if (map != null) for (Map.Entry e : map.entrySet()) l.add(pair(e.getKey(), e.getValue())); return l; } static public String replaceAngleBracketVars(String s, Map map) { return empty(map) ? s : join(replaceAngleBracketVars(javaTokWithAngleBrackets(s), map)); } static public List replaceAngleBracketVars(List tok, Map map) { if (empty(map)) return tok; tok = cloneList(tok); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (isAngleBracketed(t)) { A t2 = map.get(t); if (t2 == null) t2 = map.get(deAngleBracket(t)); if (t2 != null) tok.set(i, str(t2)); } } return tok; } static public String replaceAngleBracketVars(String s, Object... params) { return replaceAngleBracketVars(s, paramsToMap(params)); } static public String curly(String s) { return optionalCurlyBrace(s); } static public String mapPairsToLines(Iterable> l, IF2 f) { return lines(mapPairsToList(l, f)); } static public List> paramsToPairs(A... params) { List> l = emptyList(l(params) / 2); for (int i = 0; i + 1 < l(params); i += 2) l.add(pair(params[i], params[i + 1])); return l; } static public A oneOf(List l) { return empty(l) ? null : l.get(new Random().nextInt(l.size())); } static public char oneOf(String s) { return empty(s) ? '?' : s.charAt(random(l(s))); } static public String oneOf(String... l) { return oneOf(asList(l)); } static public A collectionGet(Collection c, int idx) { if (c == null || idx < 0 || idx >= l(c)) return null; if (c instanceof List) return listGet((List) c, idx); Iterator it = c.iterator(); for (int i = 0; i < idx; i++) if (it.hasNext()) it.next(); else return null; return it.hasNext() ? it.next() : null; } static public String htmlencode_noQuotes(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '<') out.append("<"); else if (c == '>') out.append(">"); else if (c > 127 || c == '&') { int cp = s.codePointAt(i); out.append("&#x"); out.append(intToHex_flexLength(cp)); out.append(';'); i += Character.charCount(cp) - 1; } else out.append(c); } return out.toString(); } static public MultiMap caseInsensitiveMultiMap() { MultiMap mm = new MultiMap(); mm.data = caseInsensitiveMap(); return mm; } static public TreeSet ciSet() { return caseInsensitiveSet(); } static public String unnull(String s) { return s == null ? "" : s; } static public Collection unnull(Collection l) { return l == null ? emptyList() : l; } static public List unnull(List l) { return l == null ? emptyList() : l; } static public int[] unnull(int[] l) { return l == null ? emptyIntArray() : l; } static public char[] unnull(char[] l) { return l == null ? emptyCharArray() : l; } static public double[] unnull(double[] l) { return l == null ? emptyDoubleArray() : l; } static public Map unnull(Map l) { return l == null ? emptyMap() : l; } static public Iterable unnull(Iterable i) { return i == null ? emptyList() : i; } static public A[] unnull(A[] a) { return a == null ? (A[]) emptyObjectArray() : a; } static public BitSet unnull(BitSet b) { return b == null ? new BitSet() : b; } static public Pt unnull(Pt p) { return p == null ? new Pt() : p; } static public Pair unnull(Pair p) { return p != null ? p : new Pair(null, null); } static public long unnull(Long l) { return l == null ? 0L : l; } static public ArrayList emptyList() { return new ArrayList(); } static public ArrayList emptyList(int capacity) { return new ArrayList(max(0, capacity)); } static public ArrayList emptyList(Iterable l) { return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList(); } static public ArrayList emptyList(Object[] l) { return emptyList(l(l)); } static public ArrayList emptyList(Class c) { return new ArrayList(); } static public void addAll(Collection c, Iterable b) { if (c != null && b != null) for (A a : b) c.add(a); } static public boolean addAll(Collection c, Collection b) { return c != null && b != null && c.addAll(b); } static public boolean addAll(Collection c, B... b) { return c != null && b != null && c.addAll(Arrays.asList(b)); } static public Map addAll(Map a, Map b) { if (a != null) a.putAll(b); return a; } static public Collection findConceptsWhereCI(Class c, Object... params) { return findConceptsWhereCI(db_mainConcepts(), c, params); } static public List findConceptsWhereCI(String c, Object... params) { return findConceptsWhereCI(db_mainConcepts(), c, params); } static public Collection findConceptsWhereCI(Concepts concepts, Class c, Object... params) { Collection l = findConceptsWhereCI_noParent(concepts, c, params); if (concepts.parent == null) return l; return concatCollections_conservative(l, findConceptsWhereCI(concepts.parent, c, params)); } static public Collection findConceptsWhereCI_noParent(Concepts concepts, Class c, Object... params) { params = expandParams(c, params); if (concepts.ciFieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getCIFieldIndex(c, (String) params[i]); if (index != null) { Collection rawList = index.getAll(params[i + 1]); params = dropEntryFromParams(params, i); if (params == null) return rawList; List l = new ArrayList(); for (A x : rawList) if (checkConceptFieldsIC(x, params)) l.add(x); return l; } } return filterConceptsIC(concepts.list(c), params); } static public List findConceptsWhereCI(Concepts concepts, String c, Object... params) { return filterConceptsIC(concepts.list(c), params); } static public Map similarEmptyMap(Map m) { if (m instanceof TreeMap) return new TreeMap(((TreeMap) m).comparator()); if (m instanceof LinkedHashMap) return new LinkedHashMap(); return new HashMap(); } static public String tok_unCurlyBracket(String s) { return isCurlyBraced(s) ? join(dropFirstThreeAndLastThree(javaTok(s))) : s; } static public String simpleSpaces_javaTok(String s) { return join(simpleSpaces(javaTok(s))); } static public List indicesOfAngleBracketVars(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) if (isAngleBracketVar(tok.get(i))) l.add(i); return l; } static public String deAngleBracket(String s) { return isAngleBracketed(s) ? dropFirstAndLast(s) : s; } static public boolean endsWithLetterOrDigit(String s) { return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length() - 1)); } static public void ping_okInCleanUp() { if (ping_pauseAll || ping_anyActions) ping_impl(true); } static public Object getThreadLocal(Object o, String name) { ThreadLocal t = (ThreadLocal) (getOpt(o, name)); return t != null ? t.get() : null; } static public A getThreadLocal(ThreadLocal tl) { return tl == null ? null : tl.get(); } static public A getThreadLocal(ThreadLocal tl, A defaultValue) { return or(getThreadLocal(tl), defaultValue); } static public ThreadLocal print_byThread_dontCreate() { return print_byThread; } static public boolean isFalse(Object o) { return eq(false, o); } static public String fixNewLines(String s) { int i = indexOf(s, '\r'); if (i < 0) return s; int l = s.length(); StringBuilder out = new StringBuilder(l); out.append(s, 0, i); for (; i < l; i++) { char c = s.charAt(i); if (c != '\r') out.append(c); else { out.append('\n'); if (i + 1 < l && s.charAt(i + 1) == '\n') ++i; } } return out.toString(); } static public void print_append(Appendable buf, String s, int max) { try { synchronized (buf) { buf.append(s); if (buf instanceof StringBuffer) rotateStringBuffer(((StringBuffer) buf), max); else if (buf instanceof StringBuilder) rotateStringBuilder(((StringBuilder) buf), max); } } catch (Exception __e) { throw rethrow(__e); } } static public void vmBus_send(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); pcallFAll(vm_busListeners_live(), msg, arg); pcallFAll(vm_busListenersByMessage_live().get(msg), msg, arg); } static public void vmBus_send(String msg) { vmBus_send(msg, (Object) null); } static public Class mc() { return main.class; } static public A uniqueConcept(Class c, Object... params) { return uniqueConcept(db_mainConcepts(), c, params); } static public A uniqueConcept(Concepts cc, Class c, Object... params) { AutoCloseable __1 = tempDBLock(cc); try { params = expandParams(c, params); A x = findConceptWhere(cc, c, params); if (x == null) { x = unlisted(c); csetAll(x, params); cc.register(x); } return x; } finally { _close(__1); } } static public AutoCloseable tempDBLock(Concepts concepts) { return tempLock(concepts.lock); } static public AutoCloseable tempDBLock() { return tempDBLock(db_mainConcepts()); } static public void typeWriterConsole() { if (isHeadless()) return; Font f = typeWriterFont(); consoleFont(f); consoleInputFont(f); } static public String hrefBlank(String link, Object contents, Object... params) { return tag("a", contents, concatArrays(new Object[] { "href", link, "target", "_blank" }, params)); } static public String appendQueryToURL(String url, Map params) { if (url == null) return null; String data = makePostData(params); if (empty(data)) return url; int idx = smartIndexOf(url, '#'); String url2 = takeFirst(url, idx); return url2 + (url2.contains("?") ? "&" : "?") + data + substring(url, idx); } static public String appendQueryToURL(String url, Object... data) { return appendQueryToURL(url, litmap(data)); } static public List javaTokC(String s) { if (s == null) return null; int l = s.length(); ArrayList tok = new ArrayList(); int i = 0; while (i < l) { int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); i = j; } return tok; } static public List nlTok(String s) { return javaTokPlusPeriod(s); } static public List sortedIgnoreCase(Collection c) { List l = cloneList(c); Collections.sort(l, caseInsensitiveComparator()); return l; } static public Chain toChain(Iterable l) { Iterator it = iterator(l); if (!it.hasNext()) return null; Chain c = new Chain<>(it.next()); Chain last = c; int size = 1; while (it.hasNext()) { ++size; Chain x = new Chain(it.next()); last.next = x; last = x; } Chain x = c; while (x != null) { x.size = size--; x = x.next; } return c; } static public Chain chainPlus(Chain chain, A a) { return new Chain(a, chain); } static public ReverseChain chainPlus(ReverseChain chain, A a) { return new ReverseChain(chain, a); } static public A last(List l) { return empty(l) ? null : l.get(l.size() - 1); } static public char last(String s) { return empty(s) ? '#' : s.charAt(l(s) - 1); } static public int last(int[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static public double last(double[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static public A last(A[] a) { return l(a) != 0 ? a[l(a) - 1] : null; } static public A last(Iterator it) { A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static public A last(Collection l) { if (l == null) return null; if (l instanceof List) return (A) last(((List) l)); if (l instanceof SortedSet) return (A) last(((SortedSet) l)); Iterator it = iterator(l); A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static public A last(SortedSet l) { return l == null ? null : l.last(); } static public A last(ReverseChain l) { return l == null ? null : l.element; } static public ThreadLocal htmlTable2_cellEncoder = new ThreadLocal(); static public String htmlTable2(Object data, Object... __) { boolean htmlEncode = optPar("htmlEncode", __, true); boolean useBr = boolPar("useBr", __); Map paramsByColName = (Map) (optPar("paramsByColName", __)); Object[] tableParams = (Object[]) (optPar("tableParams", __)); Object[] trParams = (Object[]) (optPar("trParams", __)); Object[] tdParams = (Object[]) (optPar("tdParams", __)); Map replaceHeaders = (Map) (optPar("replaceHeaders", __)); boolean noHeader = boolPar("noHeader", __); List> rows = new ArrayList(); List cols = new ContentsIndexedList(); if (data instanceof List) { for (Object x : (List) data) { try { rows.add(dataToTable_makeRow(x, cols)); } catch (Throwable __e) { _handleException(__e); } } } else if (data instanceof Map) { Map map = (Map) data; for (Object key : map.keySet()) { Object value = map.get(key); rows.add(litlist(structureOrText(key), structureOrText(value))); } } else print("Unknown data type: " + data); int w = 0; for (List row : rows) w = max(w, l(row)); StringBuilder buf = new StringBuilder(); buf.append(hopeningtag("table", paramsPlus(tableParams, "border", html_valueLessParam())) + "\n"); if (!noHeader) { buf.append("\n"); for (String cell : padList(cols, w, "")) buf.append(" " + htmlTable2_encodeCell(getOrKeep(replaceHeaders, cell), htmlEncode, useBr) + "\n"); buf.append("\n"); } for (List row : rows) { buf.append(hopeningtag("tr", trParams)); int i = 0; for (String cell : padList(row, w, "")) { String col = get(cols, i++); Object[] params = paramsPlus(tdParams, mapGet(paramsByColName, col)); buf.append(" " + tag("td", htmlTable2_encodeCell(cell, htmlEncode, useBr), params) + "\n"); } buf.append("\n"); } buf.append("\n"); return buf.toString(); } static public String htmlTable2_encodeCell(String cell, boolean useHtmlEncode, boolean useBr) { if (htmlTable2_cellEncoder.get() != null) return (String) callF(htmlTable2_cellEncoder.get(), cell); if (useHtmlEncode) cell = htmlEncode2(cell); if (useBr) cell = nlToBr(cell); return cell; } static public Object[] paramsPlus(Object[] a1, Object... a2) { if (a2 == null) return a1; if (a1 == null) return a2; if (l(a1) == 1 && a1[0] instanceof Map) return new Object[] { mapPlus((Map) a1[0], a2) }; assertEvenLength(a1); assertEvenLength(a2); Map map = paramsToOrderedMap(a1); int n = l(a2); for (int i = 0; i < n; i += 2) { Object key = a2[i]; if (key != null) map.put(key, a2[i + 1]); } return mapToParams(map); } static public Object[] paramsPlus(Map a1, Object... a2) { return paramsPlus(new Object[] { a1 }, a2); } static public boolean isJavaIdentifier(String s) { if (empty(s) || !Character.isJavaIdentifierStart(s.charAt(0))) return false; for (int i = 1; i < s.length(); i++) if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; return true; } static public boolean isCodeSafe(String code) { return isSafeCodeFragment(code); } static public HashMap, Class> loadFunctions_cache = new HashMap(); static public Lock loadFunctions_cached_lock = lock(); static public boolean loadFunctions_preferDiskCache = false; static public Class loadFunctions_cached(String... functions) { return loadFunctions_cached(asList(functions)); } static public Class loadFunctions_cached(Collection functions) { TreeSet functionSet = new TreeSet(functions); Lock __0 = loadFunctions_cached_lock; lock(__0); try { Class c = loadFunctions_cache.get(functionSet); if (c != null) return c; String transpilation = null; if (l(functions) == 1 && isSlowMachine()) { String snippetID = stdFunctions_cached().get(first(functions)); if (nempty(snippetID)) { if (!isMD5(getUpToDateSnippetTranspilationMD5(snippetID))) print("Slow machine mode: " + snippetID + " transpilation not up to date"); else { transpilation = getServerTranspiledWithoutLibs(snippetID); print("Loaded server transpilation: " + snippetID); } } } if (transpilation == null) { String cached = getTranspiledStandardFunctionsIfCached(functionSet); if (cached != null && (loadFunctions_preferDiskCache || standardFunctionsCacheUpToDate(functionSet))) transpilation = cached; } if (transpilation != null) { print("Loading " + joinWithPlus(functionSet)); c = veryQuickJava_finish(transpilation, emptyList()); } if (c == null) c = loadFunctions(functionSet); loadFunctions_cache.put(functionSet, c); assertNotNull(loadFunctions_cache.get(functionSet)); return c; } finally { unlock(__0); } } static public void loadFunctions_cached_clearCache() { Lock __1 = loadFunctions_cached_lock; lock(__1); try { loadFunctions_cache.clear(); } finally { unlock(__1); } } static public void _onLoad_loadFunctions_cached() { ownResource(vmBus_onMessage("refreshedTranspiler", new Runnable() { public void run() { try { loadFunctions_clearCache(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadFunctions_clearCache();"; } })); } static public Object evalWithTimeoutOrException(final Object f, int timeoutMS) { return evalWithTimeoutOrException(timeoutMS, f); } static public Object evalWithTimeoutOrException(int timeoutMS, final Object f) { return eitherAOpt(evalWithTimeout(timeoutMS, f)); } static public Object evalWithTimeoutOrException(double timeoutSeconds, final Object f) { return eitherAOpt(evalWithTimeout(timeoutSeconds, f)); } static public A evalWithTimeoutOrException(int timeoutMS, F0 f) { Either e = evalWithTimeout(timeoutMS, f); if (e.isA()) return (A) e.a(); throw fail(trim("Timeout after " + timeoutMS + " ms. " + unnull(stackTraceForThread(e.b())))); } static public A evalWithTimeoutOrException(double timeoutSeconds, F0 f) { return evalWithTimeoutOrException(toMS_int(timeoutSeconds), f); } static public A evalWithTimeoutOrException(int timeoutMS, IF0 f) { return evalWithTimeoutOrException(timeoutMS, if0ToF0(f)); } static public A evalWithTimeoutOrException(double timeoutSeconds, IF0 f) { return evalWithTimeoutOrException(timeoutSeconds, if0ToF0(f)); } static public F0 runnableToF0(Runnable r) { return r == null ? null : new F0() { public Object get() { try { r.run(); return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "r.run(); null;"; } }; } static public Object call_withVarargs(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findStaticMethod(method, args); if (me != null) return invokeMethod(me, null, args); List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } { if (!(isStaticMethod(m))) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, null, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me != null) return invokeMethod(me, o, args); List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, o, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } } catch (Exception __e) { throw rethrow(__e); } } static public CharSequence subCharSequence(CharSequence s, int x) { return subCharSequence(s, x, s == null ? 0 : s.length()); } static public CharSequence subCharSequence(CharSequence s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; if (x >= s.length()) return ""; if (y < x) y = x; if (y > s.length()) y = s.length(); return s.subSequence(x, y); } static volatile public PersistableThrowable lastException_lastException; static public PersistableThrowable lastException() { return lastException_lastException; } static public void lastException(Throwable e) { lastException_lastException = persistableThrowable(e); } static public String hideCredentials(URL url) { return url == null ? null : hideCredentials(str(url)); } static public String hideCredentials(String url) { try { if (startsWithOneOf(url, "http://", "https://") && isAGIBlueDomain(hostNameFromURL(url))) return url; } catch (Throwable e) { print("HideCredentials", e); } return url.replaceAll("([&?])(_pass|key|cookie)=[^&\\s\"]*", "$1$2="); } static public String hideCredentials(Object o) { return hideCredentials(str(o)); } static public List synchroList() { return Collections.synchronizedList(new ArrayList()); } static public List synchroList(List l) { return Collections.synchronizedList(l); } static public PersistableThrowable persistableThrowable(Throwable e) { return e == null ? null : new PersistableThrowable(e); } static public Throwable innerException(Throwable e) { return getInnerException(e); } static public boolean isInteger(String s) { int n = l(s); if (n == 0) return false; int i = 0; if (s.charAt(0) == '-') if (++i >= n) return false; while (i < n) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static public List concatLists_conservative(List a, List b) { if (empty(a)) return b; if (empty(b)) return a; return concatLists(a, b); } static public List concatLists_conservative(Collection a, Collection b) { if (empty(a) && b instanceof List) return ((List) b); if (empty(b) && a instanceof List) return ((List) a); return concatLists(a, b); } static public List> mapPairsB(final Object f, Iterable> l) { return mapPairB(f, l); } static public List> mapPairsB(F1 f, Iterable> l) { return mapPairB(f, l); } static public List> mapPairsB(IF1 f, Iterable> l) { return mapPairB(f, l); } static public List> mapPairsB(Iterable> l, IF1 f) { return mapPairB(l, f); } static public List> cForwardRefsWithFieldNames(Concept c, Class type) { return mapNonNulls(scanConceptForRefsWithFieldNames(c), p -> isInstanceOf(derefRef(p.a), type) ? pair((A) derefRef(p.a), p.b) : null); } static public List> findBackRefsWithFieldNames(Concept c, Class type) { List> l = new ArrayList(); if (c != null && c.backRefs != null) for (Concept.Ref r : cloneList(c.backRefs)) if (instanceOf(r.concept(), type)) l.add(pair((A) r.concept(), fieldNameForConceptLink(r.concept(), c))); return l; } static public List withoutNulls(Collection l) { if (l instanceof List) if (!containsNulls(((List) l))) return ((List) l); List l2 = new ArrayList(); for (A a : l) if (a != null) l2.add(a); return l2; } static public Map withoutNulls(Map map) { Map map2 = similarEmptyMap(map); for (A a : keys(map)) if (a != null) { B b = map.get(a); if (b != null) map2.put(a, b); } return map2; } static public List withoutNulls(A[] l) { List l2 = new ArrayList(); if (l != null) for (A a : l) if (a != null) l2.add(a); return l2; } static public int[] subArray(int[] b, int start, int end) { int[] x = new int[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public byte[] subArray(byte[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start >= end) return new byte[0]; byte[] x = new byte[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public short[] subArray(short[] b, int start, int end) { if (start <= 0 && end >= l(b)) return b; short[] x = new short[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public float[] subArray(float[] b, int start, int end) { float[] x = new float[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public Object[] subArray(Object[] b, int start) { return subArray(b, start, l(b)); } static public Object[] subArray(Object[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start >= end) return new Object[0]; Object[] x = new Object[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public String joinNempties(String sep, Object... strings) { return joinStrings(sep, strings); } static public String joinNempties(String sep, Iterable strings) { return joinStrings(sep, strings); } static public List javaTokWithAllPlusAngleBracketsC(String s) { return codeTokens(javaTokWithAllPlusAngleBrackets(s)); } static public boolean isAngleBracketed(String s) { return s.startsWith("<") && s.endsWith(">"); } static public List sortByCalculatedFieldDesc(Collection c, final Object f) { return sortByCalculatedFieldDesc_inPlace(cloneList(c), f); } static public List sortByCalculatedFieldDesc(Object f, Collection c) { return sortByCalculatedFieldDesc(c, f); } static public List sortByCalculatedFieldDesc(Iterable c, IF1 f) { List l = cloneList(c); sort(l, new Comparator() { public int compare(A a, A b) { return stdcompare(f.get(b), f.get(a)); } }); return l; } static public List sortByCalculatedFieldDesc(IF1 f, Iterable c) { return sortByCalculatedFieldDesc(c, f); } static public List javaTokWithAllPlusAngleBrackets(String s) { return tok_combineAngleBrackets_keep(javaTokWithAllBrackets(s)); } static public String joinMap(Object f, Iterable l) { return join(map(f, l)); } static public String joinMap(Iterable l, Object f) { return joinMap(f, l); } static public String joinMap(Iterable l, IF1 f) { return joinMap(f, l); } static public String joinMap(IF1 f, Iterable l) { return join(map(f, l)); } static public String joinMap(String separator, Map map, IF2 f) { return join(separator, map(map, f)); } static public boolean eqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return true; return false; } static public boolean match3(String pat, String s) { return match3(pat, s, null); } static public boolean match3(String pat, String s, Matches matches) { if (pat == null || s == null) return false; return match3(pat, parse3_cachedInput(s), matches); } static public boolean match3(String pat, List toks, Matches matches) { List tokpat = parse3_cachedPattern(pat); return match3(tokpat, toks, matches); } static public boolean match3(List tokpat, List toks, Matches matches) { String[] m = match2(tokpat, toks); if (m == null) return false; if (matches != null) matches.m = m; return true; } static public List codeTokens(List tok) { return codeTokensOnly(tok); } static public List collectInstances(Iterable i, Class c) { List l = new ArrayList(); if (i == null) return l; c = primitiveToBoxedTypeOpt(c); for (Object o : i) if (isInstance(c, o)) l.add(o); return l; } static public List collectInstances(Class c, Iterable i) { return collectInstances(i, c); } static public String shortenClassName(String name) { if (name == null) return null; int i = lastIndexOf(name, "$"); if (i < 0) i = lastIndexOf(name, "."); return i < 0 ? name : substring(name, i + 1); } static public Set synchroWeakHashSet() { return Collections.newSetFromMap((Map) newWeakHashMap()); } static public boolean instanceOf(Object o, String className) { if (o == null) return false; String c = o.getClass().getName(); return eq(c, className) || eq(c, "main$" + className); } static public boolean instanceOf(Object o, Class c) { if (c == null) return false; return c.isInstance(o); } static public boolean instanceOf(Class c, Object o) { return instanceOf(o, c); } static public Q dm_ownQ(Q q) { q.rst.enter = dm_rEnter(dm_current_mandatory()); dm_ownResource(q); return q; } static public Q startQ() { return new Q(); } static public Q startQ(String name) { return new Q(name); } static public void dm_ownTimer(Object resource, Object closerHelper) { call(dm_current_generic(), "ownTimer", resource, closerHelper); } static public A dm_ownTimer(A resource) { call(dm_current_generic(), "ownTimer", resource); return resource; } static public FixedRateTimer doEvery(long delay, final Object r) { return doEvery(delay, delay, r); } static public FixedRateTimer doEvery(long delay, long firstDelay, final Object r) { FixedRateTimer timer = new FixedRateTimer(shorten(programID() + ": " + r, 80)); timer.scheduleAtFixedRate(smartTimerTask(r, timer, toInt(delay)), toInt(firstDelay), toInt(delay)); return vmBus_timerStarted(timer); } static public FixedRateTimer doEvery(double initialSeconds, double delaySeconds, final Object r) { return doEvery(toMS(delaySeconds), toMS(initialSeconds), r); } static public FixedRateTimer doEvery(double delaySeconds, final Object r) { return doEvery(toMS(delaySeconds), r); } static public boolean isConceptFieldIndexed(Class c, String field) { return isConceptFieldIndexed(db_mainConcepts(), c, field); } static public boolean isConceptFieldIndexed(Concepts concepts, Class c, String field) { return concepts.getFieldIndex(c, field) != null; } static public ConceptFieldIndexCI indexConceptFieldCI(Class c, String field) { return indexConceptFieldCI(db_mainConcepts(), c, field); } static public ConceptFieldIndexCI indexConceptFieldCI(Concepts concepts, Class c, String field) { ConceptFieldIndexCI idx = getConceptFieldCIIndex(concepts, c, field); return idx != null ? idx : new ConceptFieldIndexCI(concepts, c, field); } static public TreeSet caseInsensitiveSet() { return caseInsensitiveSet_treeSet(); } static public TreeSet caseInsensitiveSet(Collection c) { return caseInsensitiveSet_treeSet(c); } static public TreeSet treeSet() { return new TreeSet(); } static public Collection findConceptsWhere(Class c, Object... params) { return findConceptsWhere(db_mainConcepts(), c, params); } static public Collection findConceptsWhere(String c, Object... params) { return findConceptsWhere(db_mainConcepts(), c, params); } static public Collection findConceptsWhere(Concepts concepts, Class c, Object... params) { ping(); params = expandParams(c, params); if (concepts.fieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getFieldIndex(c, (String) params[i]); if (index != null) { Collection rawList = index.getAll(params[i + 1]); params = dropEntryFromParams(params, i); if (params == null) return rawList; List l = new ArrayList(); for (A x : rawList) if (checkConceptFields(x, params)) l.add(x); return l; } } return filterConcepts(concepts.list(c), params); } static public Collection findConceptsWhere(Concepts concepts, String c, Object... params) { return filterConcepts(concepts.list(c), params); } static public void deleteConcept(long id) { db_mainConcepts().deleteConcept(id); } static public void deleteConcept(Concepts concepts, long id) { concepts.deleteConcept(id); } static public void deleteConcept(Concept c) { if (c != null) c.delete(); } static public void deleteConcept(Concept.Ref ref) { if (ref != null) deleteConcept(ref.get()); } static public HashSet lithashset(A... items) { HashSet set = new HashSet(); for (A a : items) set.add(a); return set; } static public String trimSubstring(String s, int x) { return trim(substring(s, x)); } static public String trimSubstring(String s, int x, int y) { return trim(substring(s, x, y)); } static public String trimSubstring(String s, IntRange r) { return trim(substring(s, r)); } static public String trimSubstring(int x, String s) { return trimSubstring(s, x); } static public int smartIndexOf(String s, String sub, int i) { if (s == null) return 0; i = s.indexOf(sub, min(i, l(s))); return i >= 0 ? i : l(s); } static public int smartIndexOf(String s, int i, char c) { return smartIndexOf(s, c, i); } static public int smartIndexOf(String s, char c, int i) { if (s == null) return 0; i = s.indexOf(c, min(i, l(s))); return i >= 0 ? i : l(s); } static public int smartIndexOf(String s, String sub) { return smartIndexOf(s, sub, 0); } static public int smartIndexOf(String s, char c) { return smartIndexOf(s, c, 0); } static public int smartIndexOf(List l, A sub) { return smartIndexOf(l, sub, 0); } static public int smartIndexOf(List l, int start, A sub) { return smartIndexOf(l, sub, start); } static public int smartIndexOf(List l, A sub, int start) { int i = indexOf(l, sub, start); return i < 0 ? l(l) : i; } static public String ahref_js(String js, Object contents, Object... params) { return empty(js) ? str(contents) : ahref("#", contents, paramsPlus(params, "onclick", addSuffix(trim(js), ";") + " return false;")); } static public String joinWithComma(Collection c) { return join(", ", c); } static public String joinWithComma(String... c) { return join(", ", c); } static public String joinWithComma(Pair p) { return p == null ? "" : joinWithComma(str(p.a), str(p.b)); } static public String copyTextToClipboard(Object _text) { String text = str(_text); StringSelection selection = new StringSelection(text); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); vmBus_send("newClipboardContents", text); return text; } static public A copyImageToClipboard(A img) { TransferableImage trans = new TransferableImage(img); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trans, null); vmBus_send("newClipboardContents", img); print("Copied image to clipboard (" + img.getWidth(null) + "*" + img.getHeight(null) + " px)"); return img; } static public File copyFileToClipboard(File f) { if (f == null) return null; Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new FileTransferable(f), null); vmBus_send("newClipboardContents", f); return f; } static public String javascriptQuote(String s) { return quote(s); } static public String aGlobalID() { return randomID(globalIDLength()); } static public String aGlobalID(Random random) { return randomID(random, globalIDLength()); } static public String hstyle(Object contents) { return hcss(contents); } static public String replaceDollarVars(String s, Object... params) { if (empty(params)) return s; Map vars = mapKeys(__53 -> dropDollarPrefix(__53), (Map) litcimap(params)); return replaceDollarVars_dyn(s, var -> strOrNull(vars.get(var))); } static public String hdiv(Object contents, Object... params) { return div(contents, params); } static public String unicode_smallDownPointingTriangle() { return charToString(0x25BE); } static public String[] toStringArray(Collection c) { String[] a = new String[l(c)]; Iterator it = c.iterator(); for (int i = 0; i < l(a); i++) a[i] = it.next(); return a; } static public String[] toStringArray(Object o) { if (o instanceof String[]) return (String[]) o; else if (o instanceof Collection) return toStringArray((Collection) o); else throw fail("Not a collection or array: " + getClassName(o)); } static public List objectsWhereIC(Collection c, Object... data) { if (c == null) return null; List l = new ArrayList(); for (A x : c) if (checkFieldsIC(x, data)) l.add(x); return l; } static public List lambdaMap(IF1 f, Iterable l) { return map(l, f); } static public List lambdaMap(IF1 f, A[] l) { return map(l, f); } static public List newSubListOrSame(List l, int startIndex) { return newSubListOrSame(l, startIndex, l(l)); } static public List newSubListOrSame(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = max(0, startIndex); endIndex = min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return cloneList(l.subList(startIndex, endIndex)); } static public List newSubListOrSame(List l, IntRange r) { return newSubListOrSame(l, r.start, r.end); } static public String substring(String s, int x) { return substring(s, x, strL(s)); } static public String substring(String s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; int n = s.length(); if (y < x) y = x; if (y > n) y = n; if (x >= y) return ""; return s.substring(x, y); } static public String substring(String s, IntRange r) { return r == null ? null : substring(s, r.start, r.end); } static public String substring(String s, CharSequence l) { return substring(s, l(l)); } static public int[] takeFirstOfIntArray(int[] b, int n) { return subIntArray(b, 0, n); } static public int[] takeFirstOfIntArray(int n, int[] b) { return takeFirstOfIntArray(b, n); } static public Set identityHashSet() { return Collections.newSetFromMap(new IdentityHashMap()); } static public Object[] litObjectArray(Object... l) { return l; } static public boolean isAWTThread() { if (isAndroid()) return false; if (isHeadless()) return false; return isAWTThread_awt(); } static public boolean isAWTThread_awt() { return SwingUtilities.isEventDispatchThread(); } static public Object sleepQuietly_monitor = new Object(); static public void sleepQuietly() { try { assertFalse(isAWTThread()); synchronized (sleepQuietly_monitor) { sleepQuietly_monitor.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static public List reverseInPlace(List l) { return reverseList(l); } static public List sortByFieldInPlace(List l, String field) { sort(l, fieldComparator(field)); return l; } static public List sortByFieldInPlace(String field, List l) { return sortByFieldInPlace(l, field); } static public List objectsWhereFieldGreaterThan(Collection c, String field, Object value) { List l = new ArrayList(); for (A x : unnull(c)) if (cmp(getOpt(x, field), value) > 0) l.add(x); return l; } static public double elapsedSeconds(long time) { return toSeconds(sysNow() - time); } static public Object serveText(Object s) { return call(getMainBot(), "serveByteArray", toUtf8(str(s)), "text/plain; charset=utf8"); } static public String jsonEncode_breakAtLevels(int levels, Object o) { StringBuilder buf = new StringBuilder(); jsonEncode_breakAtLevels(levels, o, buf, 1); return str(buf); } static public void jsonEncode_breakAtLevels(int levels, Object o, StringBuilder buf, int level) { if (o == null) buf.append("null"); else if (o instanceof String) buf.append(quote((String) o)); else if (o instanceof Number || o instanceof Boolean) buf.append(o); else if (o instanceof Map) { Map map = (Map) o; buf.append("{"); boolean first = true; for (Object key : keys(map)) { if (first) first = false; else buf.append(","); if (level == 1) buf.append("\n" + spaces(level * 2)); buf.append(quote((String) key)); buf.append(":"); jsonEncode_breakAtLevels(levels, map.get(key), buf, level + 1); } if (level <= levels) buf.append("\n" + spaces((level - 1) * 2)); buf.append("}"); } else if (o instanceof Collection) { Collection l = (Collection) o; buf.append("["); boolean first = true; for (Object element : l) { if (first) first = false; else buf.append(","); if (level <= levels) buf.append("\n" + spaces(level * 2)); jsonEncode_breakAtLevels(levels, element, buf, level + 1); } if (level <= levels) buf.append("\n" + spaces((level - 1) * 2)); buf.append("]"); } else throw fail("Unknown object for JSON encoding: " + className(o)); } static public Object jsonPrepareData(Object... data) { if (l(data) == 1) return data[0]; return litorderedmap(data); } static public String renderVars_str(Object... params) { List l = new ArrayList(); for (int i = 0; i + 1 < l(params); i += 2) l.add(params[i] + "=" + params[i + 1]); return trim(joinWithComma(l)); } static public A callPostProcessor(Object f, A a) { return f == null ? a : (A) callF(f, a); } static public A callPostProcessor(IF1 f, A a) { return f == null ? a : f.get(a); } static public Object mainBot; static public Object getMainBot() { return mainBot; } static public int iceil(double d) { return (int) Math.ceil(d); } static public TreeMap ciMap() { return caseInsensitiveMap(); } static public List collectField(Iterable c, String field) { List l = new ArrayList(); if (c != null) for (Object a : c) l.add(getOpt(a, field)); return l; } static public List collectField(String field, Iterable c) { return collectField(c, field); } static public IterableIterator iteratorFromFunction(final Object f) { class IFF extends IterableIterator { public A a; public boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } public void getNext() { if (done || a != null) return; a = (A) callF(f); done = a == null; } } ; return new IFF(); } static public IterableIterator iteratorFromFunction(final F0 f) { return iteratorFromFunction_f0(f); } static public List mapPairsToList(Iterable> l, F2 f) { List x = emptyList(l); if (l != null) for (Pair p : l) x.add(callF(f, p.a, p.b)); return x; } static public List mapPairsToList(Iterable> l, IF2 f) { List x = emptyList(l); if (l != null) for (Pair p : l) x.add(f.get(p.a, p.b)); return x; } static public List mapPairsToList(Object f, Iterable> l) { List x = emptyList(l); if (l != null) for (Pair p : l) x.add(callF(f, p.a, p.b)); return x; } static public boolean startsWith(String a, String b) { return a != null && a.startsWith(unnull(b)); } static public boolean startsWith(String a, char c) { return nemptyString(a) && a.charAt(0) == c; } static public boolean startsWith(String a, String b, Matches m) { if (!startsWith(a, b)) return false; m.m = new String[] { substring(a, strL(b)) }; return true; } static public boolean startsWith(List a, List b) { if (a == null || listL(b) > listL(a)) return false; for (int i = 0; i < listL(b); i++) if (neq(a.get(i), b.get(i))) return false; return true; } static public boolean endsWith(String a, String b) { return a != null && a.endsWith(b); } static public boolean endsWith(String a, char c) { return nempty(a) && lastChar(a) == c; } static public boolean endsWith(String a, String b, Matches m) { if (!endsWith(a, b)) return false; m.m = new String[] { dropLast(l(b), a) }; return true; } static public List toLinesFullTrim(String s) { List l = new ArrayList(); for (String line : toLines(s)) if (nempty(line = trim(line))) l.add(line); return l; } static public List toLinesFullTrim(File f) { List l = new ArrayList(); for (String line : linesFromFile(f)) if (nempty(line = trim(line))) l.add(line); return l; } static public Object withDBLock(Object r) { Lock __0 = db_mainConcepts().lock; lock(__0); try { return callF(r); } finally { unlock(__0); } } static public A withDBLock(F0 r) { return (A) withDBLock((Object) r); } static public Object withDBLock(Concepts concepts, Object r) { Lock __1 = concepts.lock; lock(__1); try { return callF(r); } finally { unlock(__1); } } static public A withDBLock(Concepts concepts, F0 r) { return (A) withDBLock(concepts, (Object) r); } static public A withDBLock(Concept concept, IF0 r) { return (A) withDBLock(concept._concepts, r); } static public List getPlural_specials = ll("sheep", "fish"); static public String getPlural(String s) { if (containsIgnoreCase(getPlural_specials, s)) return s; if (ewic(s, "y")) return dropSuffixIgnoreCase("y", s) + "ies"; if (ewicOneOf(s, "ss", "ch")) return s + "es"; if (ewic(s, "s")) return s; return s + "s"; } static public String htmlEncode_nlToBr(String s) { return nlToBr(htmlEncode2(s)); } static public String fromLines(Iterable lines) { StringBuilder buf = new StringBuilder(); if (lines != null) for (Object line : lines) buf.append(str(line)).append('\n'); return buf.toString(); } static public String fromLines(String... lines) { return fromLines(asList(lines)); } static public IterableIterator toLines(File f) { return linesFromFile(f); } static public List toLines(String s) { List lines = new ArrayList(); if (s == null) return lines; int start = 0; while (true) { int i = toLines_nextLineBreak(s, start); if (i < 0) { if (s.length() > start) lines.add(s.substring(start)); break; } lines.add(s.substring(start, i)); if (s.charAt(i) == '\r' && i + 1 < s.length() && s.charAt(i + 1) == '\n') i += 2; else ++i; start = i; } return lines; } static public int toLines_nextLineBreak(String s, int start) { int n = s.length(); for (int i = start; i < n; i++) { char c = s.charAt(i); if (c == '\r' || c == '\n') return i; } return -1; } static public int nfilter(Iterable c, IF1 pred) { return nfilter(pred, c); } static public int nfilter(IF1 pred, Iterable c) { int n = 0; if (c != null) for (A o : c) if (pred.get(o)) ++n; return n; } static public int nfilter(Iterable c, Object pred) { int n = 0; if (c != null) for (Object o : c) if (isTrue(callF(pred, o))) ++n; return n; } static public int nfilter(Object pred, Iterable c) { return nfilter(c, pred); } static public String formatWithThousands(long l) { return formatWithThousandsSeparator(l); } static public double fraction(double d) { return d % 1; } static public String n_fancy2(long l, String singular, String plural) { return formatWithThousandsSeparator(l) + " " + trim(l == 1 ? singular : plural); } static public String n_fancy2(Collection l, String singular, String plural) { return n_fancy2(l(l), singular, plural); } static public String n_fancy2(Map m, String singular, String plural) { return n_fancy2(l(m), singular, plural); } static public String n_fancy2(Object[] a, String singular, String plural) { return n_fancy2(l(a), singular, plural); } static public String n_fancy2(MultiSet ms, String singular, String plural) { return n_fancy2(l(ms), singular, plural); } static public String[] asStringArray(Collection c) { return toStringArray(c); } static public String[] asStringArray(Object o) { return toStringArray(o); } static public String toLower(String s) { return s == null ? null : s.toLowerCase(); } static public char toLower(char c) { return Character.toLowerCase(c); } static public List words(String s) { return codeTokens(dropPunctuation(javaTok(s))); } static public String ahref_unstyled(String link, Object contents, Object... params) { if (link == null) return str(contents); return ahref(link, contents, paramsPlus(params, "style", unparseCSSParameter(mapPlus_noOverwrite(parseCSSParameter(stringPar("style", params)), "text-decoration", "none", "color", "inherit")))); } static public String hsnippetimg(String imageID, Object... params) { return himg(snippetImageLink(imageID), params); } static public int calcHeight(int w, int h, int newWidth) { return iround(doubleRatio(h, w) * newWidth); } static public SimpleDateFormat simpleDateFormat_local(String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(localTimeZone()); return sdf; } static public Object collectionMutex(List l) { return l; } static public Object collectionMutex(Object o) { if (o instanceof List) return o; String c = className(o); if (eq(c, "java.util.TreeMap$KeySet")) c = className(o = getOpt(o, "m")); else if (eq(c, "java.util.HashMap$KeySet")) c = className(o = get_raw(o, "this$0")); if (eqOneOf(c, "java.util.TreeMap$AscendingSubMap", "java.util.TreeMap$DescendingSubMap")) c = className(o = get_raw(o, "m")); return o; } static public boolean startsWithIgnoreCase(String a, String b) { return regionMatchesIC(a, 0, b, 0, b.length()); } static public boolean isSubclass(Class a, Class b) { return a != null && b != null && b.isAssignableFrom(a); } static public List javaTokForStructure(String s) { return javaTok_noMLS(s); } static public boolean eqGet(List l, int i, Object o) { return eq(get(l, i), o); } static public boolean eqGet(Map map, A key, Object o) { return eq(mapGet(map, key), o); } static public void replaceTokens(List tok, int i, int j, String s) { clearAllTokens(tok, i + 1, j); tok.set(i, s); } static public void replaceTokens(List tok, String s) { clearAllTokens(tok, 1, l(tok)); tok.set(0, s); } static public String dropPrefix(String prefix, String s) { return s == null ? null : s.startsWith(prefix) ? s.substring(l(prefix)) : s; } static public boolean isOpeningBracket(String s) { return eqOneOf(s, "(", "{", "["); } static public boolean containsClosingBracket(List l) { return any(__54 -> isClosingBracket(__54), l); } static public List subList(List l, int startIndex) { return subList(l, startIndex, l(l)); } static public List subList(int startIndex, int endIndex, List l) { return subList(l, startIndex, endIndex); } static public List subList(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = Math.max(0, startIndex); endIndex = Math.min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return l.subList(startIndex, endIndex); } static public List subList(List l, IntRange r) { return subList(l, r.start, r.end); } static public String joinSubList(List l, int i, int j) { return join(subList(l, i, j)); } static public String joinSubList(List l, int i) { return join(subList(l, i)); } static public String joinSubList(List l, IntRange r) { return r == null ? null : joinSubList(l, r.start, r.end); } static public String spaces(int n) { return rep(' ', n); } static public boolean isClosingBracket(String s) { return eqOneOf(s, ")", "}", "]"); } static public Class __javax; static public Class getJavaX() { try { return __javax; } catch (Exception __e) { throw rethrow(__e); } } static public ThreadLocal print_byThread() { synchronized (print_byThread_lock) { if (print_byThread == null) print_byThread = new ThreadLocal(); } return print_byThread; } static public AutoCloseable tempInterceptPrint(F1 f) { return tempSetThreadLocal(print_byThread(), f); } static public String getStackTrace2(Throwable e) { return hideCredentials(getStackTrace(unwrapTrivialExceptionWraps(e)) + replacePrefix("java.lang.RuntimeException: ", "FAIL: ", hideCredentials(str(innerException2(e)))) + "\n"); } static public Object defaultDefaultClassFinder() { return new F1() { public Class get(String name) { { Class c = findClass_fullName(name); if (c != null) return c; } if (name.startsWith("loadableUtils.utils$")) { Class c = findClass_fullName("main" + name.substring(19)); if (c != null) return c; } else if (name.startsWith("main$")) { Class c = findClass_fullName("loadableUtils.utils" + name.substring(4)); if (c != null) return c; } return null; } }; } static public String programIDWithCase() { return nempty(caseID()) ? programID() + "/" + quoteUnlessIdentifierOrInteger(caseID()) : programID(); } static public void failIfUnlicensed() { assertTrue("license off", licensed()); } static public int countConcepts(Concepts concepts, Class c, Object... params) { return concepts.countConcepts(c, params); } static public int countConcepts(Class c, Object... params) { return db_mainConcepts().countConcepts(c, params); } static public int countConcepts() { return db_mainConcepts().countConcepts(); } static public int countConcepts(String className) { return db_mainConcepts().countConcepts(className); } static public int countConcepts(Concepts concepts, String className) { return concepts.countConcepts(className); } static public int countConcepts(Concepts concepts) { return concepts.countConcepts(); } static public List sortedByCalculatedField(Iterable c, Object f) { return sortByCalculatedField(c, f); } static public List sortedByCalculatedField(Object f, Iterable c) { return sortedByCalculatedField(c, f); } static public List sortedByCalculatedField(IF1 f, Iterable c) { return sortedByCalculatedField(c, f); } static public List sortedByCalculatedField(Iterable c, IF1 f) { List l = cloneList(c); sort(l, new Comparator() { public int compare(A a, A b) { return stdcompare(f.get(a), f.get(b)); } }); return l; } static public String singleFieldName(Class c) { Set l = listFields(c); if (l(l) != 1) throw fail("No single field found in " + c + " (have " + n(l(l), "fields") + ")"); return first(l); } static public void warnIfOddCount(Object... list) { if (odd(l(list))) printStackTrace("Odd list size: " + list); } static public boolean checkConceptFieldsIC(Concept x, Object... data) { for (int i = 0; i < l(data); i += 2) if (!eqicOrEq(cget(x, (String) data[i]), deref(data[i + 1]))) return false; return true; } static public boolean cicWithSmartWordBoundary(String a, String b) { return containsRegexpIC(a, phraseToRegExp(b)); } static public boolean match3_startOrEndOfLine(String pat, String s, boolean startOfLine, boolean endOfLine) { if (startOfLine) return endOfLine ? match3(pat, s) : matchStart(pat, s); else return endOfLine ? matchEnd(pat, s) : find3(pat, s); } static public boolean any(Object pred, Iterable l) { if (l != null) for (A a : l) if (isTrue(callF(pred, a))) return true; return false; } static public boolean any(IF1 pred, Iterable l) { return any((Object) pred, l); } static public boolean any(Iterable l, IF1 pred) { return any(pred, l); } static public boolean any(A[] l, IF1 pred) { if (l != null) for (A a : l) if (pred.get(a)) return true; return false; } static public boolean any(Iterable l) { if (l != null) for (Boolean a : l) if (isTrue(a)) return true; return false; } static public String tok_deRoundBracket(String s) { return tok_isRoundBracketed(s) ? join(dropFirstThreeAndLastThree(javaTok(s))) : s; } static public List javaTokWithBrackets(String s) { return javaTokPlusBrackets(s); } static public List tok_splitAtComma(String s) { return tok_splitAtComma(javaTok(s)); } static public List tok_splitAtComma(List tok) { List out = new ArrayList(); for (int i = 0; i < l(tok); i++) { int j = smartIndexOf(tok, ",", i); out.add(joinSubList(tok, i + 1, j - 1)); i = j; } return out; } static public List tok_splitAtPlus(String s) { return tok_splitAtPlus(javaTokWithAllBrackets_cached(s)); } static public List tok_splitAtPlus(List tok) { return splitAtTokens(tok, "+"); } static public A[] dropLast(A[] a) { return dropLast(a, 1); } static public A[] dropLast(A[] a, int n) { if (a == null) return null; n = Math.min(n, a.length); A[] b = arrayOfSameType(a, a.length - n); System.arraycopy(a, 0, b, 0, b.length); return b; } static public List dropLast(List l) { return subList(l, 0, l(l) - 1); } static public List dropLast(int n, List l) { return subList(l, 0, l(l) - n); } static public List dropLast(Iterable l) { return dropLast(asList(l)); } static public String dropLast(String s) { return substring(s, 0, l(s) - 1); } static public String dropLast(String s, int n) { return substring(s, 0, l(s) - n); } static public String dropLast(int n, String s) { return dropLast(s, n); } static public List tok_splitAtAsterisk(String s) { return tok_splitAtAsterisk(javaTokWithAllBrackets_cached(s)); } static public List tok_splitAtAsterisk(List tok) { return splitAtTokens(tok, "*"); } static public double parseDouble(String s) { return Double.parseDouble(s); } static public A second(List l) { return get(l, 1); } static public A second(Iterable l) { if (l == null) return null; Iterator it = iterator(l); if (!it.hasNext()) return null; it.next(); return it.hasNext() ? it.next() : null; } static public A second(A[] bla) { return bla == null || bla.length <= 1 ? null : bla[1]; } static public B second(Pair p) { return p == null ? null : p.b; } static public A second(Producer p) { if (p == null) return null; if (p.next() == null) return null; return p.next(); } static public char second(String s) { return charAt(s, 1); } static public B second(Either e) { return e == null ? null : e.bOpt(); } static public boolean isQuoted(String s) { if (isNormalQuoted(s)) return true; return isMultilineQuoted(s); } static public List tok_combineAngleBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eq(t, "<")) { int j = findEndOfAngleBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public ArrayList intArrayToList(int[] a) { if (a == null) return null; return intArrayToList(a, 0, a.length); } static public ArrayList intArrayToList(int[] a, int from, int to) { if (a == null) return null; ArrayList l = new ArrayList<>(to - from); for (int i = from; i < to; i++) l.add(a[i]); return l; } static public String angleBracket(String s) { return "<" + s + ">"; } static public void withCancelPoint(VF1 r) { CancelPoint cp = newCancelPoint(); try { try { callF(r, cp); } catch (Throwable e) { e = innerException(e); if (!(e instanceof CancelToCancelPoint && ((CancelToCancelPoint) e).cp == cp)) rethrow(e); } } finally { _close(cp); } } static public void withCancelPoint(IVF1 r) { CancelPoint cp = newCancelPoint(); try { try { r.get(cp); } catch (Throwable e) { e = innerException(e); if (!(e instanceof CancelToCancelPoint && ((CancelToCancelPoint) e).cp == cp)) rethrow(e); } } finally { _close(cp); } } static public RuntimeException cancelTo(CancelPoint cp) { if (cp.closed) throw fail("cancel point closed"); throw new CancelToCancelPoint(cp); } static public boolean flexMatchIC_iterate_debug = false; static public boolean flexMatchIC_iterate_useTokenization = true; static public void flexMatchIC_iterate(String pat, String input, VF1 onMatch, Object... __) { if (flexMatchIC_iterate_debug) print("flexMatchIC_iterate " + pat + " / " + input); IF1> tokenizer = optPar("tokenizer", __, __1 -> javaTokNPunctuation_plusAsterisk(__1)); flexMatchIC_iterate(pat, callTokenizer(tokenizer, pat), callTokenizer(tokenizer, input), onMatch, __); } static public void flexMatchIC_iterate(String pat, List tokPat, List tokInput, VF1 onMatch, Object... __) { List varIndices = flexMatchIC_getVarIndices(tokPat, tokInput); if (varIndices == null) return; if (flexMatchIC_iterate_debug) printStructs("varIndices", varIndices, "tokPat", tokPat, "tokInput", tokInput); List> spreadInputs = ai_spreadCertainIndices_2(tokPat, tokInput, varIndices); for (List tok : spreadInputs) { if (flexMatchIC_iterate_debug) print("Testing spread " + sfu(codeTokens(tokPat)) + " with input: " + sfu(codeTokens(tok))); Matches m = new Matches(); if (flexMatchIC_iterate_useTokenization ? match3(tokPat, tok, m) : match(pat, tok, m)) { if (flexMatchIC_iterate_debug) print("Got match: " + m); callF(onMatch, m); } } } static public Map matchesToMapUsingVarList_ciMap(Matches m, List vars) { if (m == null) return null; Map map = ciMap(); int n = min(l(m.m), l(vars)); for (int i = 0; i < n; i++) if (!strictPutIC(map, vars.get(i), m.get(i))) return null; return map; } static public Map classForName_cache = synchroHashMap(); static public Class classForName(String name) { try { if (classForName_cache == null) return Class.forName(name); Class c = classForName_cache.get(name); if (c == null) classForName_cache.put(name, c = Class.forName(name)); return c; } catch (Exception __e) { throw rethrow(__e); } } static public Map nuObjectWithoutArguments_cache = newDangerousWeakHashMap(); static public Object nuObjectWithoutArguments(String className) { try { return nuObjectWithoutArguments(classForName(className)); } catch (Exception __e) { throw rethrow(__e); } } static public A nuObjectWithoutArguments(Class c) { try { if (nuObjectWithoutArguments_cache == null) return (A) nuObjectWithoutArguments_findConstructor(c).newInstance(); Constructor m = nuObjectWithoutArguments_cache.get(c); if (m == null) nuObjectWithoutArguments_cache.put(c, m = nuObjectWithoutArguments_findConstructor(c)); return (A) m.newInstance(); } catch (Exception __e) { throw rethrow(__e); } } static public Constructor nuObjectWithoutArguments_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (empty(m.getParameterTypes())) { makeAccessible(m); return m; } throw fail("No default constructor found in " + c.getName()); } static public Field makeAccessible(Field f) { try { f.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, f); } return f; } static public Method makeAccessible(Method m) { try { m.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, m); } return m; } static public Constructor makeAccessible(Constructor c) { try { c.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, c); } return c; } static public List getClasses(Object[] array) { List l = emptyList(l(array)); for (Object o : array) l.add(_getClass(o)); return l; } static public boolean isInstanceX(Class type, Object arg) { if (type == boolean.class) return arg instanceof Boolean; if (type == int.class) return arg instanceof Integer; if (type == long.class) return arg instanceof Long; if (type == float.class) return arg instanceof Float; if (type == short.class) return arg instanceof Short; if (type == char.class) return arg instanceof Character; if (type == byte.class) return arg instanceof Byte; if (type == double.class) return arg instanceof Double; return type.isInstance(arg); } static public String intToHex_flexLength(int i) { return Integer.toHexString(i); } static public List dropAllTags(List tok) { List list = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && t.startsWith("<")) { list.set(list.size() - 1, list.get(list.size() - 1) + tok.get(i + 1)); ++i; } else list.add(t); } return list; } static public String dropAllTags(String html) { return join(dropAllTags(htmlcoarsetok(html))); } static public Object[] arrayPlus(Object[] a1, Object... a2) { return concatArrays(a1, a2); } static public boolean regionMatches(String a, int offsetA, String b, int offsetB, int len) { return a != null && b != null && a.regionMatches(offsetA, b, offsetB, len); } static public boolean regionMatches(String a, int offsetA, String b) { return regionMatches(a, offsetA, b, 0, l(b)); } static public String javaTok_substringN(String s, int i, int j) { if (i == j) return ""; if (j == i + 1 && s.charAt(i) == ' ') return " "; return s.substring(i, j); } static public String javaTok_substringC(String s, int i, int j) { return s.substring(i, j); } static public List javaTokWithExisting(String s, List existing) { ++javaTok_n; int nExisting = javaTok_opt && existing != null ? existing.size() : 0; ArrayList tok = existing != null ? new ArrayList(nExisting) : new ArrayList(); int l = s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' && Character.isJavaIdentifierStart(d) && i + 2 < l && "'\\".indexOf(s.charAt(i + 2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else ++j; if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static public boolean javaTokWithExisting_isCopyable(String t, String s, int i, int j) { return t.length() == j - i && s.regionMatches(i, t, 0, j - i); } static public Map javaTokForJFind_array_cache = synchronizedMRUCache(1000); static public String[] javaTokForJFind_array(String s) { String[] tok = javaTokForJFind_array_cache.get(s); if (tok == null) javaTokForJFind_array_cache.put(s, tok = codeTokensAsStringArray(jfind_preprocess(javaTok(s)))); return tok; } static public int findCodeTokens(List tok, String... tokens) { return findCodeTokens(tok, 1, false, tokens); } static public int findCodeTokens(List tok, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, 1, ignoreCase, tokens); } static public int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, startIdx, ignoreCase, tokens, null); } static public HashSet findCodeTokens_specials = lithashset("*", "", "", "", "\\*"); static public int findCodeTokens_bails, findCodeTokens_nonbails; static public interface findCodeTokens_Matcher { public boolean get(String token); } static public int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String[] tokens, Object condition) { int end = tok.size() - tokens.length * 2 + 2, nTokens = tokens.length; int i = startIdx | 1; String firstToken = tokens[0]; if (!ignoreCase && !findCodeTokens_specials.contains(firstToken)) { while (i < end && !firstToken.equals(tok.get(i))) i += 2; } findCodeTokens_Matcher[] matchers = new findCodeTokens_Matcher[nTokens]; for (int j = 0; j < nTokens; j++) { String p = tokens[j]; findCodeTokens_Matcher matcher; if (p.equals("*")) matcher = t -> true; else if (p.equals("")) matcher = t -> isQuoted(t); else if (p.equals("")) matcher = t -> isIdentifier(t); else if (p.equals("")) matcher = t -> isInteger(t); else if (p.equals("\\*")) matcher = t -> t.equals("*"); else if (ignoreCase) matcher = t -> eqic(p, t); else matcher = t -> t.equals(p); matchers[j] = matcher; } outer: for (; i < end; i += 2) { for (int j = 0; j < nTokens; j++) if (!matchers[j].get(tok.get(i + j * 2))) continue outer; if (condition == null || checkTokCondition(condition, tok, i - 1)) return i; } return -1; } static public String jreplaceExpandRefs(String s, List tokref) { if (!contains(s, '$')) return s; List tok = javaTok(s); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("$") && isInteger(t.substring(1))) { String x = tokref.get(-1 + parseInt(t.substring(1)) * 2); tok.set(i, x); } else if (t.equals("\\")) { tok.set(i, ""); i += 2; } } return join(tok); } static public void clearAllTokens(List tok) { for (int i = 0; i < tok.size(); i++) tok.set(i, ""); } static public void clearAllTokens(List tok, int i, int j) { for (; i < j; i++) tok.set(i, ""); } static public List reTok(List tok) { replaceCollection(tok, javaTok(tok)); return tok; } static public List reTok(List tok, int i) { return reTok(tok, i, i + 1); } static public List reTok(List tok, int i, int j) { i = max(i & ~1, 0); j = min(l(tok), j | 1); if (i >= j) return tok; List t = javaTok(joinSubList(tok, i, j)); replaceListPart(tok, i, j, t); return tok; } static public List reTok(List tok, IntRange r) { if (r != null) reTok(tok, r.start, r.end); return tok; } static public void mapPut(Map map, A key, B value) { if (map != null && key != null && value != null) map.put(key, value); } static public void mapPut(Map map, Pair p) { if (map != null && p != null) map.put(p.a, p.b); } static public boolean neqic(String a, String b) { return !eqic(a, b); } static public boolean neqic(char a, char b) { return !eqic(a, b); } static public A optPar(ThreadLocal tl, A defaultValue) { A a = tl.get(); if (a != null) { tl.set(null); return a; } return defaultValue; } static public A optPar(ThreadLocal tl) { return optPar(tl, null); } static public Object optPar(Object[] params, String name) { return optParam(params, name); } static public Object optPar(String name, Object[] params) { return optParam(params, name); } static public Object optPar(String name, Map params) { return optParam(name, params); } static public A optPar(Object[] params, String name, A defaultValue) { return optParam(params, name, defaultValue); } static public A optPar(String name, Object[] params, A defaultValue) { return optParam(params, name, defaultValue); } static public Object[] changeParam(Object[] params, String name, Object value) { if (eq(optPar(params, name), value)) return params; Map map = paramsToOrderedMap(params); map.put(name, value); return mapToParams(map); } static public Object[] mapToParams(Map map) { return mapToObjectArray(map); } static public Object[] unrollParams(Object[] params) { if (l(params) == 1 && params[0] instanceof Map) return mapToParams((Map) params[0]); return params; } static public String htmlQuote(String s) { return "\"" + htmlencode_forParams(s) + "\""; } static public int toInt(Object o) { if (o == null) return 0; if (o instanceof Number) return ((Number) o).intValue(); if (o instanceof String) return parseInt(((String) o)); if (o instanceof Boolean) return boolToInt(((Boolean) o)); throw fail("woot not int: " + getClassName(o)); } static public int toInt(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static public String[] drop(int n, String[] a) { n = Math.min(n, a.length); String[] b = new String[a.length - n]; System.arraycopy(a, n, b, 0, b.length); return b; } static public Object[] drop(int n, Object[] a) { n = Math.min(n, a.length); Object[] b = new Object[a.length - n]; System.arraycopy(a, n, b, 0, b.length); return b; } static public ArrayList toList(A[] a) { return asList(a); } static public ArrayList toList(int[] a) { return asList(a); } static public ArrayList toList(Set s) { return asList(s); } static public ArrayList toList(Iterable s) { return asList(s); } static public List> findContainerTag(List tok, String tag) { List> l = new ArrayList(); for (int i = 1; i < l(tok); i += 2) if (isOpeningTag(tok.get(i), tag)) { int j, level = 1; for (j = i + 2; j < tok.size(); j += 2) if (isOpeningTag(tok.get(j), tag)) ++level; else if (isTag(tok.get(j), "/" + tag)) { --level; if (level == 0) { l.add(tok.subList(i - 1, j + 2)); break; } } i = j; } return l; } static public List> findContainerTag(String html, String tag) { return findContainerTag(htmlTok(html), tag); } static public String addLineBreak(String s) { return addSuffix(s, "\n"); } static public String snippetRawURL_maxCache(String snippetID) { return snippetRawURL_maxCache(snippetID, null); } static public String snippetRawURL_maxCache(String snippetID, String contentType) { return "https://botcompany.de/serve/" + psI(snippetID) + htmlQuery("ct", contentType, "maxCache", 1); } static public BigInteger bigint(String s) { return new BigInteger(s); } static public BigInteger bigint(long l) { return BigInteger.valueOf(l); } static public String stringOptPar(Object[] params, String name) { return (String) optPar(params, name); } static public Object[] paramsWithout(Object[] a1, Object... keys) { if (l(a1) == 1 && a1[0] instanceof Map) return new Object[] { mapMinus((Map) a1[0], keys) }; Set set = lithashset(keys); List l = new ArrayList(); int n = l(a1); for (int i = 0; i < n; i += 2) if (i == n - 1) l.add(a1[i]); else if (!set.contains(a1[i])) { l.add(a1[i]); l.add(a1[i + 1]); } return toObjectArray(l); } static public A lookupIgnoreCase(Map map, String key) { for (String s : map.keySet()) if (eqic(s, key)) return map.get(s); return null; } static public List lookupIgnoreCase(MultiMap map, String key) { for (String s : map.keySet()) if (eqic(s, key)) return map.get(s); return litlist(); } static public Set synchroHashSet() { return Collections.synchronizedSet(new HashSet()); } static public Runnable _topLevelErrorHandling(final Runnable runnable) { final Object info = _threadInfo(); return new Runnable() { public void run() { try { try { _threadInheritInfo(info); runnable.run(); } catch (Throwable __e) { _handleException(__e); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcall {\r\n _threadInheritInfo(info);\r\n runnable.run();\r\n }"; } }; } static public Runnable toRunnable(final Object o) { if (o instanceof Runnable) return (Runnable) o; return new Runnable() { public void run() { try { callF(o); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(o)"; } }; } static public String defaultThreadName_name; static public String defaultThreadName() { if (defaultThreadName_name == null) defaultThreadName_name = "A thread by " + programID(); return defaultThreadName_name; } static public Object pcallF(Object f, Object... args) { return pcallFunction(f, args); } static public A pcallF(F0 f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { return null; } } static public B pcallF(F1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { return null; } } static public void pcallF(VF1 f, A a) { try { { if (f != null) f.get(a); } } catch (Throwable __e) { _handleException(__e); } } static public B pcallF(IF1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { return null; } } static public boolean setAdd(Collection c, A a) { if (c == null || c.contains(a)) return false; c.add(a); return true; } static public Runnable wrapAsActivity(Object r) { return toRunnable(r); } static public Map _registerThread_threads; static public Object _onRegisterThread; static public Thread _registerThread(Thread t) { if (_registerThread_threads == null) _registerThread_threads = newWeakHashMap(); _registerThread_threads.put(t, true); vm_generalWeakSubMap("thread2mc").put(t, weakRef(mc())); callF(_onRegisterThread, t); return t; } static public void _registerThread() { _registerThread(Thread.currentThread()); } static public void cancelThread(Thread t) { if (t == null) return; ping(); synchronized (ping_actions) { ping_actions.put(t, "cancelled"); ping_anyActions = true; } } static public int toInt_checked(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static public A setThreadLocal(ThreadLocal tl, A value) { if (tl == null) return null; A old = tl.get(); tl.set(value); return old; } static public char charAt(String s, int i) { return s != null && i >= 0 && i < s.length() ? s.charAt(i) : '\0'; } static public String firstJavaToken(String s) { if (s == null) return null; int l = s.length(); int j = 0; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } if (j >= l) return null; int i = j; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else ++j; return quickSubstring(s, i, j); } static public List htmlcoarsetok(String s) { List tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0; while (i < l) { int j = i; char c; while (j < l) { if (s.charAt(j) != '<') ++j; else if (s.substring(j, Math.min(j + 4, l)).equals("")); j = Math.min(j + 3, l); } else { char d = charAt(s, j + 1); if (d == '/' || isLetter(d)) break; else ++j; } } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); if (c == '<') { ++j; while (j < l && s.charAt(j) != '>') ++j; if (j < l) ++j; } tok.add(s.substring(i, j)); i = j; } if ((tok.size() & 1) == 0) tok.add(""); return tok; } static public String pre(Object contents, Object... params) { return tag("pre", contents, params); } static public void assertFalse(Object o) { if (!(eq(o, false))) throw fail(str(o)); } static public boolean assertFalse(boolean b) { if (b) throw fail("oops"); return b; } static public boolean assertFalse(String msg, boolean b) { if (b) throw fail(msg); return b; } static public boolean _inCore() { return false; } static public List hotwire_copyOver_after = synchroList(); static public void hotwire_copyOver(Class c) { for (String field : ll("print_log", "print_silent", "androidContext", "_userHome")) setOptIfNotNull(c, field, getOpt(mc(), field)); setOptIfNotNull(c, "mainBot", getMainBot()); setOpt(c, "creator_class", new WeakReference(mc())); pcallFAll(hotwire_copyOver_after, c); } static public String reverseString(String s) { return new StringBuilder(s).reverse().toString(); } static public String roundBracket(String s) { return "(" + s + ")"; } static public int jfind(String s, String in) { return jfind(javaTok(s), in); } static public int jfind(List tok, String in) { return jfind(tok, 1, in); } static public int jfind(List tok, int startIdx, String in) { return jfind(tok, startIdx, in, null); } static public int jfind(List tok, String in, Object condition) { return jfind(tok, 1, in, condition); } static public int jfind(List tok, String in, ITokCondition condition) { return jfind(tok, 1, in, condition); } static public int jfind(List tok, int startIndex, String in, ITokCondition condition) { return jfind(tok, startIndex, in, toTokCondition(condition)); } static public int jfind(List tok, int startIdx, String in, Object condition) { return jfind(tok, startIdx, javaTokForJFind_array(in), condition); } static public int jfind(List tok, List tokin) { return jfind(tok, 1, tokin); } static public int jfind(List tok, int startIdx, List tokin) { return jfind(tok, startIdx, tokin, null); } static public int jfind(List tok, int startIdx, String[] tokinC, Object condition) { return findCodeTokens(tok, startIdx, false, tokinC, condition); } static public int jfind(List tok, int startIdx, List tokin, Object condition) { return jfind(tok, startIdx, codeTokensAsStringArray(tokin), condition); } static public List jfind_preprocess(List tok) { for (String type : litlist("quoted", "id", "int")) replaceSublist(tok, ll("<", "", type, "", ">"), ll("<" + type + ">")); replaceSublist(tok, ll("\\", "", "*"), ll("\\*")); return tok; } static public String asciiSideBySideWithSeparator(String sep, List texts) { if (empty(texts)) return asciiSideBySide(texts); int rows = maxLineCount(texts); List out = new ArrayList(); for (int i = 0; i < l(texts); i++) { if (i != 0) out.add(repLine(rows, sep)); out.add(texts.get(i)); } return asciiSideBySide(out); } static public List pairsA(Collection> l) { return firstOfPairs(l); } static public List pairsB(Collection> l) { return secondOfPairs(l); } static public String optionalCurlyBrace(String s) { return isCurlyBraced(s) ? s : curlyBrace(s); } static public A listGet(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static public TreeMap caseInsensitiveMap() { return new TreeMap(caseInsensitiveComparator()); } static public int[] emptyIntArray_a = new int[0]; static public int[] emptyIntArray() { return emptyIntArray_a; } static public char[] emptyCharArray = new char[0]; static public char[] emptyCharArray() { return emptyCharArray; } static public double[] emptyDoubleArray = new double[0]; static public double[] emptyDoubleArray() { return emptyDoubleArray; } static public Map emptyMap() { return new HashMap(); } static public Object[] emptyObjectArray_a = new Object[0]; static public Object[] emptyObjectArray() { return emptyObjectArray_a; } static public Collection concatCollections_conservative(Collection a, Collection b) { if (empty(a)) return b; if (empty(b)) return a; return concatLists(a, b); } static public Object[] dropEntryFromParams(Object[] params, int i) { int n = l(params); if (i < 0 || i >= n) return params; if (n == 2) return null; Object[] p = new Object[n - 2]; System.arraycopy(params, 0, p, 0, i); System.arraycopy(params, i + 2, p, i, n - i - 2); return p; } static public boolean isCurlyBraced(String s) { List tok = tok_combineCurlyBrackets_keep(javaTok(s)); return l(tok) == 3 && startsWithAndEndsWith(tok.get(1), "{", "}"); } static public List dropFirstThreeAndLastThree(List l) { return dropFirstAndLast(3, l); } static public List simpleSpaces(List tok) { tok = cloneList(tok); for (int i = 0; i < l(tok); i += 2) tok.set(i, tok.get(i).equals("") ? "" : " "); return tok; } static public String simpleSpaces(String s) { return join(simpleSpaces(nlTok(s))); } static public boolean isAngleBracketVar(String s) { return isAngleBracketed(s); } static public List dropFirstAndLast(int n, List l) { return cloneSubList(l, n, l(l) - n); } static public List dropFirstAndLast(int m, int n, List l) { return cloneSubList(l, m, l(l) - n); } static public List dropFirstAndLast(List l) { return dropFirstAndLast(1, l); } static public String dropFirstAndLast(String s) { return substring(s, 1, l(s) - 1); } static public void rotateStringBuffer(StringBuffer buf, int max) { try { if (buf == null) return; synchronized (buf) { if (buf.length() <= max) return; try { int newLength = max / 2; int ofs = buf.length() - newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static public void rotateStringBuilder(StringBuilder buf, int max) { try { if (buf == null) return; synchronized (buf) { if (buf.length() <= max) return; try { int newLength = max / 2; int ofs = buf.length() - newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static public Object vmBus_wrapArgs(Object... args) { return empty(args) ? null : l(args) == 1 ? args[0] : args; } static public void pcallFAll(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) pcallF(f, args); } static public void pcallFAll(Iterator it, Object... args) { while (it.hasNext()) pcallF(it.next(), args); } static public Set vm_busListeners_live_cache; static public Set vm_busListeners_live() { if (vm_busListeners_live_cache == null) vm_busListeners_live_cache = vm_busListeners_live_load(); return vm_busListeners_live_cache; } static public Set vm_busListeners_live_load() { return vm_generalIdentityHashSet("busListeners"); } static public Map vm_busListenersByMessage_live_cache; static public Map vm_busListenersByMessage_live() { if (vm_busListenersByMessage_live_cache == null) vm_busListenersByMessage_live_cache = vm_busListenersByMessage_live_load(); return vm_busListenersByMessage_live_cache; } static public Map vm_busListenersByMessage_live_load() { return vm_generalHashMap("busListenersByMessage"); } static public A findConceptWhere(Class c, Object... params) { return findConceptWhere(db_mainConcepts(), c, params); } static public A findConceptWhere(Concepts concepts, Class c, Object... params) { ping(); params = expandParams(c, params); if (concepts.fieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getFieldIndex(c, (String) params[i]); if (index != null) { for (A x : index.getAll(params[i + 1])) if (checkConceptFields(x, params)) return x; return null; } } for (A x : concepts.list(c)) if (checkConceptFields(x, params)) return x; return null; } static public Concept findConceptWhere(Concepts concepts, String c, Object... params) { for (Concept x : concepts.list(c)) if (checkConceptFields(x, params)) return x; return null; } static public AutoCloseable tempLock(Lock lock) { return tempLock("", lock); } static public AutoCloseable tempLock(String purpose, Lock lock) { if (lock == null) return null; lock(lock); return new AutoCloseable() { public String toString() { return "unlock(lock);"; } public void close() throws Exception { unlock(lock); } }; } static public Font typeWriterFont() { return typeWriterFont(iround(14 * getSwingFontScale())); } static public Font typeWriterFont(int size) { return new Font("Courier", Font.PLAIN, size); } static public void consoleFont(Font font) { callOpt(getConsoleTextArea_gen(), "setFont", font); } static public void consoleInputFont(final Font f) { { swing(new Runnable() { public void run() { try { JTextField input = consoleInputField(); if (input != null) { input.setFont(f); revalidateFrame(input); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JTextField input = consoleInputField();\r\n if (input != null) {\r\n inpu..."; } }); } } static public String makePostData(Map map) { StringBuilder buf = new StringBuilder(); for (Map.Entry e : map.entrySet()) { String key = (String) (e.getKey()); Object val = e.getValue(); if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode((value))); } } return str(buf); } static public String makePostData(Object... params) { StringBuilder buf = new StringBuilder(); int n = l(params); for (int i = 0; i + 1 < n; i += 2) { String key = (String) (params[i]); Object val = params[i + 1]; if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode((value))); } } return str(buf); } static public List javaTokPlusPeriod(String s) { List tok = new ArrayList(); if (s == null) return tok; int l = s.length(); int i = 0; while (i < l) { int j = i; char c; String cc; while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j + 2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); cc = s.substring(i, Math.min(i + 2, l)); if (c == (char) 0x201C || c == (char) 0x201D) c = '"'; if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { char _c = s.charAt(j); if (_c == (char) 0x201C || _c == (char) 0x201D) _c = '"'; if (_c == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } if (j - 1 >= i + 1) { tok.add(opener + s.substring(i + 1, j - 1) + opener); i = j; continue; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else if (cc.equals("[[")) { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (cc.equals("[=") && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else if (s.substring(j, Math.min(j + 3, l)).equals("...")) j += 3; else if (c == '$' || c == '#') do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static public Comparator caseInsensitiveComparator() { return betterCIComparator(); } static public boolean boolPar(ThreadLocal tl) { return boolOptParam(tl); } static public boolean boolPar(Object[] __, String name) { return boolOptParam(__, name); } static public boolean boolPar(String name, Object[] __) { return boolOptParam(__, name); } static public boolean boolPar(String name, Map __) { return boolOptParam(name, __); } static public boolean boolPar(String name, Object[] params, boolean defaultValue) { return optParam(params, name, defaultValue); } static public void dataToTable_dynSet(List l, int i, Object s) { while (i >= l.size()) l.add(""); l.set(i, s); } static public List dataToTable_makeRow(Object x, List cols) { if (instanceOf(x, "DynamicObject")) x = get_raw(x, "fieldValues"); if (x instanceof Map) { Map m = (Map) x; List row = new ArrayList(); for (Object _field : keysWithoutHidden(m)) { String field = (String) _field; Object value = m.get(field); int col = cols.indexOf(field); if (col < 0) { cols.add(field); col = cols.size() - 1; } dataToTable_dynSet(row, col, dataToTable_wrapValue(value)); } return row; } if (x instanceof List) return allToString(((List) x)); return litlist(structureOrText(x)); } static public Object dataToTable_wrapValue(Object o) { if (o instanceof BufferedImage) return o; if (o instanceof MakesBufferedImage) return ((MakesBufferedImage) o).getBufferedImage(); if (o instanceof RGBImage) return o; if (o instanceof Boolean) return o; return structureOrTextForUser(o); } static public ArrayList litlist(A... a) { ArrayList l = new ArrayList(a.length); for (A x : a) l.add(x); return l; } static public String structureOrText(Object o) { return o instanceof String ? (String) o : structure(o); } static public String hopeningtag(String tag, Map params) { return hopeningTag(tag, params); } static public String hopeningtag(String tag, Object... params) { return hopeningTag(tag, params); } static public List padList(List l, int w) { return padList(l, w, null); } static public List padList(List l, int w, A a) { if (l(l) >= w) return l; List x = cloneList(l); while (l(x) < w) x.add(a); return x; } static public A getOrKeep(Map map, A a) { if (map == null) return a; A v = map.get(a); return v != null ? v : a; } static public String tr(Object contents) { return tag("tr", contents); } static public B mapGet(Map map, A a) { return map == null || a == null ? null : map.get(a); } static public B mapGet(A a, Map map) { return map == null || a == null ? null : map.get(a); } static public String nlToBr(String s) { return s.replace("\n", "
\n"); } static public Map mapPlus(Map m, Object... data) { m = cloneMap(m); litmap_impl(m, data); return m; } static public Object[] assertEvenLength(Object[] a) { assertTrue(even(l(a))); return a; } static public LinkedHashMap paramsToOrderedMap(Object... params) { return asLinkedHashMap(paramsToMap(params)); } static public boolean isSafeCodeFragment(String code) { return eq("safe", joinWithComma(getCodeFragmentSafety(code))); } static public void lock(Lock lock) { try { ping(); if (lock == null) return; try { lock.lockInterruptibly(); } catch (InterruptedException e) { Object reason = vm_threadInterruptionReasonsMap().get(currentThread()); print("Locking interrupted! Reason: " + strOr(reason, "Unknown")); printStackTrace(e); rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static public void lock(Lock lock, String msg) { print("Locking: " + msg); lock(lock); } static public void lock(Lock lock, String msg, long timeout) { print("Locking: " + msg); lockOrFail(lock, timeout); } static public ReentrantLock lock() { return fairLock(); } static public boolean isSlowMachine() { return eq("1", trimLoadTextFile(javaxDataDir("is-slow-machine.txt"))); } static public Map stdFunctions_cached_map; static public Lock stdFunctions_cached_lock = lock(); static public Map stdFunctions_cached() { Lock __0 = stdFunctions_cached_lock; lock(__0); try { if (stdFunctions_cached_map == null) stdFunctions_cached_map = stdFunctions_uncached(); return stdFunctions_cached_map; } finally { unlock(__0); } } static synchronized public void stdFunctions_clearCache() { stdFunctions_cached_map = null; } static public boolean isMD5(String s) { return l(s) == 32 && isLowerHexString(s); } static public String getUpToDateSnippetTranspilationMD5(String snippetID) { try { return loadPageSilently(tb_mainServer() + "/tb-int/get-transpilation-md5.php?id=" + psI(snippetID) + standardCredentials_noCookies()); } catch (Exception __e) { throw rethrow(__e); } } static public String getServerTranspiledWithoutLibs(String snippetID) { return dropFirstLine(getServerTranspiled2(snippetID)); } static public String getTranspiledStandardFunctionsIfCached(TreeSet functionSet) { try { File f = transpiledStandardFunctions_file(functionSet); return loadTextFile(f); } catch (Throwable __e) { return null; } } static public boolean standardFunctionsCacheUpToDate(TreeSet functionSet) { File f = transpiledStandardFunctions_file(functionSet); long date = recommendedTranspilationDateForStandardFunctions(functionSet); return date != 0 && f.lastModified() >= date; } static public String joinWithPlus(Collection c) { return join("+", c); } static public String joinWithPlus(String... c) { return join("+", c); } static public Class veryQuickJava_finish(String src, List libs) { libs = cloneList(libs); src = findTranslators2(src, libs); String dehlibs = join(" ", libs); File bytecode = null; bytecode = javaCompile_overInternalBot(src, dehlibs); return hotwireCore(concatLists(ll(bytecode), loadLibraries(libs))); } static public boolean loadFunctions_debug = false; static public Object loadFunctions_veryQuickJava; static public Class loadFunctions(String... functions) { return loadFunctions(asList(functions)); } static public Class loadFunctions(Collection functions, Object... __) { print("Compiling " + joinWithPlus(functions)); TreeSet functionSet = new TreeSet(functions); StringBuilder buf = stringBuilder(appendNewLineIfNempty(stringPar("header", __))); for (String s : functionSet) buf.append("please include function " + assertIdentifier(s) + ".\n"); long time = sysNow(); Class c; if (loadFunctions_veryQuickJava != null) c = (Class) callF(loadFunctions_veryQuickJava, str(buf)); else { veryQuickJava_transpiled.set(""); c = veryQuickJava(str(buf)); saveTranspiledStandardFunctions(functionSet, getAndClearThreadLocal(veryQuickJava_transpiled)); } if (loadFunctions_debug) done2_always(time, "loadFunctions: " + join(" ", functions)); return c; } static public
A assertNotNull(A a) { assertTrue(a != null); return a; } static public A assertNotNull(String msg, A a) { assertTrue(msg, a != null); return a; } static public void unlock(Lock lock, String msg) { if (lock == null) return; lock.unlock(); print("Unlocked: " + msg); } static public void unlock(Lock lock) { if (lock == null) return; lock.unlock(); } static public void ownResource(AutoCloseable c) { _registerAutoCloseable(c); } static public AutoCloseable vmBus_onMessage(final String msg, final VF1 onMessage) { Map map = vm_busListenersByMessage_live(); synchronized (map) { Set listeners = map.get(msg); if (listeners == null) map.put(msg, listeners = syncIdentityHashSet()); return tempAdd(listeners, new VF2() { public void get(String _msg, Object arg) { try { callF(onMessage, arg); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, arg)"; } }); } } static public AutoCloseable vmBus_onMessage(String msg, final VF2 onMessage) { return vmBus_onMessage(msg, new VF1() { public void get(Object[] o) { try { callF(onMessage, first(o), second(o)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, first(o), second(o));"; } }); } static public AutoCloseable vmBus_onMessage(String msg, final IVF2 onMessage) { return vmBus_onMessage(msg, new VF1() { public void get(Object[] o) { try { callF(onMessage, first(o), second(o)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, first(o), second(o));"; } }); } static public AutoCloseable vmBus_onMessage(String msg, Runnable onMessage) { return vmBus_onMessage(msg, runnableToVF1(onMessage)); } static public void loadFunctions_clearCache() { callOptMC("loadFunctions_cached_clearCache"); } static public A eitherAOpt(Either e) { return e != null && e.isA() ? e.a() : null; } static public String stackTraceForThread(Thread t) { return t == null ? null : lines(t.getStackTrace()); } static public F0 if0ToF0(IF0 f) { return f == null ? null : new F0() { public A get() { try { return f.get(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret f.get();"; } }; } static final public Map callOpt_cache = newDangerousWeakHashMap(); static public Object callOpt_cached(Object o, String methodName, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(methodName, args); if (me == null || (me.getModifiers() & Modifier.STATIC) == 0) return null; return invokeMethod(me, null, args); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(methodName, args); if (me == null) return null; return invokeMethod(me, o, args); } } catch (Exception __e) { throw rethrow(__e); } } static public _MethodCache callOpt_getCache(Class c) { synchronized (callOpt_cache) { _MethodCache cache = callOpt_cache.get(c); if (cache == null) callOpt_cache.put(c, cache = new _MethodCache(c)); return cache; } } static public Object invokeMethod(Method m, Object o, Object... args) { try { try { return m.invoke(o, args); } catch (InvocationTargetException e) { throw rethrow(getExceptionCause(e)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(e.getMessage() + " - was calling: " + m + ", args: " + joinWithSpace(classNames(args))); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean isStaticMethod(Method m) { return methodIsStatic(m); } static public Object[] massageArgsForVarArgsCall(Method m, Object[] args) { Class[] types = m.getParameterTypes(); int n = types.length - 1, nArgs = args.length; if (nArgs < n) return null; for (int i = 0; i < n; i++) if (!argumentCompatibleWithType(args[i], types[i])) return null; Class varArgType = types[n].getComponentType(); for (int i = n; i < nArgs; i++) if (!argumentCompatibleWithType(args[i], varArgType)) return null; Object[] newArgs = new Object[n + 1]; arraycopy(args, 0, newArgs, 0, n); Object[] varArgs = arrayOfType(varArgType, nArgs - n); arraycopy(args, n, varArgs, 0, nArgs - n); newArgs[n] = varArgs; return newArgs; } static public List classNames(Collection l) { return getClassNames(l); } static public List classNames(Object[] l) { return getClassNames(Arrays.asList(l)); } static public boolean startsWithOneOf(String s, String... l) { for (String x : l) if (startsWith(s, x)) return true; return false; } static public boolean startsWithOneOf(String s, Matches m, String... l) { for (String x : l) if (startsWith(s, x, m)) return true; return false; } static public boolean isAGIBlueDomain(String domain) { return domainIsUnder(domain, theAGIBlueDomain()); } static public String hostNameFromURL(String url) { try { return new URL(url).getHost(); } catch (Exception __e) { throw rethrow(__e); } } static public Throwable getInnerException(Throwable e) { if (e == null) return null; while (e.getCause() != null) e = e.getCause(); return e; } static public Throwable getInnerException(Runnable r) { return getInnerException(getException(r)); } static public List> mapPairB(final Object f, Iterable> l) { return map(l, new F1, Pair>() { public Pair get(Pair p) { try { return p == null ? null : pair(p.a, (C) callF(f, p.b)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "p == null ? null : pair(p.a, (C) callF(f, p.b))"; } }); } static public List> mapPairB(final F1 f, Iterable> l) { return mapPairB((Object) f, l); } static public List> mapPairB(final IF1 f, Iterable> l) { return mapPairB((Object) f, l); } static public List> mapPairB(Iterable> l, IF1 f) { return mapPairB((Object) f, l); } static public List mapNonNulls(Iterable l, Object f) { return mapNonNulls(f, l); } static public List mapNonNulls(Object f, Iterable l) { List x = new ArrayList(); if (l != null) for (Object o : l) addIfNotNull(x, callF(f, o)); return x; } static public List mapNonNulls(Object f, Object[] l) { List x = new ArrayList(); if (l != null) for (Object o : l) addIfNotNull(x, callF(f, o)); return x; } static public List mapNonNulls(Iterable l, F1 f) { return mapNonNulls(f, l); } static public List mapNonNulls(F1 f, Iterable l) { List x = new ArrayList(); if (l != null) for (Object o : l) addIfNotNull(x, callF(f, o)); return x; } static public List mapNonNulls(A[] l, IF1 f) { return mapNonNulls(f, l); } static public List mapNonNulls(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) addIfNotNull(x, f.get(o)); return x; } static public List mapNonNulls(IF1 f, Iterable l) { return mapNonNulls(l, f); } static public List> scanConceptForRefsWithFieldNames(Concept c) { List> refs = new ArrayList(); if (c != null) for (Map.Entry __0 : _entrySet(objectToMap(c))) { String field = __0.getKey(); Object o = __0.getValue(); if (o instanceof Concept.Ref) refs.add(pair(((Concept.Ref) o), field)); else if (o instanceof Concept.RefL) for (int i = 0; i < l(((Concept.RefL) o).l); i++) refs.add(pair((Concept.Ref) ((Concept.RefL) o).l.get(i), field + "[" + (i + 1) + "]")); } return refs; } static public boolean isInstanceOf(Object o, Class type) { return type.isInstance(o); } static public Object derefRef(Object o) { if (o instanceof Concept.Ref) o = ((Concept.Ref) o).get(); return o; } static public A derefRef(Concept.Ref r) { return r == null ? null : r.get(); } static public String fieldNameForConceptLink(Concept from, Concept to) { for (Pair p : scanConceptForRefsWithFieldNames(from)) if (derefRef(p.a) == to) return p.b; return null; } static public boolean containsNulls(Collection c) { return contains(c, null); } static public String joinStrings(String sep, Object... strings) { return joinStrings(sep, Arrays.asList(strings)); } static public String joinStrings(String sep, Iterable strings) { StringBuilder buf = new StringBuilder(); for (Object o : unnull(strings)) { String s = strOrNull(o); if (nempty(s)) { if (nempty(buf)) buf.append(sep); buf.append(s); } } return str(buf); } static public List sortByCalculatedFieldDesc_inPlace(List l, final Object f) { sort(l, new Comparator() { public int compare(A b, A a) { return stdcompare((Object) callF(f, a), (Object) callF(f, b)); } }); return l; } static public List sortByCalculatedFieldDesc_inPlace(Object f, List c) { return sortByCalculatedFieldDesc_inPlace(c, f); } static public void sort(T[] a, Comparator c) { if (a != null) Arrays.sort(a, c); } static public void sort(T[] a) { if (a != null) Arrays.sort(a); } static public void sort(int[] a) { if (a != null) Arrays.sort(a); } static public void sort(List a, Comparator c) { if (a != null) Collections.sort(a, c); } static public void sort(List a) { if (a != null) Collections.sort(a); } static public int stdcompare(Number a, Number b) { return cmp(a, b); } static public int stdcompare(String a, String b) { return cmp(a, b); } static public int stdcompare(long a, long b) { return a < b ? -1 : a > b ? 1 : 0; } static public int stdcompare(Object a, Object b) { return cmp(a, b); } static public List javaTokWithAllBrackets(String s) { return javaTokPlusBrackets2(s); } static public Map> parse3_cachedInput_cache = synchronizedMRUCache(1000); static public List parse3_cachedInput(String s) { List tok = parse3_cachedInput_cache.get(s); if (tok == null) parse3_cachedInput_cache.put(s, tok = parse3(s)); return tok; } static public Map> parse3_cachedPattern_cache = synchronizedMRUCache(1000); static synchronized public List parse3_cachedPattern(String s) { List tok = parse3_cachedPattern_cache.get(s); if (tok == null) parse3_cachedPattern_cache.put(s, tok = parse3(s)); return tok; } static public String[] match2(List pat, List tok) { int i = pat.indexOf("..."); if (i < 0) return match2_match(pat, tok); pat = new ArrayList(pat); pat.set(i, "*"); while (pat.size() < tok.size()) { pat.add(i, "*"); pat.add(i + 1, ""); } return match2_match(pat, tok); } static public String[] match2_match(List pat, List tok) { List result = new ArrayList(); if (pat.size() != tok.size()) { return null; } for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(i); if (eq(p, "*")) result.add(t); else if (!equalsIgnoreCase(unquote(p), unquote(t))) return null; } return result.toArray(new String[result.size()]); } static public List codeTokensOnly(List tok) { int n = l(tok); List l = emptyList(n / 2); for (int i = 1; i < n; i += 2) l.add(tok.get(i)); return l; } static public Class primitiveToBoxedTypeOpt(Class type) { return or(primitiveToBoxedType(type), type); } static public int lastIndexOf(String a, String b) { return a == null || b == null ? -1 : a.lastIndexOf(b); } static public int lastIndexOf(String a, char b) { return a == null ? -1 : a.lastIndexOf(b); } static public int lastIndexOf(List l, int i, A a) { if (l == null) return -1; for (i = min(l(l), i) - 1; i >= 0; i--) if (eq(l.get(i), a)) return i; return -1; } static public int lastIndexOf(List l, A a) { if (l == null) return -1; for (int i = l(l) - 1; i >= 0; i--) if (eq(l.get(i), a)) return i; return -1; } static public F0 dm_rEnter(final DynModule mod) { return mod == null ? null : new F0() { public AutoCloseable get() { try { return mod.enter(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret mod.enter();"; } }; } static public A dm_ownResource(A resource) { dm_currentModuleMandatory().ownResource(resource); return resource; } static public String programID() { return getProgramID(); } static public String programID(Object o) { return getProgramID(o); } static public TimerTask smartTimerTask(Object r, java.util.Timer timer, long delay) { return new SmartTimerTask(r, timer, delay, _threadInfo()); } static public class SmartTimerTask extends TimerTask implements IFieldsToList { public Object r; public java.util.Timer timer; public long delay; public Object threadInfo; public SmartTimerTask() { } public SmartTimerTask(Object r, java.util.Timer timer, long delay, Object threadInfo) { this.threadInfo = threadInfo; this.delay = delay; this.timer = timer; this.r = r; } public String toString() { return shortClassName(this) + "(" + r + ", " + timer + ", " + delay + ", " + threadInfo + ")"; } public Object[] _fieldsToList() { return new Object[] { r, timer, delay, threadInfo }; } public long lastRun; public void run() { if (!licensed()) timer.cancel(); else { _threadInheritInfo(threadInfo); AutoCloseable __1 = tempActivity(r); try { lastRun = fixTimestamp(lastRun); long now = now(); if (now >= lastRun + delay * 0.9) { lastRun = now; if (eq(false, pcallF(r))) timer.cancel(); } } finally { _close(__1); } } } } static public A vmBus_timerStarted(A timer) { vmBus_send("timerStarted", timer, costCenter()); return timer; } static public ConceptFieldIndexCI getConceptFieldCIIndex(Class c, String field) { return getConceptFieldCIIndex(db_mainConcepts(), c, field); } static public ConceptFieldIndexCI getConceptFieldCIIndex(Concepts concepts, Class c, String field) { return (ConceptFieldIndexCI) concepts.getCIFieldIndex(c, field); } static public TreeSet caseInsensitiveSet_treeSet() { return new TreeSet(caseInsensitiveComparator()); } static public TreeSet caseInsensitiveSet_treeSet(Collection c) { return toCaseInsensitiveSet_treeSet(c); } static public boolean checkConceptFields(Concept x, Object... data) { for (int i = 0; i < l(data); i += 2) if (neq(cget(x, (String) data[i]), deref(data[i + 1]))) return false; return true; } static public List filterConcepts(List list, Object... params) { if (empty(params)) return list; List l = new ArrayList(); for (A x : list) if (checkConceptFields(x, params)) l.add(x); return l; } static public String addSuffix(String s, String suffix) { return s == null || s.endsWith(suffix) ? s : s + suffix; } static public int randomID_defaultLength = 12; static public String randomID(int length) { return makeRandomID(length); } static public String randomID(Random r, int length) { return makeRandomID(r, length); } static public String randomID() { return randomID(randomID_defaultLength); } static public String randomID(Random r) { return randomID(r, randomID_defaultLength); } static public int globalIDLength() { return 16; } static public Map mapKeys(Object func, Map map) { Map m = similarEmptyMap(map); for (Object key : keys(map)) m.put(callF(func, key), map.get(key)); return m; } static public Map mapKeys(Map map, Object func) { return mapKeys(func, map); } static public Map mapKeys(Map map, IF1 func) { return mapKeys(map, (Object) func); } static public Map mapKeys(IF1 func, Map map) { return mapKeys(map, func); } static public String dropDollarPrefix(String s) { return dropPrefix("$", s); } static public TreeMap litcimap(Object... x) { return litCIMap(x); } static public String replaceDollarVars_dyn(String s, IF1 f) { if (f == null) return s; return regexpReplaceIC(s, "\\$(\\w+)", matcher -> { String var = matcher.group(1); String val = f.get(var); return val == null ? matcher.group() : str(val); }); } static public String charToString(char c) { return String.valueOf(c); } static public String charToString(int c) { return String.valueOf((char) c); } static public boolean checkFieldsIC(Object x, Object... data) { for (int i = 0; i < l(data); i += 2) if (!eqicOrEq(getOpt(x, (String) data[i]), data[i + 1])) return false; return true; } static public int strL(String s) { return s == null ? 0 : s.length(); } static public int[] subIntArray(int[] b, int start) { return subIntArray(b, start, l(b)); } static public int[] subIntArray(int[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new int[0]; int[] x = new int[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public int[] subIntArray(int[] a, IntRange r) { return r == null ? null : subIntArray(a, r.start, r.end); } static public List reverseList(List l) { Collections.reverse(l); return l; } static public Comparator fieldComparator(final String field) { return new Comparator() { public int compare(A a, A b) { return cmp(getOpt(a, field), getOpt(b, field)); } }; } static public int cmp(Number a, Number b) { return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue()); } static public int cmp(double a, double b) { return a < b ? -1 : a == b ? 0 : 1; } static public int cmp(int a, int b) { return a < b ? -1 : a == b ? 0 : 1; } static public int cmp(long a, long b) { return a < b ? -1 : a == b ? 0 : 1; } static public int cmp(Object a, Object b) { if (a == null) return b == null ? 0 : -1; if (b == null) return 1; return ((Comparable) a).compareTo(b); } static public double toSeconds(long ms) { return ms / 1000.0; } static public String toSeconds(long ms, int digits) { return formatDouble(toSeconds(ms), digits); } static public double toSeconds(double ms) { return ms / 1000.0; } static public String toSeconds(double ms, int digits) { return formatDouble(toSeconds(ms), digits); } static public byte[] toUtf8(String s) { try { return s.getBytes(utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } static public IterableIterator iteratorFromFunction_f0(final F0 f) { class IFF2 extends IterableIterator { public A a; public boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } public void getNext() { if (done || a != null) return; a = f.get(); done = a == null; } } ; return new IFF2(); } static public boolean nemptyString(String s) { return s != null && s.length() > 0; } static public int listL(Collection l) { return l == null ? 0 : l.size(); } static public char lastChar(String s) { return empty(s) ? '\0' : s.charAt(l(s) - 1); } static public CloseableIterableIterator linesFromFile(File f) { try { if (!f.exists()) return emptyCloseableIterableIterator(); if (ewic(f.getName(), ".gz")) return linesFromReader(utf8bufferedReader(newGZIPInputStream(f))); return linesFromReader(utf8bufferedReader(f)); } catch (Exception __e) { throw rethrow(__e); } } static public CloseableIterableIterator linesFromFile(String path) { return linesFromFile(newFile(path)); } static public boolean containsIgnoreCase(Collection l, String s) { if (l != null) for (String x : l) if (eqic(x, s)) return true; return false; } static public boolean containsIgnoreCase(String[] l, String s) { if (l != null) for (String x : l) if (eqic(x, s)) return true; return false; } static public boolean containsIgnoreCase(String s, char c) { return indexOfIgnoreCase(s, String.valueOf(c)) >= 0; } static public boolean containsIgnoreCase(String a, String b) { return indexOfIgnoreCase(a, b) >= 0; } static public boolean ewic(String a, String b) { return endsWithIgnoreCase(a, b); } static public boolean ewic(String a, String b, Matches m) { return endsWithIgnoreCase(a, b, m); } static public String dropSuffixIgnoreCase(String suffix, String s) { return ewic(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static public boolean ewicOneOf(String s, String... l) { if (s != null) for (String x : l) if (ewic(s, x)) return true; return false; } static public String formatWithThousandsSeparator(long l) { return NumberFormat.getInstance(new Locale("en_US")).format(l); } static public String unparseCSSParameter(Map map) { return joinWithSemicolon(map(map, new F2() { public String get(String key, String value) { try { return key + ": " + value; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "key + \": \" + value"; } })); } static public Map mapPlus_noOverwrite(Map m, Object... data) { m = cloneMap(m); litmap_impl_noOverwrite(m, data); return m; } static public Map parseCSSParameter(String s) { Map map = new LinkedHashMap(); for (String x : trimAll(splitAt(s, ";"))) { List y = trimAll(splitAtColon(x)); if (l(y) == 2) map.put(first(y), second(y)); } return map; } static public String himg(String src, Object... params) { return tag("img", "", arrayPlus(params, "src", isSnippetID(src) ? snippetImageLink(src) : src)); } static public String snippetImageLink(String snippetID) { return snippetImageURL(snippetID); } static public int iround(double d) { return (int) Math.round(d); } static public int iround(Number n) { return iround(toDouble(n)); } static public double doubleRatio(double x, double y) { return y == 0 ? 0 : x / y; } static public TimeZone localTimeZone() { return getTimeZone(standardTimeZone()); } static public boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) { return a != null && a.regionMatches(true, offsetA, b, offsetB, len); } static public List javaTok_noMLS(String s) { ArrayList tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { int c2 = s.charAt(j); if (c2 == opener || c2 == '\n' && opener == '\'') { ++j; break; } else if (c2 == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else ++j; tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static public String rep(int n, char c) { return repeat(c, n); } static public String rep(char c, int n) { return repeat(c, n); } static public List rep(A a, int n) { return repeat(a, n); } static public List rep(int n, A a) { return repeat(n, a); } static public Throwable unwrapTrivialExceptionWraps(Throwable e) { if (e == null) return e; while (e.getClass() == RuntimeException.class && e.getCause() != null && eq(e.getMessage(), str(e.getCause()))) e = e.getCause(); return e; } static public String replacePrefix(String prefix, String replacement, String s) { if (!startsWith(s, prefix)) return s; return replacement + substring(s, l(prefix)); } static public Throwable innerException2(Throwable e) { if (e == null) return null; while (empty(e.getMessage()) && e.getCause() != null) e = e.getCause(); return e; } static volatile public String caseID_caseID; static public String caseID() { return caseID_caseID; } static public void caseID(String id) { caseID_caseID = id; } static public String quoteUnlessIdentifierOrInteger(String s) { return quoteIfNotIdentifierOrInteger(s); } static volatile public boolean licensed_yes = true; static public boolean licensed() { if (!licensed_yes) return false; ping_okInCleanUp(); return true; } static public void licensed_off() { licensed_yes = false; } static public List sortByCalculatedField(Iterable c, final Object f) { List l = cloneList(c); sort(l, new Comparator() { public int compare(A a, A b) { return stdcompare(callF(f, a), callF(f, b)); } }); return l; } static public Set listFields(Object c) { TreeSet fields = new TreeSet(); for (Field f : _getClass(c).getDeclaredFields()) fields.add(f.getName()); return fields; } static public String n(long l, String name) { return l + " " + trim(l == 1 ? singular(name) : getPlural(name)); } static public String n(Collection l, String name) { return n(l(l), name); } static public String n(Map m, String name) { return n(l(m), name); } static public String n(Object[] a, String name) { return n(l(a), name); } static public String n(MultiSet ms, String name) { return n(l(ms), name); } static public boolean eqicOrEq(Object a, Object b) { return a instanceof String && b instanceof String ? eqic((String) a, (String) b) : eq(a, b); } static public boolean containsRegexpIC(String s, String pat) { return compileRegexpIC(pat).matcher(s).find(); } static public String phraseToRegExp(String b) { return (startsWithLetterOrDigit(b) ? "\\b" : "") + regexpQuote(b) + (endsWithLetterOrDigit(b) ? "\\b" : ""); } static public boolean matchStart(String pat, String s) { return matchStart(pat, s, null); } static public boolean matchStart(String pat, String s, Matches matches) { if (s == null) return false; return matchStart(pat, parse3_cachedInput(s), matches); } static public boolean matchStart(String pat, List toks, Matches matches) { if (toks == null) return false; List tokpat = parse3_cachedPattern(pat); if (toks.size() < tokpat.size()) return false; String[] m = match2(tokpat, toks.subList(0, tokpat.size())); if (m == null) return false; if (matches != null) { matches.m = new String[m.length + 1]; arraycopy(m, matches.m); matches.m[m.length] = joinSubList(toks, tokpat.size(), toks.size()); } return true; } static public boolean matchEnd(String pat, String s) { return matchEnd(pat, s, null); } static public boolean matchEnd(String pat, String s, Matches matches) { if (s == null) return false; List tokpat = parse3(pat), toks = parse3(s); if (toks.size() < tokpat.size()) return false; String[] m = match2(tokpat, takeLast(l(tokpat), toks)); if (m == null) return false; if (matches != null) { matches.m = new String[m.length + 1]; arraycopy(m, matches.m); matches.m[m.length] = join(dropLast(l(tokpat), toks)); } return true; } static public boolean find3(String pat, String s) { return find3(pat, s, null); } static public boolean find3(String pat, String s, Matches matches) { return find3(pat, parse3_cachedInput(s), matches); } static public boolean find3(String pat, List toks, Matches matches) { List tokpat = parse3_cachedPattern(pat); String[] m = find2(tokpat, toks); if (m == null) return false; if (matches != null) matches.m = m; return true; } static public boolean tok_isRoundBracketed(String s) { List tok = tok_combineRoundBrackets_keep(javaTok(s)); return l(tok) == 3 && startsWithAndEndsWith(tok.get(1), "(", ")"); } static public List javaTokPlusBrackets(String s) { return tok_combineRoundOrCurlyBrackets_keep(javaTok(s)); } static public Map> javaTokWithAllBrackets_cached_cache = synchronizedMRUCache(defaultTokenizerCacheSize()); static public List javaTokWithAllBrackets_cached(String s) { List tok = javaTokWithAllBrackets_cached_cache.get(s); if (tok == null) javaTokWithAllBrackets_cached_cache.put(s, tok = javaTokWithAllBrackets(s)); return tok; } static public List splitAtTokens(String s, List tokens) { return splitAtTokens(javaTok(s), tokens); } static public List splitAtTokens(List tok, List tokens) { List l = new ArrayList(); int i = 0; while (i < l(tok)) { int j = indexOfSubList(tok, tokens, i); if (i >= l(tok)) break; if (j < 0) j = l(tok); l.add(trimJoin(tok.subList(i, j))); i = j + l(tokens); } return l; } static public List splitAtTokens(List tok, String... tokens) { List l = new ArrayList(); int i = 0; while (i < l(tok)) { int j = indexOfSubList(tok, tokens, i); if (i >= l(tok)) break; if (j < 0) j = l(tok); l.add(trimJoin(tok.subList(i, j))); i = j + l(tokens); } return l; } static public A[] arrayOfSameType(A[] a, int n) { return newObjectArrayOfSameType(a, n); } static public boolean isNormalQuoted(String s) { int l = l(s); if (!(l >= 2 && s.charAt(0) == '"' && lastChar(s) == '"')) return false; int j = 1; while (j < l) if (s.charAt(j) == '"') return j == l - 1; else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; return false; } static public boolean isMultilineQuoted(String s) { if (!startsWith(s, "[")) return false; int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; return i < s.length() && s.charAt(i) == '['; } static public int findEndOfAngleBracketPart(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eq(cnc.get(j), "<")) ++level; else if (eq(cnc.get(j), ">")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static public CancelPoint newCancelPoint() { return new CancelPoint(); } static public List javaTokNPunctuation_plusAsterisk(String s) { List tok = javaTok(s); for (int i = 1; i < l(tok); i += 2) { int j = i; String t; while (j < l(tok) && l(t = tok.get(j)) == 1 && !Character.isLetterOrDigit(t.charAt(0)) && t.charAt(0) != '*') j += 2; if (j > i) replaceSubList(tok, i - 1, j, ll(joinSubList(tok, i - 1, j))); } return tok; } static public List callTokenizer(Object tokenizer, String s) { return (List) callF(tokenizer, s); } static public List flexMatchIC_getVarIndices(List tokPat, List tokInput) { List varIndices = new ArrayList(); for (int i = 1; i < l(tokPat); i += 2) { String t = tokPat.get(i); if (eq(t, "*")) varIndices.add(i); else if (isIdentifier(t) && !cicAtOddPosition(tokInput, t)) { return null; } } return varIndices; } static public void printStructs(Object... params) { print(renderStructs(params)); } static public List> ai_spreadCertainIndices_2(List tokPat, List tokS, List indices) { int extra = (l(tokS) - l(tokPat)) / 2; if (extra < 0 || empty(indices)) return emptyList(); List> results = new ArrayList(); for (List spread : allSpreads(extra, l(indices))) { List tok = new ArrayList(); int pos = 0, iSpread = 0, iIndices = 0; for (int i = 0; i < l(tokPat); i++) if (!eq(get(indices, iIndices), i)) tok.add(tokS.get(pos++)); else { ++iIndices; int take = spread.get(iSpread++) * 2; tok.add(joinSubList(tokS, pos, pos + take + 1)); pos += take + 1; } results.add(tok); } return results; } static public String sfu(Object o) { return structureForUser(o); } static public boolean strictPutIC(Map map, A key, String value) { if (!(map != null && key != null && value != null)) return true; String old = map.get(key); if (old == null) { map.put(key, value); return true; } return eqic(old, value); } static public Map synchroHashMap() { return Collections.synchronizedMap(new HashMap()); } static public Class _getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; } } static public Class _getClass(Object o) { return o == null ? null : o instanceof Class ? (Class) o : o.getClass(); } static public Class _getClass(Object realm, String name) { try { return getClass(realm).getClassLoader().loadClass(classNameToVM(name)); } catch (ClassNotFoundException e) { return null; } } static public Map synchronizedMRUCache(int maxSize) { return synchroMap(new MRUCache(maxSize)); } static public String[] codeTokensAsStringArray(List tok) { int n = max(0, (l(tok) - 1) / 2); String[] out = new String[n]; for (int i = 0; i < n; i++) out[i] = tok.get(i * 2 + 1); return out; } static public boolean checkTokCondition(Object condition, List tok, int i) { if (condition instanceof TokCondition) return ((TokCondition) condition).get(tok, i); return checkCondition(condition, tok, i); } static public int parseInt(String s) { return emptyString(s) ? 0 : Integer.parseInt(s); } static public int parseInt(char c) { return Integer.parseInt(str(c)); } static public void replaceCollection(Collection dest, Collection src) { if (dest == src) return; dest.clear(); if (src != null) dest.addAll(src); } static public void replaceListPart(List l, int i, int j, List l2) { replaceSublist(l, i, j, l2); } static public A optParam(ThreadLocal tl, A defaultValue) { return optPar(tl, defaultValue); } static public A optParam(ThreadLocal tl) { return optPar(tl); } static public Object optParam(String name, Map params) { return mapGet(params, name); } static public A optParam(Object[] opt, String name, A defaultValue) { int n = l(opt); if (n == 1 && opt[0] instanceof Map) { Map map = (Map) (opt[0]); return map.containsKey(name) ? (A) map.get(name) : defaultValue; } if (!even(l(opt))) throw fail("Odd parameter length"); for (int i = 0; i < l(opt); i += 2) if (eq(opt[i], name)) return (A) opt[i + 1]; return defaultValue; } static public Object optParam(Object[] opt, String name) { return optParam(opt, name, null); } static public Object optParam(String name, Object[] params) { return optParam(params, name); } static public Object[] mapToObjectArray(Map map) { List l = new ArrayList(); for (Object o : keys(map)) { l.add(o); l.add(map.get(o)); } return toObjectArray(l); } static public Object[] mapToObjectArray(Object f, Collection l) { int n = l(l); Object[] array = new Object[n]; if (n != 0) { Iterator it = iterator(l); for (int i = 0; i < n; i++) array[i] = callF(f, it.next()); } return array; } static public Object[] mapToObjectArray(Object f, Object[] l) { int n = l(l); Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = callF(f, l[i]); return array; } static public Object[] mapToObjectArray(Collection l, IF1 f) { return mapToObjectArray(f, l); } static public Object[] mapToObjectArray(A[] l, IF1 f) { return mapToObjectArray(f, l); } static public ThreadLocal htmlencode_forParams_useV2 = new ThreadLocal(); static public String htmlencode_forParams(String s) { if (s == null) return ""; if (isTrue(htmlencode_forParams_useV2.get())) return htmlencode_forParams_v2(s); StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>') { out.append("&#"); out.append((int) c); out.append(';'); } else out.append(c); } return out.toString(); } static public int boolToInt(boolean b) { return b ? 1 : 0; } static public boolean isOpeningTag(String token, String tag) { return isTag(token, tag) && !token.endsWith("/>"); } static public boolean isOpeningTag(String token) { return token.startsWith("<") && token.endsWith(">") && !token.endsWith("/>") && isLetter(token.charAt(1)); } static public boolean isTag(String token, String tag) { return token.regionMatches(true, 0, "<" + tag + " ", 0, tag.length() + 2) || token.regionMatches(true, 0, "<" + tag + ">", 0, tag.length() + 2); } static public long psI(String snippetID) { return parseSnippetID(snippetID); } static public String htmlQuery(Map params) { return empty(params) ? "" : "?" + makePostData(params); } static public String htmlQuery(Object... data) { return empty(data) ? "" : "?" + makePostData(data); } static public Map mapMinus(Map map, Object... keys) { if (empty(keys)) return map; Map m2 = cloneMap(map); for (Object key : keys) m2.remove(key); return m2; } static public Object[] toObjectArray(Collection c) { List l = asList(c); return l.toArray(new Object[l.size()]); } static public Object pcallFunction(Object f, Object... args) { try { return callFunction(f, args); } catch (Throwable __e) { _handleException(__e); } return null; } static public WeakReference weakRef(A a) { return newWeakReference(a); } static public String quickSubstring(String s, int i, int j) { if (i == j) return ""; return s.substring(i, j); } static public boolean isLetter(char c) { return Character.isLetter(c); } static public void setOptIfNotNull(Object o, String field, Object value) { if (value != null) setOpt(o, field, value); } static public TokCondition toTokCondition(ITokCondition condition) { return condition == null ? null : new TokCondition() { public boolean get(List tok, int i) { return condition.get(tok, i); } }; } static public List replaceSublist(List l, List x, List y) { if (x == null) return l; int i = 0; while (true) { i = indexOfSubList(l, x, i); if (i < 0) break; replaceSublist(l, i, i + l(x), y); i += l(y); } return l; } static public List replaceSublist(List l, int fromIndex, int toIndex, List y) { int n = y.size(), toIndex_new = fromIndex + n; if (toIndex_new < toIndex) { removeSubList(l, toIndex_new, toIndex); copyListPart(y, 0, l, fromIndex, n); } else { copyListPart(y, 0, l, fromIndex, toIndex - fromIndex); if (toIndex_new > toIndex) l.addAll(toIndex, subList(y, toIndex - fromIndex)); } return l; } static public List replaceSublist(List l, IntRange r, List y) { return replaceSublist(l, r.start, r.end, y); } static public String asciiSideBySide(List texts) { if (l(texts) < 2) return unnull(first(texts)); if (l(texts) > 2) return asciiSideBySide(ll(asciiSideBySide(dropLast(texts)), last(texts))); List l1 = lines(first(texts)), l2 = lines(second(texts)); int col1 = maxStringLength(l1), n = max(l(l1), l(l2)); StringBuilder buf = new StringBuilder(); for (int i = 0; i < n; i++) buf.append(rpad(unnull(get(l1, i)), col1)).append(unnull(get(l2, i))).append("\n"); return str(buf); } static public int maxLineCount(Collection l) { int n = 0; if (l != null) for (String s : l) n = max(n, countLines(s)); return n; } static public String repLine(int n, String s) { return lines(rep(n, s)); } static public List firstOfPairs(Collection> l) { List out = new ArrayList(); for (Pair p : unnull(l)) out.add(firstOfPair(p)); return out; } static public List secondOfPairs(Collection> l) { return lambdaMap(__55 -> secondOfPair(__55), l); } static public String curlyBrace(String s) { return "{" + s + "}"; } static public List tok_combineCurlyBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eq(t, "{")) { int j = findEndOfCurlyBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public boolean startsWithAndEndsWith(String s, String prefix, String suffix) { return startsWith(s, prefix) && endsWith(s, suffix); } static public List cloneSubList(List l, int startIndex, int endIndex) { return newSubList(l, startIndex, endIndex); } static public List cloneSubList(List l, int startIndex) { return newSubList(l, startIndex); } static public float getSwingFontScale() { return or((Float) vm_generalMap_get("swingFontScale_value"), 1f); } static public Object getConsoleTextArea_gen() { return getOpt(get(getJavaX(), "console"), "textArea"); } static public Object swing(Object f) { return swingAndWait(f); } static public A swing(F0 f) { return (A) swingAndWait(f); } static public A swing(IF0 f) { return (A) swingAndWait(f); } static public JTextField consoleInputField() { Object console = get(getJavaX(), "console"); return (JTextField) getOpt(console, "tfInput"); } static public void revalidateFrame(Component c) { revalidate(getFrame(c)); } static public betterCIComparator_C betterCIComparator_instance; static public betterCIComparator_C betterCIComparator() { if (betterCIComparator_instance == null) betterCIComparator_instance = new betterCIComparator_C(); return betterCIComparator_instance; } final static public class betterCIComparator_C implements Comparator { public int compare(String s1, String s2) { if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return 1; int n1 = s1.length(); int n2 = s2.length(); int min = Math.min(n1, n2); for (int i = 0; i < min; i++) { char c1 = s1.charAt(i); char c2 = s2.charAt(i); if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); if (c1 != c2) { return c1 - c2; } } } } return n1 - n2; } } static public boolean boolOptParam(ThreadLocal tl) { return isTrue(optPar(tl)); } static public boolean boolOptParam(Object[] __, String name) { return isTrue(optParam(__, name)); } static public boolean boolOptParam(String name, Object[] __) { return boolOptParam(__, name); } static public boolean boolOptParam(String name, Map __) { return isTrue(optPar(name, __)); } static public List keysWithoutHidden(Map map) { return filter(keys(map), new F1() { public Boolean get(Object o) { try { return !eq(o, "[hidden]") && !isStringStartingWith(o, "[hidden] "); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "!eq(o, \"[hidden]\") && !isStringStartingWith(o, \"[hidden] \")"; } }); } static public String structureOrTextForUser(Object o) { return o == null ? "" : o instanceof String ? (String) o : structureForUser(o); } static public LinkedHashMap asLinkedHashMap(Map map) { if (map instanceof LinkedHashMap) return (LinkedHashMap) map; LinkedHashMap m = new LinkedHashMap(); if (map != null) synchronized (collectionMutex(map)) { m.putAll(map); } return m; } static public Collection getCodeFragmentSafety(String code) { Map map = codeAnalysis_identifierSafetyMap(); Set identifiers = tok_allIdentifiers(code); Collection tags = treeSet(); for (String id : identifiers) { String tag; if (codeAnalysis_isSafeIdentifier(id)) tag = "safe"; else tag = or2(map.get(id), "?"); tags.addAll(tokSplitAtComma(tag)); } tags = simplifySafetyTags(tags); if (empty(tags)) tags.add("safe"); return tags; } static public Map vm_threadInterruptionReasonsMap() { return vm_generalWeakSubMap("Thread interruption reasons"); } static public String strOr(Object o, String ifNull) { return o == null ? ifNull : str(o); } static public void lockOrFail(Lock lock, long timeout) { try { ping(); if (!lock.tryLock(timeout, TimeUnit.MILLISECONDS)) { String s = "Couldn't acquire lock after " + timeout + " ms."; if (lock instanceof ReentrantLock) { ReentrantLock l = (ReentrantLock) lock; s += " Hold count: " + l.getHoldCount() + ", owner: " + call(l, "getOwner"); } throw fail(s); } ping(); } catch (Exception __e) { throw rethrow(__e); } } static public ReentrantLock fairLock() { return new ReentrantLock(true); } static public String trimLoadTextFile(String fileName) { return loadTextFile_trim(fileName); } static public String trimLoadTextFile(File f, String defaultContents) { return loadTextFile_trim(f, defaultContents); } static public String trimLoadTextFile(File fileName) { return loadTextFile_trim(fileName); } static public String trimLoadTextFile(String fileName, String defaultContents) { return loadTextFile_trim(fileName, defaultContents); } static public File javaxDataDir_dir; static public File javaxDataDir() { return javaxDataDir_dir != null ? javaxDataDir_dir : new File(userHome(), "JavaX-Data"); } static public File javaxDataDir(String... subs) { return newFile(javaxDataDir(), subs); } static public Map stdFunctions_uncached() { return stdFunctions_uncached(new HashMap()); } static public Map stdFunctions_uncached(Map map) { parseStdFunctionsList(loadSnippetSilently("#1006654"), map); parseStdFunctionsList(loadSnippetSilently("#761"), map); return map; } static public boolean isLowerHexString(String s) { for (int i = 0; i < l(s); i++) { char c = s.charAt(i); if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f') { } else return false; } return true; } static public String tb_mainServer_default = "http://code.botcompany.de:8081"; static public Object tb_mainServer_override; static public String tb_mainServer() { if (tb_mainServer_override != null) return (String) callF(tb_mainServer_override); return trim(loadTextFile(tb_mainServer_file(), tb_mainServer_default)); } static public File tb_mainServer_file() { return getProgramFile("#1001638", "mainserver.txt"); } static public boolean tb_mainServer_isDefault() { return eq(tb_mainServer(), tb_mainServer_default); } static public String standardCredentials_noCookies() { return standardCredentials() + "&noCookies=1"; } static public String dropFirstLine(String text) { if (text == null) return null; int i = text.indexOf('\n'); return i >= 0 ? text.substring(i + 1) : ""; } static public boolean getServerTranspiled2_allowLocalFallback = true, getServerTranspiled2_localFallbackVerbose = true; static public Map getServerTranspiled2_tempCache; static public String getServerTranspiled2(String id) { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getTranspiled(id); return getServerTranspiled2_noResourceLoader(id); } static public String getServerTranspiled2_noResourceLoader(String id) { id = fsIOpt(id); String transpiled = mapGet(getServerTranspiled2_tempCache, id); if (transpiled != null) return transpiled; transpiled = loadCachedTranspilation(id); String md5 = null; if (machineIsOffline() || isOfflineMode() || isLocalSnippet(id)) return transpiled; if (transpiled != null) md5 = md5(transpiled); String transpiledSrc; try { transpiledSrc = getServerTranspiled(formatSnippetID(id), md5); } catch (Throwable e) { if (!getServerTranspiled2_allowLocalFallback) rethrow(e); printExceptionShort(e); if (getServerTranspiled2_localFallbackVerbose) print("Fallback to local code"); return transpiled; } if (eq(transpiledSrc, "SAME")) { if (!isTrue(loadPage_silent.get())) print("SAME"); return mapPut_returnValue(getServerTranspiled2_tempCache, id, transpiled); } return mapPut_returnValue(getServerTranspiled2_tempCache, id, transpiledSrc); } static public File transpiledStandardFunctions_file(TreeSet functionSet) { String name = uniqueFileNameUsingMD5_80_v2(join("+", functionSet)); File dir = javaxCachesDir("Transpiled Standard Functions"); saveTextFileUnlessExists(newFile(dir, name + ".functions"), lines(functionSet)); return newFile(dir, name + ".java"); } static public String loadTextFile(String fileName) { return loadTextFile(fileName, null); } static public String loadTextFile(File f, String defaultContents) { return loadTextFile(f, defaultContents, "UTF-8"); } static public String loadTextFile(File f, String defaultContents, String encoding) { try { checkFileNotTooBigToRead(f); if (f == null || !f.exists()) return defaultContents; FileInputStream fileInputStream = new FileInputStream(f); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, encoding); return loadTextFile(inputStreamReader); } catch (Exception __e) { throw rethrow(__e); } } public static String loadTextFile(File fileName) { return loadTextFile(fileName, null); } static public String loadTextFile(String fileName, String defaultContents) { return fileName == null ? defaultContents : loadTextFile(newFile(fileName), defaultContents); } static public String loadTextFile(Reader reader) throws IOException { StringBuilder builder = new StringBuilder(); try { char[] buffer = new char[1024]; int n; while (-1 != (n = reader.read(buffer))) builder.append(buffer, 0, n); } finally { reader.close(); } return str(builder); } static public long recommendedTranspilationDateForStandardFunctions(Collection sfNames) { long date = 0; for (String name : sfNames) { long d = recommendedTranspilationDateForStandardFunction(name); if (d == 0) return 0; date = max(date, d); } return date; } static public String findTranslators2(String src, List libsOut) { return join(findTranslators2(javaTok(src), libsOut)); } static public List findTranslators2(List tok, List libsOut) { int i; while ((i = jfind(tok, "!")) >= 0) { setAdd(libsOut, tok.get(i + 2)); clearTokens(tok, i, i + 3); } return tok; } static public File javaCompile_overInternalBot(String src) { return javaCompile_overInternalBot(src, ""); } static synchronized public File javaCompile_overInternalBot(String src, String dehlibs) { return CompilerBot.compile(src, dehlibs); } static public Class hotwireCore(List files) { try { JavaXClassLoader classLoader = hotwire_makeClassLoader(files); Class theClass = classLoader.loadClass("main"); setOpt(theClass, "__javax", getJavaX()); if (getOpt(theClass, "programID") == null) setOpt(theClass, "programID", "#3999999"); if (!_inCore()) hotwire_copyOver(theClass); return theClass; } catch (Exception __e) { throw rethrow(__e); } } static public List loadLibraries(List snippetIDs) { return map("loadLibrary", snippetIDs); } static public StringBuilder stringBuilder(String s) { return new StringBuilder(unnull(s)); } static public String appendNewLineIfNempty(String s) { return empty(s) ? "" : s + "\n"; } static public String assertIdentifier(String s) { return assertIsIdentifier(s); } static public String assertIdentifier(String msg, String s) { return assertIsIdentifier(msg, s); } static public Class veryQuickJava(CharSequence mainJava) { return veryQuickJava3(str(mainJava)); } static public void saveTranspiledStandardFunctions(TreeSet functionSet, String transpiledSrc) { try { saveTextFile(transpiledStandardFunctions_file(functionSet), transpiledSrc); } catch (Throwable __e) { _handleException(__e); } } static public long done2_always(long startTime, String desc) { long time = sysNow() - startTime; saveTiming_noPrint(time); print(desc + " [" + time + " ms]"); return time; } static public long done2_always(String desc, long startTime) { return done2_always(startTime, desc); } static public long done2_always(long startTime) { return done2_always(startTime, ""); } static public Set _registerAutoCloseable_set = synchroHashSet(); static public void _registerAutoCloseable(AutoCloseable c) { addIfNotNull(_registerAutoCloseable_set, c); } static public void cleanMeUp__registerAutoCloseable() { closeAutoCloseables(getAndClearList(_registerAutoCloseable_set)); } static public Set syncIdentityHashSet() { return (Set) synchronizedSet(identityHashSet()); } static public AutoCloseable tempAdd(final Collection l, final A a) { if (l == null || l.contains(a)) return null; l.add(a); return new AutoCloseable() { public String toString() { return "l.remove(a);"; } public void close() throws Exception { l.remove(a); } }; } static public A third(List l) { return _get(l, 2); } static public A third(Iterable l) { if (l == null) return null; Iterator it = iterator(l); for (int _repeat_0 = 0; _repeat_0 < 2; _repeat_0++) { if (!it.hasNext()) return null; it.next(); } return it.hasNext() ? it.next() : null; } static public A third(Producer p) { if (p == null) return null; for (int _repeat_1 = 0; _repeat_1 < 2; _repeat_1++) { if (p.next() == null) return null; } return p.next(); } static public A third(A[] bla) { return bla == null || bla.length <= 2 ? null : bla[2]; } static public VF1 runnableToVF1(final Runnable r) { return r == null ? null : new VF1() { public void get(A a) { try { r.run(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "r.run()"; } }; } static public Object callOptMC(String method, Object... args) { return callOpt(mc(), method, args); } static public Throwable getExceptionCause(Throwable e) { Throwable c = e.getCause(); return c != null ? c : e; } static public boolean methodIsStatic(Method m) { return (m.getModifiers() & Modifier.STATIC) != 0; } static public boolean argumentCompatibleWithType(Object arg, Class type) { return arg == null ? !type.isPrimitive() : isInstanceX(type, arg); } static public void arraycopy(Object[] a, Object[] b) { if (a != null && b != null) arraycopy(a, 0, b, 0, Math.min(a.length, b.length)); } static public void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) { if (n != 0) System.arraycopy(src, srcPos, dest, destPos, n); } static public A[] arrayOfType(Class type, int n) { return makeArray(type, n); } static public A[] arrayOfType(int n, Class type) { return arrayOfType(type, n); } static public List getClassNames(Collection l) { List out = new ArrayList(); if (l != null) for (Object o : l) out.add(o == null ? null : getClassName(o)); return out; } static public boolean domainIsUnder(String domain, String mainDomain) { return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain); } static public String theAGIBlueDomain() { return "agi.blue"; } static public Throwable getException(Runnable r) { try { callF(r); return null; } catch (Throwable e) { return e; } } static public boolean addIfNotNull(Collection l, A a) { return a != null && l != null & l.add(a); } static public void addIfNotNull(MultiSet ms, A a) { if (a != null && ms != null) ms.add(a); } static public Map objectToMap(Object o) { try { if (o instanceof Map) return (Map) o; TreeMap map = new TreeMap(); Class c = o.getClass(); while (c != Object.class) { Field[] fields = c.getDeclaredFields(); for (final Field field : fields) { if ((field.getModifiers() & Modifier.STATIC) != 0) continue; field.setAccessible(true); final Object value = field.get(o); if (value != null) map.put(field.getName(), value); } c = c.getSuperclass(); } if (o instanceof DynamicObject) putAll(map, ((DynamicObject) o).fieldValues); return map; } catch (Exception __e) { throw rethrow(__e); } } static public List> objectToMap(Iterable l) { if (l == null) return null; List x = new ArrayList(); for (Object o : l) x.add(objectToMap(o)); return x; } static public List javaTokPlusBrackets2(String s) { return tok_combineRoundCurlySquareBrackets_keep(javaTok(s)); } static public List parse3(String s) { return dropPunctuation(javaTokPlusPeriod(s)); } static public boolean equalsIgnoreCase(String a, String b) { return eqic(a, b); } static public boolean equalsIgnoreCase(char a, char b) { return eqic(a, b); } static public Class primitiveToBoxedType(Class type) { if (type == boolean.class) return Boolean.class; if (type == int.class) return Integer.class; if (type == long.class) return Long.class; if (type == float.class) return Float.class; if (type == short.class) return Short.class; if (type == char.class) return Character.class; if (type == byte.class) return Byte.class; if (type == double.class) return Double.class; return null; } static public DynModule dm_currentModuleMandatory() { return dm_current_mandatory(); } static public String getProgramID() { return nempty(programID) ? formatSnippetIDOpt(programID) : "?"; } static public String getProgramID(Class c) { String id = (String) getOpt(c, "programID"); if (nempty(id)) return formatSnippetID(id); return "?"; } static public String getProgramID(Object o) { return getProgramID(getMainClass(o)); } static public AutoCloseable tempActivity(Object r) { return null; } static public long fixTimestamp(long timestamp) { return timestamp > now() ? 0 : timestamp; } static public Object costCenter() { return mc(); } static public TreeSet toCaseInsensitiveSet_treeSet(Iterable c) { if (isCISet(c)) return (TreeSet) c; TreeSet set = caseInsensitiveSet_treeSet(); addAll(set, c); return set; } static public TreeSet toCaseInsensitiveSet_treeSet(String... x) { TreeSet set = caseInsensitiveSet_treeSet(); addAll(set, x); return set; } static public String makeRandomID(int length) { return makeRandomID(length, defaultRandomGenerator()); } static public String makeRandomID(int length, Random random) { char[] id = new char[length]; for (int i = 0; i < id.length; i++) id[i] = (char) ((int) 'a' + random.nextInt(26)); return new String(id); } static public String makeRandomID(Random r, int length) { return makeRandomID(length, r); } static public TreeMap litCIMap(Object... x) { TreeMap map = caseInsensitiveMap(); litmap_impl(map, x); return map; } static public String regexpReplaceIC(String s, String pat, Object f) { return regexReplaceIC(s, pat, f); } static public String regexpReplaceIC(String s, String pat, IF1 f) { return regexReplaceIC(s, pat, f); } static public String formatDouble(double d, int digits) { String format = digits <= 0 ? "0" : "0." + rep(digits, '#'); return decimalFormatEnglish(format, d); } static public Charset utf8charset_cache; static public Charset utf8charset() { if (utf8charset_cache == null) utf8charset_cache = utf8charset_load(); return utf8charset_cache; } static public Charset utf8charset_load() { return Charset.forName("UTF-8"); } static public CloseableIterableIterator emptyCloseableIterableIterator_instance = new CloseableIterableIterator() { public Object next() { throw fail(); } public boolean hasNext() { return false; } }; static public CloseableIterableIterator emptyCloseableIterableIterator() { return emptyCloseableIterableIterator_instance; } static public CloseableIterableIterator linesFromReader(Reader r) { final BufferedReader br = bufferedReader(r); return iteratorFromFunction_f0_autoCloseable(new F0() { public String get() { try { return readLineFromReaderWithClose(br); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret readLineFromReaderWithClose(br);"; } }, _wrapIOCloseable(r)); } static public BufferedReader utf8bufferedReader(InputStream in) { try { return bufferedReader(_registerIOWrap(new InputStreamReader(in, "UTF-8"), in)); } catch (Exception __e) { throw rethrow(__e); } } static public BufferedReader utf8bufferedReader(File f) { try { return utf8bufferedReader(newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static public GZIPInputStream newGZIPInputStream(File f) { return gzInputStream(f); } static public GZIPInputStream newGZIPInputStream(InputStream in) { return gzInputStream(in); } static public File newFile(File base, String... names) { for (String name : names) base = new File(base, name); return base; } static public File newFile(String name) { return name == null ? null : new File(name); } static public File newFile(String base, String... names) { return newFile(newFile(base), names); } static public int indexOfIgnoreCase(List a, String b) { return indexOfIgnoreCase(a, b, 0); } static public int indexOfIgnoreCase(List a, String b, int i) { int n = a == null ? 0 : a.size(); for (; i < n; i++) if (eqic(a.get(i), b)) return i; return -1; } static public int indexOfIgnoreCase(String a, String b) { return indexOfIgnoreCase_manual(a, b); } static public int indexOfIgnoreCase(String a, String b, int i) { return indexOfIgnoreCase_manual(a, b, i); } static public boolean endsWithIgnoreCase(String a, String b) { int la = l(a), lb = l(b); return la >= lb && regionMatchesIC(a, la - lb, b, 0, lb); } static public boolean endsWithIgnoreCase(String a, String b, Matches m) { if (!endsWithIgnoreCase(a, b)) return false; if (m != null) m.m = new String[] { substring(a, 0, l(a) - l(b)) }; return true; } static public String joinWithSemicolon(Iterable l) { return join("; ", l); } static public void litmap_impl_noOverwrite(Map map, Object... x) { if (x != null) for (int i = 0; i < x.length - 1; i += 2) putIfNotThere(map, x[i], x[i + 1]); } static public List trimAll(Collection l) { List l2 = new ArrayList(); if (l != null) for (String s : l) l2.add(trim(s)); return l2; } static public List splitAt(String s, String splitter) { if (empty(splitter)) return null; List parts = new ArrayList(); int i = 0; if (s != null) while (i < l(s)) { int j = indexOf(s, splitter, i); if (j < 0) j = l(s); parts.add(substring(s, i, j)); i = j + l(splitter); } return parts; } static public List splitAtColon(String s) { return empty(s) ? emptyList() : asList(s.split(":")); } public static boolean isSnippetID(String s) { try { parseSnippetID(s); return true; } catch (RuntimeException e) { return false; } } static public String snippetImageURL(long snippetID) { return snippetImageURL(fsI(snippetID)); } static public String snippetImageURL(String snippetID) { return snippetImageURL(snippetID, "png"); } static public String snippetImageURL(String snippetID, String contentType) { if (snippetID == null || isURL(snippetID)) return snippetID; long id = parseSnippetID(snippetID); String url; if (isImageServerSnippet(id)) url = imageServerLink(id); else url = "https://botcompany.de/img/" + id; return url; } static public double toDouble(Object o) { if (o instanceof Number) return ((Number) o).doubleValue(); if (o instanceof BigInteger) return ((BigInteger) o).doubleValue(); if (o instanceof String) return parseDouble(((String) o)); if (o == null) return 0.0; throw fail(o); } static public TimeZone getTimeZone(String name) { return TimeZone.getTimeZone(name); } static public String standardTimeZone_name = "Europe/Berlin"; static public String standardTimeZone() { return standardTimeZone_name; } static public File loadLibrary(String snippetID) { return loadBinarySnippet(snippetID); } static public String quoteIfNotIdentifierOrInteger(String s) { if (s == null) return null; return isJavaIdentifier(s) || isInteger(s) ? s : quote(s); } static public Map singular_specials = litmap("children", "child", "images", "image", "chess", "chess"); static public Set singular_specials2 = litciset("time", "machine", "line", "rule"); static public String singular(String s) { if (s == null) return null; { String __1 = singular_specials.get(s); if (!empty(__1)) return __1; } if (singular_specials2.contains(dropSuffix("s", afterLastSpace(s)))) return dropSuffix("s", s); if (s.endsWith("ness")) return s; if (s.endsWith("ges")) return dropSuffix("s", s); if (endsWith(s, "bases")) return dropLast(s); s = dropSuffix("es", s); s = dropSuffix("s", s); return s; } static public Map compileRegexpIC_cache = syncMRUCache(10); static public java.util.regex.Pattern compileRegexpIC(String pat) { java.util.regex.Pattern p = compileRegexpIC_cache.get(pat); if (p == null) { try { compileRegexpIC_cache.put(pat, p = java.util.regex.Pattern.compile(pat, Pattern.CASE_INSENSITIVE)); } catch (PatternSyntaxException e) { throw rethrow(wrapPatternSyntaxException(e)); } } return p; } static public boolean startsWithLetterOrDigit(String s) { return nempty(s) && Character.isLetterOrDigit(s.charAt(0)); } static public String regexpQuote(String s) { return s.length() == 0 ? "" : Pattern.quote(s); } static public List takeLast(List l, int n) { return newSubList(l, l(l) - n); } static public List takeLast(int n, List l) { return takeLast(l, n); } static public String takeLast(int n, String s) { return substring(s, l(s) - n); } static public String takeLast(String s, int n) { return substring(s, l(s) - n); } static public String[] find2(List pat, List tok) { for (int idx = 0; idx < tok.size(); idx += 2) { String[] result = find2(pat, tok, idx); if (result != null) return result; } return null; } static public String[] find2(List pat, List tok, int idx) { if (idx + pat.size() > tok.size()) return null; List result = new ArrayList(); for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(idx + i); if (eq(p, "*")) result.add(t); else if (!p.equalsIgnoreCase(t)) return null; } return toStringArray(result); } static public List tok_combineRoundBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eq(t, "(")) { int j = findEndOfBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public List tok_combineRoundOrCurlyBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eqOneOf(t, "{", "(")) { int j = findEndOfBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public int defaultTokenizerCacheSize() { return 1000; } static public int indexOfSubList(List x, List y) { return indexOfSubList(x, y, 0); } static public int indexOfSubList(List x, List y, int i) { outer: for (; i + l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i + j), y.get(j))) continue outer; return i; } return -1; } static public int indexOfSubList(List x, A[] y, int i) { outer: for (; i + l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i + j), y[j])) continue outer; return i; } return -1; } static public String trimJoin(List s) { return trim(join(s)); } static public A[] newObjectArrayOfSameType(A[] a) { return newObjectArrayOfSameType(a, a.length); } static public A[] newObjectArrayOfSameType(A[] a, int n) { return (A[]) Array.newInstance(a.getClass().getComponentType(), n); } static public List replaceSubList(List l, List x, List y) { return replaceSublist(l, x, y); } static public List replaceSubList(List l, int fromIndex, int toIndex, List y) { return replaceSublist(l, fromIndex, toIndex, y); } static public boolean cicAtOddPosition(List l, String s) { int n = l(l); for (int i = 1; i < n; i += 2) if (eqic(l.get(i), s)) return true; return false; } static public String renderStructs(Object... params) { List l = new ArrayList(); if (odd(l(params))) l.add(addSuffix(str(first(params)), ":")); for (int i = l(params) & 1; i + 1 < l(params); i += 2) l.add(params[i] + "=" + sfu(params[i + 1])); return joinWithSpace(l); } static public class allSpreads_Data { public int n; public List collecting; } static public class allSpreads_StackEntry { public int remaining, take; public int position; public Object step(List stack, allSpreads_Data d) { if (position == 0) { if (l(d.collecting) >= d.n - 1) { List result = listPlus(d.collecting, remaining); popLast(stack); return result; } position++; } if (position == 1) { if (take <= remaining) { d.collecting.add(take); allSpreads_StackEntry e = new allSpreads_StackEntry(); e.remaining = remaining - take; stack.add(e); position++; } else popLast(stack); } else if (position == 2) { removeLast(d.collecting); take++; position = 1; } return null; } } static public IterableIterator> allSpreads(final int toSpread, final int buckets) { final allSpreads_Data d = new allSpreads_Data(); d.n = buckets; d.collecting = new ArrayList(); final List stack = new ArrayList(); allSpreads_StackEntry e = new allSpreads_StackEntry(); e.remaining = toSpread; stack.add(e); return iff(new F0() { public Object get() { try { while (nempty(stack)) { ping(); { Object __1 = last(stack).step(stack, d); if (__1 != null) return __1; } } return endMarker(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "while (nempty(stack)) {\r\n ping();\r\n try object last(stack).step(sta..."; } }); } static public String structureForUser(Object o) { return beautifyStructure(struct_noStringSharing(o)); } static public Class getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; } } static public Class getClass(Object o) { return o instanceof Class ? (Class) o : o.getClass(); } static public Class getClass(Object realm, String name) { try { try { return getClass(realm).getClassLoader().loadClass(classNameToVM(name)); } catch (ClassNotFoundException e) { return null; } } catch (Exception __e) { throw rethrow(__e); } } static public String classNameToVM(String name) { return name.replace(".", "$"); } static public Map synchroMap() { return synchroHashMap(); } static public Map synchroMap(Map map) { return Collections.synchronizedMap(map); } static public boolean checkCondition(Object condition, Object... args) { return isTrue(callF(condition, args)); } static public boolean checkCondition(IF1 condition, A arg) { return isTrue(callF(condition, arg)); } static public boolean emptyString(String s) { return s == null || s.length() == 0; } static public String htmlencode_forParams_v2(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { out.append("&#"); out.append((int) c); out.append(';'); } else out.append(c); } return out.toString(); } public static long parseSnippetID(String snippetID) { long id = Long.parseLong(shortenSnippetID(snippetID)); if (id == 0) throw fail("0 is not a snippet ID"); return id; } static public Object callFunction(Object f, Object... args) { return callF(f, args); } static public WeakReference newWeakReference(A a) { return a == null ? null : new WeakReference(a); } static public void removeSubList(List l, int from, int to) { if (l != null) subList(l, from, to).clear(); } static public void removeSubList(List l, int from) { if (l != null) subList(l, from).clear(); } static public void copyListPart(List a, int i1, List b, int i2, int n) { if (a == null || b == null) return; for (int i = 0; i < n; i++) b.set(i2 + i, a.get(i1 + i)); } static public int maxStringLength(Collection l) { int n = 0; if (l != null) for (String s : l) n = max(n, l(s)); return n; } static public String rpad(String s, int l) { return rpad(s, l, ' '); } static public String rpad(String s, int l, char c) { return lengthOfString(s) >= l ? s : s + rep(c, l - lengthOfString(s)); } static public String rpad(int l, String s) { return rpad(s, l); } static public int countLines(String s) { return l(toLines(s)); } static public A firstOfPair(Pair p) { return p == null ? null : p.a; } static public B secondOfPair(Pair p) { return p == null ? null : p.b; } static public int findEndOfCurlyBracketPart(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eq(cnc.get(j), "{")) ++level; else if (eq(cnc.get(j), "}")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static public List newSubList(List l, int startIndex, int endIndex) { return cloneList(subList(l, startIndex, endIndex)); } static public List newSubList(List l, int startIndex) { return cloneList(subList(l, startIndex)); } static public Object vm_generalMap_get(Object key) { return vm_generalMap().get(key); } static public void swingAndWait(Runnable r) { try { if (isAWTThread()) r.run(); else EventQueue.invokeAndWait(addThreadInfoToRunnable(r)); } catch (Exception __e) { throw rethrow(__e); } } static public Object swingAndWait(final Object f) { if (isAWTThread()) return callF(f); else { final Var result = new Var(); swingAndWait(new Runnable() { public void run() { try { result.set(callF(f)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "result.set(callF(f));"; } }); return result.get(); } } static public A revalidate(final A c) { if (c == null || !c.isShowing()) return c; { swing(new Runnable() { public void run() { try { c.revalidate(); c.repaint(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "// magic combo to actually relayout and repaint\r\n c.revalidate();\r\n c.r..."; } }); } return c; } static public void revalidate(JFrame f) { revalidate((Component) f); } static public void revalidate(JInternalFrame f) { revalidate((Component) f); } static public JFrame getFrame(final Object _o) { return swing(new F0() { public JFrame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof JFrame) return (JFrame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n if (o instanceof ButtonGroup) o = first(buttonsInGroup((Button..."; } }); } static public boolean isStringStartingWith(Object o, String prefix) { return o instanceof String && ((String) o).startsWith(prefix); } static public Map codeAnalysis_identifierSafetyMap() { return mechHashMap("JavaX Identifier Safety"); } static public Set tok_allIdentifiers(String s) { return new HashSet(filter(__56 -> isIdentifier(__56), javaTokC(s))); } static public boolean codeAnalysis_isSafeIdentifier(String id) { return startsWith(id, "$"); } static public List tokSplitAtComma(String s) { List tok = javaTok(s); List l = new ArrayList(); while (l(tok) > 1) { int i = smartIndexOf(tok, ","); l.add(trim(join(subList(tok, 0, i)))); tok = subList(tok, i + 1); } return l; } static public List simplifySafetyTags(Collection tags) { List l = uniquifyList(tags); if (l.contains("safe") && containsAnythingNeq(l, "safe")) return listMinus(l, "safe"); return l; } static public String simplifySafetyTags(String tags) { List l = tokSplitAtComma(tags); Collection l2 = simplifySafetyTags(l); return l(l2) != l(l) ? joinWithComma(l2) : tags; } static public String loadTextFile_trim(String fileName) { return trim(loadTextFile(fileName)); } static public String loadTextFile_trim(File f, String defaultContents) { return trim(loadTextFile(f, defaultContents)); } static public String loadTextFile_trim(File fileName) { return trim(loadTextFile(fileName)); } static public String loadTextFile_trim(String fileName, String defaultContents) { return trim(loadTextFile(fileName, defaultContents)); } static public String _userHome; static public String userHome() { if (_userHome == null) return actualUserHome(); return _userHome; } static public File userHome(String path) { return new File(userDir(), path); } static public Map parseStdFunctionsList(String snippetSrc) { return parseStdFunctionsList(snippetSrc, new LinkedHashMap()); } static public Map parseStdFunctionsList(String snippetSrc, Map map) { List tok = javaTok(snippetSrc); int i = findCodeTokens(tok, "standardFunctions", "=", "litlist", "("); int opening = i + 6; int closing = indexOf(tok, ")", opening) - 1; for (i = opening + 2; i < closing; i += 4) { String[] f = unquote(tok.get(i)).split("/"); map.put(f[1], f[0]); } return map; } static public String loadSnippetSilently(Snippet s) { return loadSnippetQuietly(s); } static public String loadSnippetSilently(String snippetID) { return loadSnippetQuietly(snippetID); } static public File getProgramFile(String progID, String fileName) { if (new File(fileName).isAbsolute()) return new File(fileName); return new File(getProgramDir(progID), fileName); } static public File getProgramFile(String fileName) { return getProgramFile(getProgramID(), fileName); } static public String standardCredentials() { String user = standardCredentialsUser(); String pass = standardCredentialsPass(); if (nempty(user) && nempty(pass)) return "&_user=" + urlencode(user) + "&_pass=" + urlencode(pass); return ""; } static public IResourceLoader vm_getResourceLoader() { return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader")); } static public String fsIOpt(String s) { return formatSnippetIDOpt(s); } static public String loadCachedTranspilation(String id) { try { return loadTextFilePossiblyGZipped(getCachedTranspilationFile(id)); } catch (Throwable __e) { return null; } } static public boolean machineIsOffline() { return isFalse(callF(vmGeneralMap_get("areWeOnline"))); } static public boolean isOfflineMode() { return eq("1", trim(loadProgramTextFile("#1005806", "offline-mode"))); } static public boolean isLocalSnippet(String snippetID) { return isLocalSnippetID(snippetID); } static public boolean isLocalSnippet(long snippetID) { return isLocalSnippetID(snippetID); } static public String md5(String text) { try { if (text == null) return "-"; return bytesToHex(md5_impl(toUtf8(text))); } catch (Exception __e) { throw rethrow(__e); } } static public String md5(byte[] data) { if (data == null) return "-"; return bytesToHex(md5_impl(data)); } static public byte[] md5_impl(byte[] data) { try { return MessageDigest.getInstance("MD5").digest(data); } catch (Exception __e) { throw rethrow(__e); } } static public String md5(File file) { return md5OfFile(file); } static public String getServerTranspiled(String snippetID) { return getServerTranspiled(snippetID, null); } static public boolean getServerTranspiled_printStackTrace = false; static public String getServerTranspiled(String snippetID, String expectedMD5) { try { if (getServerTranspiled_printStackTrace) printStackTrace(); long id = parseSnippetID(snippetID); String text = loadPage_utf8(tb_mainServer() + "/tb-int/get-transpiled.php?raw=1&withlibs=1&id=" + id + "&utf8=1" + (l(expectedMD5) > 1 ? "&md5=" + urlencode(expectedMD5) : "") + standardCredentials()); if (nempty(text) && neq(text, "SAME")) saveTranspiledCode(snippetID, text); return text; } catch (Exception __e) { throw rethrow(__e); } } static public String formatSnippetID(String id) { return "#" + parseSnippetID(id); } static public String formatSnippetID(long id) { return "#" + id; } static public void printExceptionShort(Throwable e) { printExceptionShort("", e); } static public void printExceptionShort(String prefix, Throwable e) { print(prefix, exceptionToStringShort(e)); } static public B mapPut_returnValue(Map map, A key, B value) { mapPut(map, key, value); return value; } static public String uniqueFileNameUsingMD5_80_v2(String fullName) { return uniqueFileNameUsingMD5_80_v2(fullName, md5(fullName)); } static public String uniqueFileNameUsingMD5_80_v2(String fullName, String md5) { return takeFirst(80 - 33, fileNameEncode(fullName)) + " - " + md5; } static public File javaxCachesDir_dir; static public File javaxCachesDir() { return javaxCachesDir_dir != null ? javaxCachesDir_dir : new File(userHome(), "JavaX-Caches"); } static public File javaxCachesDir(String sub) { return newFile(javaxCachesDir(), sub); } static public void saveTextFileUnlessExists(File f, String contents) { if (f != null && !f.exists()) saveTextFile(f, contents); } static public ThreadLocal> checkFileNotTooBigToRead_tl = new ThreadLocal(); static public void checkFileNotTooBigToRead(File f) { callF(checkFileNotTooBigToRead_tl.get(), f); } static public long recommendedTranspilationDateForStandardFunction(String sfName) { return toLong(mechMap("Recommended SF Transpilation Date").get(sfName)); } static public void clearTokens(List tok) { clearAllTokens(tok); } static public void clearTokens(List tok, int i, int j) { clearAllTokens(tok, i, j); } static public void clearTokens(List tok, IntRange r) { clearAllTokens(tok, r.start, r.end); } static public JavaXClassLoader hotwire_makeClassLoader(List files) { Collection toShare = hotwire_classesToShare(); return nempty(toShare) ? new JavaXClassLoaderWithParent2(null, files, myClassLoader(), cloneList(toShare)) : new JavaXClassLoader(null, files); } static public String assertIsIdentifier(String s) { if (!isIdentifier(s)) throw fail("Not an identifier: " + quote(s)); return s; } static public String assertIsIdentifier(String msg, String s) { if (!isIdentifier(s)) throw fail(msg + " - Not an identifier: " + quote(s)); return s; } static public boolean veryQuickJava_silent = true; static public boolean veryQuickJava_useCompilerBot = true; static public ThreadLocal veryQuickJava_transpiled = new ThreadLocal(); static public Object veryQuickJava3_cacheFunction; static public Class veryQuickJava3(String mainJava) { return veryQuickJava3(mainJava, emptyList()); } static public Class veryQuickJava3(String mainJava, List libs) { Class c = (Class) (callF(veryQuickJava3_cacheFunction, mainJava, libs)); if (c != null) return c; transpileRaw_silent = veryQuickJava_silent; String src = transpileRaw(mainJava); if (empty(src)) { printWithIndent("JAVAX> ", mainJava); throw fail("Transpiler returned empty result"); } if (veryQuickJava_transpiled.get() != null) veryQuickJava_transpiled.set(src); return veryQuickJava_finish(src, libs); } static public File saveTextFile(String fileName, String contents) throws IOException { CriticalAction action = beginCriticalAction("Saving file " + fileName + " (" + l(contents) + " chars)"); try { File file = new File(fileName); mkdirsForFile(file); String tempFileName = fileName + "_temp"; File tempFile = new File(tempFileName); if (contents != null) { if (tempFile.exists()) try { String saveName = tempFileName + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (contents != null) if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); vmBus_send("wroteFile", file); return file; } finally { action.done(); } } static public File saveTextFile(File fileName, String contents) { try { saveTextFile(fileName.getPath(), contents); return fileName; } catch (Exception __e) { throw rethrow(__e); } } static public ThreadLocal saveTiming_last = new ThreadLocal(); static public void saveTiming(long ms) { print(ms + " ms"); saveTiming_noPrint(ms); } static public void saveTiming_noPrint(long ms) { saveTiming_last.set(ms); } static public void closeAutoCloseables(Collection l) { if (l != null) for (AutoCloseable c : l) { try { c.close(); } catch (Throwable __e) { _handleException(__e); } } } static public List getAndClearList(Collection l) { if (l == null) return emptyList(); synchronized (collectionMutex(l)) { List out = cloneList(l); l.clear(); return out; } } static public Set synchronizedSet() { return synchroHashSet(); } static public Set synchronizedSet(Set set) { return Collections.synchronizedSet(set); } static public A _get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static public Object _get(Object o, String field) { return get(o, field); } static public Object _get(String field, Object o) { return get(o, field); } static public A _get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } static public A[] makeArray(Class type, int n) { return (A[]) Array.newInstance(type, n); } static public Map putAll(Map a, Map b) { if (a != null && b != null) a.putAll(b); return a; } static public MultiMap putAll(MultiMap a, Map b) { if (a != null) a.putAll((Map) b); return a; } static public Map putAll(Map a, Object... b) { if (a != null) litmap_impl(a, b); return a; } static public List tok_combineRoundCurlySquareBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eqOneOf(t, "{", "(", "[")) { int j = findEndOfBracketPart2(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public String formatSnippetIDOpt(String s) { return isSnippetID(s) ? formatSnippetID(s) : s; } static public Class getMainClass() { return mc(); } static public Class getMainClass(Object o) { try { if (o == null) return null; if (o instanceof Class && eq(((Class) o).getName(), "x30")) return (Class) o; ClassLoader cl = (o instanceof Class ? (Class) o : o.getClass()).getClassLoader(); return cl == null ? null : cl.loadClass("main"); } catch (Exception __e) { throw rethrow(__e); } } static public boolean isCISet(Iterable l) { return l instanceof TreeSet && ((TreeSet) l).comparator() == caseInsensitiveComparator(); } static public Random defaultRandomGenerator() { return ThreadLocalRandom.current(); } static public String regexReplaceIC(String s, String pat, Object f) { return regexReplace(regexpMatcherIC(pat, s), f); } static public String decimalFormatEnglish(String format, double d) { return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d); } static public BufferedReader bufferedReader(Reader r) { return bufferedReader(r, 8192); } static public BufferedReader bufferedReader(Reader r, int bufSize) { return r instanceof BufferedReader ? (BufferedReader) r : _registerIOWrap(new BufferedReader(r, bufSize), r); } static public CloseableIterableIterator iteratorFromFunction_f0_autoCloseable(final F0 f, final AutoCloseable closeable) { class IFF2 extends CloseableIterableIterator { public A a; public boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } public void getNext() { if (done || a != null) return; a = f.get(); done = a == null; } public void close() throws Exception { if (closeable != null) closeable.close(); } } ; return new IFF2(); } static public String readLineFromReaderWithClose(BufferedReader r) { try { String s = r.readLine(); if (s == null) r.close(); return s; } catch (Exception __e) { throw rethrow(__e); } } static public AutoCloseable _wrapIOCloseable(final AutoCloseable c) { return c == null ? null : new AutoCloseable() { public String toString() { return "c.close();\r\n _registerIO(c, null, false);"; } public void close() throws Exception { c.close(); _registerIO(c, null, false); } }; } static public A _registerIOWrap(A wrapper, Object wrapped) { return wrapper; } static public FileInputStream newFileInputStream(File path) throws IOException { return newFileInputStream(path.getPath()); } static public FileInputStream newFileInputStream(String path) throws IOException { FileInputStream f = new FileInputStream(path); _registerIO(f, path, true); return f; } static public int gzInputStream_defaultBufferSize = 65536; static public GZIPInputStream gzInputStream(File f) { try { return gzInputStream(new FileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static public GZIPInputStream gzInputStream(File f, int bufferSize) { try { return gzInputStream(new FileInputStream(f), bufferSize); } catch (Exception __e) { throw rethrow(__e); } } static public GZIPInputStream gzInputStream(InputStream in) { return gzInputStream(in, gzInputStream_defaultBufferSize); } static public GZIPInputStream gzInputStream(InputStream in, int bufferSize) { try { return _registerIOWrap(new GZIPInputStream(in, gzInputStream_defaultBufferSize), in); } catch (Exception __e) { throw rethrow(__e); } } static public int indexOfIgnoreCase_manual(String a, String b) { return indexOfIgnoreCase_manual(a, b, 0); } static public int indexOfIgnoreCase_manual(String a, String b, int i) { int la = strL(a), lb = strL(b); if (la < lb) return -1; int n = la - lb; loop: for (; i <= n; i++) { for (int j = 0; j < lb; j++) { char c1 = a.charAt(i + j), c2 = b.charAt(j); if (!eqic(c1, c2)) continue loop; } return i; } return -1; } static public void putIfNotThere(Map map, A key, B value) { if (map != null && key != null && value != null && !map.containsKey(key)) map.put(key, value); } static public String fsI(String id) { return formatSnippetID(id); } static public String fsI(long id) { return formatSnippetID(id); } static public boolean isURL(String s) { return startsWithOneOf(s, "http://", "https://", "file:"); } static public boolean isImageServerSnippet(long id) { return id >= 1100000 && id < 1200000; } static public String imageServerLink(String md5OrID) { if (possibleMD5(md5OrID)) return "https://botcompany.de/images/md5/" + md5OrID; return imageServerLink(parseSnippetID(md5OrID)); } static public String imageServerLink(long id) { return "https://botcompany.de/images/" + id; } static public File loadBinarySnippet(String snippetID) { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadBinarySnippet_noResourceLoader(snippetID); } static public File loadBinarySnippet_noResourceLoader(String snippetID) { try { long id = parseSnippetID(snippetID); if (isImageServerSnippet(id)) return loadImageAsFile(snippetID); File f = DiskSnippetCache_getLibrary(id); if (fileSize(f) == 0) f = loadDataSnippetToFile_noResourceLoader(snippetID); return f; } catch (Exception __e) { throw rethrow(__e); } } static public String afterLastSpace(String s) { return s == null ? null : substring(s, s.lastIndexOf(' ') + 1); } static public Map syncMRUCache(int size) { return synchroMap(new MRUCache(size)); } static public RuntimeException wrapPatternSyntaxException(PatternSyntaxException e) { if (e == null) return null; String pat = e.getPattern(); int i = e.getIndex(); return new RuntimeException("Regular expression error between " + multiLineQuoteWithSpaces(substring(pat, 0, i)) + " and " + multiLineQuoteWithSpaces(substring(pat, i)) + " - " + e.getMessage()); } static public int findEndOfBracketPart(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eqOneOf(cnc.get(j), "{", "(")) ++level; else if (eqOneOf(cnc.get(j), "}", ")")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static public A popLast(List l) { return liftLast(l); } static public List popLast(int n, List l) { return liftLast(n, l); } static public void removeLast(List l) { if (!l.isEmpty()) l.remove(l(l) - 1); } static public void removeLast(List l, int n) { removeSubList(l, l(l) - n); } static public void removeLast(int n, List l) { removeLast(l, n); } static public IterableIterator iff(Object f) { return iteratorFromFunction_withEndMarker(f); } static public IterableIterator iff(F0 f) { return iteratorFromFunction_withEndMarker(f); } static public IterableIterator iff(IF0 f) { return iteratorFromFunction_withEndMarker(f); } static public Object endMarker() { return iteratorFromFunction_endMarker; } static public String beautifyStructure(String s) { List tok = javaTokForStructure(s); structure_addTokenMarkers(tok); jreplace(tok, "lhm", ""); return join(tok); } static public String struct_noStringSharing(Object o) { structure_Data d = new structure_Data(); d.noStringSharing = true; return structure(o, d); } static public String shortenSnippetID(String snippetID) { if (snippetID.startsWith("#")) snippetID = snippetID.substring(1); String httpBlaBla = "http://tinybrain.de/"; if (snippetID.startsWith(httpBlaBla)) snippetID = snippetID.substring(httpBlaBla.length()); return "" + parseLong(snippetID); } static public int lengthOfString(String s) { return s == null ? 0 : s.length(); } static public Map vm_generalMap_map; static public Map vm_generalMap() { if (vm_generalMap_map == null) vm_generalMap_map = (Map) get(javax(), "generalMap"); return vm_generalMap_map; } static public Runnable addThreadInfoToRunnable(final Object r) { final Object info = _threadInfo(); return info == null ? asRunnable(r) : new Runnable() { public void run() { try { _inheritThreadInfo(info); callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_inheritThreadInfo(info); callF(r);"; } }; } static public List buttonsInGroup(ButtonGroup g) { if (g == null) return ll(); return asList(g.getElements()); } static public Map>> mechHashMap_cache = synchroMap(); static public Map mechHashMap(String listName) { Pair> p = mechHashMap_cache.get(listName); String text = mechList_raw(listName); if (p != null && eq(p.a, text)) return p.b; String parsing = first(mechList_opt(listName + " | Parsing")); p = pair(text, (Map) (parsing != null ? asHashMap((Map) callAndMake(parsing, text)) : parseDoubleArrowMap(new HashMap(), tlft(text)))); mechHashMap_cache.put(listName, p); return p.b; } static public List uniquifyList(Collection l) { if (l == null) return null; if (l(l) < 2) return asList(l); HashSet set = new HashSet(); List out = new ArrayList(); for (A a : l) if (set.add(a)) out.add(a); return out; } static public boolean containsAnythingNeq(Collection l, A a) { for (A x : unnull(l)) if (neq(x, a)) return true; return false; } static public List listMinus(Collection l, Object... stuff) { if (l == null) return null; List l2 = similarEmptyList(l); Set set = lithashset(stuff); for (Object o : l) if (!set.contains(o)) l2.add(o); return l2; } static public String actualUserHome_value; static public String actualUserHome() { if (actualUserHome_value == null) { if (isAndroid()) actualUserHome_value = "/storage/emulated/0/"; else actualUserHome_value = System.getProperty("user.home"); } return actualUserHome_value; } static public File actualUserHome(String sub) { return newFile(new File(actualUserHome()), sub); } static public File userDir() { return new File(userHome()); } static public File userDir(String path) { return new File(userHome(), path); } static public File getProgramDir() { return programDir(); } static public File getProgramDir(String snippetID) { return programDir(snippetID); } static public String standardCredentialsUser() { return trim(loadTextFile(oneOfTheFiles(javaxSecretDir("tinybrain-username"), userDir(".tinybrain/username")))); } static public String standardCredentialsPass() { return trim(loadTextFile(oneOfTheFiles(javaxSecretDir("tinybrain-userpass"), userDir(".tinybrain/userpass")))); } static public A proxy(Class intrface, final Object target) { if (target == null) return null; if (isInstance(intrface, target)) return (A) target; return (A) java.lang.reflect.Proxy.newProxyInstance(intrface.getClassLoader(), new Class[] { intrface }, new proxy_InvocationHandler(target)); } static public A proxy(Object target, Class intrface) { return proxy(intrface, target); } static public String loadTextFilePossiblyGZipped(String fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static public String loadTextFilePossiblyGZipped(String fileName, String defaultContents) { File gz = new File(fileName + ".gz"); return gz.exists() ? loadGZTextFile(gz) : loadTextFile(fileName, defaultContents); } static public String loadTextFilePossiblyGZipped(File fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static public String loadTextFilePossiblyGZipped(File fileName, String defaultContents) { return loadTextFilePossiblyGZipped(fileName.getPath(), defaultContents); } static public File getCachedTranspilationFile(String id) { return newFile(getCodeProgramDir(id), "Transpilation"); } static public Object vmGeneralMap_get(Object key) { return vm_generalMap_get(key); } static public String loadProgramTextFile(String name) { return loadTextFile(getProgramFile(name)); } static public String loadProgramTextFile(String progID, String name) { return loadTextFile(getProgramFile(progID, name)); } static public String loadProgramTextFile(String progID, String name, String defaultText) { return loadTextFile(getProgramFile(progID, name), defaultText); } static public boolean isLocalSnippetID(String snippetID) { return isSnippetID(snippetID) && isLocalSnippetID(psI(snippetID)); } static public boolean isLocalSnippetID(long snippetID) { return snippetID >= 1000 && snippetID <= 9999; } public static String bytesToHex(byte[] bytes) { return bytesToHex(bytes, 0, bytes.length); } public static String bytesToHex(byte[] bytes, int ofs, int len) { StringBuilder stringBuilder = new StringBuilder(len * 2); for (int i = 0; i < len; i++) { String s = "0" + Integer.toHexString(bytes[ofs + i]); stringBuilder.append(s.substring(s.length() - 2, s.length())); } return stringBuilder.toString(); } static public boolean md5OfFile_verbose = false; static public String md5OfFile(String path) { return md5OfFile(newFile(path)); } static public String md5OfFile(File f) { try { if (!f.exists()) return "-"; if (md5OfFile_verbose) print("Getting MD5 of " + f); MessageDigest md5 = MessageDigest.getInstance("MD5"); FileInputStream in = new FileInputStream(f); try { byte[] buf = new byte[65536]; int l; while (true) { l = in.read(buf); if (l <= 0) break; md5.update(buf, 0, l); } return bytesToHex(md5.digest()); } finally { _close(in); } } catch (Exception __e) { throw rethrow(__e); } } static public void saveTranspiledCode(String progID, String code) { File dir = getCodeProgramDir(progID); new File(dir, "Transpilation").delete(); saveGZTextFile(new File(dir, "Transpilation.gz"), code); } static public String exceptionToStringShort(Throwable e) { lastException(e); e = getInnerException(e); String msg = hideCredentials(unnull(e.getMessage())); if (msg.indexOf("Error") < 0 && msg.indexOf("Exception") < 0) return baseClassName(e) + prependIfNempty(": ", msg); else return msg; } static public String fileNameEncode_safeChars = " ()[]#,!"; static public String fileNameEncode(String s) { StringBuilder buf = new StringBuilder(); int n = l(s); for (int i = 0; i < n; i++) { char c = s.charAt(i); if (contains(fileNameEncode_safeChars, c)) buf.append(c); else buf.append(urlencode(str(c))); } return str(buf); } static public Map mechMap(String listName) { return mechMapCI(listName); } static public Set hotwire_classesToShare = synchroSet(); static public Set hotwire_classesToShare() { return hotwire_classesToShare; } static public ClassLoader myClassLoader() { return _getClass(mc()).getClassLoader(); } static public boolean transpileRaw_silent = true; static public boolean transpileRaw_useDiskCache = false; static public Class transpileRaw_trans; static public boolean transpileRaw_mine = true; static public boolean transpileRaw_verySilent = false; static public boolean transpileRaw_dontCopyFromCreator = false; static public Lock transpileRaw_lock = lock(); static public ThreadLocal transpileRaw_asInclude = new ThreadLocal(); static public String transpileRaw(String mainJava) { return transpileRaw(mainJava, false, transpileRaw_useDiskCache); } static public String transpileRaw(String mainJava, boolean fragment) { return transpileRaw(mainJava, fragment, transpileRaw_useDiskCache); } static public String transpileRaw(String mainJava, boolean fragment, boolean useDiskCache) { mainJava = dropTranslators(mainJava); if (!transpileRaw_dontCopyFromCreator) transpileRaw_copyFromCreator(); Lock __0 = transpileRaw_lock; lock(__0); try { File cacheFile = null; if (useDiskCache) { cacheFile = new File(javaxCodeDir(), "Transpilations/" + uniqueFileNameUsingMD5_80_v2(mainJava) + ".java"); { String __3 = loadTextFile(cacheFile); if (!empty(__3)) return __3; } } AutoCloseable __4 = transpileRaw_verySilent ? null : tempLoadingAnim("Transpiling..."); try { transpileRaw_translator(); setOpt(transpileRaw_trans, "localStuffOnly", fragment); setOpt(transpileRaw_trans, "asInclude", isTrue(transpileRaw_asInclude.get())); set(transpileRaw_trans, "mainJava", mainJava); set(transpileRaw_trans, "print_byThread", print_byThread); if (!transpileRaw_verySilent) print("Running translator " + getOpt(transpileRaw_trans, "programID")); callMain(transpileRaw_trans); String main = (String) (get(transpileRaw_trans, "mainJava")); if (useDiskCache) { saveTextFile(new File(cacheFile.getPath() + "x"), mainJava); saveTextFile(cacheFile, main); } return main; } finally { _close(__4); } } finally { unlock(__0); } } static public Class transpileRaw_translator() { if (transpileRaw_trans == null) { transpileRaw_trans = hotwireSharingLibraries_silently(defaultJavaXTranslatorID()); transpileRaw_mine = true; makeDependent(transpileRaw_trans); } setOpt(transpileRaw_trans, "print_silent", transpileRaw_silent); return transpileRaw_trans; } static public void transpileRaw_copyFromCreator() { Lock __1 = transpileRaw_lock; lock(__1); try { if (transpileRaw_trans != null) return; Object c = creator(); if (c == null) return; Class trans = (Class) (getOpt(c, "transpileRaw_trans")); Lock lock = (Lock) (getOpt(c, "transpileRaw_lock")); if (trans != null && lock != null) { print("Using creator's transpiler: " + getProgramID(c) + " => " + programID()); transpileRaw_lock = lock; transpileRaw_trans = trans; transpileRaw_mine = false; } } finally { unlock(__1); } } static public void cleanMeUp_transpileRaw() { if (transpileRaw_mine) cleanUp(transpileRaw_trans); transpileRaw_trans = null; } static public A printWithIndent(A o) { return printIndent(o); } static public A printWithIndent(String indent, A o) { return printIndent(indent, o); } static public void printWithIndent(int indent, Object o) { printIndent(indent, o); } static public List beginCriticalAction_inFlight = synchroList(); static public class CriticalAction { public String description; public CriticalAction() { } public CriticalAction(String description) { this.description = description; } public void done() { beginCriticalAction_inFlight.remove(this); } } static public CriticalAction beginCriticalAction(String description) { ping(); CriticalAction c = new CriticalAction(description); beginCriticalAction_inFlight.add(c); return c; } static public void cleanMeUp_beginCriticalAction() { int n = 0; while (nempty(beginCriticalAction_inFlight)) { int m = l(beginCriticalAction_inFlight); if (m != n) { n = m; try { print("Waiting for " + n2(n, "critical actions") + ": " + join(", ", collect(beginCriticalAction_inFlight, "description"))); } catch (Throwable __e) { _handleException(__e); } } sleepInCleanUp(10); } } public static File mkdirsForFile(File file) { File dir = file.getParentFile(); if (dir != null) { dir.mkdirs(); if (!dir.isDirectory()) if (dir.isFile()) throw fail("Please delete the file " + f2s(dir) + " - it is supposed to be a directory!"); else throw fail("Unknown IO exception during mkdirs of " + f2s(file)); } return file; } public static String mkdirsForFile(String path) { mkdirsForFile(new File(path)); return path; } static public File copyFile(File src, File dest) { try { FileInputStream inputStream = new FileInputStream(src.getPath()); FileOutputStream outputStream = newFileOutputStream(dest.getPath()); try { copyStream(inputStream, outputStream); inputStream.close(); } finally { outputStream.close(); } return dest; } catch (Exception __e) { throw rethrow(__e); } } static public FileOutputStream newFileOutputStream(File path) throws IOException { return newFileOutputStream(path.getPath()); } static public FileOutputStream newFileOutputStream(String path) throws IOException { return newFileOutputStream(path, false); } static public FileOutputStream newFileOutputStream(File path, boolean append) throws IOException { return newFileOutputStream(path.getPath(), append); } static public FileOutputStream newFileOutputStream(String path, boolean append) throws IOException { mkdirsForFile(path); FileOutputStream f = new FileOutputStream(path, append); _registerIO(f, path, true); return f; } static public int findEndOfBracketPart2(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eqOneOf(cnc.get(j), "{", "(", "[")) ++level; else if (eqOneOf(cnc.get(j), "}", ")", "]")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static public String regexReplace(String s, String pat, Object f) { Matcher m = Pattern.compile(pat).matcher(s); return regexReplace(m, f); } static public String regexReplace(Matcher m, Object f) { StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, m.quoteReplacement(str(callF(f, m)))); m.appendTail(buf); return str(buf); } static public String regexReplace(String s, String pat, IF1 f) { return regexReplace(s, pat, (Object) f); } static public Matcher regexpMatcherIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static public void _registerIO(Object object, String path, boolean opened) { } static public boolean possibleMD5(String s) { return isMD5(s); } static public Object iteratorFromFunction_endMarker = new Object(); static public IterableIterator iteratorFromFunction_withEndMarker(final Object f) { class IFF extends IterableIterator { public A a; public boolean have, done; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; have = false; return _a; } public void getNext() { if (done || have) return; Object o = callF(f); if (o == iteratorFromFunction_endMarker) { done = true; return; } a = (A) o; have = true; } } ; return new IFF(); } static public IterableIterator iteratorFromFunction_withEndMarker(final F0 f) { return iteratorFromFunction_withEndMarker_f0(f); } static public File loadImageAsFile(String snippetIDOrURL) { try { if (isURL(snippetIDOrURL)) throw fail("not implemented"); if (!isSnippetID(snippetIDOrURL)) throw fail("Not a URL or snippet ID: " + snippetIDOrURL); String snippetID = "" + parseSnippetID(snippetIDOrURL); File file = imageSnippetCacheFile(snippetID); if (fileSize(file) > 0) return file; String imageURL = snippetImageURL_noHttps(snippetID); System.err.println("Loading image: " + imageURL); byte[] data = loadBinaryPage(imageURL); saveBinaryFile(file, data); return file; } catch (Exception __e) { throw rethrow(__e); } } static public File DiskSnippetCache_file(long snippetID) { return new File(getGlobalCache(), "data_" + snippetID + ".jar"); } public static File DiskSnippetCache_getLibrary(long snippetID) throws IOException { File file = DiskSnippetCache_file(snippetID); return file.exists() ? file : null; } public static void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException { saveBinaryFile(DiskSnippetCache_file(snippetID), data); } static public byte[] loadDataSnippetImpl(String snippetID) throws IOException { byte[] data; try { URL url = new URL(dataSnippetLink(snippetID)); print("Loading library: " + hideCredentials(url)); try { data = loadBinaryPage(url.openConnection()); } catch (RuntimeException e) { data = null; } if (data == null || data.length == 0) { url = new URL(tb_mainServer() + "/blobs/" + parseSnippetID(snippetID)); print("Loading library: " + hideCredentials(url)); data = loadBinaryPage(url.openConnection()); } print("Bytes loaded: " + data.length); } catch (FileNotFoundException e) { throw new IOException("Binary snippet #" + snippetID + " not found or not public"); } return data; } static public long fileSize(String path) { return getFileSize(path); } static public long fileSize(File f) { return getFileSize(f); } static public File loadDataSnippetToFile(String snippetID) { try { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadDataSnippetToFile_noResourceLoader(snippetID); } catch (Exception __e) { throw rethrow(__e); } } static public File loadDataSnippetToFile_noResourceLoader(String snippetID) { try { snippetID = fsI(snippetID); File f = DiskSnippetCache_file(parseSnippetID(snippetID)); List urlsTried = new ArrayList(); List errors = new ArrayList(); try { URL url = addAndReturn(urlsTried, new URL(dataSnippetLink(snippetID))); print("Loading library: " + hideCredentials(url)); try { loadBinaryPageToFile(openConnection(url), f); if (fileSize(f) == 0) throw fail(); } catch (Throwable e) { errors.add(e); url = addAndReturn(urlsTried, new URL(tb_mainServer() + "/blobs/" + psI(snippetID))); print(e); print("Trying other server: " + hideCredentials(url)); loadBinaryPageToFile(openConnection(url), f); print("Got bytes: " + fileSize(f)); } if (fileSize(f) == 0) throw fail(); System.err.println("Bytes loaded: " + fileSize(f)); } catch (Throwable e) { errors.add(e); throw fail("Binary snippet " + snippetID + " not found or not public. URLs tried: " + allToString(urlsTried) + ", errors: " + allToString(errors)); } return f; } catch (Exception __e) { throw rethrow(__e); } } static public String multiLineQuoteWithSpaces(String s) { return multiLineQuote(" " + s + " "); } static public A liftLast(List l) { if (empty(l)) return null; int i = l(l) - 1; A a = l.get(i); l.remove(i); return a; } static public List liftLast(int n, List l) { int i = l(l) - n; List part = cloneSubList(l, i); removeSubList(l, i); return part; } static public String structure_addTokenMarkers(String s) { return join(structure_addTokenMarkers(javaTokForStructure(s))); } static public List structure_addTokenMarkers(List tok) { TreeSet refs = new TreeSet(); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("t") && isInteger(t.substring(1))) refs.add(parseInt(t.substring(1))); } if (empty(refs)) return tok; for (int i : refs) { int idx = i * 2 + 1; if (idx >= l(tok)) continue; String t = ""; if (endsWithLetterOrDigit(tok.get(idx - 1))) t = " "; tok.set(idx, t + "m" + i + " " + tok.get(idx)); } return tok; } static public Runnable asRunnable(Object o) { return toRunnable(o); } static public void _inheritThreadInfo(Object info) { _threadInheritInfo(info); } static public ExpiringMap2 mechList_raw_cache = new ExpiringMap2(10000).setMap(ciMap()); static public Lock mechList_raw_lock = lock(); static public int mechList_raw_timeout = 60000; static public String mechList_raw(String name) { try { Lock __0 = mechList_raw_lock; lock(__0); try { if (empty(name)) return ""; String src = mechList_raw_cache.get(name); if (src != null) return src; src = mechList_raw_fresh(name); if (src != null) mechList_raw_cache.put(name, src); return src; } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } static public VF2 mechList_raw_listener = new VF2() { public void get(String msg, Object arg) { try { if (eq(msg, "mechChange") && arg instanceof String) { mechList_raw_cache.remove((String) arg); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(msg, 'mechChange) && arg instanceof S) {\r\n //print(\"Got change noti..."; } }; static public void _onLoad_mechList_raw() { add(vm_busListeners_live(), mechList_raw_listener); } static public void cleanMeUp_mechList_raw() { remove(vm_busListeners_live(), mechList_raw_listener); } static public List mechList_opt(String name) { return mechList_opt_tlft(name); } static public HashMap asHashMap(Map map) { if (map instanceof HashMap) return (HashMap) map; HashMap m = new HashMap(l(map)); m.putAll(map); return m; } static public Object callAndMake(String functionName, Object... args) { return callAndMake_orDirect(functionName, args); } static public Map parseDoubleArrowMap(Map map, List l) { for (String s : l) { List x = splitAtDoubleArrow_bothDirections(s); if (l(x) == 2) map.put(first(x), second(x)); } return map; } static public List similarEmptyList(Collection m) { return new ArrayList(); } static public File programDir_mine; static public File programDir() { return programDir(getProgramID()); } static public File programDir(String snippetID) { boolean me = sameSnippetID(snippetID, programID()); if (programDir_mine != null && me) return programDir_mine; File dir = new File(javaxDataDir(), formatSnippetIDOpt(snippetID)); if (me) { String c = caseID(); if (nempty(c)) dir = newFile(dir, c); } return dir; } static public File programDir(String snippetID, String subPath) { return new File(programDir(snippetID), subPath); } static public File oneOfTheFiles(String... paths) { if (paths != null) for (String path : paths) if (fileExists(path)) return newFile(path); return null; } static public File oneOfTheFiles(File... files) { return oneOfTheFiles(asList(files)); } static public File oneOfTheFiles(Iterable files) { if (files != null) for (File f : files) if (fileExists(f)) return f; return null; } static public File javaxSecretDir_dir; static public File javaxSecretDir() { return javaxSecretDir_dir != null ? javaxSecretDir_dir : new File(userHome(), "JavaX-Secret"); } static public File javaxSecretDir(String sub) { return newFile(javaxSecretDir(), sub); } static public String loadGZTextFile(File file) { try { if (!file.isFile()) return null; ping(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream fis = new FileInputStream(file); try { GZIPInputStream gis = newGZIPInputStream(fis); byte[] buffer = new byte[1024]; int len; while ((len = gis.read(buffer)) != -1) baos.write(buffer, 0, len); baos.close(); return fromUtf8(baos.toByteArray()); } finally { _close(fis); } } catch (Exception __e) { throw rethrow(__e); } } static public File getCodeProgramDir() { return getCodeProgramDir(getProgramID()); } static public File getCodeProgramDir(String snippetID) { return new File(javaxCodeDir(), formatSnippetID(snippetID)); } static public File getCodeProgramDir(long snippetID) { return getCodeProgramDir(formatSnippetID(snippetID)); } static public void saveGZTextFile(File file, String contents) { saveGZTextFile(file, contents, "UTF-8"); } static public void saveGZTextFile(File file, String contents, String encoding) { try { File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = file.getPath() + "_temp"; File tempFile = new File(tempFileName); if (contents != null) { if (tempFile.exists()) try { String saveName = tempFileName + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); GZIPOutputStream gos = new GZIPOutputStream(fileOutputStream); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(gos, encoding); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); gos.close(); fileOutputStream.close(); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + file.getPath()); if (contents != null) if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); } catch (Exception __e) { throw rethrow(__e); } } static public String baseClassName(String className) { return substring(className, className.lastIndexOf('.') + 1); } static public String baseClassName(Object o) { return baseClassName(getClassName(o)); } static public String prependIfNempty(String prefix, String s) { return empty(s) ? unnull(s) : prefix + s; } static public Map>> mechMapCI_cache = synchroMap(); static public Map mechMapCI(String listName) { Pair> p = mechMapCI_cache.get(listName); String text = mechList_raw(listName); if (p != null && eq(p.a, text)) return p.b; String parsing = first(mechList_opt(listName + " | Parsing")); Map map; if (parsing == null) map = parseDoubleArrowMapCI(tlft(text)); else map = asCIMap((Map) callMC(parsing, text)); p = pair(text, map); mechMapCI_cache.put(listName, p); return p.b; } static public String dropTranslators(String src) { return findTranslators2(src, null); } static public List dropTranslators(List tok) { return findTranslators2(tok, null); } static public File javaxCodeDir_dir; static public File javaxCodeDir() { return javaxCodeDir_dir != null ? javaxCodeDir_dir : new File(userHome(), "JavaX-Code"); } static public File javaxCodeDir(String sub) { return newFile(javaxCodeDir(), sub); } static public AutoCloseable tempLoadingAnim(String msg) { return tempDisposeWindow(loadingAnim(msg)); } static public A set(A o, String field, Object value) { if (o == null) return null; if (o instanceof Class) set((Class) o, field, value); else try { Field f = set_findField(o.getClass(), field); makeAccessible(f); smartSet(f, o, value); } catch (Exception e) { throw new RuntimeException(e); } return o; } static public void set(Class c, String field, Object value) { if (c == null) return; try { Field f = set_findStaticField(c, field); makeAccessible(f); smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static public Field set_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static public Field set_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } static public Class hotwireSharingLibraries_silently(String progID) { AutoCloseable __1 = temp_loadPage_silent(); try { return hotwireSharingLibraries(progID); } finally { _close(__1); } } static public String defaultJavaXTranslatorID_value = "#759"; static public String defaultJavaXTranslatorID() { return defaultJavaXTranslatorID_value; } static public Object makeDependent_postProcess; static public void makeDependent(Object c) { if (c == null) return; assertTrue("Not a class", c instanceof Class); dependentClasses(); hotwire_classes.add(new WeakReference(c)); Object local_log = getOpt(mc(), "local_log"); if (local_log != null) setOpt(c, "local_log", local_log); Object print_byThread = getOpt(mc(), "print_byThread"); if (print_byThread != null) setOpt(c, "print_byThread", print_byThread); callF(makeDependent_postProcess, c); } static public WeakReference creator_class; static public Object creator() { return creator_class == null ? null : creator_class.get(); } static public boolean cleanUp_interruptThreads = false; static public void cleanUp(Object c) { if (c == null) return; if (c instanceof AutoCloseable) { close_pcall(((AutoCloseable) c)); return; } if (c instanceof java.util.Timer) { ((java.util.Timer) c).cancel(); return; } if (c instanceof Collection) { cleanUp((Collection) c); return; } if (c instanceof Map) { for (Object o : keys((Map) c)) cleanUp(o); for (Object o : values((Map) c)) cleanUp(o); ((Map) c).clear(); return; } try { preCleanUp(c); setOpt(c, "ping_pauseAll", false); innerCleanUp(c); List androids = (List) getOpt(c, "record_list"); for (Object android : unnull(androids)) pcallOpt(android, "dispose"); List classes = (List) (getOpt(c, "hotwire_classes")); if (classes != null) for (WeakReference cc : classes) { try { cleanUp(cc.get()); } catch (Throwable __e) { _handleException(__e); } } if (cleanUp_interruptThreads) { List threads = registeredThreads(c); if (nempty(threads)) { print("cleanUp: Interrupting " + n2(threads, "thread") + ": " + joinWithComma(allToString(threads))); interruptThreads(threads); } } } catch (Throwable __e) { _handleException(__e); } setOpt(c, "cleaningUp_flag", false); if (c instanceof Class && ((Class) c).getName().equals("main")) retireClassLoader(((Class) c).getClassLoader()); } static public void cleanUp(Collection l) { if (l == null) return; for (Object c : l) cleanUp(c); l.clear(); } static public A printIndent(A o) { print(indentx(str(o))); return o; } static public A printIndent(String indent, A o) { print(indentx(indent, str(o))); return o; } static public void printIndent(int indent, Object o) { print(indentx(indent, str(o))); } static public void sleepInCleanUp(long ms) { try { if (ms < 0) return; Thread.sleep(ms); } catch (Exception __e) { throw rethrow(__e); } } static public String f2s(File f) { return f == null ? null : f.getAbsolutePath(); } static public String f2s(String s) { return f2s(newFile(s)); } static public String f2s(java.nio.file.Path p) { return p == null ? null : f2s(p.toFile()); } static public void copyStream(InputStream in, OutputStream out) { try { byte[] buf = new byte[65536]; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean loadBufferedImage_useImageCache = true; static public BufferedImage loadBufferedImage(String snippetIDOrURLOrFile) { try { ping(); if (snippetIDOrURLOrFile == null) return null; if (isURL(snippetIDOrURLOrFile)) return imageIO_readURL(snippetIDOrURLOrFile); if (isAbsolutePath(snippetIDOrURLOrFile)) return loadBufferedImage(new File(snippetIDOrURLOrFile)); if (!isSnippetID(snippetIDOrURLOrFile)) throw fail("Not a URL or snippet ID or file: " + snippetIDOrURLOrFile); String snippetID = "" + parseSnippetID(snippetIDOrURLOrFile); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return loadBufferedImage(rl.loadLibrary(snippetID)); File dir = imageSnippetsCacheDir(); if (loadBufferedImage_useImageCache) { dir.mkdirs(); File file = new File(dir, snippetID + ".png"); if (file.exists() && file.length() != 0) try { return ImageIO.read(file); } catch (Throwable e) { e.printStackTrace(); } } String imageURL = snippetImageURL_http(snippetID); print("Loading image: " + imageURL); BufferedImage image = imageIO_readURL(imageURL); if (loadBufferedImage_useImageCache) { File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis()); ImageIO.write(image, "png", tempFile); tempFile.renameTo(new File(dir, snippetID + ".png")); } return image; } catch (Exception __e) { throw rethrow(__e); } } static public BufferedImage loadBufferedImage(File file) { try { return file.isFile() ? ImageIO.read(file) : null; } catch (Exception __e) { throw rethrow(__e); } } static public Map parseDoubleLeftArrowMapCI_tlft(String s) { return parseDoubleLeftArrowMapCI(tlft(s)); } static public IterableIterator iteratorFromFunction_withEndMarker_f0(final F0 f) { class IFF2 extends IterableIterator { public A a; public boolean have, done; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; have = false; return _a; } public void getNext() { if (done || have) return; Object o = f.get(); if (o == iteratorFromFunction_endMarker) { done = true; return; } a = (A) o; have = true; } } ; return new IFF2(); } static public File imageSnippetCacheFile(String snippetID) { File dir = imageSnippetsCacheDir(); if (!loadBufferedImage_useImageCache) return null; return new File(dir, parseSnippetID(snippetID) + ".png"); } static public String snippetImageURL_noHttps(String snippetID) { return snippetImageURL_noHttps(snippetID, "png"); } static public String snippetImageURL_noHttps(String snippetID, String contentType) { return snippetImageURL(snippetID, contentType).replace("https://www.botcompany.de:8443/", "http://www.botcompany.de:8080/").replace("https://botcompany.de/", "http://botcompany.de/"); } static public ThreadLocal>> loadBinaryPage_responseHeaders = new ThreadLocal(); static public ThreadLocal> loadBinaryPage_extraHeaders = new ThreadLocal(); static public byte[] loadBinaryPage(String url) { try { print("Loading " + url); return loadBinaryPage(loadPage_openConnection(new URL(url))); } catch (Exception __e) { throw rethrow(__e); } } static public byte[] loadBinaryPage(URLConnection con) { try { Map extraHeaders = getAndClearThreadLocal(loadBinaryPage_extraHeaders); setHeaders(con); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); return loadBinaryPage_noHeaders(con); } catch (Exception __e) { throw rethrow(__e); } } static public byte[] loadBinaryPage_noHeaders(URLConnection con) { try { ByteArrayOutputStream buf = new ByteArrayOutputStream(); InputStream inputStream = con.getInputStream(); loadBinaryPage_responseHeaders.set(con.getHeaderFields()); long len = 0; try { len = con.getContentLength(); } catch (Throwable e) { printStackTrace(e); } int n = 0; while (true) { int ch = inputStream.read(); if (ch < 0) break; buf.write(ch); if (++n % 100000 == 0) println(" " + n + (len != 0 ? "/" + len : "") + " bytes loaded."); } inputStream.close(); return buf.toByteArray(); } catch (Exception __e) { throw rethrow(__e); } } public static byte[] saveBinaryFile(String fileName, byte[] contents) { try { File file = new File(fileName); File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = fileName + "_temp"; FileOutputStream fileOutputStream = newFileOutputStream(tempFileName); fileOutputStream.write(contents); fileOutputStream.close(); if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (!new File(tempFileName).renameTo(file)) throw new IOException("Can't rename " + tempFileName + " to " + fileName); vmBus_send("wroteFile", file); return contents; } catch (Exception __e) { throw rethrow(__e); } } static public byte[] saveBinaryFile(File fileName, byte[] contents) { return saveBinaryFile(fileName.getPath(), contents); } static public File getGlobalCache() { File file = new File(javaxCachesDir(), "Binary Snippets"); file.mkdirs(); return file; } static public String dataSnippetLink(String snippetID) { long id = parseSnippetID(snippetID); if (id >= 1100000 && id < 1200000) return imageServerURL() + id; if (id >= 1200000 && id < 1300000) { String pw = muricaPassword(); if (empty(pw)) throw fail("Please set 'murica password by running #1008829"); return "https://botcompany.de/files/" + id + "?_pass=" + pw; } return fileServerURL() + "/" + id; } static public A addAndReturn(Collection c, A a) { if (c != null) c.add(a); return a; } static public void loadBinaryPageToFile(String url, File file) { try { print("Loading " + url); loadBinaryPageToFile(openConnection(new URL(url)), file); } catch (Exception __e) { throw rethrow(__e); } } static public void loadBinaryPageToFile(URLConnection con, File file) { try { setHeaders(con); loadBinaryPageToFile_noHeaders(con, file); } catch (Exception __e) { throw rethrow(__e); } } static public void loadBinaryPageToFile_noHeaders(URLConnection con, File file) { try { File ftemp = new File(f2s(file) + "_temp"); FileOutputStream buf = newFileOutputStream(mkdirsFor(ftemp)); try { InputStream inputStream = con.getInputStream(); long len = 0; try { len = con.getContentLength(); } catch (Throwable e) { printStackTrace(e); } String pat = " {*}" + (len != 0 ? "/" + len : "") + " bytes loaded."; copyStreamWithPrints(inputStream, buf, pat); inputStream.close(); buf.close(); file.delete(); renameFile_assertTrue(ftemp, file); } finally { if (buf != null) buf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public URLConnection openConnection(String url) { try { return openConnection(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static public URLConnection openConnection(URL url) { try { ping(); callOpt(javax(), "recordOpenURLConnection", str(url)); return url.openConnection(); } catch (Exception __e) { throw rethrow(__e); } } static public String multiLineQuote(String s) { for (int i = 0; ; i++) { String closer = "]" + rep('=', i) + "]"; if (!contains(s, closer)) return "[" + rep('=', i) + "[" + s + closer; } } static public String mechList_raw_fresh(String name) { return mechList_opt_raw_fresh(name); } static public void add(BitSet bs, int i) { bs.set(i); } static public boolean add(Collection c, A a) { return c != null && c.add(a); } static public void add(Container c, Component x) { addToContainer(c, x); } static public void remove(List l, int i) { if (l != null && i >= 0 && i < l(l)) l.remove(i); } static public void remove(Collection l, A a) { if (l != null) l.remove(a); } static public List mechList_opt_tlft(String name) { return mechList_opt_tlft_cached(name); } static public Object callAndMake_orDirect(String functionName, List args) { return callAndMake_orDirect(functionName, toObjectArray(args)); } static public Object callAndMake_orDirect(String functionName, Object... args) { if (functionName == null) return null; if (hasMethod(mc(), functionName, args)) return callMC(functionName, args); else return makeAndCall_cached(functionName, args); } static public List splitAtDoubleArrow_bothDirections(String s) { return splitAtDoubleArrow_bothDirections(javaTok(s)); } static public List splitAtDoubleArrow_bothDirections(List tok) { List l = splitAtDoubleArrow(tok); if (l(l) != 2) l = reversedList(splitAtDoubleLeftArrow(tok)); return l; } static public boolean sameSnippetID(String a, String b) { if (!isSnippetID(a) || !isSnippetID(b)) return false; return parseSnippetID(a) == parseSnippetID(b); } static public boolean fileExists(String path) { return path != null && new File(path).exists(); } static public boolean fileExists(File f) { return f != null && f.exists(); } static public String fromUtf8(byte[] bytes) { try { return bytes == null ? null : new String(bytes, utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } static public Map parseDoubleArrowMapCI(List l) { return parseDoubleArrowMap((Map) ciMap(), l); } static public Map parseDoubleArrowMapCI(String s) { return parseDoubleArrowMapCI_tlft(s); } static public TreeMap asCIMap(Map map) { return asCaseInsensitiveMap(map); } static public AutoCloseable tempDisposeWindow(final Window w) { return new AutoCloseable() { public void close() { disposeWindow(w); } }; } static public JWindow loadingAnim() { return showLoadingAnimation(); } static public JWindow loadingAnim(String text) { return showLoadingAnimation(text); } static public void smartSet(Field f, Object o, Object value) throws Exception { try { f.set(o, value); } catch (Exception e) { Class type = f.getType(); if (type == int.class && value instanceof Long) value = ((Long) value).intValue(); if (type == LinkedHashMap.class && value instanceof Map) { f.set(o, asLinkedHashMap((Map) value)); return; } try { if (f.getType() == Concept.Ref.class) { f.set(o, ((Concept) o).new Ref((Concept) value)); return; } if (o instanceof Concept.Ref) { f.set(o, ((Concept.Ref) o).get()); return; } } catch (Throwable _e) { } throw e; } } static public AutoCloseable temp_loadPage_silent() { return tempSetThreadLocal(loadPage_silent, true); } static public Class hotwireSharingLibraries(String progID) { try { Pair p = CompilerBot.compileSnippet2(progID); File jar = p.a; assertTrue(f2s(jar), jar.isFile()); List files = ll(jar); String dehlibs = unnull(loadTextFileFromZip(jar, "libraries")); List myLibraries = myLibraryFiles(); Matcher matcher = Pattern.compile("\\d+").matcher(dehlibs); while (matcher.find()) { String libID = matcher.group(); File lib = loadLibrary(libID); if (myLibraries.contains(lib)) { } else { files.add(lib); } } JavaXClassLoaderWithParent classLoader = new JavaXClassLoaderWithParent(progID, files, myClassLoader()); return hotwire_finish(classLoader, progID, p.b); } catch (Exception __e) { throw rethrow(__e); } } static public List dependentClasses() { return cleanUpAndGetWeakReferencesList(hotwire_classes); } static public void close_pcall(AutoCloseable c) { if (c != null) { try { c.close(); } catch (Throwable __e) { _handleException(__e); } } } static public void preCleanUp(Object c) { if (c instanceof Collection) { for (Object o : ((Collection) c)) preCleanUp(o); return; } callOpt(c, "licensed_off"); setOpt(c, "ping_anyActions", true); setOpt(c, "cleaningUp_flag", true); } static public void innerCleanUp(Object c) { if (!isFalse(pcallOpt(c, "cleanMeUp"))) for (String name : sorted(methodsStartingWith(c, "cleanMeUp_"))) try { callOpt(c, name); } catch (Throwable e) { print("Error cleaning up: " + programID(c)); _handleException(e); } } static public void innerCleanUp() { innerCleanUp(mc()); } static public Object pcallOpt(Object o, String method, Object... args) { try { return callOpt(o, method, args); } catch (Throwable __e) { _handleException(__e); } return null; } static public List registeredThreads(Object o) { Map map = (Map) (getOpt(o, "_registerThread_threads")); if (map == null) return ll(); map.size(); synchronized (map) { return asList(keys(map)); } } static public List registeredThreads() { _registerThread_threads.size(); return asList(keys(_registerThread_threads)); } static public void interruptThreads(Collection threads) { for (Thread t : unnull(threads)) interruptThread(t); } static public void interruptThreads(Class mainClass) { interruptThreads(registeredThreads(mainClass)); } static public void retireClassLoader(ClassLoader cl) { if (isJavaXClassLoader(cl)) setOptAll(cl, "retired", true, "retiredMarker", new DefunctClassLoader()); } static public String indentx(String s) { return indentx(indent_default, s); } static public String indentx(int n, String s) { return dropSuffix(repeat(' ', n), indent(n, s)); } static public String indentx(String indent, String s) { return dropSuffix(indent, indent(indent, s)); } static public List> hotwire_classes = synchroList(); static public Class hotwireDependent(String src) { Class c = hotwire(src); makeDependent(c); return c; } static public BufferedImage imageIO_readURL(String url) { try { return ImageIO.read(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static public boolean isAbsolutePath(String s) { return s != null && new File(s).isAbsolute(); } static public boolean isAbsolutePath(File f) { return f != null && f.isAbsolute(); } static public File imageSnippetsCacheDir() { return javaxCachesDir("Image-Snippets"); } static public String snippetImageURL_http(String snippetID) { return snippetImageURL_http(snippetID, "png"); } static public String snippetImageURL_http(String snippetID, String contentType) { return replacePrefix("https://", "http://", snippetImageURL(snippetID, contentType)).replace(":8443", ":8080"); } static public Map parseDoubleLeftArrowMapCI(List l) { return parseDoubleLeftArrowMap((Map) ciMap(), l); } static public int loadPage_defaultTimeout = 60000; static public ThreadLocal loadPage_charset = new ThreadLocal(); static public boolean loadPage_allowGzip = true, loadPage_debug; static public boolean loadPage_anonymous = false; static public int loadPage_verboseness = 100000; static public int loadPage_retries = 1; static public ThreadLocal loadPage_silent = new ThreadLocal(); static volatile public int loadPage_forcedTimeout; static public ThreadLocal loadPage_forcedTimeout_byThread = new ThreadLocal(); static public ThreadLocal>> loadPage_responseHeaders = new ThreadLocal(); static public ThreadLocal> loadPage_extraHeaders = new ThreadLocal(); static public ThreadLocal loadPage_sizeLimit = new ThreadLocal(); public static String loadPageSilently(String url) { try { return loadPageSilently(new URL(loadPage_preprocess(url))); } catch (Exception __e) { throw rethrow(__e); } } public static String loadPageSilently(URL url) { try { if (!networkAllowanceTest(str(url))) throw fail("Not allowed: " + url); IOException e = null; for (int tries = 0; tries < loadPage_retries; tries++) try { URLConnection con = loadPage_openConnection(url); return loadPage(con, url); } catch (IOException _e) { e = _e; if (loadPageThroughProxy_enabled) { print("Trying proxy because of: " + e); try { return loadPageThroughProxy(str(url)); } catch (Throwable e2) { print(" " + exceptionToStringShort(e2)); } } else if (loadPage_debug) print(exceptionToStringShort(e)); if (tries < loadPage_retries - 1) sleepSeconds(1); } throw e; } catch (Exception __e) { throw rethrow(__e); } } static public String loadPage_preprocess(String url) { if (url.startsWith("tb/")) url = tb_mainServer() + "/" + url; if (url.indexOf("://") < 0) url = "http://" + url; return url; } static public String loadPage(String url) { try { url = loadPage_preprocess(url); if (!isTrue(loadPage_silent.get())) printWithTime("Loading: " + hideCredentials(url)); return loadPageSilently(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static public String loadPage(URL url) { return loadPage(url.toExternalForm()); } static public String loadPage(URLConnection con, URL url) throws IOException { return loadPage(con, url, true); } static public String loadPage(URLConnection con, URL url, boolean addHeaders) throws IOException { Map extraHeaders = getAndClearThreadLocal(loadPage_extraHeaders); Long limit = optPar(loadPage_sizeLimit); if (addHeaders) try { if (!loadPage_anonymous) setHeaders(con); if (loadPage_allowGzip) con.setRequestProperty("Accept-Encoding", "gzip"); con.setRequestProperty("X-No-Cookies", "1"); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); } catch (Throwable e) { } vm_generalSubMap("URLConnection per thread").put(currentThread(), con); loadPage_responseHeaders.set(con.getHeaderFields()); InputStream in = null; try { in = urlConnection_getInputStream(con); if (loadPage_debug) print("Put stream in map: " + currentThread()); String contentType = con.getContentType(); if (contentType == null) { throw new IOException("Page could not be read: " + hideCredentials(url)); } String charset = loadPage_charset == null ? null : loadPage_charset.get(); if (charset == null) charset = loadPage_guessCharset(contentType); if ("gzip".equals(con.getContentEncoding())) { if (loadPage_debug) print("loadPage: Using gzip."); in = newGZIPInputStream(in); } Reader r; try { r = new InputStreamReader(in, unquote(charset)); } catch (UnsupportedEncodingException e) { print(toHex(utf8(charset))); throw e; } boolean silent = isTrue(loadPage_silent.get()); StringBuilder buf = new StringBuilder(); int n = 0; while (limit == null || n < limit) { ping(); int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; if (!silent && (n % loadPage_verboseness) == 0) print(" " + n + " chars read"); } return buf.toString(); } finally { if (loadPage_debug) print("loadPage done"); vm_generalSubMap("URLConnection per thread").remove(currentThread()); if (in != null) in.close(); } } static public String loadPage_guessCharset(String contentType) { Matcher m = regexpMatcher("text/[a-z]+;\\s*charset=([^\\s]+)\\s*", contentType); String match = m.matches() ? m.group(1) : null; if (loadPage_debug) print("loadPage: contentType=" + contentType + ", match: " + match); return or(match, "UTF-8"); } static public URLConnection loadPage_openConnection(URL url) { URLConnection con = openConnection(url); int timeout = toInt(loadPage_forcedTimeout_byThread.get()); if (timeout == 0) timeout = loadPage_forcedTimeout; if (timeout != 0) setURLConnectionTimeouts(con, loadPage_forcedTimeout); else setURLConnectionDefaultTimeouts(con, loadPage_defaultTimeout); return con; } static public void setHeaders(URLConnection con) throws IOException { String computerID = getComputerID_quick(); if (computerID != null) try { con.setRequestProperty("X-ComputerID", computerID); con.setRequestProperty("X-OS", System.getProperty("os.name") + " " + System.getProperty("os.version")); } catch (Throwable e) { } } static public A println(A a) { return print(a); } static public String imageServerURL() { return or2(trim(loadTextFile(javaxDataDir("image-server-url.txt"))), "http://botcompany.de/images/raw/"); } static volatile public boolean muricaPassword_pretendNotAuthed = false; static public String muricaPassword() { if (muricaPassword_pretendNotAuthed) return null; return trim(loadTextFile(muricaPasswordFile())); } static public String fileServerURL() { return "https://botcompany.de/files"; } public static File mkdirsFor(File file) { return mkdirsForFile(file); } static public void copyStreamWithPrints(InputStream in, OutputStream out, String pat) { try { byte[] buf = new byte[65536]; int total = 0; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); if ((total + n) / 100000 > total / 100000) print(pat.replace("{*}", str(roundDownTo(100000, total)))); total += n; } } catch (Exception __e) { throw rethrow(__e); } } static public void renameFile_assertTrue(File a, File b) { try { if (!a.exists()) throw fail("Source file not found: " + f2s(a)); if (b.exists()) throw fail("Target file exists: " + f2s(b)); mkdirsForFile(b); if (!a.renameTo(b)) throw fail("Can't rename " + f2s(a) + " to " + f2s(b)); } catch (Exception __e) { throw rethrow(__e); } } static public String mechList_opt_raw_fresh(String name) { Object readMode = mechMode().readMode; if (readMode instanceof File) { String md5Name = uniqueFileNameUsingMD5_80_v2(upper(name)); return loadTextFileFromZipFile((File) readMode, md5Name); } boolean useLocal = false, useRemote = true; if (eq(readMode, "mergeLocalAndRemote")) useLocal = true; else if (eq(readMode, "local")) { useLocal = true; useRemote = false; } String s = ""; if (useRemote) { if (eq(mechMode().readMode, "localCopies")) s = unnull(loadTextFile(remoteMechListMirrorFile(name))); else s = serverMechList_raw_fresh(name, true); } if (useLocal) s = appendNewLineIfNempty(s) + localMechList_opt_raw_fresh(name); return s; } static public void addToContainer(Container a, Component... b) { if (a == null) return; { swing(new Runnable() { public void run() { try { for (Component c : unnull(b)) if (c != null) a.add(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (Component c : unnull(b))\r\n if (c != null) \r\n a.add(c);"; } }); } } static public Map>> mechList_opt_tlft_cached_cache = ciMap(); static public Lock mechList_opt_tlft_cached_lock = lock(); static public List mechList_opt_tlft_cached(String name) { MechListDependentCache> listCache; { Lock __0 = mechList_opt_tlft_cached_lock; lock(__0); try { listCache = mechList_opt_tlft_cached_cache.get(name); if (listCache == null) mechList_opt_tlft_cached_cache.put(name, listCache = new MechListDependentCache(name, new F1>() { public List get(String x) { try { return tlft(x); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tlft(x)"; } })); } finally { unlock(__0); } } return listCache.get(); } static public boolean hasMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args) != null; } static public ThreadLocal makeAndCall_initChild = new ThreadLocal(); static public Object makeAndCall_cached(String functionName, Object... args) { Class c = loadFunctions_cached(functionName); AutoCloseable closer = (AutoCloseable) (callF(makeAndCall_initChild.get(), c)); AutoCloseable __1 = closer; try { return preciseCall(c, functionName, args); } finally { _close(__1); } } static public List splitAtDoubleArrow(String s) { return splitAtDoubleArrow(javaTok(s)); } static public List splitAtDoubleArrow(List tok) { List l = new ArrayList(); int i = 0; while (i < l(tok)) { int j = indexOfSubList(tok, splitAtDoubleArrow_tok(), i); if (j < 0) j = l(tok); l.add(trimJoin(tok.subList(i, j))); i = j + 3; } return l; } static public List splitAtDoubleLeftArrow(String s) { return splitAtDoubleLeftArrow(javaTok(s)); } static public List splitAtDoubleLeftArrow(List tok) { List l = new ArrayList(); int i = 0; while (i < l(tok)) { int j = indexOfSubList(tok, ll("<", "", "="), i); if (i >= l(tok)) break; if (j < 0) j = l(tok); l.add(trimJoin(tok.subList(i, j))); i = j + 3; } return l; } static public Map parseDoubleArrowMapCI_tlft(String s) { return parseDoubleArrowMapCI(tlft(s)); } static public TreeMap asCaseInsensitiveMap(Map map) { if (isCIMap(map)) return (TreeMap) map; TreeMap m = ciMap(); putAll(m, map); return m; } static public void disposeWindow(final Window window) { if (window != null) { swing(new Runnable() { public void run() { try { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); myFrames_list.remove(window); window.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); //..."; } }); } } static public void disposeWindow(final Component c) { disposeWindow(getWindow(c)); } static public void disposeWindow(Object o) { if (o != null) disposeWindow(((Component) o)); } static public void disposeWindow() { disposeWindow(heldInstance(Component.class)); } static public JWindow showLoadingAnimation() { return showLoadingAnimation("Hold on user..."); } static public JWindow showLoadingAnimation(String text) { try { return showAnimationInTopRightCorner("#1003543", text); } catch (Throwable __e) { return null; } } static public String loadTextFileFromZip(File inZip, String fileName) { return loadTextFileFromZipFile(inZip, fileName); } static public List myLibraryFiles() { return (List) get(myClassLoader(), "files"); } static public Class hotwire_finish(ClassLoader classLoader, String progID, String javaSource) { return hotwire_finish(classLoader, progID, javaSource, "main"); } static public Class hotwire_finish(ClassLoader classLoader, String progID, String javaSource, String mainClass) { try { Class theClass = classLoader.loadClass(mainClass); Class j = getJavaX(); setOpt(theClass, "myJavaSource_code", javaSource); synchronized (j) { call(j, "setVars", theClass, progID); callOpt(j, "addInstance", progID, theClass); } hotwire_copyOver(theClass); vmBus_send("hotwireFinished", theClass, mc()); return theClass; } catch (Exception __e) { throw rethrow(__e); } } static public List cleanUpAndGetWeakReferencesList(List> l) { if (l == null) return null; synchronized (l) { List out = new ArrayList(); for (int i = 0; i < l(l); i++) { A a = l.get(i).get(); if (a == null) l.remove(i--); else out.add(a); } return out; } } static public List sorted(Collection c, final Object comparator) { List l = cloneList(c); sort(l, makeComparator(comparator)); return l; } static public List sorted(Collection c) { List l = cloneList(c); sort(l); return l; } static public List methodsStartingWith(Object o, final String prefix) { return filter(allMethodNames(o), new F1() { public Object get(String s) { try { return startsWith(s, prefix); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "startsWith(s, prefix)"; } }); } static public boolean interruptThread_verbose = false; static public void interruptThread(Thread t) { if (t == null) return; if (interruptThread_verbose) print("Interrupting thread " + t); vm_threadInterruptionReasonsMap().put(t, getStackTrace()); t.interrupt(); URLConnection c = (URLConnection) (vm_generalSubMap("URLConnection per thread").get(t)); if (c != null) { try { print("Closing URLConnection of interrupted thread."); call(c, "disconnect"); } catch (Throwable __e) { _handleException(__e); } } } static public boolean isJavaXClassLoader(ClassLoader cl) { return startsWithOneOf(className(cl), "main$JavaXClassLoader", "x30$JavaXClassLoader"); } static public void setOptAll(Object o, Map fields) { if (fields == null) return; for (String field : keys(fields)) setOpt(o, field, fields.get(field)); } static public void setOptAll(Object o, Object... values) { warnIfOddCount(values); for (int i = 0; i + 1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i + 1]; setOpt(o, field, value); } } static public Map myFrames_list = weakHashMap(); static public List myFrames() { return swing(new F0>() { public List get() { try { return keysList(myFrames_list); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret keysList(myFrames_list);"; } }); } static public Map parseDoubleLeftArrowMap(Map map, List l) { for (String s : l) { List x = splitAtDoubleLeftArrow(s); if (l(x) == 2) map.put(second(x), first(x)); } return map; } static public boolean networkAllowanceTest(String url) { return isAllowed("networkAllowanceTest", url); } static final public boolean loadPageThroughProxy_enabled = false; static public String loadPageThroughProxy(String url) { return null; } static public A printWithTime(A a) { return printWithTime("", a); } static public A printWithTime(String s, A a) { print(hmsWithColons() + ": " + s, a); return a; } static public Map vm_generalSubMap(Object name) { synchronized (get(javax(), "generalMap")) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = synchroMap()); return map; } } static public InputStream urlConnection_getInputStream(URLConnection con) throws IOException { UnknownHostException lastException = null; for (int _repeat_0 = 0; _repeat_0 < 2; _repeat_0++) { try { if (con instanceof HttpURLConnection) if (((HttpURLConnection) con).getResponseCode() == 500) throw new IOException(joinNemptiesWithColonSpace("Server code 500", tryToReadErrorStreamFromURLConnection(((HttpURLConnection) con)))); return con.getInputStream(); } catch (UnknownHostException e) { lastException = e; print("Retrying because of: " + e); continue; } } throw lastException; } static public String toHex(byte[] bytes) { return bytesToHex(bytes); } static public String toHex(byte[] bytes, int ofs, int len) { return bytesToHex(bytes, ofs, len); } static public byte[] utf8(String s) { return toUtf8(s); } static public Matcher regexpMatcher(String pat, String s) { return compileRegexp(pat).matcher(unnull(s)); } static public URLConnection setURLConnectionTimeouts(URLConnection con, long timeout) { con.setConnectTimeout(toInt(timeout)); con.setReadTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout || con.getReadTimeout() != timeout) print("Warning: Timeouts not set by JDK."); return con; } static public URLConnection setURLConnectionDefaultTimeouts(URLConnection con, long timeout) { if (con.getConnectTimeout() == 0) { con.setConnectTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout) print("Warning: URL connect timeout not set by JDK."); } if (con.getReadTimeout() == 0) { con.setReadTimeout(toInt(timeout)); if (con.getReadTimeout() != timeout) print("Warning: URL read timeout not set by JDK."); } return con; } static public String getComputerID_quick() { return computerID(); } static public File muricaPasswordFile() { return new File(javaxSecretDir(), "murica/muricaPasswordFile"); } static public int roundDownTo(int n, int x) { return x / n * n; } static public long roundDownTo(long n, long x) { return x / n * n; } static public MechMode mechMode_value = new MechMode(); static public MechMode mechMode() { return mechMode_value; } static public String upper(String s) { return s == null ? null : s.toUpperCase(); } static public char upper(char c) { return Character.toUpperCase(c); } static public String loadTextFileFromZipFile(File inZip, String fileName) { try { if (!fileExists(inZip)) return null; try { ZipFile zip = new ZipFile(inZip); try { return loadTextFileFromZipFile(zip, fileName); } finally { _close(zip); } } catch (Throwable e) { throw fail(f2s(inZip), e); } } catch (Exception __e) { throw rethrow(__e); } } static public String loadTextFileFromZipFile(ZipFile zip, String fileName) { try { ZipEntry entry = zip.getEntry(fileName); if (entry == null) return null; InputStream fin = zip.getInputStream(entry); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); copyStream(fin, baos); return fromUTF8(baos.toByteArray()); } finally { _close(fin); } } catch (Exception __e) { throw rethrow(__e); } } static public File remoteMechListMirrorFile(String listName) { return newFile(remoteMechListMirrorsDir(), uniqueFileNameUsingMD5_80_v2(upper(listName))); } static public boolean serverMechList_raw_fresh_verbose = false; static public String serverMechList_raw_fresh(String name) { return serverMechList_raw_fresh(name, false); } static public String serverMechList_raw_fresh(String name, boolean opt) { Lock __0 = downloadLock(); lock(__0); try { String text = null; try { text = loadTextFile(remoteMechListMirrorFile(name)); } catch (Throwable __e) { _handleException(__e); } Object[] params = muricaCredentialsPlus("md5", md5OrNull(text), "l", l(text), "opt", opt ? 1 : 0, "withStatus", 1); String url = "http://butter.botcompany.de:8080/mech/raw/list-text/" + urlencode(name); String page = postPageSilently(url, params); Map map = jsonDecodeMap(page); boolean same = eq(map.get("Same"), true); boolean appended = eq(map.get("Appended"), true); saveTextFile(remoteMechListMirrorMetaFile(name), struct(getMultipleKeys(map, "Name", "Status"))); if (!same) { if (appended) text += (String) map.get("Text"); else text = (String) map.get("Text"); saveTextFile(remoteMechListMirrorFile(name), text); File nameFile = remoteMechListMirrorNameFile(name); if (!fileExists(nameFile)) { String actualName = or((String) map.get("Name"), name); saveTextFile(nameFile, actualName); } } if (serverMechList_raw_fresh_verbose) print("Mech list " + name + ": " + (appended ? "appended" : same ? "same" : "downloaded") + ": " + n2(countLines(text), "line")); if (!same) vmBus_send("remoteMechListMirrorChanged", name); return text; } finally { unlock(__0); } } static public String localMechList_opt_raw_fresh(String name) { return unnull(loadTextFile(localMechListFile(name))); } static public Method findMethod_cached(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { _MethodCache cache = callOpt_getCache(((Class) o)); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (isStaticMethod(m) && findMethod_checkArgs(m, args, false)) return m; return null; } else { _MethodCache cache = callOpt_getCache(o.getClass()); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (findMethod_checkArgs(m, args, false)) return m; return null; } } catch (Exception __e) { throw rethrow(__e); } } static public boolean preciseCall_debug = false; static public Object preciseCall(Object o, String method, Object... args) { try { if (o instanceof Class) { _MethodCache cache = callOpt_getCache(((Class) o)); List methods = cache.cache.get(method); Lowest best = new Lowest(); if (methods != null) for (Method m : methods) { { if (!(isStaticMethod(m))) continue; } int score = methodApplicabilityScore(m, args); if (score < Integer.MAX_VALUE) { if (preciseCall_debug) print("Method score: " + m + " " + score); best.put(m, score); } } Method m = best.get(); if (m != null) return invokeMethod(m, null, args); return call_withVarargs(((Class) o), method, args); } else throw todo(); } catch (Exception __e) { throw rethrow(__e); } } static public List splitAtDoubleArrow_tok; static public List splitAtDoubleArrow_tok() { if (splitAtDoubleArrow_tok == null) splitAtDoubleArrow_tok = ll("=", "", ">"); return splitAtDoubleArrow_tok; } static public boolean isCIMap(Map m) { return m instanceof TreeMap && ((TreeMap) m).comparator() == caseInsensitiveComparator(); } static public Window getWindow(Object o) { if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof Window) return (Window) c; c = c.getParent(); } return null; } static public A heldInstance(Class c) { List l = holdInstance_l.get(); for (int i = l(l) - 1; i >= 0; i--) { Object o = l.get(i); if (isInstanceOf(o, c)) return (A) o; } throw fail("No instance of " + className(c) + " held"); } static public boolean showAnimationInTopRightCorner_alwaysOnTop = true; static public boolean showAnimationInTopRightCorner_on = true; static public JWindow showAnimationInTopRightCorner(String imageID, String text) { if (isHeadless() || !showAnimationInTopRightCorner_on) return null; return showAnimationInTopRightCorner(imageIcon(imageID), text); } static public JWindow showAnimationInTopRightCorner(final Image image, final String text) { if (image == null || isHeadless() || !showAnimationInTopRightCorner_on) return null; return showAnimationInTopRightCorner(imageIcon(image), text); } static public JWindow showAnimationInTopRightCorner(final ImageIcon imageIcon, final String text) { if (isHeadless() || !showAnimationInTopRightCorner_on) return null; return (JWindow) swingAndWait(new F0() { public Object get() { try { JLabel label = new JLabel(imageIcon); if (nempty(text)) { label.setText(text); label.setVerticalTextPosition(SwingConstants.BOTTOM); label.setHorizontalTextPosition(SwingConstants.CENTER); } final JWindow window = showInTopRightCorner(label); onClick(label, new Runnable() { public void run() { try { window.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "window.dispose()"; } }); if (showAnimationInTopRightCorner_alwaysOnTop) window.setAlwaysOnTop(true); return window; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JLabel label = new JLabel(imageIcon);\r\n if (nempty(text)) {\r\n label.s..."; } }); } static public JWindow showAnimationInTopRightCorner(final String imageID) { return showAnimationInTopRightCorner(imageID, ""); } static public JWindow showAnimationInTopRightCorner(String imageID, double seconds) { return showAnimationInTopRightCorner(imageID, "", seconds); } static public JWindow showAnimationInTopRightCorner(String imageID, String text, double seconds) { if (isHeadless()) return null; return disposeWindowAfter(iround(seconds * 1000), showAnimationInTopRightCorner(imageID, text)); } static public JWindow showAnimationInTopRightCorner(BufferedImage img, String text, double seconds) { return disposeWindowAfter(iround(seconds * 1000), showAnimationInTopRightCorner(img, text)); } static public Comparator makeComparator(final Object f) { if (f instanceof Comparator) return (Comparator) f; return new Comparator() { public int compare(Object a, Object b) { return (Integer) callF(f, a, b); } }; } static public List allMethodNames(Object o) { Class c = _getClass(o); TreeSet names = new TreeSet(); while (c != null) { for (Method m : c.getDeclaredMethods()) names.add(m.getName()); c = c.getSuperclass(); } return asList(names); } static public ThreadLocal> holdInstance_l = new ThreadLocal(); static public AutoCloseable holdInstance(Object o) { if (o == null) return null; listThreadLocalAdd(holdInstance_l, o); return new AutoCloseable() { public void close() { listThreadLocalPopLast(holdInstance_l); } }; } static public Map weakHashMap() { return newWeakHashMap(); } static public List keysList(Map map) { return cloneListSynchronizingOn(keys(map), map); } static public List keysList(MultiSet ms) { return ms == null ? null : keysList(ms.map); } static volatile public Object isAllowed_function; static volatile public boolean isAllowed_all = true; static public boolean isAllowed(String askingMethod, Object... args) { Object f = vm_generalMap_get("isAllowed_function"); if (f != null && !isTrue(callF(f, askingMethod, args))) return false; return isAllowed_all || isTrue(callF(isAllowed_function, askingMethod, args)); } static public String hmsWithColons() { return hmsWithColons(now()); } static public String hmsWithColons(long time) { return new SimpleDateFormat("HH:mm:ss").format(time); } static public Object vm_generalMap_put(Object key, Object value) { return mapPutOrRemove(vm_generalMap(), key, value); } static public String joinNemptiesWithColonSpace(String... strings) { return joinNempties(": ", strings); } static public String joinNemptiesWithColonSpace(Collection strings) { return joinNempties(": ", strings); } static public String tryToReadErrorStreamFromURLConnection(URLConnection conn) { try { if (conn instanceof HttpURLConnection) return stream2string(((HttpURLConnection) conn).getErrorStream()); return null; } catch (Throwable __e) { return null; } } static public Map compileRegexp_cache = syncMRUCache(10); static public java.util.regex.Pattern compileRegexp(String pat) { java.util.regex.Pattern p = compileRegexp_cache.get(pat); if (p == null) { compileRegexp_cache.put(pat, p = java.util.regex.Pattern.compile(pat)); } return p; } static public String _computerID; static public Lock computerID_lock = lock(); public static String computerID() { if (_computerID == null) { Lock __0 = computerID_lock; lock(__0); try { if (_computerID != null) return _computerID; File file = computerIDFile(); _computerID = loadTextFile(file.getPath()); if (_computerID == null) { _computerID = loadTextFile(userDir(".tinybrain/computer-id")); if (_computerID == null) _computerID = makeRandomID(12, new SecureRandom()); saveTextFile(file, _computerID); } } finally { unlock(__0); } } return _computerID; } static public String fromUTF8(byte[] bytes) { return fromUtf8(bytes); } static public File remoteMechListMirrorsDir() { return javaxDataDir("Remote Mech Lists"); } static public Lock downloadLock_lock = fairLock(); static public Lock downloadLock() { return downloadLock_lock; } static public Object[] muricaCredentialsPlus(Object... params) { return concatArrays(muricaCredentials(), params); } static public String md5OrNull(String s) { return s == null ? null : md5(s); } static public String postPageSilently(String url, Object... params) { return doPostSilently(litmap(params), url); } static public Map jsonDecodeMap(String s) { Object o = jsonDecode(s); if (o instanceof List && empty((List) o)) return new HashMap(); if (o instanceof Map) return (Map) o; else throw fail("Not a JSON map: " + s); } static public File remoteMechListMirrorMetaFile(String listName) { return javaxDataDir("Remote Mech Lists/" + uniqueFileNameUsingMD5_80_v2(upper(listName)) + ".meta"); } static public Map getMultipleKeys(Map map, A... keys) { Map map2 = similarEmptyMap(map); if (map != null) for (A key : keys) map2.put(key, map.get(key)); return map2; } static public File remoteMechListMirrorNameFile(String listName) { return javaxDataDir("Remote Mech Lists/" + uniqueFileNameUsingMD5_80_v2(upper(listName)) + ".name"); } static public File localMechListFile(String listName) { return newFile(localMechListsDir(), uniqueFileNameUsingMD5_80_v2(listName) + ".text"); } static public Method findMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args); } static public boolean findMethod_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static public int methodApplicabilityScore(Method m, Object[] args) { Class[] types = m.getParameterTypes(); if (types.length != args.length) return Integer.MAX_VALUE; int score = 0; for (int i = 0; i < types.length; i++) { Object a = args[i]; Class c = types[i]; if (a == null) ++score; else if (c == a.getClass()) { } else if (isInstanceX(c, a)) ++score; else return Integer.MAX_VALUE; } return score; } static public RuntimeException todo() { throw new RuntimeException("TODO"); } static public RuntimeException todo(Object msg) { throw new RuntimeException("TODO: " + msg); } static public int imageIcon_cacheSize = 10; static public boolean imageIcon_verbose = false; static public Map imageIcon_cache; static public Lock imageIcon_lock = lock(); static public ThreadLocal imageIcon_fixGIF = new ThreadLocal(); static public ImageIcon imageIcon(String imageID) { try { if (imageID == null) return null; Lock __0 = imageIcon_lock; lock(__0); try { if (imageIcon_cache == null) imageIcon_cache = new MRUCache(imageIcon_cacheSize); imageID = fsI(imageID); ImageIcon ii = imageIcon_cache.get(imageID); if (ii == null) { if (imageIcon_verbose) print("Loading image icon: " + imageID); File f = loadBinarySnippet(imageID); Boolean b = imageIcon_fixGIF.get(); if (!isFalse(b)) ii = new ImageIcon(loadBufferedImageFixingGIFs(f)); else ii = new ImageIcon(f.toURI().toURL()); } else imageIcon_cache.remove(imageID); imageIcon_cache.put(imageID, ii); return ii; } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } static public ImageIcon imageIcon(File f) { try { return new ImageIcon(f.toURI().toURL()); } catch (Exception __e) { throw rethrow(__e); } } static public ImageIcon imageIcon(Image img) { return new ImageIcon(img); } static public ImageIcon imageIcon(RGBImage img) { return imageIcon(img.getBufferedImage()); } static public JWindow showInTopRightCorner(Component c) { return swing(() -> { JWindow w = new JWindow(); w.add(c); w.pack(); moveToTopRightCorner(w); w.setVisible(true); return w; }); } static public A onClick(final A c, final Object runnable) { if (c != null) { swing(new Runnable() { public void run() { try { c.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { callF(runnable, e); } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.addMouseListener(new MouseAdapter {\r\n public void mouseClicked(MouseEv..."; } }); } return c; } static public void onClick(JButton btn, final Object runnable) { onEnter(btn, runnable); } static public A disposeWindowAfter(int delay, final A w) { if (w != null) swingLater(delay, new Runnable() { public void run() { try { w.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "w.dispose();"; } }); return w; } static public A disposeWindowAfter(A w, double seconds) { return disposeWindowAfter(toMS_int(seconds), w); } static public A disposeWindowAfter(double seconds, A w) { return disposeWindowAfter(w, seconds); } static public void listThreadLocalAdd(ThreadLocal> tl, A a) { List l = tl.get(); if (l == null) tl.set(l = new ArrayList()); l.add(a); } static public A listThreadLocalPopLast(ThreadLocal> tl) { List l = tl.get(); if (l == null) return null; A a = popLast(l); if (empty(l)) tl.set(null); return a; } static public ArrayList cloneListSynchronizingOn(Collection l, Object mutex) { if (l == null) return new ArrayList(); synchronized (mutex) { return new ArrayList(l); } } static public B mapPutOrRemove(Map map, A key, B value) { if (map != null && key != null) if (value != null) return map.put(key, value); else return map.remove(key); return null; } static public String stream2string(InputStream in) { return utf8streamToString(in); } static public File computerIDFile() { return javaxDataDir("Basic Info/computer-id.txt"); } static public Object[] muricaCredentials() { String pass = muricaPassword(); return nempty(pass) ? new Object[] { "_pass", pass } : new Object[0]; } static public String doPostSilently(Map urlParameters, String url) { return doPostSilently(makePostData(urlParameters), url); } static public String doPostSilently(String urlParameters, String url) { doPost_silently.set(true); return doPost(urlParameters, url); } static public boolean jsonDecode_useOrderedMaps = true; static public Object jsonDecode(final String text) { final List tok = jsonTok(text); if (l(tok) == 1) return null; class Y { public int i = 1; public Object parse() { String t = tok.get(i); if (t.startsWith("\"") || t.startsWith("'")) { String s = unquote(tok.get(i)); i += 2; return s; } if (t.equals("{")) return parseMap(); if (t.equals("[")) return this.parseList(); if (t.equals("null")) { i += 2; return null; } if (t.equals("false")) { i += 2; return false; } if (t.equals("true")) { i += 2; return true; } boolean minus = false; if (t.equals("-")) { minus = true; i += 2; t = get(tok, i); } if (isInteger(t)) { int j = i; i += 2; if (eqOneOf(get(tok, i), ".", "e", "E")) { while (isInteger(get(tok, i)) || eqOneOf(get(tok, i), ".", "e", "E", "-")) i += 2; double d = parseDouble(joinSubList(tok, j, i - 1)); if (minus) d = -d; return d; } else { long l = parseLong(t); if (minus) l = -l; return l != (int) l ? (Object) new Long(l) : new Integer((int) l); } } throw new RuntimeException("Unknown token " + (i + 1) + ": " + t + ": " + text); } public Object parseList() { consume("["); List list = new ArrayList(); while (!tok.get(i).equals("]")) { list.add(parse()); if (tok.get(i).equals(",")) i += 2; } consume("]"); return list; } public Object parseMap() { consume("{"); Map map = jsonDecode_useOrderedMaps ? new LinkedHashMap() : new TreeMap(); while (!tok.get(i).equals("}")) { String key = unquote(tok.get(i)); i += 2; consume(":"); Object value = parse(); map.put(key, value); if (tok.get(i).equals(",")) i += 2; } consume("}"); return map; } public void consume(String s) { if (!tok.get(i).equals(s)) { String prevToken = i - 2 >= 0 ? tok.get(i - 2) : ""; String nextTokens = join(tok.subList(i, Math.min(i + 4, tok.size()))); throw fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")"); } i += 2; } } return new Y().parse(); } static public File localMechListsDir() { return javaxDataDir("Mech Lists"); } static public boolean loadBufferedImageFixingGIFs_debug = false; static public ThreadLocal> loadBufferedImageFixingGIFs_output = new ThreadLocal(); static public Image loadBufferedImageFixingGIFs(File file) { try { if (!file.exists()) return null; if (!isGIF(file)) return ImageIO.read(file); if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": checking gif"); ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next(); reader.setInput(ImageIO.createImageInputStream(file)); int numImages = reader.getNumImages(true); IIOMetadata imageMetaData = reader.getImageMetadata(0); String metaFormatName = imageMetaData.getNativeMetadataFormatName(); boolean foundBug = false; for (int i = 0; i < numImages && !foundBug; i++) { IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(i).getAsTree(metaFormatName); int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { String delay = ((IIOMetadataNode) node).getAttribute("delayTime"); if (Integer.parseInt(delay) == 0) { foundBug = true; } break; } } } if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": " + f2s(file) + " foundBug=" + foundBug); Image image; if (!foundBug) { image = Toolkit.getDefaultToolkit().createImage(f2s(file)); } else { ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); { ImageOutputStream ios = ImageIO.createImageOutputStream(baoStream); try { ImageWriter writer = ImageIO.getImageWriter(reader); writer.setOutput(ios); writer.prepareWriteSequence(null); for (int i = 0; i < numImages; i++) { BufferedImage frameIn = reader.read(i); IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(i).getAsTree(metaFormatName); int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { String delay = ((IIOMetadataNode) node).getAttribute("delayTime"); if (Integer.parseInt(delay) == 0) { ((IIOMetadataNode) node).setAttribute("delayTime", "10"); } break; } } IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(frameIn), null); metadata.setFromTree(metadata.getNativeMetadataFormatName(), root); IIOImage frameOut = new IIOImage(frameIn, null, metadata); writer.writeToSequence(frameOut, writer.getDefaultWriteParam()); } writer.endWriteSequence(); } finally { _close(ios); } } byte[] data = baoStream.toByteArray(); setVar(loadBufferedImageFixingGIFs_output.get(), data); if (loadBufferedImageFixingGIFs_debug) print("Data size: " + l(data)); image = Toolkit.getDefaultToolkit().createImage(data); } return image; } catch (Exception __e) { throw rethrow(__e); } } static public int moveToTopRightCorner_inset = 20; static public A moveToTopRightCorner(A a) { return moveToTopRightCorner(moveToTopRightCorner_inset, moveToTopRightCorner_inset, a); } static public A moveToTopRightCorner(int insetX, int insetY, A a) { Window w = getWindow(a); if (w != null) w.setLocation(getScreenSize().width - w.getWidth() - insetX, insetY); return a; } static public JTextField onEnter(final JTextField tf, final Object action) { if (action == null || tf == null) return tf; tf.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { tf.selectAll(); callF(action); } catch (Throwable __e) { messageBox(__e); } } }); return tf; } static public JButton onEnter(JButton btn, final Object action) { if (action == null || btn == null) return btn; btn.addActionListener(actionListener(action)); return btn; } static public JList onEnter(JList list, Object action) { list.addKeyListener(enterKeyListener(rCallOnSelectedListItem(list, action))); return list; } static public JComboBox onEnter(final JComboBox cb, final Object action) { { swing(new Runnable() { public void run() { try { if (cb.isEditable()) { JTextField text = (JTextField) cb.getEditor().getEditorComponent(); onEnter(text, action); } else { cb.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); cb.getActionMap().put("enter", abstractAction("", new Runnable() { public void run() { try { cb.hidePopup(); callF(action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.hidePopup(); callF(action);"; } })); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (cb.isEditable()) {\r\n JTextField text = (JTextField) cb.getEditor().g..."; } }); } return cb; } static public JTable onEnter(final JTable table, final Object action) { table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter"); table.getActionMap().put("Enter", new AbstractAction() { public void actionPerformed(ActionEvent e) { callF(action, table.getSelectedRow()); } }); return table; } static public JTextField onEnter(Object action, JTextField tf) { return onEnter(tf, action); } static public void swingLater(long delay, final Object r) { javax.swing.Timer timer = new javax.swing.Timer(toInt(delay), actionListener(wrapAsActivity(r))); timer.setRepeats(false); timer.start(); } static public void swingLater(Object r) { SwingUtilities.invokeLater(toRunnable(r)); } static public String utf8streamToString(InputStream in) { return readerToString(utf8bufferedReader(in)); } static public ThreadLocal doPost_silently = new ThreadLocal(); static public ThreadLocal doPost_timeout = new ThreadLocal(); static public ThreadLocal> doPost_extraHeaders = new ThreadLocal(); static public String doPost(Map urlParameters, String url) { return doPost(makePostData(urlParameters), url); } static public String doPost(String urlParameters, String url) { try { URL _url = new URL(url); ping(); return doPost(urlParameters, _url.openConnection(), _url); } catch (Exception __e) { throw rethrow(__e); } } static public String doPost(String urlParameters, URLConnection conn, URL url) { try { boolean silently = isTrue(optParam(doPost_silently)); Long timeout = optParam(doPost_timeout); Map extraHeaders = optPar(doPost_extraHeaders); setHeaders(conn); for (String key : keys(extraHeaders)) { conn.setRequestProperty(key, extraHeaders.get(key)); } int l = lUtf8(urlParameters); if (!silently) print("Sending POST request: " + hideCredentials(url) + " (" + l + " bytes)"); if (timeout != null) setURLConnectionTimeouts(conn, timeout); ((HttpURLConnection) conn).setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("Content-Length", str(l)); OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); writer.write(urlParameters); writer.flush(); String contents = loadPage_utf8(conn, url, false); writer.close(); return contents; } catch (Exception __e) { throw rethrow(__e); } } static public List jsonTok(String s) { List tok = new ArrayList(); int l = l(s); int i = 0; while (i < l) { int j = i; char c; String cc; while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j + 2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isLetter(c)) do ++j; while (j < l && Character.isLetter(s.charAt(j))); else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static public byte[] isGIF_magic = bytesFromHex("47494638"); static public boolean isGIF(byte[] data) { return byteArrayStartsWith(data, isGIF_magic); } static public boolean isGIF(File f) { return isGIF(loadBeginningOfBinaryFile(f, l(isGIF_magic))); } static public void setVar(IVar v, A value) { if (v != null) v.set(value); } static public Dimension getScreenSize() { return Toolkit.getDefaultToolkit().getScreenSize(); } static public void messageBox(final String msg) { if (headless()) print(msg); else { swing(new Runnable() { public void run() { try { JOptionPane.showMessageDialog(null, msg, "JavaX", JOptionPane.INFORMATION_MESSAGE); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JOptionPane.showMessageDialog(null, msg, \"JavaX\", JOptionPane.INFORMATION_MES..."; } }); } } static public void messageBox(Throwable e) { printStackTrace(e); messageBox(hideCredentials(innerException2(e))); } static public ActionListener actionListener(final Object runnable) { return actionListener(runnable, null); } static public ActionListener actionListener(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; final Object info = _threadInfo(); return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { _threadInheritInfo(info); AutoCloseable __1 = holdInstance(instanceToHold); try { callF(runnable); } finally { _close(__1); } } catch (Throwable __e) { messageBox(__e); } } }; } static public KeyListener enterKeyListener(final Object action) { return new KeyAdapter() { public void keyPressed(KeyEvent ke) { if (ke.getKeyCode() == KeyEvent.VK_ENTER) pcallF(action); } }; } static public Runnable rCallOnSelectedListItem(final JList list, final Object action) { return new Runnable() { public void run() { try { pcallF(action, getSelectedItem(list)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(action, getSelectedItem(list))"; } }; } static public AbstractAction abstractAction(String name, final Object runnable) { return new AbstractAction(name) { public void actionPerformed(ActionEvent evt) { pcallF(runnable); } }; } static public String readerToString(Reader r) { try { try { StringBuilder buf = new StringBuilder(); int n = 0; while (true) { int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; } return buf.toString(); } finally { r.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public int lUtf8(String s) { return l(utf8(s)); } static public byte[] bytesFromHex(String s) { return hexToBytes(s); } static public boolean byteArrayStartsWith(byte[] a, byte[] b) { if (a == null || b == null) return false; if (a.length < b.length) return false; for (int i = 0; i < b.length; i++) if (a[i] != b[i]) return false; return true; } static public byte[] loadBeginningOfBinaryFile(File file, int maxBytes) { return loadBinaryFilePart(file, 0, maxBytes); } static public boolean headless() { return isHeadless(); } static public String getSelectedItem(JList l) { return (String) l.getSelectedValue(); } static public String getSelectedItem(JComboBox cb) { return strOrNull(cb.getSelectedItem()); } static public byte[] hexToBytes(String s) { if (odd(l(s))) throw fail("Hex string has odd length: " + quote(shorten(10, s))); int n = l(s) / 2; byte[] bytes = new byte[n]; for (int i = 0; i < n; i++) { int a = parseHexChar(s.charAt(i * 2)); int b = parseHexChar(s.charAt(i * 2 + 1)); if (a < 0 || b < 0) throw fail("Bad hex byte: " + quote(substring(s, i * 2, i * 2 + 2)) + " at " + i * 2 + "/" + l(s)); bytes[i] = (byte) ((a << 4) | b); } return bytes; } static public byte[] loadBinaryFilePart(File file, long start, long end) { try { RandomAccessFile raf = new RandomAccessFile(file, "r"); int n = toInt(min(raf.length(), end - start)); byte[] buffer = new byte[n]; try { raf.seek(start); raf.readFully(buffer, 0, n); return buffer; } finally { raf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public int parseHexChar(char c) { if (c >= '0' && c <= '9') return charDiff(c, '0'); if (c >= 'a' && c <= 'f') return charDiff(c, 'a') + 10; if (c >= 'A' && c <= 'F') return charDiff(c, 'A') + 10; return -1; } static public int charDiff(char a, char b) { return (int) a - (int) b; } static public int charDiff(String a, char b) { return charDiff(stringToChar(a), b); } static public char stringToChar(String s) { if (l(s) != 1) throw fail("bad stringToChar: " + s); return firstChar(s); } static public char firstChar(String s) { return s.charAt(0); } static abstract public class VF2 { abstract public void get(A a, B b); } static public class Var implements IVar { public Var() { } public Var(A v) { this.v = v; } public A v; public synchronized void set(A a) { if (v != a) { v = a; notifyAll(); } } public synchronized A get() { return v; } public synchronized boolean has() { return v != null; } public synchronized void clear() { v = null; } public String toString() { return str(get()); } } static public class DefunctClassLoader { } static public interface ITokCondition { public boolean get(List tok, int i); } static abstract public class TokCondition { abstract public boolean get(List tok, int i); } static public class ConceptsRefChecker { public Concepts cc; public List errors = new ArrayList(); static public class Err { } static public class ErrNoBackRef extends Err implements IFieldsToList { static final public String _fieldOrder = "ref dest"; public Concept.Ref ref; public Concept dest; public ErrNoBackRef() { } public ErrNoBackRef(Concept.Ref ref, Concept dest) { this.dest = dest; this.ref = ref; } public String toString() { return shortClassName(this) + "(" + ref + ", " + dest + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrNoBackRef)) return false; ErrNoBackRef __1 = (ErrNoBackRef) o; return eq(ref, __1.ref) && eq(dest, __1.dest); } public int hashCode() { int h = -1351603866; h = boostHashCombine(h, _hashCode(ref)); h = boostHashCombine(h, _hashCode(dest)); return h; } public Object[] _fieldsToList() { return new Object[] { ref, dest }; } } static public class ErrSuperfluousBackRef extends Err implements IFieldsToList { static final public String _fieldOrder = "ref dest"; public Concept.Ref ref; public Concept dest; public ErrSuperfluousBackRef() { } public ErrSuperfluousBackRef(Concept.Ref ref, Concept dest) { this.dest = dest; this.ref = ref; } public String toString() { return shortClassName(this) + "(" + ref + ", " + dest + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrSuperfluousBackRef)) return false; ErrSuperfluousBackRef __2 = (ErrSuperfluousBackRef) o; return eq(ref, __2.ref) && eq(dest, __2.dest); } public int hashCode() { int h = 1840777816; h = boostHashCombine(h, _hashCode(ref)); h = boostHashCombine(h, _hashCode(dest)); return h; } public Object[] _fieldsToList() { return new Object[] { ref, dest }; } } static public class ErrDuplicateRef extends Err implements IFieldsToList { public Concept c; public ErrDuplicateRef() { } public ErrDuplicateRef(Concept c) { this.c = c; } public String toString() { return shortClassName(this) + "(" + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrDuplicateRef)) return false; ErrDuplicateRef __3 = (ErrDuplicateRef) o; return eq(c, __3.c); } public int hashCode() { int h = 1148352877; h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { c }; } } static public class ErrNullRef extends Err implements IFieldsToList { public Concept c; public ErrNullRef() { } public ErrNullRef(Concept c) { this.c = c; } public String toString() { return shortClassName(this) + "(" + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrNullRef)) return false; ErrNullRef __4 = (ErrNullRef) o; return eq(c, __4.c); } public int hashCode() { int h = 209467527; h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { c }; } } static public class ErrMissingRef extends Err implements IFieldsToList { public Concept c; public Concept.Ref ref; public ErrMissingRef() { } public ErrMissingRef(Concept c, Concept.Ref ref) { this.ref = ref; this.c = c; } public String toString() { return shortClassName(this) + "(" + c + ", " + ref + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrMissingRef)) return false; ErrMissingRef __5 = (ErrMissingRef) o; return eq(c, __5.c) && eq(ref, __5.ref); } public int hashCode() { int h = 1969969266; h = boostHashCombine(h, _hashCode(c)); h = boostHashCombine(h, _hashCode(ref)); return h; } public Object[] _fieldsToList() { return new Object[] { c, ref }; } } static public class ErrSuperfluousRef extends Err implements IFieldsToList { public Concept c; public Concept.Ref ref; public ErrSuperfluousRef() { } public ErrSuperfluousRef(Concept c, Concept.Ref ref) { this.ref = ref; this.c = c; } public String toString() { return shortClassName(this) + "(" + c + ", " + ref + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrSuperfluousRef)) return false; ErrSuperfluousRef __6 = (ErrSuperfluousRef) o; return eq(c, __6.c) && eq(ref, __6.ref); } public int hashCode() { int h = 762378943; h = boostHashCombine(h, _hashCode(c)); h = boostHashCombine(h, _hashCode(ref)); return h; } public Object[] _fieldsToList() { return new Object[] { c, ref }; } } static public class ErrDanglingSource extends Err implements IFieldsToList { static final public String _fieldOrder = "ref dest"; public Concept.Ref ref; public Concept dest; public ErrDanglingSource() { } public ErrDanglingSource(Concept.Ref ref, Concept dest) { this.dest = dest; this.ref = ref; } public String toString() { return shortClassName(this) + "(" + ref + ", " + dest + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrDanglingSource)) return false; ErrDanglingSource __7 = (ErrDanglingSource) o; return eq(ref, __7.ref) && eq(dest, __7.dest); } public int hashCode() { int h = 666937292; h = boostHashCombine(h, _hashCode(ref)); h = boostHashCombine(h, _hashCode(dest)); return h; } public Object[] _fieldsToList() { return new Object[] { ref, dest }; } } static public class ErrDanglingDestination extends Err implements IFieldsToList { static final public String _fieldOrder = "ref dest"; public Concept.Ref ref; public Concept dest; public ErrDanglingDestination() { } public ErrDanglingDestination(Concept.Ref ref, Concept dest) { this.dest = dest; this.ref = ref; } public String toString() { return shortClassName(this) + "(" + ref + ", " + dest + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrDanglingDestination)) return false; ErrDanglingDestination __8 = (ErrDanglingDestination) o; return eq(ref, __8.ref) && eq(dest, __8.dest); } public int hashCode() { int h = -1158731011; h = boostHashCombine(h, _hashCode(ref)); h = boostHashCombine(h, _hashCode(dest)); return h; } public Object[] _fieldsToList() { return new Object[] { ref, dest }; } } public ConceptsRefChecker() { } public ConceptsRefChecker(Concepts cc) { this.cc = cc; } public List run() { errors.clear(); if (cc == null) return errors; Collection concepts = cc.allConcepts(); print("Checking " + nConcepts(concepts)); for (Concept c : concepts) try { Object badElement = firstElementNotSubclassing(c.backRefs, Concept.Ref.class); if (badElement != null) { print("Bad element in backRefs of " + c + ": " + badElement); continue; } for (Concept.Ref ref : cloneList(c.backRefs)) { if (ref.get() != c) errors.add(new ErrSuperfluousBackRef(ref, c)); if (ref.concept()._concepts != cc) errors.add(new ErrDanglingSource(ref, c)); } badElement = firstElementNotSubclassing(c.refs, Concept.Ref.class); if (badElement != null) { print("Bad element in backRefs of " + c + ": " + badElement); continue; } List refs = cloneList(c.refs); if (!allUnique(refs)) errors.add(new ErrDuplicateRef(c)); if (contains(refs, null)) errors.add(new ErrNullRef(c)); refs = nonNulls(refs); Collection actualRefs = scanConceptForRefs(c); for (Concept.Ref ref : listMinusSet(refs, actualRefs)) errors.add(new ErrSuperfluousRef(c, ref)); for (Concept.Ref ref : listMinusSet(actualRefs, refs)) errors.add(new ErrMissingRef(c, ref)); for (Concept.Ref ref : refs) if (ref.has()) { if (!contains(ref.get().backRefs, ref)) errors.add(new ErrNoBackRef(ref, c)); if (ref.get()._concepts != cc) errors.add(new ErrDanglingDestination(ref, c)); } } catch (Throwable e) { _handleException(e); print("Error processing concept " + c); } return errors; } public List errors() { return errors; } public String fixAll() { List out = new ArrayList(); for (Err err : reversed(cloneAndClear(errors))) { try { out.add("Processing " + err); if (err instanceof ErrNoBackRef) { ((ErrNoBackRef) err).ref.index(); out.add(" reference added"); } else if (err instanceof ErrSuperfluousRef) { ((ErrSuperfluousRef) err).ref.unindexAndDrop(); out.add(" reference dropped"); } else if (err instanceof ErrDanglingSource) { ((ErrDanglingSource) err).ref.get()._removeBackRef(((ErrDanglingSource) err).ref); out.add(" reference removed from destination"); } else if (err instanceof ErrDanglingDestination) { ((ErrDanglingDestination) err).ref.get()._removeBackRef(((ErrDanglingDestination) err).ref); out.add(" reference removed from destination"); } else if (err instanceof ErrMissingRef) { ((ErrMissingRef) err).ref.registerRef(); out.add(" reference registered"); } else out.add(" TODO - fix not implemented"); } catch (Throwable __e) { _handleException(__e); } } return lines(out); } public String runAndFixAll() { run(); return fixAll(); } } static public class CancelToCancelPoint extends QuickException { public CancelPoint cp; public CancelToCancelPoint(CancelPoint cp) { this.cp = cp; } } final static public class ConceptFieldIndexDesc implements IConceptIndex, IFieldIndex, IConceptCounter { public Class cc; public String field; public HashMap objectToValue = new HashMap(); public MultiSetMap valueToObject; public ConceptFieldIndexDesc() { valueToObject = treeMultiSetMap(reverseOrder()); } public ConceptFieldIndexDesc(Class cc, String field) { this(db_mainConcepts(), cc, field); } public ConceptFieldIndexDesc(Concepts concepts, Class cc, String field) { this(); this.field = field; this.cc = cc; concepts.addConceptIndex(this); for (A c : list(concepts, cc)) updateImpl(c); concepts.addFieldIndex(cc, field, this); } public void update(Concept c) { if (!isInstance(cc, c)) return; updateImpl(c); } synchronized public void updateImpl(Concept c) { Val newValue = (Val) (cget(c, field)); Val oldValue = objectToValue.get(c); if (newValue == null || newValue != oldValue) { valueToObject.remove(oldValue, (A) c); valueToObject.put(newValue, (A) c); objectToValue.put((A) c, newValue); } } public synchronized void remove(Concept c) { if (!isInstance(cc, c)) return; Val value = (Val) (cget(c, field)); objectToValue.remove(c); valueToObject.remove(value, (A) c); } synchronized public A get(Val value) { return valueToObject.getFirst(value); } public synchronized Collection getAll(Val value) { return valueToObject.get(value); } public synchronized List allValues() { return cloneKeys_noSync(valueToObject.data); } public IterableIterator objectIterator() { return navigableMultiSetMapValuesIterator_concurrent(valueToObject, this); } public synchronized MultiSet allValues_multiSet() { return multiSetMapToMultiSet(valueToObject); } public Class conceptClass() { return cc; } public int countConcepts() { return l(objectToValue); } public Collection allConcepts() { return (Collection) keys(objectToValue); } public Object mutex() { return this; } synchronized public List objectsWithValueGreaterThan(Object value) { SortedMap> subMap = ((SortedMap>) valueToObject.data).headMap(value); return concatLists(values(subMap)); } } static public class FixedRateTimer extends java.util.Timer { public FixedRateTimer() { this(false); } public FixedRateTimer(boolean daemon) { this(defaultTimerName(), daemon); } public FixedRateTimer(String name) { this(name, false); } public FixedRateTimer(String name, boolean daemon) { super(name, daemon); _registerTimer(this); } public List entries = synchroList(); static public class Entry implements IFieldsToList { public TimerTask task; public long firstTime; public long period; public Entry() { } public Entry(TimerTask task, long firstTime, long period) { this.period = period; this.firstTime = firstTime; this.task = task; } public String toString() { return shortClassName(this) + "(" + task + ", " + firstTime + ", " + period + ")"; } public Object[] _fieldsToList() { return new Object[] { task, firstTime, period }; } } public void scheduleAtFixedRate(TimerTask task, long delay, long period) { entries.add(new Entry(task, now() + delay, period)); super.scheduleAtFixedRate(task, delay, period); } public void cancel() { entries.clear(); super.cancel(); } public int purge() { entries.clear(); return super.purge(); } public FixedRateTimer changeRate(int newPeriod) { Object r = ((SmartTimerTask) first(entries).task).r; cancel(); return doEvery(newPeriod, r); } } static public class ConceptFieldIndex implements IConceptIndex, IFieldIndex, IConceptCounter { public Class cc; public String field; public HashMap objectToValue = new HashMap(); public MultiSetMap valueToObject = new MultiSetMap(); public ConceptFieldIndex() { } public ConceptFieldIndex(Class cc, String field) { this(db_mainConcepts(), cc, field); } public ConceptFieldIndex(Concepts concepts, Class cc, String field) { this.field = field; this.cc = cc; concepts.addConceptIndex(this); for (A c : list(concepts, cc)) updateImpl(c); concepts.addFieldIndex(cc, field, this); } public void update(Concept c) { if (!isInstance(cc, c)) return; updateImpl(c); } synchronized public void updateImpl(Concept c) { Val newValue = (Val) (cget(c, field)); Val oldValue = objectToValue.get(c); if (newValue == null || newValue != oldValue) { valueToObject.remove(oldValue, (A) c); valueToObject.put(newValue, (A) c); objectToValue.put((A) c, newValue); } } public synchronized void remove(Concept c) { if (!isInstance(cc, c)) return; Val value = (Val) (cget(c, field)); objectToValue.remove(c); valueToObject.remove(value, (A) c); } synchronized public A get(Val value) { return valueToObject.getFirst(value); } public synchronized Collection getAll(Val value) { return valueToObject.get(value); } public synchronized List allValues() { return cloneKeys_noSync(valueToObject.data); } public synchronized MultiSet allValues_multiSet() { return multiSetMapToMultiSet(valueToObject); } public Class conceptClass() { return cc; } public int countConcepts() { return l(objectToValue); } public Collection allConcepts() { return (Collection) keys(objectToValue); } } static abstract public class IterableIterator implements Iterator, Iterable { public Iterator iterator() { return this; } public void remove() { unsupportedOperation(); } } static abstract public class F2 { abstract public C get(A a, B b); } static public class Flag implements Runnable { public boolean up = false; public synchronized boolean raise() { if (!up) { up = true; notifyAll(); return true; } else return false; } public synchronized void waitUntilUp() { while (!up) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void waitUntilUp(long timeout) { if (!up) { try { wait(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized boolean isUp() { return up; } public boolean get() { return isUp(); } public String toString() { return isUp() ? "up" : "down"; } public void waitForThisOr(Flag otherFlag) { try { while (!isUp() && !otherFlag.isUp()) Thread.sleep(50); } catch (Exception __e) { throw rethrow(__e); } } public void run() { raise(); } } final static public class ContentsIndexedList extends RandomAccessAbstractList implements IContentsIndexedList, IContentsIndexedList2 { public Map>> index = new HashMap(); final public ArrayList> list = new ArrayList(); final static public class Elem extends HasIndex { public A s; public String toString() { return "Elem " + quote(s) + "@" + idx; } } public ContentsIndexedList() { } public ContentsIndexedList(Map>> index) { this.index = index; } public ContentsIndexedList(Collection l) { addAll(l); } public A get(int i) { return list.get(i).s; } public int size() { return list.size(); } public A set(int i, A s) { Elem t = list.get(i); A old = t.s; if (eq(old, s)) return old; removeFromIdx(t); t.s = s; addToIdx(t); return old; } public boolean add(A s) { ++modCount; Elem t = new Elem(); t.s = s; t.idx = size(); list.add(t); addToIdx(t); return true; } public void add(int i, A s) { ++modCount; Elem t = new Elem(); t.s = s; t.idx = i; list.add(i, t); reorder(i + 1); addToIdx(t); } public boolean addAll(int i, Collection l) { int n = l.size(); if (n == 0) return false; ++modCount; List> l2 = emptyList(n); int j = i; for (A s : l) { Elem t = new Elem(); t.s = s; t.idx = j++; l2.add(t); } list.addAll(i, l2); reorder(i + n); for (Elem t : l2) addToIdx(t); return true; } public A remove(int i) { ++modCount; Elem t = list.get(i); removeFromIdx(t); list.remove(i); reorder(i); return t.s; } public void reorder(int fromIdx) { int n = size(); for (int i = fromIdx; i < n; i++) list.get(i).idx = i; } public void removeFromIdx(Elem t) { TreeSet> idx = index.get(t.s); idx.remove(t); if (idx.isEmpty()) index.remove(t.s); } public void addToIdx(Elem t) { TreeSet> idx = index.get(t.s); if (idx == null) index.put(t.s, idx = new TreeSet()); idx.add(t); } @Override public int indexOf(Object s) { TreeSet> l = index.get(s); return l == null ? -1 : first(l).idx; } @Override public int lastIndexOf(Object s) { TreeSet> l = index.get(s); return l == null ? -1 : last(l).idx; } @Override public boolean contains(Object s) { return index.containsKey(s); } public void clear() { ++modCount; index.clear(); list.clear(); } public void removeRange(int fromIndex, int toIndex) { if (fromIndex == toIndex) return; ++modCount; for (int i = fromIndex; i < toIndex; i++) removeFromIdx(list.get(i)); list.subList(fromIndex, toIndex).clear(); reorder(fromIndex); } public int[] indicesOf(Object o) { TreeSet> idx = index.get(o); if (idx == null) return emptyIntArray(); int[] a = new int[idx.size()]; int i = 0; for (Elem t : idx) a[i++] = t.idx; return a; } public TreeSet indicesOf_treeSetOfHasIndex(Object o) { return (TreeSet) index.get(o); } } static public class FileTransferable implements Transferable { public List files = new ArrayList(); public FileTransferable(File f) { files.add(f); } public FileTransferable(List files) { this.files = files; } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[] { DataFlavor.javaFileListFlavor }; } public boolean isDataFlavorSupported(DataFlavor flavor) { return eq(flavor, DataFlavor.javaFileListFlavor); } public Object getTransferData(DataFlavor flavor) { return files; } } static public class StringBufferWithMaxSize implements Appendable { public int maxSize; public StringBuilder buf = new StringBuilder(); public StringBufferWithMaxSize(int maxSize) { this.maxSize = maxSize; } public Appendable append(char c) { return append(str(c)); } public Appendable append(CharSequence csq, int start, int end) { return append(csq.subSequence(start, end)); } public int size() { return l(buf); } public synchronized Appendable append(CharSequence csq) { if (full()) return this; int n = l(csq); if (size() + n > maxSize) buf.append(subCharSequence(csq, maxSize - size())); else buf.append(csq); return this; } public boolean full() { return size() >= maxSize; } synchronized public String toString() { return str(buf); } } static abstract public class CloseableIterableIterator extends IterableIterator implements AutoCloseable { public void close() throws Exception { } } static public class ExpiringMap2 extends AbstractMap { public Map> byKey = new HashMap(); public PriorityBlockingQueue> queue = new PriorityBlockingQueue(); public long standardExpiryTime; public boolean renewOnOverwrite = true, renewOnGet; public Object onChange; public ExpiringMap2() { } public ExpiringMap2(long standardExpiryTime) { this.standardExpiryTime = standardExpiryTime; } public ExpiringMap2(long standardExpiryTime, Object onChange) { this.onChange = onChange; this.standardExpiryTime = standardExpiryTime; } synchronized public boolean clean() { boolean changes = false; Pair p; while ((p = queue.peek()) != null && sysTime() >= p.a) { p = queue.poll(); Pair v = byKey.get(p.b); if (v != null) { byKey.remove(p.b); changes = true; change(); } } return changes; } public void change() { callF(onChange); } synchronized public B put(A a, B b) { clean(); long timeout = sysTime() + standardExpiryTime; Pair p = byKey.get(a); if (p != null && renewOnOverwrite) queue.remove(new Pair(p.a, a)); byKey.put(a, pair(timeout, b)); change(); if (p == null || renewOnOverwrite) queue.add(new Pair(timeout, a)); return pairB(p); } synchronized public B remove(Object a) { clean(); Pair p = byKey.get(a); if (p == null) return null; queue.remove(new Pair(p.a, a)); byKey.remove(a); change(); return p.b; } synchronized public B get(Object a) { clean(); Pair p = byKey.get(a); if (renewOnGet && p != null) { queue.remove(new Pair(p.a, a)); long timeout = sysTime() + standardExpiryTime; byKey.put((A) a, pair(timeout, p.b)); queue.add(new Pair(timeout, a)); } return pairB(p); } synchronized public Set> entrySet() { clean(); return synchronizedSet(mapValues("pairB", byKey).entrySet()); } synchronized public Set keySet() { clean(); return synchronizedSet(byKey.keySet()); } synchronized public int size() { clean(); return byKey.size(); } public void setStandardExpiryTime(long ms) { standardExpiryTime = ms; } synchronized public ExpiringMap2 setMap(Map innerMap) { byKey = innerMap; return this; } } static public interface IFieldsToList { public Object[] _fieldsToList(); } static public interface IF2 { public C get(A a, B b); } static public class ConceptFieldIndexCI implements IConceptIndex, IFieldIndex, IConceptCounter { public Class cc; public String field; public HashMap objectToValue = new HashMap(); public MultiSetMap valueToObject = ciMultiSetMap(); public ConceptFieldIndexCI() { } public ConceptFieldIndexCI(Class cc, String field) { this(db_mainConcepts(), cc, field); } public ConceptFieldIndexCI(Concepts concepts, Class cc, String field) { this.field = field; this.cc = cc; concepts.addConceptIndex(this); for (A c : list(concepts, cc)) updateImpl(c); concepts.addCIFieldIndex(cc, field, this); } public void update(Concept c) { if (!isInstance(cc, c)) return; updateImpl(c); } synchronized public void updateImpl(Concept c) { String newValue = (String) (cget(c, field)); String oldValue = objectToValue.get(c); if (newValue == null || newValue != oldValue) { valueToObject.remove(oldValue, (A) c); valueToObject.put(newValue, (A) c); objectToValue.put((A) c, newValue); } } public synchronized void remove(Concept c) { if (!isInstance(cc, c)) return; String value = (String) (cget(c, field)); objectToValue.remove(c); valueToObject.remove(value, (A) c); } synchronized public A get(String value) { return valueToObject.getFirst(value); } public synchronized List getAll(String value) { return cloneList(valueToObject.get(value)); } public Class conceptClass() { return cc; } public int countConcepts() { return l(objectToValue); } public Collection allConcepts() { return (Collection) keys(objectToValue); } public synchronized List allValues() { return cloneKeys_noSync(valueToObject.data); } public synchronized MultiSet allValues_multiSet() { return multiSetMapToMultiSet(valueToObject); } public IterableIterator objectIterator() { return navigableMultiSetMapValuesIterator(valueToObject); } } static public interface IVar extends IF0 { public void set(A a); public A get(); default public boolean has() { return get() != null; } default public void clear() { set(null); } } static public class MechMode implements IFieldsToList { public Object readMode; public Object writeMode; public MechMode() { } public MechMode(Object readMode, Object writeMode) { this.writeMode = writeMode; this.readMode = readMode; } public String toString() { return shortClassName(this) + "(" + readMode + ", " + writeMode + ")"; } public boolean equals(Object o) { if (!(o instanceof MechMode)) return false; MechMode __1 = (MechMode) o; return eq(readMode, __1.readMode) && eq(writeMode, __1.writeMode); } public int hashCode() { int h = -866263200; h = boostHashCombine(h, _hashCode(readMode)); h = boostHashCombine(h, _hashCode(writeMode)); return h; } public Object[] _fieldsToList() { return new Object[] { readMode, writeMode }; } } final static public class _MethodCache { final public Class c; final public HashMap> cache = new HashMap(); public _MethodCache(Class c) { this.c = c; _init(); } public void _init() { Class _c = c; while (_c != null) { for (Method m : _c.getDeclaredMethods()) if (!isAbstract(m) && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); _c = _c.getSuperclass(); } for (Class intf : allInterfacesImplementedBy(c)) for (Method m : intf.getDeclaredMethods()) if (m.isDefault() && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); } public Method findMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } public Method findStaticMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (isStaticMethod(me) && call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } } static public String passwordSalt() { File f = programSecretFile("password-salt"); if (fileExists(f)) return loadTextFile(f); File global = javaxSecretDir("password-salt"); if (fileExists(global)) return loadTextFile(global); return loadTextFileOrCreateWithRandomID(f); } static public class PostReferenceable extends Concept { } static public class User extends PostReferenceable { static final public String _fieldOrder = "name passwordMD5 contact isMaster botToken"; public String name; public SecretValue passwordMD5; public String contact; public boolean isMaster = false; public SecretValue botToken = aSecretGlobalID(); public String toString() { return nempty(name) ? "User " + name : super.toString(); } public String notificationSetting; } static public class UserCreatedObject extends PostReferenceable { static final public String _fieldOrder = "creator botInfo"; public Ref creator = new Ref(); public String botInfo; } static public class UserPost extends UserCreatedObject { public String type, title, text; public boolean isPublic = true, hidden; public boolean creating = false; public long xmodified; public long bumped; static public List fieldsToSaveOnDelete = ll("id", "text", "title", "type", "creatorID", "postRefs", "postRefTags", "hidden", "isPublic", "created", "_modified", "xmodified", "botInfo", "creating"); public String text() { return text; } public RefL postRefs = new RefL(); public List postRefTags = new ArrayList(); static public String _fieldOrder = "title text type postRefs isPublic"; public String toString() { String content = nempty(title) ? shorten(title) : escapeNewLines(shorten(text)); return content + " [by " + author() + "]"; } public boolean isReply() { return nempty(postRefs); } public boolean isBotPost() { return nempty(botInfo); } public boolean isMasterMade() { return creator.has() && creator.get().isMaster; } public String author() { String author = userName(creator.get()); if (isBotPost()) author += "'s bot " + quote(botInfo); return author; } public void change() { super.change(); ((DynGazelleRocks) botMod()).distributePostChanges(this); } public List> postRefsWithTags() { return zipTwoListsToPairs_lengthOfFirst(postRefs, postRefTags); } public List postRefsWithTag(String tag) { return pairsAWhereB(postRefsWithTags(), t -> eqic_unnull(t, tag)); } public UserPost primaryRefPost() { return optCast(UserPost.class, first(postRefsWithTag(""))); } public void _setModified(long modified) { super._setModified(modified); setXModified(modified); } public void bump() { bumped = now(); _change_withoutUpdatingModifiedField(); for (UserPost p : syncInstancesOf(UserPost.class, postRefs)) p.setXModified(); } public long modifiedOrBumped() { return max(_modified, bumped); } public void setXModified() { setXModified(now()); } public void setXModified(long modified) { boolean changed = modified > xmodified; xmodified = modified; _change_withoutUpdatingModifiedField(); if (changed) ((DynGazelleRocks) botMod()).distributePostChanges(this); } public void _backRefsModified() { super._backRefsModified(); setXModified(now()); } public int distanceToUserPost() { int n = 0; UserPost post = this; while (post != null && n < 100) { if (!post.isBotPost()) return n; post = post.primaryRefPost(); } return -1; } public boolean isJavaXCode() { return eqicOrSwicPlusSpace(type, "JavaX Code"); } } abstract static public class DynGazelleRocks extends DynNewBot2 { transient public boolean inlineSearch = false; static public boolean _switchableField_webPushEnabled = true; public boolean webPushEnabled = true; static public boolean _switchableField_showPostStats = true; public boolean showPostStats = false; static public boolean _switchableField_showSuggestorBot = true; public boolean showSuggestorBot = true; static public boolean _switchableField_showMetaBotOnEveryPage = true; public boolean showMetaBotOnEveryPage = true; static public boolean _switchableField_delayAfterSuggestion = true; public int delayAfterSuggestion = 1000; static public boolean _switchableField_defaultBotPost = true; public int defaultBotPost = 238410; static public boolean _switchableField_teamPostID = true; public long teamPostID; static public boolean _switchableField_favIconID = true; public long favIconID; static public boolean _switchableField_gazelleBotURL = true; public String gazelleBotURL = "https://gazellebot.botcompany.de"; transient public double systemLoad; transient public long processSize; public void init() { dm_require("#1017856/SystemLoad"); dm_vmBus_onMessage("systemLoad", new VF1() { public void get(Double load) { try { if (setField("systemLoad", load)) distributeDivChanges("serverLoadRightHemi"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (setField(systemLoad := load))\r\n distributeDivChanges(\"serverLoadRi..."; } }); dm_vmBus_onMessage("processSize", new VF1() { public void get(Long processSize) { try { if (setField("processSize", processSize)) distributeDivChanges("memRightHemi"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (setField(+processSize))\r\n distributeDivChanges(\"memRightHemi\");"; } }); botName = heading = adminName = "gazelle.rocks"; templateID = "#1030086"; cssID = "237267"; enableUsers = true; useWebSockets = true; showRegisterLink = true; showTalkToBotLink = false; alwaysRedirectToHttps = true; redirectOnLogout = true; showFullErrors = true; inlineSearch = true; lockWhileDoingBotActions = false; passwordSalt(); } public void makeIndices() { super.makeIndices(); indexConceptFieldCI(User.class, "name"); indexConceptFieldDesc(UserPost.class, "xmodified"); indexConceptFieldDesc(UserPost.class, "_modified"); indexConceptFieldCI(UserPost.class, "botInfo"); } public void start() { init(); super.start(); db_mainConcepts().modifyOnCreate = true; printConceptIndices(); onConceptsChange(new Runnable() { public int postCount = countConcepts(UserPost.class); public void run() { int count = countConcepts(UserPost.class); if (count != postCount) { postCount = count; distributeDivChanges("postCount"); } } }); internalUser(); } public void requestServed() { distributeDivChanges("webRequestsRightHemi"); } public class WebSocketInfo { public String uri; public Map params; public Set> liveDivs = new HashSet(); } transient public Map webSockets = syncWeakHashMap(); public void cleanMeUp_webSockets() { closeAllKeysAndClear((Map) webSockets); } public void handleWebSocket(Object ws) { set(ws, "onClose", new Runnable() { public void run() { try { webSockets.remove(ws); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "webSockets.remove(ws)"; } }); set(ws, "onOpen", new Runnable() { public void run() { try { AutoCloseable __6 = enter(); try { String uri = (String) (rcall("getUri", ws)); Map params = (Map) (rcall("getParms", ws)); print("WebSocket opened! uri: " + uri + ", params: " + params); WebSocketInfo info = new WebSocketInfo(); info.uri = uri; info.params = params; webSockets.put(ws, info); long objectID = toLong(params.get("objectID")); long modified = toLong(params.get("modified")); if (objectID != 0) { UserPost c = getConceptOpt(UserPost.class, objectID); print("Modification: " + c.xmodified + " / " + c._modified + " / " + modified); if (c != null && c.xmodified > modified) reloadBody(ws); } } finally { _close(__6); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); \r\n String uri = (String) (rcall getUri(ws));\r\n Map..."; } }); setFieldToIVF1Proxy(ws, "onMessage", msg -> { AutoCloseable __7 = enter(); try { try { WebSocketInfo info = webSockets.get(ws); if (info == null) return; String data = rcall_string("getTextPayload", msg); Map map = jsonDecodeMap(data); Object div = map.get("liveDiv"); if (div instanceof String) { String contentDesc = ((String) div); syncAdd(info.liveDivs, pair(((String) div), (Object) contentDesc)); reloadDiv(ws, ((String) div), calcDivContent(contentDesc)); } } catch (Throwable __e) { _handleException(__e); } } finally { _close(__7); } }); } public String serveRegisterForm(Map params) { String user = trim(params.get("user")); String pw = trim(params.get("f_pw")); String pw2 = trim(params.get("pw2")); String redirect = params.get("redirect"); String contact = trim(params.get("contact")); redirect = dropParamFromURL(redirect, "logout"); if (empty(redirect)) redirect = baseLink + "/"; List msgs = new ArrayList(); if (nempty(user) || nempty(pw)) { Lock __1 = dbLock(); lock(__1); try { if (empty(user)) msgs.add("Please enter a user name"); else if (l(user) < 4) msgs.add("Minimum user name length: 4 characters"); else if (l(user) > 30) msgs.add("Maximum user name length: 30 characters"); else if (hasConceptIC(User.class, "name", user)) msgs.add("This user exists, please choose a different name"); if (regexpContainsIC("[^a-z0-9\\-\\.]", user)) msgs.add("Bad characters in user name (please use only a-z, 0-9, - and .)"); if (empty(pw)) msgs.add("Please enter a password"); else if (l(pw) < 6) msgs.add("Minimum password length: 6 characters"); if (neq(pw, pw2)) msgs.add("Passwords don't match"); if (empty(msgs)) { cnew(User.class, "name", user, "passwordMD5", new SecretValue(hashPW(pw)), "contact", contact); return hrefresh(5.0, redirect) + "User " + user + " created! Redirecting..."; } } finally { unlock(__1); } } return hhtml(hhead(htitle("Register new user") + hsansserif() + hmobilefix() + hresponstable()) + hbody(hfullcenter(h3_htmlEncode(adminName + " | Register new user") + hpostform(hhidden("redirect", redirect) + tag("table", (empty(msgs) ? "" : tr(td() + td() + td(htmlEncode2_nlToBr(lines_rtrim(msgs))))) + tr(td_valignTop("Choose a user name:") + td_valignTop(hinputfield("user", user) + "
" + "(Minimum length 4. Characters allowed: a-z, 0-9, - and .)")) + tr(td_valignTop("Choose a password:") + td_valignTop(hpassword("f_pw", pw) + "
" + "(Minimum length 6 characters)")) + tr(td_valignTop("Repeat the password please:") + td(hpassword("pw2", pw2))) + tr(td_valignTop("Way to contact you (e.g. e-mail) - optional:") + td(hinputfield("contact", contact))) + tr(td() + td(hsubmit("Register"))), "class", "responstable"), "action", baseLink + "/register")))); } public boolean calcMasterAuthed(Req req) { return super.calcMasterAuthed(req) || req.auth != null && req.auth.user.has() && req.auth.user.get().isMaster; } public Object serveOtherPage(Req req) { String uri = req.uri; Matches m = new Matches(); if (eq(uri, "/register")) return serveRegisterForm(req.params); if (eq(uri, "/becomeMaster") && req.auth != null && req.auth.user != null) { String pw = trim(req.params.get("masterPW")); if (eq(pw, realPW())) { cset(req.auth.user, "isMaster", true); return "You are master, " + req.auth.user + "!"; } if (nempty(pw)) return "Bad master PW"; return hhtml(hhead(htitle("Become master") + hsansserif() + hmobilefix() + hresponstable()) + hbody(hfullcenter(h3_htmlEncode(adminName + " | Become master") + hpostform(tag("table", tr(td_valignTop("You are:") + td_valignTop(htmlEncode2(req.auth.user.get().name))) + tr(td_valignTop("Enter the master password:") + td_valignTop(hpassword("masterPW", pw))) + tr(td() + td(hsubmit("Become master user"))), "class", "responstable"), "action", baseLink + "/becomeMaster")))); } if (swic(uri, "/text/", m)) { long id = parseLong(m.rest()); UserPost post = getConceptOpt(UserPost.class, id); if (post == null) return serve404("Post with ID " + id + " not found"); if (!post.isPublic) return serve404("Post is not public"); String ct = req.params.get("ct"); Object response = nempty(ct) ? serveWithContentType(post.text(), ct) : serveText(post.text()); if (eq(ct, "text/javascript")) addHeader("Service-Worker-Allowed", "/", response); return response; } if (swic(uri, "/postRefs/", m)) { long id = parseLong(m.rest()); UserPost post = getConceptOpt(UserPost.class, id); if (post == null) return serve404("Post with ID " + id + " not found"); if (!post.isPublic) return serve404("Post is not public"); return serveJSON(lmap(__57 -> conceptID(__57), post.postRefs)); } if (swic(uri, "/postRefsWithTags/", m)) { long id = parseLong(m.rest()); UserPost post = getConceptOpt(UserPost.class, id); if (post == null) return serve404("Post with ID " + id + " not found"); if (!post.isPublic) return serve404("Post is not public"); return serveJSON(map(post.postRefsWithTags(), p -> litorderedmap("id", conceptID(p.a), "as", p.b))); } String uri2 = dropSlashPrefix(uri); if (isInteger(uri2)) { long id = parseLong(uri2); { Object __4 = serveIntegerLink(req, id); if (__4 != null) return __4; } } { Object __5 = serveOtherPage2(req); if (__5 != null) return __5; } return super.serveOtherPage(req); } static public boolean _switchableField_bot_maxPollSeconds = true; public double bot_maxPollSeconds = 600; static public boolean _switchableField_bot_pollInterval = true; public int bot_pollInterval = 500; public Object serveOtherPage2(Req req) { Matches m = new Matches(); String uri = dropTrailingSlashIfNemptyAfterwards(req.uri); if (eq(uri, "/admin")) return hrefresh(baseLink + "/crud/Sequence"); if (eq(uri, "/latestPost")) { UserPost post = highestConceptByField(UserPost.class, "created"); if (post == null) return serve404("No posts in database"); return servePost(post, req); } if (eq(uri, "/latestModifiedPost")) { UserPost post = highestConceptByField(UserPost.class, "_modified"); if (post == null) return serve404("No posts in database"); return servePost(post, req); } if (eq(uri, "/rootPosts")) { Collection posts = sortedByConceptIDDesc(filter(list(UserPost.class), post -> empty(post.postRefs))); framer().navBeforeTitle = true; framer().title = "Root Posts"; framer().add(ul(lmap(__94 -> postToHTMLWithDate(__94), posts))); return framer().render(); } if (eq(uri, "/allPosts")) { Collection posts = sortedByConceptIDDesc(list(UserPost.class)); framer().navBeforeTitle = true; framer().title = "All Posts"; framer().add(ul(lmap(__95 -> postToHTMLWithDate(__95), posts))); return framer().render(); } if (eq(uri, "/latestPosts")) { Collection posts = takeFirst(50, sortedByConceptIDDesc(list(UserPost.class))); framer().navBeforeTitle = true; framer().title = "Latest Posts & Replies"; framer().add(ul(lmap(__96 -> postToHTMLWithDate(__96), posts))); return framer().render(); } if (eq(uri, "/latestModifiedPosts")) { Collection posts = takeFirst(50, sortedByFieldDesc("_modified", list(UserPost.class))); framer().navBeforeTitle = true; framer().title = "Latest Modified Posts & Replies"; framer().add(ul(lmap(__97 -> postToHTMLWithDate(__97), posts))); return framer().render(); } if (eq(uri, "/mainPosts")) { Collection posts = takeFirst(50, sortedByConceptID(conceptsWhereCI(UserPost.class, "type", "Main"))); framer().navBeforeTitle = true; framer().title = "Main Posts"; framer().add(ul(lmap(__98 -> postToHTMLWithDate(__98), posts))); return framer().render(); } if (swic(uri, "/html/", m) && isInteger(m.rest())) { long id = parseLong(m.rest()); return serveHTMLPost(id); } if (swic(uri, "/htmlEmbedded/", m) && isInteger(m.rest())) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); HTMLFramer1 framer = framer(); framer.title = "[" + post.id + "] " + or2(post.title, shorten(post.text)); framer.add(hcomment("Post begins here") + "\n" + post.text + "\n" + hcomment("Post ends here")); return framer.render(); } if (swic(uri, "/css/", m) && isInteger(m.rest())) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); return serveWithContentType(post.text, "text/css"); } if (eq(uri, "/search")) { framer().navBeforeTitle = true; String q = trim(req.params.get("q")); framer().title = joinNemptiesWithColon("Search", q); framer().add(hcomment("cookie: " + req.webRequest.cookie())); framer().add(hform(hinputfield("q", q, "autofocus", true) + " " + hsubmit("Search"))); framer().add(p(small("Search help: If you search for multiple words, they can appear in any order in the text. An underscore matches any character. Plus means space. Post titles, texts and types are searched."))); if (nempty(q)) { ScoredSearcher searcher = new ScoredSearcher<>(q); long id = parseLongOpt_pcall(q); for (UserPost post : list(UserPost.class)) searcher.add(post, (post.id == id ? 4 : 0) + searcher.score(post.title) * 3 + searcher.score(post.text) * 2 + searcher.score(post.type) + searcher.score(joinWithSpace(post.postRefTags)) * 0.5); List posts = searcher.get(); framer().add(p(b(addPlusToCount(searcher.maxResults, l(posts), nPosts(posts)) + " found for " + htmlEncode2(q)))); framer().add(ul(lmap(__99 -> postToHTMLWithDate(__99), posts))); } return framer().render(); } if (eq(uri, "/jstree/replies")) { UserPost post = getConcept(UserPost.class, parseLong(req.params.get("post"))); if (post == null) return serveJSON(ll()); Collection refs = referencingPosts(post); return serveJSON(map(refs, p -> litorderedmap("id", p.id, "text", postToHTMLWithDate(post), "children", nempty(referencingPosts(p)) ? true : null, "type", "root"))); } if (startsWith(uri, "/touchPost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); if (!canEditPost(post)) return "You are not authorized to do this"; touchConcept(post); return hscript("setTimeout('history.go(-1)', 1000);") + "Post " + post.id + " touched"; } if (startsWith(uri, "/hidePost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); if (!canEditPost(post)) return "You are not authorized to do this"; cset(post, "hidden", true); return hrefresh(postLink(post)); } if (startsWith(uri, "/unhidePost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); if (!canEditPost(post)) return "You are not authorized to do this"; cset(post, "hidden", false); return hrefresh(postLink(post)); } if (startsWith(uri, "/markSafe/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); UserPost codePost = optCast(UserPost.class, first(post.postRefs)); if (codePost == null) return "Code post not found"; if (!canEditPost(codePost)) return "You are not authorized to do this"; uniqCI(UserPost.class, "creator", currentUser(), "text", "Mark safe", "postRefs", ll(post)); sleepSeconds(6); touchConcept(codePost); return hrefresh(postLink(codePost)); } if (eq(uri, "/mirrorAllConversations")) { if (!req.masterAuthed) return serveAuthForm(rawLink(uri)); for (Conversation c : list(Conversation.class)) rstUpdateMirrorPosts.add(c); return "OK"; } if (startsWith(uri, "/mirrorConversation/", m)) { if (!req.masterAuthed) return serveAuthForm(rawLink(uri)); long id = parseLong(m.rest()); Conversation conv = getConcept(Conversation.class, id); if (conv == null) return "Conversation not found"; conv.updateMirrorPost(); return "Mirror post updated (" + htmlEncode2(str(conv.mirrorPost.get())) + ")"; } if (eqic(uri, "/favicon.ico")) return serveFavIcon(); if (startsWith(uri, "/bot/")) { String json = req.params.get("json"); Map data = new HashMap(); if (nempty(json)) data = jsonDecodeMap(json); data.putAll(withoutKey("json", req.params)); String userName = (String) (data.get("_user")); if (userName == null) return serveJSON("error", "Need _user"); String botToken = (String) (data.get("_botToken")); if (botToken == null) return serveJSON("error", "Need _botToken"); User user = conceptWhereIC(User.class, "name", userName); if (user == null) return serveJSON("error", "User not found"); if (!eq(botToken, getVar(user.botToken))) return serveJSON("error", "Wrong bot token"); req.webRequest.noSpam(); String function = dropPrefix("/bot/", uri); if (eq(function, "authTest")) return serveJSON("status", "You are authorized as " + user.name); if (eq(function, "postCount")) return serveJSON("result", countConcepts(UserPost.class)); if (eq(function, "listPosts")) { List fields = unnull(stringToStringListOpt(__115 -> tok_identifiersInOrder(__115), data.get("fields"))); if (!fields.contains("id")) fields.add(0, "id"); long changedAfter = toLong(data.get("changedAfter")); long repliesTo = toLong(data.get("repliesTo")); double pollFor = min(bot_maxPollSeconds, toLong(data.get("pollFor"))); long startTime = sysNow(); if (changedAfter > 0 && changedAfter == now()) sleep(1); Collection posts; while (true) { if (repliesTo != 0) { posts = referencingPosts(getConcept(UserPost.class, repliesTo)); if (changedAfter != 0) posts = objectsWhereFieldGreaterThan(posts, "_modified", changedAfter); } else { posts = changedAfter == 0 ? list(UserPost.class) : conceptsWithFieldGreaterThan_sorted(UserPost.class, "_modified", changedAfter); } if (nempty(posts) || pollFor == 0 || elapsedSeconds_sysNow(startTime) >= pollFor) return serveJSON_breakAtLevels(2, "result", map(posts, post -> mapToValues(fields, field -> getPostFieldForBot(post, field)))); sleep(bot_pollInterval); } } if (eq(function, "createPost")) { Either e = createPostArgs(user, data); if (e.isB()) return serveJSON("error", e.b()); Pair post = uniq2(UserPost.class, e.a()); if (!post.b) post.a.bump(); return serveJSON("status", post.b ? "Post created" : "Post existed already, bumped", "postID", post.a.id); } if (eq(function, "editPost")) { long postID = toLong(data.get("postID")); UserPost post = getConcept(UserPost.class, postID); if (post == null) return serveJSON("error", "Post " + postID + " not found"); Either e = createPostArgs(user, data); if (e.isB()) return serveJSON("error", e.b()); int changes = cset(post, e.a()); return serveJSON(changes > 0 ? "Post updated" : "Post updated, no changes", "postID", postID); } if (eq(function, "deletePosts")) { List ids = allToLong(tok_integersInOrder((String) data.get("ids"))); List results = new ArrayList(); List errors = new ArrayList(); for (long id : unnull(ids)) { UserPost post = getConceptOpt(UserPost.class, id); if (post == null) errors.add("Post " + id + " not found"); else { if (!user.isMaster && neq(post.creator.get(), user)) errors.add("Can't delete post " + id + " from other user"); else { deletePost(post); results.add("Post " + id + " deleted"); } } } return serveJSON(litorderedmap("results", results, "errors", errors)); } return serveBotFunction(req, function, data, user); } if (teamPostID != 0 && eq(uri, "/team")) return serveHTMLPost(teamPostID); if (startsWith(uri, "/history/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); return servePostHistory(post); } if (startsWith(uri, "/htmlBot/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); return loadPage(htmlBotURLOnBotServer(id)); } if (eq(uri, "/deletedPosts")) { CloseableIterableIterator lines = linesFromFile(deletedPostsFile()); try { List posts = new ArrayList(); while (lines.hasNext()) { String line = lines.next(); if (isProperlyQuoted(line)) { Map map = safeUnstructureMap(unquote(line)); posts.add(onlyKeys(map, "id", "title", "type")); } } return serveText("Deleted posts:\n" + lines(lmap(__100 -> struct(__100), posts))); } finally { _close(lines); } } if (eq(uri, "/formToPost")) { User user = currentUser(); if (user == null) serve500("Please log in first"); Map params = cloneMap(req.params); String type = or2(getAndRemove(params, "_type"), "Form Input"); String title = getAndRemove(params, "_title"); List postRefs = map(id -> getConceptOpt(UserPost.class, parseLong(id)), tok_integersInOrder(getAndRemove(params, "_postRefs"))); List postRefTags = lines(getAndRemove(params, "_postRefTags")); String text = sortLinesAlphaNumIC(mapToLines(params, (k, v) -> urlencode(k) + "=" + urlencode(v))); Pair p = uniq2(UserPost.class, "creator", user, "text", text, "type", type, "title", title, "postRefs", postRefs, "postRefTags", postRefTags); return (p.b ? "Post " + p.a.id + " created" : "Post " + p.a.id + " exists") + hrefresh(2.0, "/" + p.a.id); } if (eq(uri, "/webPushSubscribe")) { Map data = jsonDecodeMap(mapGet(req.webRequest.files(), "postData")); printVars_str("webPushSubscribe", "data", data); cnew(WebPushSubscription.class, "data", data, "clientIP", req.webRequest.clientIP()); return serveJSON(litmap("message", "success")); } if (eq(uri, "/webPushNotify")) { if (!req.masterAuthed) return serveAuthForm(rawLink(uri)); String msg = or2(req.params.get("msg"), "Hello user. It is " + localTimeWithSeconds() + " on the server"); WebPushSubscription sub = getConcept(WebPushSubscription.class, toLong(req.params.get("webPushSubID"))); if (sub == null) return serve404("webPushSubID not found"); String mod = dm_require("#1030463/WebPushKeyManager"); dm_call(mod, "sendNotification", sub.data, msg); return "Push message sent"; } if (eq(uri, "/hashPW") && req.masterAuthed) return hashPW(req.params.get("pw")); return null; } public Object servePostHistory(UserPost post) { return serveText(unquoteAllLines(loadTextFile(postHistoryFile(post)))); } public Either createPostArgs(User user, Map data) { String text = (String) (data.get("text")); String type = (String) (data.get("type")); String title = (String) (data.get("title")); String botInfo = or2((String) data.get("botInfo"), "Made by bot"); List postRefTags = unnull(lines((String) data.get("refTags"))); List postRefs = new ArrayList(); Object _refs = data.get("refs"); if (_refs instanceof String) for (String s : tok_integersInOrder(((String) _refs))) { UserPost ref = getConcept(UserPost.class, parseLong(s)); if (ref == null) return eitherB("Post " + s + " not found"); postRefs.add(ref); } if (empty(text) && empty(title)) return eitherB("Need either a text or a title"); boolean isPublic = eqOneOf(data.get("isPublic"), null, true, "1", "t", "true"); return eitherA(litparams("creator", user, "text", text, "type", type, "title", title, "isPublic", isPublic, "botInfo", botInfo, "postRefs", postRefs, "postRefTags", postRefTags)); } public Object serveBotFunction(Req req, String function, Map data, User user) { return serveJSON("error", "You are logged in correctly but function is unknown: " + function); } public Object servePost(UserPost post, Req req) { if (!post.isPublic) return serve404("Post is not public"); HTMLFramer1 framer = framer(); framer.add(hjs("webSocketQuery = " + jsQuote("?objectID=" + post.id + "&modified=" + post.xmodified) + ";\n" + "if (ws != null) ws.url = ws.url.split(\"?\")[0] + webSocketQuery;")); framer.title = "[" + post.id + "] " + or2(post.title, shorten(post.text)); framer.add(p("By " + htmlEncode2(post.author()) + ". " + renderConceptDate(post))); if (nempty(post.type)) framer.add(p("Post type: " + htmlEncode2(post.type))); List actions = new ArrayList(); if (eqic(post.type, "HTML")) actions.add(targetBlank("/html/" + post.id, "Show as HTML page")); if (eqic(post.type, "HTML (embedded)")) actions.add(targetBlank("/htmlEmbedded/" + post.id, "Show as HTML page")); if (eqicOneOf(post.type, "JavaX Code (HTML Bot)", "JavaX Code (Live Home Page)")) actions.add(targetBlank(htmlBotURL(post.id), "Show as HTML page")); if (eqic(post.type, "Conversation HTML")) actions.add(targetBlank("/demo?cookie=htmlDemo&_autoOpenBot=1&chatContentsPost=" + post.id, "Show in chat box")); if (canEditPost(post)) { actions.add(ahref(conceptEditLink(post), "Edit post")); actions.add(ahref(touchLink(post), "Touch post")); actions.add(post.hidden ? ahref(unhideLink(post), "Unhide post") : ahref(hideLink(post), "Hide post")); } actions.add(ahref(replyLink(post), "Reply")); actions.add(ahref(conceptDuplicateLink(post), "Duplicate")); actions.add(ahref(conceptEditLink(post, "onlyFields", "title"), "Rename")); if (postHasHistory(post)) actions.add(ahref("/history/" + post.id, "History")); actions.add(ahref(baseLink + "/text/" + post.id, "Raw Text")); if (post.isJavaXCode()) { actions.add(targetBlank(simulateBotLink(post), "Talk to this bot")); actions.add(ahref(gazelleBotURL + "/transpilation/" + post.id, "Show Java transpilation")); } framer.add(p_vbar(actions)); List postRefs = cloneList(post.postRefs); if (nempty(postRefs)) { framer.add(p("In reference to:")); List> l = post.postRefsWithTags(); framer.add(ul(mapPairsToList(l, (ref, as) -> htmlEncode2(as) + " " + objectToHTML(ref)))); } String text = post.text; String html = null; if (post.isJavaXCode()) { try { JavaXHyperlinker hl = new JavaXHyperlinker(); hl.targetBlank = true; html = hl.codeToHTML(text); } catch (Throwable __e) { _handleException(__e); } } if (html == null) html = htmlEncodeWithLinking(post.text); if (eq(req.params.get("showLineFeeds"), "1")) html = html_showLineFeedsForPRE(html); framer.add(div(sourceCodeToHTML_noEncode(html), "style", hstyle_sourceCodeLikeInRepo())); Collection refs = referencingPosts(post); refs = reversed(refs); Pair, List> p = filterAntiFilter(refs, post2 -> !post2.hidden); if (nempty(p.a)) { framer.add(p("Referenced by posts (latest first):")); UserPost latestCodeSafetyPost = highestBy(p2 -> p2.modifiedOrBumped(), filter(p.a, p2 -> eqic(p2.botInfo, "Code Safety Checker"))); framer.add(ul(map(p.a, p2 -> { String html2 = htmlEncode2(squareBracketIfNempty(getPostRefTag(p2, post))) + " " + objectToHTML(p2); if (p2 == latestCodeSafetyPost && cic(p2.text, "Unknown identifiers:")) html2 += " " + hbuttonLink("/markSafe/" + p2.id, htmlEncode2("Mark safe")); return html2; }))); } if (nempty(p.b)) { framer.add(p("Referenced by hidden posts:")); framer.add(ul(map(p.b, p2 -> htmlEncode2(squareBracketIfNempty(getPostRefTag(p2, post))) + " " + objectToHTML(p2)))); } if (showPostStats) { String stats = nLines(countLines(post.text)) + ", distance to user post: " + post.distanceToUserPost(); framer.add(p_alignRight(small(span_title(stats, "Post stats")))); } return framer.render(); } public String getPostRefTag(UserPost a, UserPost b) { return get(a.postRefTags, indexOf(a.postRefs, b)); } public String htmlEncodeWithLinking(String text) { String html = htmlEncode2(text); return regexpReplace(html, gazelle_postMentionRegexp(), matcher -> { UserPost post = getConceptOpt(UserPost.class, parseLong(matcher.group(1))); return post == null ? matcher.group() : ahref(postLink(post), matcher.group()); }); } public List referencingPosts(UserPost post) { return sortedByCalculatedField(p -> p.modifiedOrBumped(), instancesOf(UserPost.class, allBackRefs(post))); } public List referencingPostsWithTag(UserPost post, String tag) { return filter(referencingPosts(post), p -> eqic_unnull(getPostRefTag(p, post), tag)); } public String serveAuthForm(String redirect) { return hAddToHead(super.serveAuthForm(redirect), hInitWebSocket()); } public String authFormMoreContent() { return navDiv(); } public String navDiv() { return div_vbar(navLinks(), "style", "margin-bottom: 0.5em"); } public Object handleAuth(Req req, String cookie) { String name = trim(req.params.get("user")), pw = trim(req.params.get("pw")); if (nempty(name) && nempty(pw) && nempty(cookie)) { Domain authDomain; User user = conceptWhereCI(User.class, "name", name); if (user == null) return errorMsg("User " + htmlEncode2(name) + " not found"); if (!eq(getVar(user.passwordMD5), hashPW(pw))) return errorMsg("Bad password, please try again"); cset(uniq(AuthedDialogID.class, "cookie", cookie), "restrictedToDomain", null, "master", user.isMaster, "user", user); String redirect = req.params.get("redirect"); if (nempty(redirect)) return hrefresh(redirect); } return null; } public Object serve2(Req req) { if (req.auth != null) cset(req.auth, "userMode", false); return super.serve2(req); } public String hashPW(String pw) { return md5(pw + passwordSalt()); } public boolean inMasterMode(Req req) { return req.masterAuthed && !req.auth.userMode; } public Map filtersForClass(Class c, Req req) { if (c == UserPost.class) { if (req.auth != null && !inMasterMode(req)) return litmap("creator", req.auth.user.get()); } return super.filtersForClass(c, req); } public String loggedInUserDesc(Req req) { return req.auth == null ? "not logged in" : req.auth.user.get() == null ? (req.masterAuthed ? "master user" : "weird user") : "user " + req.auth.user.get().name; } public
HCRUD_Concepts crudData(Class c, Req req) { HCRUD_Concepts cc = super.crudData(c, req); if (c == UserPost.class) { cc.useDynamicComboBoxes = true; cc.lsMagic = true; cc.itemName = () -> "Post"; cc.dropEmptyListValues = false; if (eq(req.params.get("noace"), "1")) cc.addRenderer("text", new HCRUD_Data.TextArea(80, 20)); else cc.addRenderer("text", new HCRUD_Data.AceEditor(80, 20)); cc.addRenderer("postRefTags", new HCRUD_Data.FlexibleLengthList(new HCRUD_Data.TextField(20))); cc.addRenderer("type", new HCRUD_Data.ComboBox(true, itemPlus("", userPostTypesByPopularity()))); cc.fieldHelp("type", "Type of post (any format, optional)", "title", "Title for this post (any format, optional)", "text", "Text contents of this post (any format)", "nameInRepo", "Name in repository (not really used yet)", "botInfo", "Info on which bot made this post (if any)"); cc.massageItemMapForList = (item, map) -> { applyFunctionToValue(__101 -> shorten(__101), map, "text", "title", "type", "nameInRepo"); List refs = ((UserPost) item).postRefs; map.put("postRefs", new HTML(joinWithBR(lmap(__58 -> objectToHTML(__58), refs)))); }; cc.getObject = id -> { Map map = cc.getObject_base(id); List refs = (List) (map.get("postRefs")); List tags = (List) (map.get("postRefTags")); print("counts:" + l(refs) + "/" + l(tags)); map.put("postRefTags", padList(tags, l(refs), "")); return map; }; cc.emptyObject = () -> { Map item = cc.emptyObject_base(); item.put("creator", req.auth.user.get()); return item; }; cc.getObjectForDuplication = id -> { Map item = cc.getObjectForDuplication_base(id); item.put("creator", req.auth.user.get()); UserPost post = getConcept(UserPost.class, toLong(id)); List postRefs = cloneList((List) item.get("postRefs")); List tags = cloneList((List) item.get("postRefTags")); for (int i = 0; i < l(tags); i++) if (eqic(tags.get(i), "created from")) { remove(postRefs, i); tags.remove(i--); } int idx = l(postRefs); postRefs.add(post); listSet(tags, idx, "created from"); item.put("postRefs", postRefs); item.put("postRefTags", tags); print("tags", tags); return item; }; cc.fieldsToHideInCreationForm = litset("hidden", "creating"); cc.lockDB = true; cc.afterUpdate = (post, oldValues) -> { Map newValues = cgetAll_cloneLists(post, keys(oldValues)); for (Map.Entry __0 : _entrySet(newValues)) { String field = __0.getKey(); Object newVal = __0.getValue(); Object oldVal = oldValues.get(field); if (eq(oldVal, newVal)) { printVars_str("field", field, "oldVal", oldVal); continue; } IF1 f = o -> o instanceof Concept ? ((Concept) o).id : null; Object oldValForLog = defaultMetaTransformer().transform(f, oldVal); Object newValForLog = defaultMetaTransformer().transform(f, newVal); Map logEntry = litorderedmap("date", now(), "field", field, "oldVal", oldValForLog, "newVal", newValForLog); printStruct("logEntry", logEntry); logStructure(postHistoryFile(((UserPost) post)), logEntry); } }; cc.actuallyDeleteConcept = post -> deletePost(((UserPost) post)); } return cc; } public HCRUD makeCRUD(Class c, Req req) { HCRUD crud = super.makeCRUD(c, req); if (c == UserPost.class) { crud.refreshAfterCommand = (params, msgs) -> { UserPost post = getConcept(UserPost.class, toLong(crud.objectIDToHighlight)); return post != null ? hrefresh(postLink(post)) : crud.refreshAfterCommand_base(params, msgs); }; crud.renderCmds = map -> { UserPost post = getConcept(UserPost.class, toLong(crud.itemID(map))); return joinNemptiesWithVBar(crud.renderCmds_base(map), ahref(postLink(post), "Show post"), ahref(touchLink(post), "Touch", "title", "Mark post as modified so it is looked at by bots again")); }; crud.uneditableFields = litset("xmodified", "creating", "bumped"); if (showSuggestorBot) crud.moreSelectizeOptions = name -> ", onChange: function() { console.log(\"selectize onChange\"); sugTrigger(); }"; crud.showQuickSaveButton = true; crud.massageFormMatrix = (map, matrix) -> { int idx1 = indexOfPred(matrix, row -> cic(first(row), "Post Refs")); int idx2 = indexOfPred(matrix, row -> cic(first(row), "Post Ref Tags")); if (idx1 < 0 || idx2 < 0) return; List row1 = matrix.get(idx1), row2 = matrix.get(idx2); row1.set(1, hcrud_mergeTables(row1.get(1), row2.get(1), "as")); matrix.remove(idx2); if (showSuggestorBot) { List entries = ((HCRUD_Concepts) crud.data).comboBoxItems(conceptsWhereIC(UserPost.class, "type", "JavaX Code (Post Edit Suggestor)")); String js = hscript(replaceVars("\r\n const suggestorSelector = $(\"[name=suggestorID]\");\r\n var sugLoading = false, sugTriggerAgain = false;\r\n\r\n function sugTrigger() {\r\n //console.log(\"sugTrigger\");\r\n if (sugLoading) { sugTriggerAgain = true; return; }\r\n\r\n const sugText = suggestorSelector.text();\r\n //console.log(\"sugText=\" + sugText);\r\n const sugMatch = sugText.match(/\\d+/);\r\n if (!sugMatch) {\r\n //$(\"#suggestorResult\").html(\"\");\r\n $(\"#suggestorResult\").hide();\r\n return;\r\n }\r\n const suggestorID = sugMatch[0];\r\n\r\n // get form data as JSON\r\n \r\n var data = {};\r\n $(suggestorSelector).closest(\"form\").serializeArray().map(function(x){data[x.name] = x.value;});\r\n const json = JSON.stringify(data);\r\n console.log(\"JSON: \" + json);\r\n \r\n const url = \"" + gazelleBotURL + "/chatBotReply/\" + suggestorID;\r\n console.log(\"Loading \" + url);\r\n sugLoading = true;\r\n $.post(url, {q : json},\r\n function(result) {\r\n console.log(\"Suggestor result: \" + result);\r\n const answer = !result ? \"\" : JSON.parse(result).answer;\r\n if (answer) {\r\n $(\"#suggestorResult .sectionContents\").html(answer);\r\n $(\"#suggestorResult\").show();\r\n } else\r\n $(\"#suggestorResult\").hide();\r\n //$(\"#suggestorResult\").html(answer ? \"Suggestor says: \" + answer : \"\");\r\n }\r\n ).always(function() {\r\n console.log(\"sug loading done\");\r\n setTimeout(function() {\r\n sugLoading = false;\r\n if (sugTriggerAgain) { sugTriggerAgain = false; sugTrigger(); }\r\n }, delayAfterSuggestion);\r\n });\r\n }\r\n\r\n $(document).ready(function() {\r\n $(\"input[type=text], input[type=hidden], textarea, select\").on('input propertychange change', sugTrigger);\r\n sugTrigger();\r\n });\r\n suggestorSelector.change(sugTrigger);\r\n ", "delayAfterSuggestion", delayAfterSuggestion)); long defaultSuggestor = parseFirstLong(userDefaults(req.auth.user.get()).get("Default Suggestor Bot")); String selectedSuggestor = firstWhereFirstLongIs(entries, defaultSuggestor); matrix.add(0, ll("Suggestor Bot", crud.addHelpText("Choose a bot to assist you in editing this post [feature in development]", p_alignRight(crud.renderComboBox("suggestorID", selectedSuggestor, entries, false))) + htitledSectionWithDiv("Suggestion", "", "id", "suggestorResult", "style", "display: none", "innerDivStyle", "max-height: 150px; overflow: auto") + js)); } }; crud.flexibleLengthListLeeway = 3; } if (c == User.class) { crud.allowCreate = false; crud.uneditableFields = litset("passwordMD5"); } return crud; } public String authFormHeading() { return h3_htmlEncode("Welcome to the Gazelle AI System") + p(hsnippetimg_scaleToWidth(200, "#1101482", 425, 257, "title", "Gazelle")); } public void makeFramer(Req req) { super.makeFramer(req); req.framer.renderTitle = () -> h1(ahref(baseLink + "/", himgsnippet("#1102967", "style", "height: 1em; vertical-align: bottom", "title", "Gazelle.rocks Logo")) + " " + htmlEncode2(req.framer.title)); req.framer.add(navDiv()); if (showMetaBotOnEveryPage && !eq(req.params.get("_reloading"), "1")) req.framer.willRender.add(new Runnable() { public void run() { try { req.framer.add(hscript("var botConfig = \"codePost=" + defaultBotPost + "\"; ") + hjssrc(baseLink + "/script")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "req.framer.add(hscript(\"var botConfig = \\\"codePost=\" + defaultBotPost + \"\\\"; ..."; } }); } public HTMLFramer1 framer() { Req req = currentReq.get(); if (req.framer == null) makeFramer(req); return req.framer; } public String postLink(UserPost post) { return objectLink(post); } public String postLink(long postID) { return objectLink(getConcept(UserPost.class, postID)); } public String touchLink(UserPost post) { return baseLink + "/touchPost/" + post.id; } public String hideLink(UserPost post) { return baseLink + "/hidePost/" + post.id; } public String unhideLink(UserPost post) { return baseLink + "/unhidePost/" + post.id; } public String objectLink(Concept c) { return baseLink + "/" + c.id; } public String objectToHTML(Concept c) { return c == null ? "-" : ahref(objectLink(c), htmlEncode2(str(c))); } public String postToHTMLWithDate(UserPost post) { return post == null ? "" : objectToHTML(post) + " " + span(htmlEncode2(renderHowLongAgoPlusModified(post.created, post._modified)), "style", "color: #888"); } public boolean canEditPost(UserPost post) { User user = currentUser(); return user != null && (user.isMaster || user == post.creator.get()); } public User currentUser() { Req req = currentReq.get(); return req != null && req.auth != null ? req.auth.user.get() : null; } public String replyLink(UserPost post) { return appendQueryToURL(crudLink(UserPost.class), "cmd", "new", "fList_postRefs_0", post == null ? null : post.id); } public String newPostLink() { return replyLink(null); } public List navLinks(Object... __) { return gazelle_navLinks(baseLink, inlineSearch && !eq(currentReq.get().uri, "/search") ? "" : null, paramsPlus(__, "withTeam", teamPostID != 0)); } public List botCmdClasses() { return ll(); } public List crudClasses(Req req) { List l = super.crudClasses(req); l = listMinusSet(l, hiddenCrudClasses()); l.add(UserPost.class); l.add(UploadedImage.class); if (req.masterAuthed) { l.add(User.class); if (webPushEnabled) l.add(WebPushSubscription.class); } return l; } public Set hiddenCrudClasses() { return litset(Lead.class, ConversationFeedback.class, Domain.class, UserKeyword.class, UploadedSound.class, Settings.class); } public Object getPostFieldForBot(UserPost post, String field) { if (eq(field, "creatorID")) return post.creator.get().id; if (eq(field, "creatorName")) return post.creator.get().name; if (eq(field, "creatorIsMaster")) return post.creator.get().isMaster; if (eq(field, "postRefs")) return lmap(__59 -> conceptID(__59), post.postRefs); return cget(post, field); } public void deletePost(UserPost post) { if (post == null) return; print("Deleting post " + post); Lock __2 = dbLock(); lock(__2); try { long filePos = l(deletedPostsFile()); logStructure(deletedPostsFile(), mapToValues(UserPost.fieldsToSaveOnDelete, field -> getPostFieldForBot(post, field))); for (Pair p : post.postRefsWithTags()) if (p.a instanceof UserPost) logStructure(deletedRepliesFile((UserPost) p.a), litorderedmap("tag", p.b, "id", post.id, "filePos", filePos, "type", post.type)); cdelete(post); } finally { unlock(__2); } } public File deletedPostsFile() { return programFile("deleted-posts.log"); } public Object serveHTMLPost(long id) { UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post " + id + " not found"); return post.text; } transient public ReliableSingleThread_Multi rstDistributePostChanges = new ReliableSingleThread_Multi<>(1000, __10 -> distributePostChanges_impl(__10)); public void distributePostChanges(UserPost post) { rstDistributePostChanges.add(post); } public void distributePostChanges_impl(UserPost post) { AutoCloseable __8 = enter(); try { String uri = "/" + post.id; for (Pair p : syncMapToPairs(webSockets)) { if (eq(p.b.uri, uri)) reloadBody(p.a); } if (eqic(post.type, "Line Labels")) { UserPost parent = post.primaryRefPost(); print("Line labels post " + post.id + ", parent=" + parent); updateLineLabels(parent); } } finally { _close(__8); } } public void updateLineLabels(UserPost post) { try { if (post == null || !eqic(post.type, "Detailed Conversation Mirror")) return; print("Looking at conversation mirror " + post.id + " - " + post.title); long convID = toLong(regexpFirstGroupIC("Conversation (\\d+) with details", post.title)); Conversation conv = getConcept(Conversation.class, convID); if (conv == null) return; print("updateLineLabels " + convID + " / " + post.id); MultiMap, String> labels = new MultiMap(); for (UserPost p : referencingPostsWithTag(post, "")) if (eqic(p.type, "Line Labels")) { try { Map map = safeUnstructMapAllowingClasses(p.text(), Pair.class); print("Got labels map: " + map); putAll(labels, map); } catch (Throwable __e) { _handleException(__e); } } boolean change = false; for (Msg msg : cloneList(conv.msgs)) { List lbls = uniquifyAndSortAlphaNum(allToUpper(labels.get(pair(msg.time, msg.text)))); if (nempty(lbls)) print("Got labels: " + lbls); if (!eq(msg.labels, lbls)) { msg.labels = lbls; change = true; } } if (change) conv.incReloadCounter(); } catch (Throwable __e) { _handleException(__e); } } public void reloadBody(Object ws) { print("Reloading body through WebSocket"); String jsCode = " {\r\n const loc = new URL(document.location);\r\n const params = new URLSearchParams(loc.search);\r\n params.set('_reloading', '1');\r\n loc.search = params;\r\n console.log(\"Getting: \" + loc);\r\n $.get(loc, function(html) {\r\n var bodyHtml = /([\\s\\S]*)<\\/body>/.exec(html)[1];\r\n if (bodyHtml) {\r\n //$(\"body\").html(bodyHtml);\r\n $('body > *:not(.chatbot)').remove();\r\n $(\"body\").prepend(bodyHtml);\r\n }\r\n });\r\n } "; dm_call(ws, "send", jsonEncode(litmap("eval", jsCode))); } transient public ReliableSingleThread_Multi rstDistributeDivChanges = new ReliableSingleThread_Multi<>(1000, __11 -> distributeDivChanges_impl(__11), new F0() { public AutoCloseable get() { try { return enter(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret enter();"; } }); public void distributeDivChanges(String contentDesc) { rstDistributeDivChanges.add(contentDesc); } public void distributeDivChanges_impl(String contentDesc) { AutoCloseable __9 = enter(); try { String content = null; for (Pair p : syncMapToPairs(webSockets)) { for (String div : asForPairsWithB(p.b.liveDivs, contentDesc)) { if (content == null) content = calcDivContent(contentDesc); if (content == null) { print("No content for " + contentDesc); return; } reloadDiv(p.a, div, content); } } } finally { _close(__9); } } public void reloadDiv(Object ws, String div, String content) { String jsCode = replaceDollarVars(" $(\"#\" + $div).html($content);", "div", jsQuote(div), "content", jsQuote(content)); dm_call(ws, "send", jsonEncode(litmap("eval", jsCode))); } public String calcDivContent(String contentDesc) { if (eq(contentDesc, "postCount")) return nPosts(countConcepts(UserPost.class)); if (eq(contentDesc, "webRequestsRightHemi")) return n2(requestsServed); if (eq(contentDesc, "serverLoadRightHemi")) return formatDoubleX(systemLoad, 1); if (eq(contentDesc, "memRightHemi")) return str_toM(processSize); return null; } public int countUserPosts() { return countConcepts(UserPost.class, "botInfo", null) + countConcepts(UserPost.class, "botInfo", ""); } public int countBotPosts() { return countConcepts(UserPost.class) - countUserPosts(); } public Collection allUserPosts() { return filter(list(UserPost.class), p -> !p.isBotPost()); } public List userPostTypesByPopularity() { return listToTopTenCI(map(allUserPosts(), p -> p.type)); } public void startMainScript(Conversation conv) { UserPost post = getConceptOpt(UserPost.class, parseLong(mapGet(conv.botConfig, "codePost"))); if (post != null) { CustomBotStep step = uniq(CustomBotStep.class, "codePostID", post.id); if (executeStep(step, conv)) nextStep(conv); } else super.startMainScript(conv); } public String simulateBotLink(UserPost post) { return appendQueryToURL(baseLink + "/demo", "_botConfig", makePostData("codePost", post.id), "_newConvCookie", 1, "_autoOpenBot", 1); } @Override public boolean isRequestFromBot(Req req) { return startsWith(req.uri, "/bot/"); } public User internalUser() { return uniqCI(User.class, "name", "internal"); } transient public ReliableSingleThread_Multi rstUpdateMirrorPosts = new ReliableSingleThread_Multi<>(100, c -> c.updateMirrorPost()); public File postHistoryFile(UserPost post) { return programFile("Post Histories/" + post.id + ".log"); } public boolean postHasHistory(UserPost post) { return fileNempty(postHistoryFile(post)); } public File deletedRepliesFile(UserPost post) { return programFile("Deleted Replies/" + post.id + ".log"); } public String makeClassNavItem(Class c, Req req) { String html = super.makeClassNavItem(c, req); if (c == UserPost.class) html += " " + roundBracket(n2(countUserPosts()) + " from users, " + n2(countBotPosts()) + " from bots"); return html; } @Override public String modifyTemplateBeforeDelivery(String html, Req req) { String contentsPostID = req.params.get("chatContentsPost"); if (nempty(contentsPostID)) { html = html.replace("#N#", "99999"); html = html.replace("chatBot_interval = 1000", "chatBot_interval = 3600*1000"); html = html.replace("#INCREMENTALURL#", baseLink + "/text/" + contentsPostID + "?"); } return html; } public String headingForReq(Req req) { String codePost = decodeHQuery(req.params.get("_botConfig")).get("codePost"); if (nempty(codePost)) { UserPost post = getConcept(UserPost.class, parseLong(codePost)); return post == null ? null : post.title; } return null; } public UserPost homePagePost() { return firstThat(p -> p.isMasterMade(), conceptsWhereIC(UserPost.class, "type", "JavaX Code (Live Home Page)")); } public String serveHomePage() { try { UserPost post = homePagePost(); if (post != null) return loadPage(htmlBotURLOnBotServer(post.id)); } catch (Throwable __e) { _handleException(__e); } return null; } public String htmlBotURL(long postID) { return baseLink + "/htmlBot/" + postID; } public String htmlBotURLOnBotServer(long postID) { return gazelleBotURL + "/htmlBot/" + postID; } public UserPost userDefaultsPost(User user) { return conceptWhereIC(UserPost.class, "creator", user, "type", "My Defaults"); } public Map userDefaults(User user) { UserPost post = userDefaultsPost(user); return post == null ? emptyMap() : parseColonPropertyCIMap(post.text); } public Object serveFavIcon() { if (favIconID != 0) { UploadedFile f = getConcept(UploadedFile.class, favIconID); if (f != null) return serveFile(f.theFile(), faviconMimeType()); return serve404(); } return serveFile(loadLibrary("#1400439"), faviconMimeType()); } public String cssURL() { return gazelle_textURL(parseLong(cssID)); } public String getText(long postID) { UserPost post = getConcept(UserPost.class, postID); return post == null ? null : post.text(); } @Override public void addThingsAboveCRUDTable(Req req, Class c, List aboveTable) { if (c == User.class) aboveTable.add(p(ahref(baseLink + "/register", "Register new user"))); } public User user(Req req) { if (req == null) return null; AuthedDialogID auth = req.auth; return auth == null ? null : auth.user(); } public Object serveIntegerLink(Req req, long id) { UserPost post = getConceptOpt(UserPost.class, id); if (post == null) return serve404("Post with ID " + id + " not found"); return servePost(post, req); } } static public class CustomBotStep extends BotStep implements IInputHandler { public long codePostID; public String toString() { return "CustomBotStep " + codePostID; } public boolean run(Conversation conv) { String answer; try { Map result = (Map) (postJSONPage(replyURL(), "initial", 1, "cookie", conv.cookie)); answer = (String) result.get("answer"); } catch (Throwable e) { _handleException(e); answer = "Error: " + e.getMessage(); } conv.add(new Msg(false, answer)); cset(conv, "inputHandler", this); return false; } public String replyURL() { return ((DynGazelleRocks) botMod()).gazelleBotURL + "/chatBotReply/" + codePostID; } public boolean handleInput(String s, Conversation conv) { String answer; try { Map result = (Map) (postJSONPage(replyURL(), "q", s, "cookie", conv.cookie)); answer = (String) result.get("answer"); } catch (Throwable e) { _handleException(e); answer = "Error: " + e.getMessage(); } conv.add(new Msg(false, answer)); return true; } } static public String userName(User user) { return user != null ? user.name : "?"; } static public class WebPushSubscription extends Concept { public String clientIP; public Map data; } static public class Chain implements Iterable { public A element; public Chain next; public int size; public Chain() { } public Chain(A element) { this.element = element; size = 1; } public Chain(A element, Chain next) { this.next = next; this.element = element; size = next != null ? next.size + 1 : 1; } public String toString() { return str(toList()); } public ArrayList toList() { ArrayList l = emptyList(size); Chain c = this; while (c != null) { l.add(c.element); c = c.next; } return l; } public Iterator iterator() { return toList().iterator(); } } static public class ConceptWithGlobalID extends Concept implements IHasGlobalID { public GlobalID globalID = aGlobalIDObjUnlessLoading(); public GlobalID globalID() { return globalID; } public String globalIDStr() { return strOrNull(globalID); } public String prependGlobalID(String s) { return globalID == null ? s : "[" + globalID + "] " + s; } } static public class MechListDependentCache extends Cache { public String listName, lastListContents; public MechListDependentCache() { } public MechListDependentCache(String listName, Object maker) { this.maker = maker; this.listName = listName; } public A make() { return (A) callF(maker, lastListContents); } public A get() { if (hasLock(lock)) return value; { String listContents = mL_raw(listName); Lock __0 = lock; lock(__0); try { if (!eqOrSame(listContents, lastListContents)) clear(); lastListContents = listContents; } finally { unlock(__0); } } return super.get(); } } static public class MultiMap { public Map> data = new HashMap>(); public MultiMap() { } public MultiMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); } public MultiMap(MultiMap map) { putAll(map); } public MultiMap(Map> data) { this.data = data; } public void put(A key, B value) { synchronized (data) { List list = data.get(key); if (list == null) data.put(key, list = _makeEmptyList()); list.add(value); } } public void add(A key, B value) { put(key, value); } public void addAll(A key, Collection values) { putAll(key, values); } public void addAllIfNotThere(A key, Collection values) { synchronized (data) { for (B value : values) setPut(key, value); } } public void setPut(A key, B value) { synchronized (data) { if (!containsPair(key, value)) put(key, value); } } public boolean containsPair(A key, B value) { synchronized (data) { return get(key).contains(value); } } public void putAll(A key, Collection values) { synchronized (data) { if (nempty(values)) getActual(key).addAll(values); } } public void putAll(Iterable> pairs) { synchronized (data) { for (Pair p : unnull(pairs)) put(p.a, p.b); } } public void removeAll(A key, Collection values) { synchronized (data) { for (B value : values) remove(key, value); } } public List get(A key) { synchronized (data) { List list = data.get(key); return list == null ? Collections.emptyList() : list; } } public List getOpt(A key) { synchronized (data) { return data.get(key); } } public List getActual(A key) { synchronized (data) { List list = data.get(key); if (list == null) data.put(key, list = _makeEmptyList()); return list; } } public void clean(A key) { synchronized (data) { List list = data.get(key); if (list != null && list.isEmpty()) data.remove(key); } } public Set keySet() { synchronized (data) { return data.keySet(); } } public Set keys() { synchronized (data) { return data.keySet(); } } public void remove(A key) { synchronized (data) { data.remove(key); } } public void remove(A key, B value) { synchronized (data) { List list = data.get(key); if (list != null) { list.remove(value); if (list.isEmpty()) data.remove(key); } } } public void clear() { synchronized (data) { data.clear(); } } public boolean containsKey(A key) { synchronized (data) { return data.containsKey(key); } } public B getFirst(A key) { synchronized (data) { List list = get(key); return list.isEmpty() ? null : list.get(0); } } public void addAll(MultiMap map) { putAll(map); } public void putAll(MultiMap map) { synchronized (data) { for (A key : map.keySet()) putAll(key, map.get(key)); } } public void putAll(Map map) { synchronized (data) { if (map != null) for (Map.Entry e : map.entrySet()) put(e.getKey(), e.getValue()); } } public int keysSize() { synchronized (data) { return l(data); } } public int size() { synchronized (data) { int n = 0; for (List l : data.values()) n += l(l); return n; } } public List reverseGet(B b) { synchronized (data) { List l = new ArrayList(); for (A key : data.keySet()) if (data.get(key).contains(b)) l.add(key); return l; } } public Map> asMap() { synchronized (data) { return cloneMap(data); } } public boolean isEmpty() { synchronized (data) { return data.isEmpty(); } } public List _makeEmptyList() { return new ArrayList(); } public Collection> allLists() { synchronized (data) { return new ArrayList(data.values()); } } public Collection> values() { return allLists(); } public List allValues() { return concatLists(data.values()); } public Object mutex() { return data; } public String toString() { return "mm" + str(data); } } static public class HTMLTabs { public String id = "tabs_" + aGlobalID(); public List tabs = new ArrayList(); public class Tab { public String id = aGlobalID(); public String label; public String contents; public Tab(String label, String contents) { this.contents = contents; this.label = label; } } public String css() { return "\r\n .tab-selectors {\r\n background: #add8e6;\r\n display: flex;\r\n }\r\n \r\n .tab-selector {\r\n flex: 1;\r\n cursor: pointer;\r\n }\r\n \r\n .tab-selectors .selected {\r\n font-weight: bold;\r\n }\r\n "; } public String html() { return hcss(css()) + div(div(mapToLines(tabs, tab -> div(tab.label, "class", "tab-selector" + stringIf(tab == first(tabs), " selected"), "onclick", "$(" + jsQuote("#" + id + " .tab-selector") + ").removeClass('selected'); " + "$(this).addClass('selected'); " + "$(" + jsQuote("#" + id + " .tab-page") + ").hide(); " + "$(" + jsQuote("#" + tab.id) + ").show();")), "class", "tab-selectors") + mapToLines(tabs, tab -> div(tab.contents, "class", "tab-page", "style", tab == first(tabs) ? "" : "display: none", "id", tab.id)), "id", id, "class", "tabs-container"); } public void add(String label, Object contents) { tabs.add(new Tab(label, strOrNull(contents))); } } static public class Lowest { public A best; public double score; transient public Object onChange; synchronized public boolean isNewBest(double score) { return best == null || score < this.score; } synchronized public double bestScore() { return best == null ? Double.NaN : score; } public double score() { return bestScore(); } synchronized public float floatScore() { return best == null ? Float.NaN : (float) score; } synchronized public float floatScoreOr(float defaultValue) { return best == null ? defaultValue : (float) score; } public boolean put(A a, double score) { boolean change = false; synchronized (this) { if (a != null && isNewBest(score)) { best = a; this.score = score; change = true; } } if (change) pcallF(onChange); return change; } synchronized public void clear() { best = null; score = 0; } synchronized public A get() { return best; } synchronized public boolean has() { return best != null; } synchronized public Pair pair() { return best == null ? null : new Pair(best, bestScore()); } public String toString() { return "Score " + formatDouble_significant2(score, 4) + ": " + best; } } static public class JavaScript extends Var { public JavaScript() { } public JavaScript(String src) { super(src); } public String javaScriptSource() { return get(); } public String toString() { return hjs(get()); } } static public interface IResourceLoader { public String loadSnippet(String snippetID); public String getTranspiled(String snippetID); public int getSnippetType(String snippetID); public String getSnippetTitle(String snippetID); public File loadLibrary(String snippetID); default public File pathToJavaXJar() { return pathToJavaxJar_noResourceLoader(); } default public File getSnippetJar(String snippetID, String transpiledSrc) { return null; } } static public class BreadthFirstPathFinder_withLinkType implements Steppable { public LinkedList queue = new LinkedList(); public MultiMap> links = new MultiMap(); public IF1>> getChildren; public BreadthFirstPathFinder_withLinkType() { } public BreadthFirstPathFinder_withLinkType(IF1>> getChildren) { this.getChildren = getChildren; } public BreadthFirstPathFinder_withLinkType(IF1>> getChildren, A startNode) { this.getChildren = getChildren; add(startNode); } public void add(A a) { add(a, null, null); } public void add(A a, A prev, B linkType) { if (!links.containsKey(a)) { links.put(a, prev == null ? null : pair(prev, linkType)); queue.add(a); } } public boolean step() { ping(); if (empty(queue)) return false; A a = popFirst(queue); for (Pair link : unnull(getChildren.get(a))) add(link.a, a, link.b); return true; } public boolean nodeReached(A a) { return links.containsKey(a); } public Collection getBackLinks(A a) { return pairsA(links.get(a)); } public Collection> getBackLinksWithTypes(A a) { return links.get(a); } public List> examplePathWithTypes(A start, A dest) { List> path = new ArrayList(); A node = dest; path.add(pair(node, null)); while (node != start) { ping(); Pair link = first(getBackLinksWithTypes(node)); if (link == null) return null; path.add(link); node = link.a; } return reversed(path); } } static public class Either { public byte which; public Object value; public Either() { } public Either(int which, Object value) { this.which = (byte) which; this.value = value; } public boolean isA() { return which == 1; } public boolean isB() { return which == 2; } public A a() { if (which != 1) _failMe(); return (A) value; } public B b() { if (which != 2) _failMe(); return (B) value; } public A aOpt() { return which != 1 ? null : (A) value; } public B bOpt() { return which != 2 ? null : (B) value; } public void _failMe() { throw fail("Either object is of wrong type: " + shortClassName(value)); } public String toString() { return "Either" + (isA() ? "A" : "B") + "(" + value + ")"; } } static public class ReliableSingleThread_Multi { public IVF1 processObject; public int delay; public ReliableSingleThread_Multi(IVF1 processObject) { this.processObject = processObject; } public ReliableSingleThread_Multi(int delay, IVF1 processObject) { this.processObject = processObject; this.delay = delay; } public ReliableSingleThread_Multi(int delay, IVF1 processObject, F0 enter) { this.processObject = processObject; this.delay = delay; setEnter(enter); } public Set changedObjects = synchroSet(); public ReliableSingleThread rst = new ReliableSingleThread(new Runnable() { public void run() { try { process(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "process();"; } }); public void add(A a) { if (changedObjects.add(a)) rst.trigger(); } public void addAll(Iterable l) { for (A a : unnull(l)) add(a); } final public void process() { sleep(delay); for (A object : syncCloneAndClearList(changedObjects)) pcallF(processObject, object); } public void setEnter(F0 enter) { rst.enter = enter; } } static public interface Steppable { public boolean step(); } static public class proxy_InvocationHandler implements InvocationHandler { public Object target; public proxy_InvocationHandler() { } public proxy_InvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) { return call(target, method.getName(), unnull(args)); } } static public class MMOPattern { static public class Phrase extends MMOPattern implements IFieldsToList { public String phrase; public boolean quoted = false; public Phrase() { } public Phrase(String phrase, boolean quoted) { this.quoted = quoted; this.phrase = phrase; } public String toString() { return shortClassName(this) + "(" + phrase + ", " + quoted + ")"; } public boolean equals(Object o) { if (!(o instanceof Phrase)) return false; Phrase __1 = (Phrase) o; return eq(phrase, __1.phrase) && eq(quoted, __1.quoted); } public int hashCode() { int h = -1905095975; h = boostHashCombine(h, _hashCode(phrase)); h = boostHashCombine(h, _hashCode(quoted)); return h; } public Object[] _fieldsToList() { return new Object[] { phrase, quoted }; } } static public class And extends MMOPattern implements IFieldsToList { public List l; public And() { } public And(List l) { this.l = l; } public String toString() { return shortClassName(this) + "(" + l + ")"; } public boolean equals(Object o) { if (!(o instanceof And)) return false; And __2 = (And) o; return eq(l, __2.l); } public int hashCode() { int h = 65975; h = boostHashCombine(h, _hashCode(l)); return h; } public Object[] _fieldsToList() { return new Object[] { l }; } } static public class Or extends MMOPattern implements IFieldsToList { public List l; public Or() { } public Or(List l) { this.l = l; } public String toString() { return shortClassName(this) + "(" + l + ")"; } public boolean equals(Object o) { if (!(o instanceof Or)) return false; Or __3 = (Or) o; return eq(l, __3.l); } public int hashCode() { int h = 2563; h = boostHashCombine(h, _hashCode(l)); return h; } public Object[] _fieldsToList() { return new Object[] { l }; } } static public class Not extends MMOPattern implements IFieldsToList { public MMOPattern p; public Not() { } public Not(MMOPattern p) { this.p = p; } public String toString() { return shortClassName(this) + "(" + p + ")"; } public boolean equals(Object o) { if (!(o instanceof Not)) return false; Not __4 = (Not) o; return eq(p, __4.p); } public int hashCode() { int h = 78515; h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] { p }; } } static public class Weighted extends MMOPattern implements IFieldsToList { static final public String _fieldOrder = "weight p"; public double weight; public MMOPattern p; public Weighted() { } public Weighted(double weight, MMOPattern p) { this.p = p; this.weight = weight; } public String toString() { return shortClassName(this) + "(" + weight + ", " + p + ")"; } public boolean equals(Object o) { if (!(o instanceof Weighted)) return false; Weighted __5 = (Weighted) o; return weight == __5.weight && eq(p, __5.p); } public int hashCode() { int h = -446368457; h = boostHashCombine(h, _hashCode(weight)); h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] { weight, p }; } } static public class StartOfLine extends MMOPattern implements IFieldsToList { public MMOPattern p; public StartOfLine() { } public StartOfLine(MMOPattern p) { this.p = p; } public String toString() { return shortClassName(this) + "(" + p + ")"; } public boolean equals(Object o) { if (!(o instanceof StartOfLine)) return false; StartOfLine __6 = (StartOfLine) o; return eq(p, __6.p); } public int hashCode() { int h = -326863539; h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] { p }; } } static public class EndOfLine extends MMOPattern implements IFieldsToList { public MMOPattern p; public EndOfLine() { } public EndOfLine(MMOPattern p) { this.p = p; } public String toString() { return shortClassName(this) + "(" + p + ")"; } public boolean equals(Object o) { if (!(o instanceof EndOfLine)) return false; EndOfLine __7 = (EndOfLine) o; return eq(p, __7.p); } public int hashCode() { int h = -810372346; h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] { p }; } } } static public class CompilerBot { static public boolean verbose = false; static public File compileSnippet(String snippetID) { return compileSnippet(snippetID, ""); } static public Pair compileSnippet2(String snippetID) { return compileSnippet2(snippetID, ""); } static public File compileSnippet(String snippetID, String javaTarget) { return compileSnippet2(snippetID, javaTarget).a; } static public Pair compileSnippet2(String snippetID, String javaTarget) { String transpiledSrc = getServerTranspiled2(snippetID); if (transpiledSrc == null) throw fail("Snippet not found or not public: " + snippetID); int i = transpiledSrc.indexOf('\n'); String libs = transpiledSrc.substring(0, Math.max(0, i)); if (verbose) print("Compiling snippet: " + snippetID + ". Libs: " + libs); transpiledSrc = transpiledSrc.substring(i + 1); return pair(compile(transpiledSrc, libs, javaTarget, snippetID), transpiledSrc); } static public File compile(String src) { return compile(src, ""); } static public File compile(String src, String libs) { return compile(src, libs, null); } static public File compile(String src, String dehlibs, String javaTarget) { return compile(src, dehlibs, javaTarget, null); } static public File compile(String src, String dehlibs, String javaTarget, String progID) { if (verbose) print("Compiling " + l(src) + " chars"); String md5 = md5(dehlibs + "\n" + src + "\n" + fsIOpt(progID)); File jar = getJarFile(md5); if (jar == null || jar.length() <= 22) { List mainClass = findMainClass(javaTok(src)); boolean canRename = mainClass != null && useDummyMainClasses() && isSnippetID(progID) && !tok_classHasModifier(mainClass, "public"); if (verbose) print("useRenaming: " + useDummyMainClasses() + ", canRename: " + canRename + ", progID: " + progID); javaCompileToJar_optionalRename(src, dehlibs, jar, canRename ? progID : null, progID); } else { if (verbose) print("Getting classes from cache (" + jar.getAbsolutePath() + ", " + jar.length() + " bytes)"); touchFile(jar); } return jar; } static public File getJarFile(String md5) { assertTrue(isMD5(md5)); String sub = "JavaX-Caches/#1002203/" + md5 + ".jar"; File f = actualUserDir(sub); return fileExists(f) ? f : userDir(sub); } } static public class Pair implements Comparable> { public A a; public B b; public Pair() { } public Pair(A a, B b) { this.b = b; this.a = a; } public int hashCode() { return hashCodeFor(a) + 2 * hashCodeFor(b); } public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Pair)) return false; Pair t = (Pair) o; return eq(a, t.a) && eq(b, t.b); } public String toString() { return "<" + a + ", " + b + ">"; } public int compareTo(Pair p) { if (p == null) return 1; int i = ((Comparable) a).compareTo(p.a); if (i != 0) return i; return ((Comparable) b).compareTo(p.b); } } static public class HTMLFramer1 { public String title; public List navItems = new ArrayList(); public List contents = new ArrayList(); public LinkedHashSet headElements = new LinkedHashSet(); public boolean navBeforeTitle = false; public List willRender = new ArrayList(); static public class NavItem implements IFieldsToList { static final public String _fieldOrder = "link html targetBlank"; public String link; public String html; public NavItem() { } public NavItem(String link, String html) { this.html = html; this.link = link; } public String toString() { return shortClassName(this) + "(" + link + ", " + html + ")"; } public boolean equals(Object o) { if (!(o instanceof NavItem)) return false; NavItem __1 = (NavItem) o; return eq(link, __1.link) && eq(html, __1.html); } public int hashCode() { int h = -900864330; h = boostHashCombine(h, _hashCode(link)); h = boostHashCombine(h, _hashCode(html)); return h; } public Object[] _fieldsToList() { return new Object[] { link, html }; } public boolean targetBlank = false; } transient public IF0 render; public String render() { return render != null ? render.get() : render_base(); } final public String render_fallback(IF0 _f) { return _f != null ? _f.get() : render_base(); } public String render_base() { callFAll(willRender); return hhtml(hhead(htitle(title) + lines(headElements)) + hbody((navBeforeTitle ? renderNav() + renderTitle() : renderTitle() + renderNav()) + lines(contents))); } transient public IF0 renderTitle; public String renderTitle() { return renderTitle != null ? renderTitle.get() : renderTitle_base(); } final public String renderTitle_fallback(IF0 _f) { return _f != null ? _f.get() : renderTitle_base(); } public String renderTitle_base() { return h1(htmlEncode2(title)); } transient public IF0 renderNav; public String renderNav() { return renderNav != null ? renderNav.get() : renderNav_base(); } final public String renderNav_fallback(IF0 _f) { return _f != null ? _f.get() : renderNav_base(); } public String renderNav_base() { if (empty(navItems)) return ""; return p(joinWithVBar(map(navItems, ni -> ahref_possiblyTargetBlank(ni.link, ni.html, ni.targetBlank)))); } public void addNavItem(String html) { navItems.add(new NavItem(null, html)); } public void addNavItem(String link, String html, Object... __) { navItems.add(setAll(new NavItem(link, html), filterParams(__, "targetBlank"))); } public void addInHead(Object html) { headElements.add(str(html)); } public void add(Object html) { addIfNempty(contents, strOrEmpty(html)); } } static public class JavaXClassLoader extends URLClassLoader { public String progID; public List files; public Set triedToLoad = synchroSet(); public Set loadedClasses = synchroSet(); public boolean retired = false; public Object retiredMarker; public JavaXClassLoader(String progID, List files) { this(progID, files, getSystemClassLoader()); } public JavaXClassLoader(String progID, List files, ClassLoader parent) { super(new URL[0], parent); this.progID = progID; this.files = files; { try { for (File f : files) addURL(f.toURI().toURL()); } catch (Exception __e) { throw rethrow(__e); } } fixACCInClassLoader(this); } public Class findClass(String name) throws ClassNotFoundException { boolean triedBefore = !triedToLoad.add(name); try { Class c = super.findClass(name); loadedClasses.add(c); if (eq(name, "main")) callOpt(javax(), "registerAMainClass", c); return c; } catch (ClassNotFoundException e) { throw new ClassNotFoundException("Class " + name + " not found in " + joinWithComma(map("f2s", files)) + " (progID=" + progID + ")" + (triedBefore ? ", tried to load before" : ""), e); } } public String toString() { return "JavaXClassLoader[" + systemHashCodeHex(this) + "] - " + progID; } } static public class JavaXClassLoaderWithParent extends JavaXClassLoader { public ClassLoader virtualParent; public JavaXClassLoaderWithParent(String progID, List files, ClassLoader virtualParent) { super(progID, files); this.virtualParent = virtualParent; } public Class findClass(String name) throws ClassNotFoundException { if (virtualParent != null && !eq(name, "main") && !name.startsWith("main$")) { try { return virtualParent.loadClass(name); } catch (ClassNotFoundException e) { } } return super.findClass(name); } } static public class CancelPoint implements AutoCloseable { volatile public boolean closed = false; public void close() { closed = true; } } static public class MRUCache extends LinkedHashMap { public int maxSize = 10; public MRUCache() { } public MRUCache(int maxSize) { this.maxSize = maxSize; } public boolean removeEldestEntry(Map.Entry eldest) { return size() > maxSize; } public Object _serialize() { return ll(maxSize, cloneLinkedHashMap(this)); } static public MRUCache _deserialize(List l) { MRUCache m = new MRUCache(); m.maxSize = (int) first(l); m.putAll((LinkedHashMap) second(l)); return m; } } static public class TransferableImage implements Transferable { public Image i; public TransferableImage(Image i) { this.i = i; } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (flavor.equals(DataFlavor.imageFlavor) && i != null) { return i; } else { throw new UnsupportedFlavorException(flavor); } } public DataFlavor[] getTransferDataFlavors() { DataFlavor[] flavors = new DataFlavor[1]; flavors[0] = DataFlavor.imageFlavor; return flavors; } public boolean isDataFlavorSupported(DataFlavor flavor) { DataFlavor[] flavors = getTransferDataFlavors(); for (int i = 0; i < flavors.length; i++) { if (flavor.equals(flavors[i])) { return true; } } return false; } } static public class FieldIndicator implements IFieldsToList { public String field; public boolean forward = false; public FieldIndicator() { } public FieldIndicator(String field, boolean forward) { this.forward = forward; this.field = field; } public String toString() { return shortClassName(this) + "(" + field + ", " + forward + ")"; } public boolean equals(Object o) { if (!(o instanceof FieldIndicator)) return false; FieldIndicator __1 = (FieldIndicator) o; return eq(field, __1.field) && eq(forward, __1.forward); } public int hashCode() { int h = 698778197; h = boostHashCombine(h, _hashCode(field)); h = boostHashCombine(h, _hashCode(forward)); return h; } public Object[] _fieldsToList() { return new Object[] { field, forward }; } } static public class JavaXClassLoaderWithParent2 extends JavaXClassLoader { public ClassLoader virtualParent; public List classesToSkip; public JavaXClassLoaderWithParent2(String progID, List files, ClassLoader virtualParent, List classesToSkip) { super(progID, files); this.virtualParent = virtualParent; this.classesToSkip = classesToSkip; } public Class findClass(String name) throws ClassNotFoundException { if (shouldDelegate(name)) { Class c = virtualParent.loadClass(name); if (c != null) return c; } return super.findClass(name); } public boolean shouldDelegate(String name) { for (String s : classesToSkip) if (eq(name, s) || startsWith(name, s + "$")) return true; return false; } } static public class ReverseChain implements Iterable { public A element; public ReverseChain prev; public int size; public ReverseChain() { } public ReverseChain(ReverseChain prev, A element) { this.element = element; this.prev = prev; if (prev == null) size = 1; else { prev.check(); size = prev.size + 1; } } public void check() { if (size < 1) throw fail("You called the ReverseChain default constructor. Don't do that"); } public String toString() { return str(toList()); } public ArrayList toList() { check(); ArrayList l = emptyList(size); for (int i = 0; i < size; i++) l.add(null); int i = size; ReverseChain c = this; while (c != null) { l.set(--i, c.element); c = c.prev; } return l; } public Iterator iterator() { return toList().iterator(); } } static public class MultiSetMap { public Map> data = new HashMap>(); public int size; public MultiSetMap() { } public MultiSetMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); } public MultiSetMap(MultiSetMap map) { putAll(map); } public MultiSetMap(Map> data) { this.data = data; } public boolean put(A key, B value) { synchronized (data) { Set set = data.get(key); if (set == null) data.put(key, set = _makeEmptySet()); if (!set.add(value)) return false; { ++size; return true; } } } public boolean add(A key, B value) { return put(key, value); } public void addAll(A key, Collection values) { synchronized (data) { putAll(key, values); } } public void addAllIfNotThere(A key, Collection values) { synchronized (data) { for (B value : values) setPut(key, value); } } public void setPut(A key, B value) { synchronized (data) { if (!containsPair(key, value)) put(key, value); } } public boolean containsPair(A key, B value) { synchronized (data) { return get(key).contains(value); } } public void putAll(A key, Collection values) { synchronized (data) { for (B value : values) put(key, value); } } public void removeAll(A key, Collection values) { synchronized (data) { for (B value : values) remove(key, value); } } public Set get(A key) { synchronized (data) { Set set = data.get(key); return set == null ? Collections.emptySet() : set; } } public Set getOpt(A key) { synchronized (data) { return data.get(key); } } public Set getActual(A key) { synchronized (data) { Set set = data.get(key); if (set == null) data.put(key, set = _makeEmptySet()); return set; } } public void clean(A key) { synchronized (data) { Set list = data.get(key); if (list != null && list.isEmpty()) data.remove(key); } } public Set keySet() { synchronized (data) { return data.keySet(); } } public Set keys() { synchronized (data) { return data.keySet(); } } public void remove(A key) { synchronized (data) { size -= l(data.get(key)); data.remove(key); } } public void remove(A key, B value) { synchronized (data) { Set set = data.get(key); if (set != null) { if (set.remove(value)) { --size; if (set.isEmpty()) data.remove(key); } } } } public void clear() { synchronized (data) { data.clear(); size = 0; } } public boolean containsKey(A key) { synchronized (data) { return data.containsKey(key); } } public B getFirst(A key) { synchronized (data) { return first(get(key)); } } public void addAll(MultiSetMap map) { putAll(map); } public void putAll(MultiSetMap map) { synchronized (data) { for (A key : map.keySet()) putAll(key, map.get(key)); } } public void putAll(Map map) { synchronized (data) { if (map != null) for (Map.Entry e : map.entrySet()) put(e.getKey(), e.getValue()); } } public int keysSize() { synchronized (data) { return l(data); } } public int size() { synchronized (data) { return size; } } public int getSize(A key) { return l(data.get(key)); } public int count(A key) { return getSize(key); } public Set reverseGet(B b) { synchronized (data) { Set l = new HashSet(); for (A key : data.keySet()) if (data.get(key).contains(b)) l.add(key); return l; } } public Map> asMap() { synchronized (data) { return cloneMap(data); } } public boolean isEmpty() { synchronized (data) { return data.isEmpty(); } } public Set _makeEmptySet() { return new HashSet(); } public Collection> allLists() { synchronized (data) { return new HashSet(data.values()); } } public List allValues() { return concatLists(values(data)); } public Object mutex() { return data; } public String toString() { return "mm" + str(data); } public Pair firstEntry() { if (empty(data)) return null; Map.Entry> entry = data.entrySet().iterator().next(); return pair(entry.getKey(), first(entry.getValue())); } } static public class JavaXHyperlinker { public boolean targetBlank = false; public Map shortFor = litmap("BigInt", "BIgInteger", "$1", "m.unq(0)", "$2", "m.unq(1)", "$3", "m.unq(2)", "LS", "List", "sclass", "static class", "asclass", "abstract static class", "svoid", "static void", "SS", "Map", "S", "String", "ret", "return", "L", "List", "Cl", "Collection", "O", "Object", "sO", "static Object", "sS", "static String", "fO", "final Object", "fS", "final String", "sS", "static String", "sbool", "static boolean", "fbool", "final boolean", "bool", "boolean", "Int", "Integer", "cast", "casting to the type required on the left-hand side", "°", "()", "ItIt", "IterableIterator", "ES", "Ext (string plus extended information)", "CloseableItIt", "CloseableIterableIterator", "LPairS", "List>", "ISegmenter", "IF1>"); public String explFunc = "anonymous function declaration (similar to Java 8 lambdas)"; public String explPNoconsole = "Main program including Substance L&F, started in non-AWT thread, hiding the console"; public Map tokenExplanations = litmap("~.", "short for accessing a field or calling a method by reflection", "beaConcept", "a BEA concept is just a concept (database-enabled Java class) derived from BEAObject (the AGI base class)", "== null ?:", "short for: == null ? null :", "p-exp {", "main program with automatic upgrade", "mapLike", "a function that takes a global function name as first argument and can be called like this: (...)", "mapMethodLike", "a function that takes a method or field name as first argument and can be called like this: (...)", "func(", explFunc, "func{", explFunc, "voidfunc", "anonymous function declaration without return value (similar to Java 8 lambdas)", "ctex", "ctex rethrows exceptions as RuntimeExceptions so you don't have to declare them", "p {", "short for: public static void main(String[] args)", "p-experiment {", "Main program with a nice big console & auto-restart", "p-substance {", "Main program including Substance L&F, started in AWT thread", "p-subst {", "Main program including Substance L&F, started in non-AWT thread", "p-noconsole {", explPNoconsole, "pn {", explPNoconsole, "answer {", "Answer function - static S answer(S s) { new Matches m; ...; null; }", "time {", "Run the code block and print how long it took", "cprint {", "A module with default class name derived from DynPrintLog", "semiauto {", "In a semiauto block, JavaX automatically adds a ; to (almost) every line", "autosemi {", "In an autosemi block, JavaX automatically adds a ; to (almost) every line", "Clusters", "Clusters is short for Map>", "temp", "temp is like try (...) extending to the end of the current block", "pcall {", "protected call - try { ... } catch { print exception }", "r {", "r { ... } is short for: new Runnable() { public void run() { ... } }", "runnable {", "runnable { ... } is short for: new Runnable() { public void run() { ... } }", "pcall-short {", "protected call, shorter output - try { ... } catch { printShortException }", "LPair<", "LPair<...> is short for: L>", "visualize {", "Visualisation method for an OS module; returns a Swing component", "visualize as", "define a visualization for the module", "enhanceFrame {", "Method that changes properties of an OS module's frame", "run {", "short for: public void run()", "start {", "Method that is run when an OS module is loaded", "enter {", "Methods in a module should be marked 'enter' for bookkeeping", "vf<", "reference to function as voidfunc", "compact module", "try to save memory by reusing code between modules", "cmodule", "cmodule = compact module for Stefan's OS. compact = try to save memory by reusing code between modules", "cmodule2", "cmodule2 = compact module for Stefan's OS (newer version). compact = try to save memory by reusing code between modules", "rThread {", "Runnable in a new thread", "shit(", "short for: return with print", "shit:", "short for: return with print", ":=", "the := operator translates to a simple comma, but converts an identifier on its left-hand side into a string", "noeq", "don't auto-generate equals+hashCode methods", "for single (", "for single is for ping + singletonUnlessNull", "selfType", "selfType is replaced with the enclosing class's name", "runnable class", "short for: class X implementing Runnable { run { ... }}"); public Map sc, sf; public StringTree2 tokenExplanationsTree; public JavaXHyperlinker() { clearCaches(); tokenExplanationsTree = stringTree2_javaTok(tokenExplanations); } public String codeToHTML(String code) { return codeToHTML(code, true); } public String codeToHTML(String code, boolean real) { List tok = javaTok(code); Map links = new HashMap(); Map explanations = new HashMap(); putMultipleKeys(explanations, allPlus(4, jfindAll(tok, "void q {")), "Function will execute in module's queue"); Matches m = new Matches(); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); String prev = get(tok, i - 2), prevPrev = get(tok, i - 4); String next = get(tok, i + 2); String sfID = sf.get(t); if (startsWith(t, "lambda", m) && isInteger(m.rest()) && isIdentifier(next)) explanations.put(i, ("lambda reference to a " + (m.rest()) + "-argument function")); if (eq(t, "methodLambda0") && isIdentifier(next)) explanations.put(i, ("short for: x -> x." + next + "() (with a fresh variable instead of x)")); if (eq(t, "swappable") && isIdentifier(next)) explanations.put(i, "swappable functions can be exchanged per object instance"); if (eq(t, "autoDispose") && isIdentifier(next)) explanations.put(i, "autoDispose adds a cleanMeUp method that properly disposes of this variable"); if (eq(t, "virtual") && isIdentifier(next)) explanations.put(i, "\"virtual\" represents a type that is not visible in this realm, so it is transpiled to just Object"); if (eq(t, "concept") && isIdentifier(next)) explanations.put(i, "A concept is like a Java class, but persistable"); if (eq(t, "flexeq") && isIdentifier(next)) explanations.put(i, "flexeq is a fix for records inside parameterized classes"); if (eq(t, "switchable") && isIdentifier(next)) explanations.put(i, "A field that can be changed through the module's popup menu"); if (eq(t, "embedded") && isIdentifier(next)) explanations.put(i, "\"embedded\" allows you to put a function where they would not normally be allowed"); if (eq(t, "visual") && isIdentifier(next)) explanations.put(i, "short definition of the visualize() function"); if (eq(t, "dm_q") && isIdentifier(next)) explanations.put(i, "Function reference delegating to module queue"); if (eq(t, "!") && isIdentifier(prev) && neq(next, "=")) explanations.put(i, "! is short for .get()"); if (eq(t, "#") && isIdentifier(next)) explanations.put(i, "# makes an identifier local to the scope"); if (eq(t, "f") && isIdentifier(next)) explanations.put(i, "f references a static function in the main class"); if (eq(t, "r") && isIdentifier(next)) explanations.put(i, "short for: r { " + next + "() }"); if (eqOneOf(t, "rThread", "rThreadEnter") && isIdentifier(next)) explanations.put(i, "short for: " + t + " { " + next + "() }"); if (eq(t, "dispose") && isIdentifier(next)) explanations.put(i, "short for: cleanUp(" + next + "); " + next + " = null;"); if (eq(t, "*") && eq(next, "(")) explanations.put(i, "Short syntax for a constructor declaration"); if (eq(t, "thread") && eq(next, "{")) explanations.put(i, "Start a new thread with the following code"); if (eq(t, "module") && isIdentifier(next)) explanations.put(i, "A module is a class that can be loaded in Stefan's OS"); if (eq(t, "record") && isIdentifier(next)) explanations.put(i, "A record is a value-based class"); if (eq(t, "srecord") && isIdentifier(next)) explanations.put(i, "An srecord is a static value-based class"); if (eqOneOf(t, "cached", "simplyCached") && isIdentifier(next)) explanations.put(i, "A function that caches its return value"); if (eq(t, "thread") && isQuoted(next)) explanations.put(i, "Start a new thread with the following name & code"); if (eq(t, "if") && isQuoted(next)) { try { List tok2 = tok_subListWithoutBorderNTokens(tok, i, i + 3); tok_expandIfQuoted(tok2); explanations.put(i, "short for: " + join(tok2)); } catch (Throwable __e) { _handleException(__e); } } if (eq(t, "html") && eq(next, "{")) explanations.put(i, "short for: static Object html(String uri, final Map params) ctex {"); if (eq(t, "try") && eq(next, "answer")) doublePut(explanations, i, i + 2, "\"try answer\" returns the expression if it isn't null or empty"); if (isSingleQuoteIdentifier(t)) explanations.put(i, "string constant, " + quote(fromSingleQuoteIdentifier(t))); if (eq(t, "event") && isIdentifier(next)) explanations.put(i, "declare a function called " + next + "() plus helpers for adding listeners"); if (eqOneOf(t, "null", "false", "true", "this") && eq(next, ";") && tok_tokenBeforeLonelyReturnValue(tok, i - 2)) doublePut(explanations, i, i + 2, "short for: return " + t + ";"); String e = shortFor.get(t); if (e != null) mapPut(explanations, i, "short for: " + e); if (!explanations.containsKey(i) && sfID != null) { if (eqOneOf(prev, "f", "r", "rThread") || startsWith(prev, "lambda") || isIdentifier(next) && eqGet(tok, i + 4, "(") || eqOneOf(next, "(", "°") && (neq(prev, ".") || eq(prevPrev, "main") && neq(get(tok, i - 6), ".")) || eq(prev, "{") && eq(next, "}") && eq(prevPrev, "postProcess") || eq(prev, ":") && eq(prevPrev, ":")) links.put(i, sfID); } List fewTokens = codeTokens(subList(tok, i - 1, i + 2 * 5)); Pair p = stringTreeLeafValue2(tokenExplanationsTree, fewTokens); if (p != null) { int lastCodeToken = i + p.b * 2 - 2; if (eq(get(tok, lastCodeToken), "{")) lastCodeToken -= 2; mapPutInRange(explanations, i, lastCodeToken + 1, p.a); } if (isQuoted(t) && eq(prev, "(") && isIdentifier(prevPrev) && isMechFunction(prevPrev)) mapPut(links, i, neatMechListURL(unquote(t))); String id = sc.get(t); if (id != null) links.put(i, id); } StringBuilder out = new StringBuilder(); Map titles = getSnippetTitles(filter(__60 -> isSnippetID(__60), values(links))); for (int i = 0; i < l(tok); i++) { String t = tok.get(i), id = links.get(i), ex = explanations.get(i); if (empty(t)) continue; if (t.startsWith("[[") && t.endsWith("]]")) { String explanation = "[[...]] denotes a multi-line string constant (as in Lua)"; out.append(dottedSpan("[[", explanation)); String inner = htmlencode(dropPrefix("[[", dropSuffix("]]", t))); out.append(span(inner, "style", "background-color: #77FF77")); out.append(dottedSpan("]]", explanation)); continue; } if (t.startsWith("[=[") && t.endsWith("]=]")) { String explanation = "[=[...]=] denotes a multi-line string constant (as in Lua)"; out.append(dottedSpan("[=[", explanation)); String inner = htmlencode(dropPrefix("[=[", dropSuffix("]=]", t))); out.append(span(inner, "style", "background-color: #77FF77")); out.append(dottedSpan("]=]", explanation)); continue; } String enc = htmlencode(t); out.append(id != null ? ahref(makeLink(real, id), enc, "title", isSnippetID(id) ? titles.get(fsI(id)) : ex, "style", "text-decoration: none; color: black; border-bottom: dotted 1px", "target", targetBlank ? "_blank" : null) : ex != null ? dottedSpan(enc, ex) : enc); } String html = str(out); html = dynamize_noEncode(html); return html; } public String makeLink(boolean real, String id) { if (isURL(id)) return id; if (real) return longSnippetLink(id); return "/" + psI(id); } public void clearCaches() { stdFunctions_clearCache(); sc = standardClassesMap(); sf = stdFunctions_cached(); } public boolean isMechFunction(String s) { return startsWithOneOf(s, "mech", "mL"); } } static public interface IContentsIndexedList extends List { public int[] indicesOf(Object o); } abstract static public class RandomAccessAbstractList extends AbstractList implements RandomAccess { } static public class Not implements IFieldsToList, Transformable, Visitable { public A a; public Not() { } public Not(A a) { this.a = a; } public String toString() { return shortClassName(this) + "(" + a + ")"; } public boolean equals(Object o) { if (!(o instanceof Not)) return false; Not __0 = (Not) o; return eq(a, __0.a); } public int hashCode() { int h = 78515; h = boostHashCombine(h, _hashCode(a)); return h; } public Object[] _fieldsToList() { return new Object[] { a }; } public Object transformUsing(IF1 f) { return new Not((A) f.get(a)); } public void visitUsing(IVF1 f) { f.get(a); } public Boolean get(Object o) { return not((Boolean) callF(a, o)); } } static public interface IHasGlobalID { public GlobalID globalID(); } static public class QuickException extends RuntimeException { public Throwable fillInStackTrace() { return this; } public QuickException() { } public QuickException(Throwable e) { super(e); } public QuickException(String msg) { super(msg); } public QuickException(String msg, Throwable e) { super(msg, e); } } static public interface IContentsIndexedList2 extends List { public TreeSet indicesOf_treeSetOfHasIndex(Object o); } static public class Worker extends Concept { public String loginName, displayName; public boolean available = false; public long lastOnline; public Ref image = new Ref(); static public String _fieldOrder = "loginName displayName"; public String renderAsHTML() { return htmlEncode2(loginName + " (display name: " + displayName + ")"); } } abstract static public class DynNewBot2 extends DynPrintLogAndEnabled { public void setEleu(Object eleu) { mainBot = eleu; } public int maxRefsToShow = 5; volatile public long requestsServed; transient public String templateID = "#1029809"; static public String cssID = "#1029808"; transient public String botName = "DynNewBot2"; transient public String heading = "DynNewBot2"; transient public String adminName = "DynNewBot2 Admin"; transient public String botImageID = "#1102935"; transient public String userImageID = "#1102803"; transient public String chatHeaderImageID = "#1102802"; transient public String timeZone = ukTimeZone_string(); transient public String baseLink = ""; transient public boolean newDesign = true; transient public boolean ariaLiveTrick = false; transient public boolean ariaLiveTrick2 = true; public class WorkerChat { public int workerLongPollTick = 200; public int workerLongPollMaxWait = 1000 * 30; public long lastWorkerRequested; public String mainAdminLink = "/"; public Object html(DynNewBot2.Req req) { Map params = req.params; String uri = req.uri, uri2 = appendSlash(uri); boolean requestAuthed = req.auth != null; Conversation conv = req.conv; if (startsWith(uri2, "/worker/")) { if (!req.webRequest.isHttps()) return subBot_serveRedirect("https://" + req.webRequest.domain() + req.uri + htmlQuery(req.params)); if (!requestAuthed) return serveAuthForm(params.get("uri")); if (nempty(params.get("turnBotOn"))) conv.turnBotOn(); return serveWorkerPage(req); } return null; } public String serveWorkerPage(DynNewBot2.Req req) { AuthedDialogID auth = req.auth; Conversation conv = req.conv; String uri = req.uri; Map params = req.params; String cookie = conv.cookie; String uri2 = afterLastSlash(uri); if (eq(uri2, "availableWorkers")) return "Available workers: " + or2(joinWithComma(map(workersAvailable(), w -> w.renderAsHTML())), "-"); if (nempty(params.get("workerLogOut"))) cset(auth, "loggedIn", null); if (auth.loggedIn != null && nempty(params.get("workerAvailableBox"))) if (cset_trueIfChanged(auth.loggedIn, "available", nempty(params.get("workerAvailable")))) noteConversationChange(); if (nempty(params.get("acceptConversation"))) { if (conv.worker == null) { cset(conv, "worker", auth.loggedIn); conv.turnBotOff(); } } String loginID = params.get("workerLogIn"); if (nempty(loginID)) cset(auth, "loggedIn", getConcept(Worker.class, parseLong(loginID))); Map map = prependEmptyOptionForHSelect(mapToOrderedMap(conceptsSortedByFieldCI(Worker.class, "loginName"), w -> pair(w.id, w.loginName))); if (auth.loggedIn == null) return hsansserif() + p("You are not logged in as a worker") + hpostform("Log in as: " + hselect("workerLogIn", map, conceptID(auth.loggedIn)) + " " + hsubmit("OK"), "action", botMod().baseLink + "/worker"); if (eq(uri2, "conversation")) { if (conv == null) return "Conversation not found"; String onOffURL = botMod().baseLink + "/worker/botOnOff" + hquery("cookie", cookie) + "&on="; return hsansserif() + loadJQuery() + hhidden("cookie", cookie) + hpostform(hhidden("cookie", cookie) + p(renderBotStatus(conv)) + p(conv.botOn ? hsubmit("Accept conversation", "name", "acceptConversation") : hsubmit("Turn bot back on", "name", "turnBotOn")), "action", botMod().baseLink + "/worker/innerFrameSet", "target", "innerFrameSet") + hscriptsrc(botMod().baseLink + "/script" + hquery("workerMode", 1, "cookie", conv.cookie)); } if (eq(uri2, "conversations")) { cset(auth.loggedIn, "lastOnline", now()); boolean poll = eq("1", params.get("poll")); String content = ""; if (poll) { long seenChange = parseLong(params.get("lastChange")); vmBus_send("chatBot_startingWorkerPoll", mc(), conv); long start = sysNow(); List msgs; boolean first = true; while (licensed() && sysNow() < start + workerLongPollMaxWait && lastConversationChange == seenChange) sleep(workerLongPollTick); printVars_str("lastWorkerRequested", lastWorkerRequested, "seenChange", seenChange); if (lastWorkerRequested > seenChange) content = hscript("\r\n window.parent.parent.frames[0].sendDesktopNotification(\"A worker is requested!\", { action: function() { window.focus(); } });\r\n window.parent.parent.frames[0].playWorkerRequestedSound();\r\n "); } long pingThreshold = now() - activeConversationTimeout(); List convos = sortByCalculatedFieldDesc(c -> c.lastMsgTime(), conceptsWithFieldGreaterThan(Conversation.class, "lastPing", pingThreshold)); content += hhiddenWithID("lastConversationChange", lastConversationChange) + tag("table", hsimpletableheader("IP", "Country", "Bot/worker status", "Last change", "Last messages") + mapToLines(convos, c -> { List lastMsgs = lastTwo(c.msgs); String style = c == conv ? "background: #90EE90" : null; String convLink = botMod().baseLink + "/worker/innerFrameSet" + hquery("cookie", c.cookie); return tag("tr", td(ahref(convLink, c.ip, "target", "innerFrameSet")) + td(getCountry(c)) + td(renderBotStatus(c)) + td(renderHowLongAgo(c.lastMsgTime())) + td(ahref(convLink, hparagraphs(lambdaMap(__102 -> renderMsgForWorkerChat(__102), lastMsgs)), "target", "innerFrameSet", "style", "text-decoration: none")), "style", style); }), "class", "responstable"); if (poll) return content; String incrementalURL = botMod().baseLink + "/worker/conversations?poll=1&lastChange="; return hhtml(hhead(hsansserif() + loadJQuery() + hscript_clickableRows()) + hbody(h3(botName) + hpostform("Logged in as " + htmlEncode2(auth.loggedIn.loginName) + " (display name: " + htmlEncode2(auth.loggedIn.displayName) + ")" + hhidden("workerAvailableBox", 1) + "   " + hcheckboxWithText("workerAvailable", "I am available", auth.loggedIn.available, "onclick", "form.submit()") + "   " + hsubmit("Log out", "name", "workerLogOut"), "target", "innerFrameSet", "action", botMod().baseLink + "/worker/innerFrameSet") + p("Available workers: " + b(or2(joinWithComma(map(workersAvailable(), w -> w.displayName)), "none"))) + h3("Active conversations") + hcss_responstable() + hdivWithID("contentArea", content) + hscript("\r\n function poll_start() {\r\n var lastChange = $(\"#lastConversationChange\").val();\r\n if (!lastChange)\r\n setTimeout(poll_start, 1000);\r\n else {\r\n var url = \"#INCREMENTALURL#\" + lastChange;\r\n console.log(\"Loading \" + url);\r\n $.get(url, function(src) {\r\n if (src.match(/^ERROR/)) console.log(src);\r\n else {\r\n console.log(\"Loaded \" + src.length + \" chars\");\r\n $(\"#contentArea\").html(src);\r\n }\r\n setTimeout(poll_start, 1000);\r\n }, 'text')\r\n .fail(function() {\r\n console.log(\"Rescheduling after fail\");\r\n setTimeout(poll_start, 1000);\r\n });\r\n }\r\n }\r\n poll_start();\r\n ".replace("#INCREMENTALURL#", incrementalURL)))); } if (eq(uri2, "notificationArea")) return hhtml(hhead(hsansserif() + loadJQuery()) + hbody(hdesktopNotifications() + div(small(span(hbutton("CLICK HERE to enable notification sounds!"), "id", "enableSoundsBtn") + " | " + span("", "id", "notiStatus")), "style", "float: right") + hscript("\r\n function enableSounds() {\r\n document.removeEventListener('click', enableSounds);\r\n $(\"#enableSoundsBtn\").html(\"Notification sounds enabled\");\r\n }\r\n document.addEventListener('click', enableSounds);\r\n \r\n if (window.workerRequestedSound == null) {\r\n console.log(\"Loading worker requested sound\");\r\n window.workerRequestedSound = new Audio(\"https://botcompany.de/files/1400404/worker-requested.mp3\");\r\n }\r\n \r\n function playWorkerRequestedSound() {\r\n console.log(\"Playing worker requested sound\");\r\n window.workerRequestedSound.play();\r\n }\r\n window.playWorkerRequestedSound = playWorkerRequestedSound;\r\n\r\n "))); if (eq(uri2, "innerFrameSet")) return hhtml(hhead_title("Worker Chat [" + auth.loggedIn.loginName + "]") + hframeset_cols("*,*", tag("frame", "", "name", "conversations", "src", botMod().baseLink + "/worker/conversations" + hquery("cookie", cookie)) + tag("frame", "", "name", "conversation", "src", conv == null ? null : botMod().baseLink + "/worker/conversation" + hquery("cookie", cookie)))); return hhtml(hhead_title("Worker Chat [" + auth.loggedIn.loginName + "]") + hframeset_rows("50,*", tag("frame", "", "name", "notificationArea", "src", botMod().baseLink + "/worker/notificationArea") + tag("frame", "", "name", "innerFrameSet", "src", conv == null ? null : botMod().baseLink + "/worker/innerFrameSet" + hquery("cookie", cookie)))); } public String renderMsgForWorkerChat(Msg msg) { return (msg.fromWorker != null ? htmlEncode2(msg.fromWorker.displayName) : msg.fromUser ? "User" : "Bot") + ": " + b(htmlEncode2If(shouldHtmlEncodeMsg(msg), msg.text)); } public Collection workersAvailable() { long timestamp = now() - workerLongPollMaxWait - 10000; return filter(list(Worker.class), w -> w.available && w.lastOnline >= timestamp); } public boolean anyWorkersAvailable() { return nempty(workersAvailable()); } public String renderBotStatus(Conversation conv) { return "Bot is " + b(conv.botOn ? "on" : "off") + "
" + "Assigned worker: " + b(conv.worker == null ? "none" : conv.worker.displayName); } } transient public WorkerChat workerChat = new WorkerChat(); transient public ReliableSingleThread rstBotActions = dm_rst(this, new Runnable() { public void run() { try { botActions(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "botActions();"; } }); transient public String defaultHeaderColorLeft = "#2a27da"; transient public String defaultHeaderColorRight = "#00ccff"; transient public boolean enableUsers = false; transient public boolean useWebSockets = false; transient public boolean showRegisterLink = false; transient public boolean showTalkToBotLink = false; transient public boolean alwaysRedirectToHttps = false; transient public boolean redirectOnLogout = false; transient public boolean showFullErrors = false; transient public boolean lockWhileDoingBotActions = false; transient public boolean standardButtonsAsSymbols = false; transient public boolean enableVars = false; transient public boolean enableAvatars = false; transient public boolean enableRandomActions = false; transient public boolean recordExecutionsAndInputs = true; transient public boolean phoneNumberSpecialInputField = true; transient public boolean enableRadioButtons = false; transient public boolean newDialogAfterWindowClosed = false; transient public boolean showJoiningConversation = false; transient public boolean quickRadioButtons = false; transient public boolean useDynamicComboBoxes = false; transient public boolean prefixPrintsWithConvID = true; transient public boolean enableUndoStates = false; transient public boolean showCRUDToEveryone = false; transient public boolean showOnlySelectedObject = false; transient public boolean storeBaseClassesInStructure = false; public String mailSenderInfo; transient public int typingTimeshift = 2000; transient public ThreadLocal currentReq = new ThreadLocal(); transient volatile public Scorer consistencyCheckResults; transient public Lock statsLock = lock(); transient public Map specialPurposes = litcimap("bad email address", "Please enter a valid e-mail address", "bad phone number", "Please enter a valid phone number"); public void start() { super.start(); dm_setModuleName(botName); dm_assertFirstSibling(); concepts_setUnlistedByDefault(true); standardTimeZone(); standardTimeZone_name = timeZone; print("DB program ID: " + dbProgramID()); realPW(); pWebChatBot(); dm_doEvery(60.0, new Runnable() { public void run() { try { cleanConversations(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cleanConversations();"; } }); rstBotActions.trigger(); } public void indexAllLinkableClasses() { ensureConceptClassesAreIndexed(allLinkableClasses()); } public JComponent visualize() { JComponent _c = super.visualize(); addToControlArea(jPopDownButton_noText(popDownButtonEntries())); return _c; } public Object[] popDownButtonEntries() { return litobjectarray("Show/edit master password...", runnableThread(new Runnable() { public void run() { try { AutoCloseable __23 = enter(); try { editMasterPassword(); } finally { _close(__23); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); editMasterPassword();"; } }), "Show/edit mail sender info...", runnableThread(new Runnable() { public void run() { try { AutoCloseable __24 = enter(); try { editMailSenderInfo(); } finally { _close(__24); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); editMailSenderInfo();"; } })); } static public class Req { public IWebRequest webRequest; public String uri; public Map params; public AuthedDialogID auth; public Domain authDomainObj; public String authDomain; public HTMLFramer1 framer; public boolean masterAuthed = false; public Conversation conv; public String uri() { return uri; } public Map params() { return params; } public boolean requestAuthed() { return auth != null; } public String get(String param) { return webRequest.get(param); } public void markNoSpam() { webRequest.noSpam(); } public void noSpam() { markNoSpam(); } } public boolean calcMasterAuthed(Req req) { return req.auth != null && req.auth.master; } public Object html(IWebRequest request) { AutoCloseable __18 = enter(); try { try { return html2(request); } catch (Throwable e) { printStackTrace(e); return serve500(showFullErrors ? getStackTrace(e) : "Error."); } } finally { _close(__18); } } public void requestServed() { } public Object html2(IWebRequest request) { htmlencode_forParams_useV2(); { Lock __2 = statsLock; lock(__2); try { requestsServed++; change(); requestServed(); } finally { unlock(__2); } } String uri = request.uri(); Map params = request.params(); Req req = new Req(); req.webRequest = request; req.uri = uri; req.params = params; if (alwaysRedirectToHttps) { Object __10 = redirectToHttps(req); if (__10 != null) return __10; } if (eq(params.get("_newConvCookie"), "1")) return hrefresh(appendQueryToURL(req.uri, mapPlus(mapMinus(req.params, "_newConvCookie"), "cookie", "test_" + aGlobalID()))); String cookie = request.cookie(); boolean workerMode = nempty(params.get("workerMode")) || startsWith(uri, "/worker"); String domain = request.domain(), _domain = domain; saveDeliveredDomain(domain); Domain domainObj = findDomainObj(domain); String convCookie = params.get("cookie"); Conversation conv = isRequestFromBot(req) ? null : nempty(convCookie) ? getConv(convCookie) : nempty(cookie) ? getConv(cookie) : null; req.conv = conv; AutoCloseable tempThing = conv == null || !prefixPrintsWithConvID ? null : temp_printPrefix("Conv " + conv.cookie + ": "); AutoCloseable __19 = tempThing; try { AutoCloseable __20 = tempSetTL(currentReq, req); try { String botConfig = params.get("_botConfig"); Map botConfigParams = decodeURIParams(botConfig); String simulatedDomain = botConfigParams.get("domain"); Domain domainObj2 = nempty(simulatedDomain) ? findDomainObj(simulatedDomain) : domainObj; if (nempty(botConfigParams)) cset(conv, "botConfig", botConfigParams); if (conv != null && !workerMode) if (cset_trueIfChanged(conv, "ip", request.clientIP(), "domain", domain, "domainObj", domainObj2)) { calcCountry(conv); initAvatar(conv); } { Object __11 = handleAuth(req, cookie); if (__11 != null) return __11; } Matches m = new Matches(); if (startsWith(uri, "/worker-image/", m)) { long id = parseLong(m.rest()); return subBot_serveFile_maxCache(workerImageFile(id), "image/jpeg"); } if (startsWith(uri, "/uploaded-image/", m)) { long id = parseLong(m.rest()); UploadedImage img = getConcept(UploadedImage.class, id); return img == null ? serve404() : subBot_serveFile_maxCache(img.imageFile(), "image/jpeg"); } if (startsWith(uri, "/uploaded-sound/", m)) { long id = parseLong(m.rest()); UploadedSound sound = getConcept(UploadedSound.class, id); return sound == null ? serve404() : subBot_serveFile_maxCache(sound.soundFile(), mp3mimeType()); } if (startsWith(uri, "/uploaded-file/", m)) { long id = parseLong(dropAfterSlash(m.rest())); UploadedFile f = getConcept(UploadedFile.class, id); return f == null ? serve404() : subBot_serveFile_maxCache(f.theFile(), or2(params.get("ct"), or2(trim(f.mimeType), binaryMimeType()))); } AuthedDialogID auth = authObject(cookie); if (eq(params.get("logout"), "1")) { cdelete(auth); if (redirectOnLogout) return hrefresh(req.uri); auth = null; } req.auth = auth; boolean requestAuthed = auth != null; boolean masterAuthed = req.masterAuthed = calcMasterAuthed(req); Domain authDomainObj = !requestAuthed ? null : auth.restrictedToDomain.get(); req.authDomainObj = authDomainObj; String authDomain = !requestAuthed ? null : auth.domain(); req.authDomain = authDomain; if (requestAuthed) req.markNoSpam(); { Object __12 = serve2(req); if (__12 != null) return __12; } makeFramer(req); HTMLFramer1 framer = req.framer; if (requestAuthed || showCRUDToEveryone) { Object __13 = serveCRUD(req); if (__13 != null) return __13; } if (!requestAuthed && settings().talkToBotOnlyWithAuth) return serveAuthForm(params.get("uri")); if (eq(uri, "/emoji-picker/index.js")) return withHeader(subBot_maxCacheHeaders(serveInputStream(bufferedFileInputStream(loadLibrary("#1400436")), "text/javascript"))); if (eq(uri, "/emoji-picker-test")) return loadSnippet("#1029870"); if (eq(uri, "/logs")) { if (!masterAuthed) return serveAuthForm(rawLink(uri)); return webChatBotLogsHTML2(rawLink(uri), params); } if (eq(uri, "/refchecker")) { if (!masterAuthed) return serveAuthForm(rawLink(uri)); ConceptsRefChecker refChecker = new ConceptsRefChecker(db_mainConcepts()); List errors = refChecker.run(); if (eq(params.get("fix"), "1")) return serveText(refChecker.fixAll()); else return serveText(jsonEncode_breakAtLevels(2, litorderedmap("errors", allToString(errors)))); } if (eq(uri, "/backupDBNow")) { if (!masterAuthed) return serveAuthForm(rawLink(uri)); return serveText("Backed up DB as " + fileInfo(backupConceptsNow())); } if (eq(uri, "/auth-only")) { if (!requestAuthed) return serveAuthForm(params.get("uri")); return ""; } if (eq(uri, "/leads-api")) return serveLeadsAPI(request); if (workerChat != null) { Object __14 = workerChat.html(req); if (__14 != null) return __14; } String message = trim(params.get("btn")); if (empty(message)) message = trim(params.get("message")); if (match("new dialog", message)) { Lock __3 = dbLock(); lock(__3); try { conv.newDialog(); message = null; } finally { unlock(__3); } } if (eqic(message, "!toggle notifications")) { cset(conv, "notificationsOn", !conv.notificationsOn); message = null; } if (eqic(message, "!undo states")) { conv.add(new Msg(false, n2(conv.undoStates, "undo state"))); message = null; } this.conv.set(conv); if (nempty(message) && !lastUserMessageWas(conv, message)) { Lock __4 = dbLock(); lock(__4); try { print("Adding message: " + message); possiblyTriggerNewDialog(conv); if (workerMode) { Msg msg = new Msg(false, message); msg.fromWorker = auth.loggedIn; conv.add(msg); } else { conv.add(new Msg(true, message)); addScheduledAction(new OnUserMessage(conv)); } } finally { unlock(__4); } } String testMode = params.get("testMode"); if (nempty(testMode)) { print("Setting testMode", testMode); cset(conv, "testMode", eq("1", testMode)); } if (eq(uri, "/msg")) return withHeader("OK"); if (eq(uri, "/typing")) { if (workerMode) { conv.botTyping = now(); print(conv.botTyping + " Bot typing in: " + conv.cookie); } else { conv.userTyping = now(); print(conv.userTyping + " User typing in: " + conv.cookie); } return withHeader("OK"); } if (eq(uri, "/renderMessages")) { long msgTime = parseLong(params.get("msgTime")); List msgs = conv.allMsgs(); if (msgTime != 0) msgs = filter(msgs, msg -> msg.time == msgTime); StringBuilder buf = new StringBuilder(); renderMessages(conv, buf, msgs, msg -> false); return hhtml_title_body(nMessages(msgs), hstylesheetsrc(cssURL()) + p(nMessages(msgs) + " found") + buf); } if (eq(uri, "/incremental")) { if (newDialogAfterWindowClosed && !conv.isActive()) { print("Clearing conversation, timed out"); Lock __5 = dbLock(); lock(__5); try { conv.newDialog(); } finally { unlock(__5); } } long start = sysNow(), start2 = now(); print("start2", start2); cset(conv, "lastPing", now()); possiblyTriggerNewDialog(conv); int a = parseInt(params.get("a")); int reloadCounter = conv.reloadCounter; List msgs; boolean first = true; int timeout = toInt(req.params.get("timeout")); long endTime = start + (timeout <= 0 || timeout > longPollMaxWait / 1000 ? longPollMaxWait : timeout * 1000L); while (licensed() && sysNow() < endTime) { int as = conv.archiveSize(); msgs = cloneSubList(conv.msgs, a - as); boolean reloadTriggered = conv.reloadCounter > reloadCounter; boolean actuallyNewDialog = a < as; boolean newDialog = actuallyNewDialog || reloadTriggered; if (newDialog) msgs = cloneList(conv.msgs); long typing = workerMode ? conv.userTyping : conv.botTyping; boolean otherPartyTyping = typing >= start2 - typingTimeshift; boolean anyEvent = nempty(msgs) || newDialog || otherPartyTyping; if (!anyEvent) { if (first) { first = false; } sleep(longPollTick); } else { if (eq(req.params.get("json"), "1")) return serveJSON_breakAtLevels(2, litorderedmap("n", conv.allCount(), "newDialog", trueOrNull(newDialog), "otherPartyTyping", trueOrNull(otherPartyTyping), "msgs", map(msgs, msg -> litorderedmap("time", msg.time, "fromUser", msg.fromUser, "fromWorker", msg.fromWorker == null ? null : msg.fromWorker.displayName, "text", msg.text, "labels", msg.labels)))); StringBuilder buf = new StringBuilder(); if (newDialog) { String l = or2_trim(domainObj2.headerColorLeft, defaultDomain().headerColorLeft, defaultHeaderColorLeft), r = or2_trim(domainObj2.headerColorRight, defaultDomain().headerColorRight, defaultHeaderColorRight); buf.append(hcss(".chat_header { background: linear-gradient(135deg, " + hexColorToCSSRGB(l) + " 0%, " + hexColorToCSSRGB(r) + " 100%); }")); buf.append(hscript("$('#chatBot_notiToggleText').text(" + jsQuote("Turn " + (conv.notificationsOn ? "off" : "on") + " notifications") + ");")); if (showJoiningConversation) { buf.append(hscript("$('#otherSideTyping .joining').html(" + jsQuote(nameOfBotSide(conv) + " now joining conversation...") + ");" + "setTimeout(function() { $('#otherSideTyping .joining').html(''); }, 5000);")); } } if (otherPartyTyping) { buf.append(hscript("showTyping(" + jsQuote(conv.botImg()) + ");")); } renderMessages(conv, buf, msgs); if (ariaLiveTrick2 && !workerMode) { Msg msg = lastBotMsg(msgs); if (msg != null) { String author = msg.fromWorker != null ? htmlEncode2(msg.fromWorker.displayName) : botName; buf.append(hscript("$(\"#screenreadertrick\").html(" + jsQuote(author + " says: " + msg.text) + ");")); } } if (a != 0 && anyInterestingMessages(msgs, workerMode)) buf.append(hscript(stringIf(conv.notificationsOn, "window.playChatNotification();\n") + "window.setTitleStatus(" + jsQuote((workerMode ? "User" : botName) + " says…") + ");")); String html = str(buf); return withHeader("\n" + html); } } return withHeader(""); } if (eqOneOf(uri, "/script", "/demo")) { Lock __6 = dbLock(); lock(__6); try { String myTemplateID = templateID; String templateIDParam = req.params.get("templateID"); if (nempty(templateIDParam) && allowedTemplateID(templateIDParam)) myTemplateID = templateIDParam; String html = loadSnippet_cached(myTemplateID); String botLayout = req.params.get("botLayout"); String layout = or2(botLayout, defaultBotLayout()); html = modifyTemplateBeforeDelivery(html, req); String heading = or2(headingForReq(req), or2(trim(domainObj2.botName), this.heading)); String botImg = botImageForDomain(domainObj); UploadedSound sound = settings().notificationSound.get(); String notificationSound = sound != null ? sound.soundURL() : defaultNotificationSound(); String miscParam = workerMode ? "workerMode=1&" : ""; if (nempty(botLayout)) miscParam += "botLayout=" + urlencode(botLayout) + "&"; String incrementalURL = baseLink + "/incremental?" + miscParam + "a="; String typingURL = baseLink + "/typing?" + miscParam; String msgURL = baseLink + "/msg?" + miscParam + "message="; if (eqic(layout, "sahil")) { html = replaceDollarVars(html, "incrementalURL", incrementalURL, "typingURL", typingURL, "msgURL", msgURL, "n", 0, "notificationSound", notificationSound, "workerMode", workerMode, "heading", heading, "botImg", botImg); } else { String langlinks = ""; if (html.contains(langlinks)) html = html.replace(langlinks, ahref(rawLink("eng"), "English") + " | " + ahref(rawLink("deu"), "German")); html = html.replace("#COUNTRY#", lower(conv.country)); html = html.replace("#BOTIMG#", botImg); html = html.replace("#N#", "0"); html = html.replace("#INCREMENTALURL#", incrementalURL); html = html.replace("#MSGURL#", msgURL); html = html.replace("#TYPINGURL#", typingURL); html = html.replace("#CSS_ID#", psI_str(cssID)); if (ariaLiveTrick || ariaLiveTrick2) html = html.replace("aria-live=\"polite\">", ">"); html = html.replace("#OTHERSIDE#", workerMode ? "User" : "Representative"); if (nempty(params.get("debug"))) html = html.replace("var showActions = false;", "var showActions = true;"); html = html.replace("#AUTOOPEN#", jsBool(workerMode || eq(params.get("_autoOpenBot"), "1") || botAutoOpen(domainObj2))); html = html.replace("#BOT_ON#", jsBool(botOn() || eq(uri, "/demo"))); html = html.replace("$HEADING", heading); html = html.replace("#WORKERMODE", jsBool(workerMode)); html = html.replace("#NOTIFICATIONSOUND#", notificationSound); html = html.replace("", ""); html = hreplaceTitle(html, heading); } if (eq(uri, "/demo")) return hhtml(hhead(htitle(heading) + loadJQuery2()) + hbody(hjavascript(html))); else return withHeader(subBot_serveJavaScript(html)); } finally { unlock(__6); } } { Object __15 = serveOtherPage(req); if (__15 != null) return __15; } if (eq(uri, "/")) { Object __16 = serveHomePage(); if (__16 != null) return __16; } if (!startsWith(uri, "/crud/")) { UploadedFile fileToServe = conceptWhere(UploadedFile.class, "liveURI", urldecode(dropSlashPrefix(uri))); if (fileToServe != null) return subBot_serveFile(fileToServe.theFile(), nempty(fileToServe.mimeType) ? fileToServe.mimeType : guessMimeTypeFromFileName(afterLastSlash(fileToServe.liveURI))); } if (!requestAuthed) return serveAuthForm(params.get("uri")); if (masterAuthed && eq(uri, "/dialogTree")) { BotStep step = getConcept(BotStep.class, toLong(params.get("stepID"))); if (step == null) return serve404("Step not found"); return hhtml_head_title_body("Dialog Tree for " + step, hmobilefix() + hsansserif() + h2("Dialog Tree") + hcss_linkColorInherit() + hcss("\r\n .dialogTree li { margin-top: 0.8em; }\r\n ") + renderDialogTree(step)); } if (eq(uri, "/thoughts")) return serveThoughts(req); if (masterAuthed && eq(uri, "/search")) return serveSearch(req); if (eq(uri, "/leads-csv")) { String text = leadsToCSV(conceptsWhere(Lead.class, mapToParams(filtersForClass(Lead.class, req)))); String name = "bot-leads" + (authDomainObj == null ? "" : "-" + replace(str(authDomainObj), "/", "-")) + "-" + ymd_minus_hm() + ".csv"; return serveCSVWithFileName(name, text); } if (eq(uri, "/cleanConversations") && masterAuthed) { cleanConversations(); return hrefresh(baseLink + "/crud/Conversation"); } if (eq(uri, "/deleteDeliveredDomains") && masterAuthed) { deleteDeliveredDomains(); return hrefresh(baseLink + "/crud/DeliveredDomain"); } if (eq(uri, "/emojis")) { framer.title = "Emoji List"; framer.contents.add(htmlTable2(map(emojiShortNameMap(), (code, emoji) -> litorderedmap("Shortcode", code, "Emoji", emoji)))); } if (eq(uri, "/embedCode")) { String goDaddyEmbedCode = ""; framer.title = "Embed Code"; framer.contents.add(h2("Chat bot embed code") + (empty(goDaddyEmbedCode) ? "" : h3("GoDaddy Site Builder") + p("Add an HTML box with this code:") + pre(htmlEncode2(goDaddyEmbedCode)) + h3("Other")) + p("Add this code in front of your " + tt(htmlEncode2("")) + " tag:") + pre(htmlEncode2(hjavascript_src_withType("https://" + request.domain() + baseLink + "/script")))); } if (eq(uri, "/stats")) { long us = db_mainConcepts().uncompressedSize; framer.add(htableRaw2(llNonNulls(ll("Concepts", n2(conceptCount())), ll("DB size on disk", htmlEncode2(toK_str(fileSize(conceptsFile())))), us == 0 ? null : ll("DB size uncompressed", htmlEncode2(toK_str(us))), ll("DB load time", htmlEncode2(renderDBLoadTime())), ll("DB save time", htmlEncode2(renderDBSaveTime())), ll("Last saved", htmlEncode2(renderHowLongAgo(db_mainConcepts().lastSaveWas)))), ll("class", "responstable"), null, null)); } if (eq(uri, "/unpackToWeb") && req.masterAuthed) { UploadedFile file = getConcept(UploadedFile.class, parseLong(req.params.get("fileID"))); if (file == null) return serve404("File not found"); String path = unnull(req.params.get("path")); File zipFile = file.theFile(); int changes = 0; for (String filePath : listZIP(zipFile)) { String liveURI = appendSlash(path) + filePath; UploadedFile entry = uniq(UploadedFile.class, "liveURI", liveURI); byte[] data = loadBinaryFromZip(zipFile, filePath); if (!fileContentsIs(entry.theFile(), data)) { ++changes; saveBinaryFile(entry.theFile(), data); touchConcept(entry); } } return "Unpacked, " + nChanges(changes); } { Object __17 = serveDefaultPage(req); if (__17 != null) return __17; } return completeFrame(req); } finally { _close(__20); } } finally { _close(__19); } } public Object serveDefaultPage(Req req) { return null; } public Object completeFrame(Req req) { HTMLFramer1 framer = req.framer; if (req.requestAuthed()) { if (settings().enableWorkerChat) framer.addNavItem(baseLink + "/worker", "Worker chat"); framer.addNavItem(baseLink + "?logout=1", "Log out"); } return framer.render(); } public Object serve2(Req req) { return null; } public Object serveOtherPage(Req req) { return null; } public
A getDomainValue(Domain domainObj, IF1 getter, A defaultValue) { if (domainObj != null) { A val = getter.get(domainObj); if (val != null) return val; } { A val = getter.get(defaultDomain()); if (val != null) return val; } return defaultValue; } public void makeFramer(Req req) { HTMLFramer1 framer = new HTMLFramer1(); req.framer = framer; framer.title = adminName + " " + squareBracket(loggedInUserDesc(req)); framer.addInHead(hsansserif() + hmobilefix() + hresponstable() + hcss_responstableForForms()); framer.addInHead(loadJQuery2()); framer.addInHead(hjs_selectize()); framer.addInHead(hjs_copyToClipboard()); framer.addInHead(hNotificationPopups()); framer.addInHead(hcss_linkColorInherit()); if (useWebSockets) framer.addInHead(webSocketHeadStuff(req)); if (showTalkToBotLink) framer.addNavItem(simulateDomainLink(req.authDomain), "Talk to bot", "targetBlank", true); List classes = crudClasses(req); List cmdClasses = req.masterAuthed ? botCmdClasses() : null; for (Class c : classes) framer.addNavItem(makeClassNavItem(c, req)); if (nempty(cmdClasses)) framer.contents.add(p("Bot actions: " + joinWithVBar(map(cmdClasses, c -> makeClassNavItem(c, req))))); } public HCRUD makeCRUD(Class c, Req req) { return makeCRUD(c, req, req.framer); } public HCRUD makeCRUD(Class c, Req req, HTMLFramer1 framer) { HCRUD_Concepts data = crudData(c, req); data.referencesBlockDeletion = true; String search = trim(req.get("search")); data.customFilter = crudSearchFilter(req, data, search); HCRUD crud = new HCRUD(crudLink(c), data); crud.searchQuery = search; crud.params = req.params; crud.buttonsOnTop = neqOneOf(c, UploadedFile.class, UploadedSound.class, UploadedImage.class); crud.haveJQuery = crud.haveSelectizeJS = true; crud.sortable = true; crud.paginate = true; crud.paginator.step = 25; crud.cmdsLeft = true; crud.showCheckBoxes = true; crud.tableClass = "responstable"; crud.formTableClass = "responstableForForms"; if (!req.requestAuthed()) crud.disableAllMutationRights(); crud.renderValue_inner = value -> { if (isConceptList(value)) { List l = (List) value; return joinMap(l, ref -> p(ahref(conceptLink(ref), htmlEncode_nlToBr_withIndents(str(ref))))); } String html = crud.renderValue_inner_base(value); if (value instanceof Concept) return ahref(conceptLink(((Concept) value)), html); return html; }; if (c == Conversation.class) { crud.nav = () -> joinNemptiesWithVBar(crud.nav_base(), ahref(baseLink + "/cleanConversations", "Clean list")); crud.unshownFields = litset("oldDialogs", "worker", "botOn", "lastPing", "cookie", "form", "testMode", "userMessageProcessed", "newDialogTriggered"); } if (c == DeliveredDomain.class || c == Conversation.class || c == Lead.class || c == ConversationFeedback.class) crud.allowCreate = crud.allowEdit = false; if (c == Settings.class) { crud.singleton = countConcepts(Settings.class) == 1; if (!settings().multiLanguageMode) crud.unshownFields = litset("defaultLanguage"); { if (framer != null) framer.add(p(joinNemptiesWithVBar(ahref(baseLink + "/emojis", "Emojis"), ahref(baseLink + "/stats", "Stats"), ahref(baseLink + "/embedCode", "Embed Code")))); } } if (c == Lead.class) { if (framer != null) framer.add(p(ahref(baseLink + "/leads-csv", "Export as CSV"))); } if (c == BotOutgoingQuestion.class) { crud.unlistedFields = litset("multipleChoiceSeparator", "placeholder"); if (!enableRadioButtons) crud.unlistedFields.add("radioButtons"); crud.massageFormMatrix = (map, matrix) -> { int idx = indexOfPred(matrix, row -> cic(first(row), "Actions")); BotOutgoingQuestion item = getConcept(BotOutgoingQuestion.class, toLong(map.get(crud.idField()))); if (item == null) return; if (idx < 0) return; List row = matrix.get(idx); row.set(1, hcrud_mergeTables(row.get(1), tag("table", map(s -> tr(td() + td(htmlEncode2(s))), item.buttons)), "for:")); }; } data.addFilters(filtersForClass(c, req)); if (c == Domain.class) { crud.renderCmds = map -> { Domain dom = getConcept(Domain.class, toLong(crud.itemID(map))); return joinNemptiesWithVBar(crud.renderCmds_base(map), targetBlank(simulateDomainLink(dom.domainAndPath), "Talk to bot")); }; { if (framer != null) framer.add(p("See also the " + ahref(crudLink(DeliveredDomain.class), "list of domains the bot was delivered on"))); } } if (c == DeliveredDomain.class) { crud.nav = () -> joinNemptiesWithVBar(crud.nav_base(), ahref("/deleteDeliveredDomains", "Delete all")); crud.renderCmds = map -> { DeliveredDomain dom = getConcept(DeliveredDomain.class, toLong(crud.itemID(map))); return joinNemptiesWithVBar(crud.renderCmds_base(map), targetBlank(simulateDomainLink(dom.domain), "Talk to bot")); }; } if (c == UploadedImage.class) { crud.massageFormMatrix = (map, matrix) -> { UploadedImage item = getConcept(UploadedImage.class, toLong(crud.itemID(map))); addInFront(matrix, ll("Upload image", hjs_imgUploadBase64Encoder() + himageupload("id", "imgUploader") + hhiddenWithIDAndName("f_img_base64"))); }; crud.formParameters = () -> paramsPlus(crud.formParameters_base(), "onsubmit", "return submitWithImageConversion(this)"); } if (c == UploadedSound.class) { crud.massageFormMatrix = (map, matrix) -> { UploadedSound item = getConcept(UploadedSound.class, toLong(crud.itemID(map))); matrix.add(ll("Upload MP3", hjs_fileUploadBase64Encoder() + hmp3upload("id", "fileUploader") + hhiddenWithIDAndName("f_file_base64"))); }; crud.formParameters = () -> litparams("onsubmit", "return submitWithFileConversion(this)"); } if (c == UploadedFile.class) { crud.massageFormMatrix = (map, matrix) -> { UploadedFile item = getConcept(UploadedFile.class, toLong(crud.itemID(map))); matrix.add(ll("Upload File", hjs_fileUploadBase64Encoder() + hfileupload("id", "fileUploader") + hhiddenWithIDAndName("f_file_base64") + hjs("\r\n $(\"input[name=thefile]\").change(function(e) {\r\n var name = e.target.files[0].name;\r\n if (name)\r\n $(\"input[name=f_name]\").val(name); \r\n });\r\n "))); }; crud.formParameters = () -> litparams("onsubmit", "return submitWithFileConversion(this)"); } if (isSubclassOf(c, BotStep.class)) { crud.renderCmds = map -> { BotStep step = getConcept(BotStep.class, toLong(crud.itemID(map))); return joinNemptiesWithVBar(crud.renderCmds_base(map), targetBlank(simulateScriptLink(step), "Test in bot"), hPopDownButton(targetBlank(baseLink + "/dialogTree?stepID=" + step.id, "Show Dialog Tree"))); }; { if (framer != null) framer.add(p("See also the " + ahref(crudLink(DeliveredDomain.class), "list of domains the bot was delivered on"))); } } if (c == Worker.class) { crud.unshownFields = litset("lastOnline"); crud.uneditableFields = litset("available", "lastOnline"); } crud.postProcessTableRow = (item, rendered) -> { long id = crud.itemIDAsLong(item); Concept concept = getConcept(id); if (concept == null) return rendered; Collection refs = allBackRefs(concept); if (empty(refs)) return rendered; refs = sortedByConceptID(refs); String rts = req.get("refsToShow"); int refsToShow = empty(rts) ? maxRefsToShow : parseInt(rts); int more = l(refs) - refsToShow; return mapPlus(rendered, span_title("Where is this object used", "References"), joinMap(takeFirst(refsToShow, refs), ref -> p(ahref(conceptLink(ref), htmlEncode_nlToBr_withIndents(str(ref))))) + (more <= 0 ? "" : "
" + ahref(addParamsToURL(crudLink(concept), "refsToShow", 10000), "+" + more + " more"))); }; return crud; } public boolean isLinkableConcept(Concept c, Req req) { return req != null && c != null && contains(allLinkableClasses(req), _getClass(c)); } public String crudLink(Concept c) { return conceptLink(c, currentReq.get()); } public String conceptLink(Concept c) { return conceptLink(c, null); } public String conceptLink(Concept c, Req req) { if (req != null && !isLinkableConcept(c, req)) return null; return c == null ? null : appendQueryToURL(crudLink(c.getClass()), "selectObj", c.id, "showOnlySelected", showOnlySelectedObject ? "1" : null) + "#obj" + c.id; } public String conceptEditLink(Concept c, Object... __) { return c == null ? null : appendQueryToURL(crudLink(c.getClass()), paramsPlus(__, "edit", c.id)); } public String conceptDuplicateLink(Concept c) { return c == null ? null : appendQueryToURL(crudLink(c.getClass()), "duplicate", c.id); } public
String makeClassNavItem(Class c, Req req) { HCRUD_Concepts data = crudData(c, req); HCRUD crud = makeCRUD(c, req, null); Map filters = filtersForClass(c, req); int count = countConcepts(c, mapToParams(filters)); return (crud.singleton ? "" : n2(count) + " ") + ahref(crudLink(c), count == 1 ? data.itemName() : data.itemNamePlural()) + (!crud.actuallyAllowCreate() ? "" : " " + ahref(crud.newLink(), "+", "title", "Create New " + data.itemName())); } public Collection allLinkableClasses() { Req req = new Req(); req.masterAuthed = true; return allLinkableClasses(req); } public Collection allLinkableClasses(Req req) { return joinSets(crudClasses(req), botCmdClasses()); } public List botCmdClasses() { return dynNewBot2_botCmdClasses(); } public List dynNewBot2_botCmdClasses() { List l = ll(BotMessage.class, UploadedImage.class, BotImage.class, BotOutgoingQuestion.class, BotPause.class, Sequence.class); if (enableRandomActions) l.add(BotRandomAction.class); if (settings().multiLanguageMode) l.add(BotSwitchLanguage.class); return l; } public List crudClasses(Req req) { return dynNewBot2_crudClasses(req); } public List dynNewBot2_crudClasses(Req req) { if (req == null ? null : req.masterAuthed) { List l = ll(Conversation.class, Lead.class, ConversationFeedback.class, Domain.class, UserKeyword.class, UploadedSound.class, UploadedFile.class); if (enableAvatars) l.add(Avatar.class); l.add(Settings.class); if (settings().multiLanguageMode) l.add(Language.class); if (settings().enableWorkerChat) l.add(Worker.class); if (recordExecutionsAndInputs) addAll(l, ExecutedStep.class, InputHandled.class); return l; } else return ll(Conversation.class, Lead.class, ConversationFeedback.class); } public Map filtersForClass(Class c, Req req) { if (c == Conversation.class && req.authDomainObj != null) return litmap("domainObj", req.authDomainObj); if (eqOneOf(c, Lead.class, ConversationFeedback.class) && req.authDomainObj != null) return litmap("domain", req.authDomainObj); return null; } public String crudLink(Class c) { return baseLink + "/crud/" + shortName(c); } public HCRUD_Concepts crudData(Class c, Req req) { HCRUD_Concepts cc = new HCRUD_Concepts<>(c); if (useDynamicComboBoxes) cc.useDynamicComboBoxes = true; if (eq(req.get("dynamicComboBoxes"), "1")) cc.useDynamicComboBoxes = true; cc.trimAllSingleLineValues = true; cc.fieldHelp("comment", "Put any comment about this object here"); cc.itemName = () -> replaceIfEquals(dropPrefix("Bot ", cc.itemName_base()), "Jump Button", "Button"); cc.valueConverter = new DefaultValueConverterForField() { public OrError convertValue(Object object, Field field, Object value) { print("convertValue " + field + " " + className(value)); if (value instanceof String && eq(field.getGenericType(), type_LS())) { print("tlft"); return new OrError(tlft((String) value)); } return super.convertValue(object, field, value); } }; if (c == InputHandled.class) { cc.itemNamePlural = () -> "Inputs Handled"; } if (c == Domain.class) { cc.fieldHelp("domainAndPath", "without http:// or https://", "botName", "Bot name for this domain (optional)", "headerColorLeft", "Hex color for left end of header gradient (optional)", "headerColorRight", "Hex color for right end of header gradient (optional)", "autoOpenBot", "Open the bot when page is loaded", "password", "A separate password for people who can see only this domain", "pageRegexp", "A Java-style regular expression that filters which page the bot is shown on"); cc.massageItemMapForList = (item, map) -> { map.put("domainAndPath", new HTML(b(htmlEncode2(((Domain) item).domainAndPath)))); map.put("password", new SecretValue(map.get("password"))); }; } if (c == BotOutgoingQuestion.class) { cc.dropEmptyListValues = false; cc.addRenderer("displayText", new HCRUD_Data.TextArea(80, 10)); cc.addRenderer("buttons", new HCRUD_Data.TextArea(80, 10, o -> lines_rtrim((List) o))); cc.fieldHelp("displayText", displayTextHelp(), "key", "Internal key for question (any format, can be empty, put \"-\" to disable storing answer)", "defaultValue", "What the input field is prefilled with", "placeholder", "A text the empty input field shows as a hint", "buttons", "Buttons to offer as standard answers (one per line, use | to add a shortened version submitted as user input)", "allowFreeText", "Can user enter free text in addition to clicking a button?", "multipleChoice", "Can user select multiple buttons?", "optional", "Can user skip the question by entering nothing?", "multipleChoiceSeparator", "Internal field, just leave as it is", "answerCheck", "Select this to validate user's answer against a pattern", "buttonActions", "Optional actions (one for each button in the list above)", "radioButtons", "Show buttons as radio buttons"); cc.addRenderer("answerCheck", new HCRUD_Data.ComboBox("", "email address", "phone number")); cc.massageItemMapForList = (item, map) -> { map.put("buttons", new HTML(ol_htmlEncode(((BotOutgoingQuestion) item).buttons))); map.put("buttonActions", new HTML(ul(map(((BotOutgoingQuestion) item).buttonActions, action -> ahref(conceptLink(action), htmlEncode2_nlToBr(str(action))))))); }; } if (c == UserKeyword.class) { cc.fieldHelp("language", "Language that this keyword matches in (optional)", "pattern", targetBlank("http://code.botcompany.de:8081/getraw.php?id=1030319", "'PhraseCache'") + " matching pattern (most important field)", "examples", "Example inputs that should be matched (one per line, optional)", "counterexamples", "Example inputs that should be NOT matched (one per line, optional)", "action", "What bot does when input is matched", "enabled", "Uncheck to disable this keyword", "priority", "If set, this keyword overrides other input handlers (e.g. from outgoing questions)", "precedence", "Precedence over other keywords (higher value = match first)"); for (String field : ll("examples", "counterexamples")) cc.addRenderer(field, new HCRUD_Data.TextArea(80, 5, o -> lines_rtrim((List) o))); cc.massageItemMapForList = (item, map) -> { map.put("examples", lines_rtrim(((UserKeyword) item).examples)); map.put("counterexamples", lines_rtrim(((UserKeyword) item).counterexamples)); }; } if (c == Settings.class) { cc.fieldHelp("mainDomainName", "Domain where bot is hosted (to correctly send image and sound links)", "botTypingDelay", "Delay in seconds before bot sends message, base value", "botTypingDelayPerWord", "Delay in seconds before bot sends message, per word", "botTypingMaxDelay", "Delay in seconds before bot sends message, max value", "preferredCountryCodes", "Country codes to display first in list (e.g. \"+1, +91\")", "notificationSound", "Bot message notification sound (can leave empty, then we use the " + ahref(defaultNotificationSound(), "default sound"), "talkToBotOnlyWithAuth", "Show bot only to authorized persons", "mailLeadsTo", "Where to send a mail when a new lead occurs (addresses separated by comma)", "leadMailSubject", "Subject for lead notification mails"); } if (c == Conversation.class) cc.massageItemMapForList = (item, map) -> { replaceMap(map, litorderedmap("id", map.get("id"), "IP", map.get("ip"), "started", formatLocalDateWithMinutes(((Conversation) item).created), "country", map.get("country"), "msgs", lines_rtrim(((Conversation) item).msgs), "avatar", map.get("avatar"), "answers", htmlEncode2(renderColonProperties(((Conversation) item).answers)), "stack", new HTML(ol(cloneMap(((Conversation) item).stack, activeSeq -> htmlEncode2(str(activeSeq))))))); }; if (c == BotMessage.class) { cc.addRenderer("text", new HCRUD_Data.TextArea(80, 10)); cc.addRenderer("specialPurpose", new HCRUD_Data.ComboBox(itemPlus("", keys(specialPurposes)))); cc.fieldHelp("text", displayTextHelp(), "specialPurpose", "Special occasion when to display this message", "disableInput", "Check to disable user input while this message is showing"); } if (c == Form.class) cc.massageItemMapForList = (item, map) -> { map.put("steps", pnlToStringWithEmptyLines_rtrim(((Form) item).steps)); }; if (c == Sequence.class) cc.massageItemMapForList = (item, map) -> { map.put("steps", new HTML(ol(map(((Sequence) item).steps, step -> ahref(conceptLink(step), htmlEncode2_nlToBr(str(step))))))); }; if (c == BotImage.class) cc.massageItemMapForList = (item, map) -> { String url = ((BotImage) item).imageURL(); if (isURL(url)) map.put("Image Preview", new HTML(himg(url, "style", hcrud_imagePreviewStyle()))); map.put(cc.fieldNameToHTML("imageURL"), new HTML(htmlEncode2(url) + " " + himgsnippet("#1101381", "onclick", "copyToClipboard(" + jsQuote(url) + "); " + "window.createNotification({ theme: 'success', showDuration: 3000 })({ message: " + jsQuote("Image URL copied to clipboard") + "});"))); }; if (c == UploadedImage.class) { cc.massageItemMapForList = (item, map) -> { String url = ((UploadedImage) item).imageURL(); File f = ((UploadedImage) item).imageFile(); map.put("Image Size", toK_str(fileSize(f))); if (fileSize(f) > 0) map.put("Image Preview", new HTML(himg(url, "style", hcrud_imagePreviewStyle()))); }; IVF2 massageItemMapForUpdate_old = cc.massageItemMapForUpdate; cc.massageItemMapForUpdate = (item, map) -> { cc.massageItemMapForUpdate_fallback(massageItemMapForUpdate_old, item, map); String base64 = (String) map.get("img_base64"); print("Got base64 data: " + l(base64)); if (nempty(base64)) { File f = ((UploadedImage) item).imageFile(); saveFileVerbose(f, base64decode(base64)); } map.remove("img_base64"); }; } if (c == UploadedSound.class) { cc.massageItemMapForList = (item, map) -> { String url = ((UploadedSound) item).soundURL(); File f = ((UploadedSound) item).soundFile(); map.put("Sound Size", toK_str(fileSize(f))); if (fileSize(f) > 0) map.put("Test Sound", new HTML(ahref(url, "Test Sound"))); }; IVF2 massageItemMapForUpdate_old = cc.massageItemMapForUpdate; cc.massageItemMapForUpdate = (item, map) -> { cc.massageItemMapForUpdate_fallback(massageItemMapForUpdate_old, item, map); String base64 = (String) map.get("file_base64"); print("Got base64 data: " + l(base64)); if (nempty(base64)) { File f = ((UploadedSound) item).soundFile(); saveFileVerbose(f, base64decode(base64)); } map.remove("file_base64"); }; } if (c == UploadedFile.class) { cc.fieldHelp("name", "Also used as file name when downloading", "mimeType", "Content type (MIME type) for this file (optional)"); cc.massageItemMapForList = (item, map) -> { String url = ((UploadedFile) item).downloadURL(); File f = ((UploadedFile) item).theFile(); map.put("File Size", toK_str(fileSize(f))); if (fileSize(f) > 0) map.put("Download", new HTML(ahref(url, "Download"))); }; IVF2 massageItemMapForUpdate_old = cc.massageItemMapForUpdate; cc.massageItemMapForUpdate = (item, map) -> { cc.massageItemMapForUpdate_fallback(massageItemMapForUpdate_old, item, map); String base64 = (String) map.get("file_base64"); print("Got base64 data: " + l(base64)); if (nempty(base64)) { File f = ((UploadedFile) item).theFile(); saveFileVerbose(f, base64decode(base64)); } map.remove("file_base64"); }; } if (c == Worker.class) { cc.massageItemMapForList = (item, map) -> { AbstractBotImage image = ((Worker) item).image.get(); if (image != null) map.put("Image Preview", new HTML(himg(image.imageURL(), "style", hcrud_imagePreviewStyle()))); }; } if (c == Avatar.class) { cc.fieldHelp("shift", "hours when avatar is active, e.g. 8-18 (leave empty if always on shift, put 0-0 if never on shift)"); cc.massageItemMapForList = (item, map) -> { map.put("On Shift Now", ((Avatar) item).onShift()); }; } return cc; } public Map crudHelp() { return litmap(DeliveredDomain.class, "This list is filled by the bot with the domains it was delivered on. " + "Some may be bogus, we write down whatever the browser sends."); } public void saveDeliveredDomain(String domain) { if (empty(domain)) return; uniqCI(DeliveredDomain.class, "domain", beforeColonOrAll(domain)); } public void cleanConversations() { withDBLock(new Runnable() { public void run() { try { cdelete(filter(list(Conversation.class), c -> l(c.msgs) <= 1 && elapsedSeconds_timestamp(c.created) >= 60 & c.lastPing == 0)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cdelete(filter(list(Conversation), c -> l(c.msgs) <= 1\r\n && elapsedSec..."; } }); } public void deleteDeliveredDomains() { cdelete(DeliveredDomain.class); } public Object serveThoughts(Req req) { HTMLFramer1 framer = new HTMLFramer1(); framer.addInHead(hsansserif() + hmobilefix()); framer.add(div_floatRight(hbutton("Reload", "onclick", "location.reload()"))); framer.add(h2("Bot Thoughts")); if (req.conv == null) framer.add("No conversation"); else { framer.add(p("Conversation cookie: " + req.conv.cookie)); Conversation conv = req.conv; framer.add(h3("Stack")); framer.add(empty(conv.stack) ? p("empty") : ol(lmap(__61 -> htmlEncode2_gen(__61), reversed(conv.stack)))); } return framer.render(); } public Object serveSearch(Req req) { makeFramer(req); HTMLFramer1 framer = req.framer; framer.add("Search here"); return framer.render(); } transient public boolean debug = false; public Domain findDomainObj(String domain) { Domain domainObj = conceptWhereCI(Domain.class, "domainAndPath", domain); if (domainObj == null) domainObj = defaultDomain(); return domainObj; } public Domain defaultDomain() { return uniqCI(Domain.class, "domainAndPath", ""); } transient public int longPollTick = 200; transient public int longPollMaxWait = 1000 * 30; transient public int activeConversationSafetyMargin = 30000; transient public Set specialButtons = litciset("Cancel", "Back", "Abbrechen", "Zurück"); public String dbStats() { Collection all = list(Conversation.class); int nRealConvos = countPred(all, c -> l(c.msgs) > 1); return nConversations(nRealConvos); } public String realPW() { return loadTextFileOrCreateWithRandomID(realPWFile()); } public File realPWFile() { return secretProgramFile("password.txt"); } public String serveAuthForm(String redirect) { redirect = dropParamFromURL(redirect, "logout"); if (empty(redirect)) redirect = baseLink + "/"; return hhtml(hhead(htitle(botName + ": Log-In") + hsansserif() + hmobilefix()) + hbody(hfullcenter(authFormHeading() + hpostform(hhidden("redirect", redirect) + tag("table", (enableUsers ? tr(td("User:") + td(hinputfield("user")) + td()) : "") + tr(td("Password:") + td(hpassword("pw")) + td(hsubmit("Log in")))), "action", baseLink) + (!showTalkToBotLink ? "" : p(ahref(baseLink + "/demo", "Talk to bot"))) + (!showRegisterLink ? "" : p(hbuttonLink(baseLink + "/register", "Register as new user"))) + authFormMoreContent()))); } public String authFormHeading() { return h3_htmlEncode(adminName); } public String authFormMoreContent() { return ""; } public String leadsToCSV(Collection leads) { List fields = ciContentsIndexedList(); List rows = new ArrayList(); for (Lead lead : unnull(leads)) { List row = new ArrayList(); for (Map.Entry __21 : _entrySet(unnull(mapPlus_inFront((Map) (Map) lead.answers, "Date", formatLocalDateWithMinutes(lead.date.date), "Domain", lead.domain.get(), "Conversation ID", conceptID(lead.conversation.get()))))) { String key = __21.getKey(); Object val = __21.getValue(); int idx = fields.indexOf(key); if (idx < 0) idx = addAndReturnIndex(fields, key); listSet(row, idx, val, ""); } rows.add(row); } return formatCSVFileForExcel2(itemPlusList(fields, rows)); } public String countryCodeOptions(Conversation conv) { Collection countryCodes = putSetElementsFirst(keys(countryDialCodesMultiMap()), splitAtComma_trim(settings().preferredCountryCodes)); String selected = dialCodeStringForCountryCode(conv.country); return mapToLines(c -> { List cdc = countryDialCodesMultiMap().get(c); String text = nempty(cdc) ? c + " [" + joinWithComma(collectSorted("countryCode", cdc)) + "]" : c; return tag("option", text, "value", c, "selected", eq(c, selected) ? html_valueLessParam() : null); }, itemPlus("", countryCodes)); } public List addTypingDelays(List steps) { return concatMap(steps, step -> { double delay = step.preTypingDelay(); if (delay <= 0) return ll(step); return ll(new BotSendTyping(), new BotPause(delay), step); }); } public BotMessage messageForPurpose(String specialPurpose) { return conceptWhere(BotMessage.class, "specialPurpose", specialPurpose); } public Object serveLeadsAPI(Object req) { Map headers = (Map) (rcall("headers", req)); Map params = (Map) (get("params", req)); String tenantID = params.get("tenantID"); if (empty(tenantID)) return serveJSONError("Empty tenantID"); String pw = params.get("pw"); if (empty(pw)) pw = dropPrefix_trim("Bearer ", headers.get("Authorization")); if (empty(pw)) return serveJSONError("Empty password"); Domain domain = conceptWhere(Domain.class, "tenantID", tenantID); if (domain == null) return serveJSONError("Tenant ID not found"); if (neq(domain.password, pw)) return serveJSONError("Bad passsword"); Collection leads = conceptsWhere(Lead.class, "domain", domain); return serveJSON(map(leads, lead -> { Map map = litorderedmap("tenantID", tenantID, "leadID", lead.id, "domain", str(lead.domain), "date", formatLocalDateWithSeconds(lead.created), "data", lead.answers); return map; })); } public Object serveJSONError(String error) { return serveJSON(litorderedmap("error", error)); } public String botImageForDomain(Domain domainObj) { String botImg = imageSnippetURLOrEmptyGIF(chatHeaderImageID); if (domainObj != null && domainObj.botImage.has()) botImg = domainObj.botImage.get().imageURL(); else if (defaultDomain().botImage.has()) botImg = defaultDomain().botImage.get().imageURL(); return botImg; } public String simulateDomainLink(String domain) { return appendQueryToURL(baseLink + "/demo", "_botConfig", makePostData("domain", domain), "_newConvCookie", 1, "_autoOpenBot", 1); } public String simulateScriptLink(BotStep script) { return appendQueryToURL(baseLink + "/demo", "_botConfig", makePostData("mainScript", script.id), "_newConvCookie", 1, "_autoOpenBot", 1); } public Scorer consistencyCheckResults() { if (consistencyCheckResults == null) consistencyCheckResults = doConsistencyChecks(); return consistencyCheckResults; } public Scorer doConsistencyChecks() { Scorer scorer = scorerWithSuccessesAndErrors(); for (UserKeyword uk : list(UserKeyword.class)) try { localConsistencyCheck(uk, scorer); } catch (Throwable e) { scorer.addError(htmlEncode2(str(e))); } try { globalConsistencyCheck(scorer); } catch (Throwable e) { scorer.addError(htmlEncode2(str(e))); } return scorer; } public void localConsistencyCheck(UserKeyword uk, Scorer scorer) { String patHTML = span_title(str(uk.parsedPattern()), htmlEncode2(uk.pattern)); String item = "[Entry " + ahref(conceptLink(uk), uk.id) + "] "; for (String input : unnull(uk.examples)) { boolean ok = uk.matchWithTypos(input); scorer.add(ok, ok ? item + "Example OK: " + patHTML + " => " + htmlEncode2(quote(input)) : item + "Example doesn't match pattern: " + patHTML + " => " + htmlEncode2(quote(input))); } for (String input : unnull(uk.counterexamples)) { boolean ok = !uk.matchWithTypos(input); scorer.add(ok, ok ? item + "Counterexample OK: " + patHTML + " => " + htmlEncode2(quote(input)) : item + "Counterexample matches pattern: " + patHTML + " => " + htmlEncode2(quote(input))); } } public void globalConsistencyCheck(Scorer scorer) { List list = concatLists(enabledUserKeywordsForPriority(true), enabledUserKeywordsForPriority(false)); for (UserKeyword uk : list) for (String example : unnull(uk.examples)) { String item1 = ahref(conceptLink(uk), uk.id); UserKeyword found = firstThat(list, uk2 -> uk2.matchWithTypos(example)); if (found == null) continue; if (found == uk) scorer.addOK("[Entry " + item1 + "] Global check OK for input " + htmlEncode2(quote(example))); else { String item2 = ahref(conceptLink(found), found.id); String items = "[Entries " + item1 + " and " + item2 + "] "; scorer.addError(items + "Input " + htmlEncode2(quote(example)) + " shadowed by pattern: " + htmlEncode2(quote(found.pattern)) + ". Try reducing precedence value of entry " + item2 + " or increasing precedence value of entry " + item1); } } } static public Collection enabledUserKeywordsForPriority(boolean priority) { return sortByFieldDesc("precedence", conceptsWhere(UserKeyword.class, onlyNonNullParams("priority", priority))); } public boolean handleGeneralUserInput(Conversation conv, Msg msg, Boolean priority) { for (UserKeyword qa : enabledUserKeywordsForPriority(priority)) { if (qa.enabled && qa.matchWithTypos(msg.text)) { print("Matched pattern: " + qa.pattern + " / " + msg.text); conv.noteEvent(new EvtMatchedUserKeyword(qa, msg)); conv.callSubroutine(qa.action.get()); conv.scheduleNextStep(); return true; } } return false; } public void didntUnderstandUserInput(Conversation conv, Msg msg) { } transient public Settings settings_cache; public Settings settings() { if (settings_cache == null) settings_cache = settings_load(); return settings_cache; } public Settings settings_load() { return conceptWhere(Settings.class); } public String displayTextHelp() { return "Text to show to user (can include HTML and " + targetBlank(baseLink + "/emojis", "emojis") + ")"; } public void botActions() { Lock __7 = lockWhileDoingBotActions ? dbLock() : null; lock(__7); try { while (licensed()) { ScheduledAction action = lowestConceptByField(ScheduledAction.class, "time"); if (action == null) break; if (action.time > now()) { doAfter(100, rstBotActions); break; } cdelete(action); print("Executing action " + action); try { action.run(); } catch (Throwable __e) { _handleException(__e); } } } finally { unlock(__7); } } public void addScheduledAction(ScheduledAction action) { addScheduledAction(action, 0); } public void addScheduledAction(ScheduledAction action, long delay) { action.time = now() + delay; registerConcept(action); rstBotActions.trigger(); } transient public ThreadLocal out = new ThreadLocal(); transient public ThreadLocal conv = new ThreadLocal(); transient public long lastConversationChange = now(); public void makeIndices() { indexConceptFieldDesc(ScheduledAction.class, "time"); indexConceptFieldCI(Domain.class, "domainAndPath"); indexConceptFieldCI(DeliveredDomain.class, "domain"); indexConceptFieldCI(CannedAnswer.class, "hashTag"); indexConceptFieldCI(Language.class, "languageName"); indexConceptField(Lead.class, "domain"); indexConceptField(ConversationFeedback.class, "domain"); indexConceptField(UploadedFile.class, "liveURI"); } public void startDB() { db(); } public void pWebChatBot() { db_mainConcepts().storeBaseClassesInStructure = storeBaseClassesInStructure || storeBaseClassesInStructure; startDB(); indexConceptFields(Conversation.class, "cookie", Conversation.class, "worker", Conversation.class, "lastPing", Worker.class, "loginName", AuthedDialogID.class, "cookie"); db_mainConcepts().miscMapPut(DynNewBot2.class, this); indexSingletonConcept(Settings.class); uniq(Settings.class); makeIndices(); indexAllLinkableClasses(); uniq(BotSaveLead.class); uniq(BotSaveFeedback.class); uniq(BotClearStack.class); uniq(BotEndConversation.class); uniq(BotDoNothing.class); uniq(BotIdleMode.class); uniq(BotNewDialog.class); if (enableUndoStates) uniq(BotGoBack.class); if (enableAvatars) uniq(RandomAvatar.class); } public void addReplyToConvo(Conversation conv, IF0 think) { out.set(new Out()); String reply = ""; try { reply = think.get(); } catch (Throwable __e) { _handleException(__e); } Msg msg = new Msg(false, reply); msg.out = out.get(); conv.add(msg); } public Msg msgFromThinkFunction(IF0 think) { out.set(new Out()); String reply = ""; try { reply = think.get(); } catch (Throwable __e) { _handleException(__e); } Msg msg = new Msg(false, reply); msg.out = out.get(); return msg; } public Object withHeader(String html) { return withHeader(subBot_noCacheHeaders(subBot_serveHTML(html))); } public Object withHeader(Object response) { call(response, "addHeader", "Access-Control-Allow-Origin", "*"); return response; } public String renderMessageText(String text, boolean htmlEncode) { text = trim(text); if (eqic(text, "!rate conversation")) text = "Rate this conversation"; if (htmlEncode) text = htmlEncode2(text); text = nlToBr(text); return html_emojisToUnicode(text); } public void renderMessages(Conversation conv, StringBuilder buf, List msgs) { renderMessages(conv, buf, msgs, msg -> msg == last(msgs)); } public void renderMessages(Conversation conv, StringBuilder buf, List msgs, IF1 showButtons) { if (empty(msgs)) return; ChatRenderer renderer = makeChatRenderer(currentReq.get()); for (Msg m : msgs) { boolean showTheButtons = showButtons.get(m); if (m.fromUser || neqOneOf(m.text, "-", "") || showTheButtons && m.out != null && nempty(m.out.buttons)) renderer.appendMsg(conv, buf, m, showTheButtons); if (showTheButtons) { buf.append(hscript(botMod().phoneNumberSpecialInputField ? "$(\"#chat_telephone, .iti\").hide(); $(\"#chat_message\").show().prop('disabled', false).focus();" : "$(\"#chat_message\").prop('disabled', false).focus();")); if (m.out != null && nempty(m.out.javaScript)) buf.append(hscript(m.out.javaScript)); } } } abstract public class ChatRenderer { abstract public void appendMsg(Conversation conv, StringBuilder buf, Msg m, boolean showButtons); public Conversation conv; public String id; public Msg m; public String html; public String name; public String time; public String text; public boolean bot = false; public Worker fromWorker; public Out out; public List labels; public boolean useTrick = false; public String author; public String imgURL; public void prepare(Conversation conv, Msg m) { this.conv = conv; this.m = m; html = renderMessageText(m.text, shouldHtmlEncodeMsg(m)); name = m.fromUser ? defaultUserName() : botName; time = formatTime(m.time); text = html; modifyTextForRendering(); bot = !m.fromUser; fromWorker = m.fromWorker; out = m.out; labels = m.labels; useTrick = ariaLiveTrick; id = randomID(); author = fromWorker != null ? htmlEncode2(fromWorker.displayName) : botName; if (bot) { if (fromWorker != null && fileExists(workerImageFile(fromWorker.id))) imgURL = fullRawLink("worker-image/" + fromWorker.id); else imgURL = conv.botImg(); } } public void modifyTextForRendering() { if (eqic(text, "!back")) text = unicode_undoArrow(); } abstract public String renderMultipleChoice(List buttons, Collection selections, String multipleChoiceSeparator); public String renderSingleChoice(List buttons) { List out = new ArrayList(); for (int i = 0; i < l(buttons); i++) { String code = buttons.get(i); String text = replaceButtonText(code); String userInput = htmldecode_dropAllTags(text); List split = splitAtVerticalBar(text); if (l(split) == 2) { userInput = second(split); text = code = first(split); } out.add(hbuttonOnClick_returnFalse(text, "submitAMsg(" + jsQuote(userInput) + ")", "class", "chatbot-choice-button automated-message", "title", eq(code, text) ? null : code)); if (!specialButtons.contains(code) && i + 1 < l(buttons) && specialButtons.contains(buttons.get(i + 1))) out.add("  "); } return lines(out); } } public class ChatRendererSahilStyle extends ChatRenderer { public void appendMsg(Conversation conv, StringBuilder buf, Msg m, boolean showButtons) { prepare(conv, m); List div = new ArrayList(); List inMessage = new ArrayList(); List afterMessage = new ArrayList(); if (!bot) imgURL = "/pays5/imgs/icons/avatar.svg"; if (nempty(imgURL)) { div.add(div("", "class", "bg-img", "role", "img", "aria-labelledby", m.fromUser ? "Avatar" : "Bot", "style", "background-image: url('" + imgURL + "')")); } if (showButtons) appendButtons(inMessage, afterMessage, m.out); div.add(span(text + lines(inMessage), "class", "message")); div.add(span(time, "class", "message-timestamp")); buf.append(div(lines(div) + lines(afterMessage), "class", "message-wrapper" + stringUnless(bot, " user"))).append("\n"); } public void appendButtons(List inMessage, List afterMessage, Out out) { String placeholder = out == null ? "" : unnull(out.placeholder); String defaultInput = out == null ? "" : unnull(out.defaultInput); inMessage.add(hscript("chatBot_setInput(" + jsQuote(defaultInput) + ", " + jsQuote(placeholder) + ");")); if (out == null) return; List buttons = out.buttons; if (empty(buttons)) return; String buttonsHtml; if (out.multipleChoice) inMessage.add(span(renderMultipleChoice(buttons, text_multipleChoiceSplit(out.defaultInput, out.multipleChoiceSeparator), out.multipleChoiceSeparator), "class", "select-options")); else if (out.radioButtons) inMessage.add(span(renderRadioButtons(buttons, out.defaultInput), "class", "select-options")); else afterMessage.add(div(renderSingleChoice(buttons), "class", "automated-messages")); } public String renderMultipleChoice(List buttons, Collection selections, String multipleChoiceSeparator) { Set selectionSet = asCISet(selections); String rand = randomID(); String className = "chat_multiplechoice_" + rand; String allCheckboxes = "$(\"." + className + "\")"; if (eq(multipleChoiceSeparator, ",")) multipleChoiceSeparator += " "; return joinWithBR(map(buttons, name -> span(span("", "class", "square-box") + " " + name, "class", className + " option" + stringIf(contains(selectionSet, name), " selected"), "data-value", name))) + "
" + hbuttonOnClick_returnFalse("OK", "submitMsg()", "class", "btn btn-ok") + hscript(replaceDollarVars("\r\n $(\".$className *, .$className\").click(function(e) {\r\n e.stopImmediatePropagation(); // prevent double firing\r\n\r\n // toggle check box\r\n console.log(\"Target: \" + e.target);\r\n $(e.target).closest(\".option\").toggleClass(\"selected\");\r\n\r\n // update message\r\n var theList = $('.$className.selected').map(function() { return this.dataset.value; }).get();\r\n console.log('theList: ' + theList);\r\n $('#chat_message').val(theList.join($sep));\r\n });\r\n //$(\".$className *\").click(function(e) { e.stopPropagation(); });\r\n ", "className", className, "sep", jsQuote(multipleChoiceSeparator))); } public String renderRadioButtons(List buttons, String selection) { String rand = randomID(); String className = "chat_radio_" + rand; String allRadioButtons = "$(\"." + className + "\")"; return joinWithBR(map(buttons, name -> span(span("", "class", "square-box round") + " " + name, "class", className + " option" + stringIf(eqic(selection, name), " selected"), "data-value", name))) + (quickRadioButtons ? "" : "
" + hbuttonOnClick_returnFalse("OK", "submitMsg()", "class", "btn btn-ok")) + hscript(replaceDollarVars("\r\n $(\".$className *, .$className\").click(function(e) {\r\n e.stopImmediatePropagation(); // prevent double firing\r\n var option = $(e.target).closest(\".option\");\r\n \r\n // clear other radio buttons\r\n $(\".$className\").removeClass(\"selected\");\r\n\r\n // activate radio button\r\n option.addClass(\"selected\");\r\n\r\n // update message\r\n $('#chat_message').val(option[0].dataset.value);\r\n\r\n if ($quickRadioButtons)\r\n submitMsg();\r\n });\r\n //$(\".$className *\").click(function(e) { e.stopPropagation(); });\r\n ", "className", className, "quickRadioButtons", quickRadioButtons)); } } public class ChatRendererHusainStyle extends ChatRenderer { public void appendMsg(Conversation conv, StringBuilder buf, Msg m, boolean showButtons) { prepare(conv, m); String tag = useTrick ? "div" : "span"; if (bot) { if (nempty(m.text)) { if (fromWorker != null) buf.append("

" + author + "

"); buf.append("<" + tag + " class=\"chat_msg_item chat_msg_item_admin\"" + (useTrick ? " id=\"" + id + "\" aria-live=\"polite\" tabindex=\"-1\"" : "") + ">"); if (nempty(imgURL)) buf.append("\r\n
\r\n \r\n
".replace("$IMG", imgURL)); buf.append("" + (fromWorker != null ? "" : botName + " ") + "says"); buf.append(text); buf.append(""); if (fromWorker != null) buf.append("
"); if (useTrick) buf.append(hscript("$('#" + id + "').focus();")); } } else buf.append(("\r\n You say\r\n <" + tag + " class=\"chat_msg_item chat_msg_item_user\"" + (useTrick ? " aria-live=\"polite\"" : "") + ">$TEXT\r\n ").replace("$TEXT", text)); if (nempty(labels)) buf.append(span(join("   ", map(labels, lbl -> span("  " + lbl + "  "))), "class", "labels chat_msg_item chat_msg_item_user")).append("\n"); if (showButtons) appendButtons(buf, out, null); } public void appendButtons(StringBuilder buf, Out out, Set buttonsToSkip) { String placeholder = out == null ? "" : unnull(out.placeholder); String defaultInput = out == null ? "" : unnull(out.defaultInput); if (out != null && out.disableInput) buf.append(hscript(jsDisableInputField())); else buf.append(hscript("chatBot_setInput(" + jsQuote(defaultInput) + ", " + jsQuote(placeholder) + ");")); if (out == null) return; List buttons = listMinusSet(out.buttons, buttonsToSkip); if (empty(buttons)) return; String buttonsHtml; if (out.multipleChoice) buttonsHtml = renderMultipleChoice(buttons, text_multipleChoiceSplit(out.defaultInput, out.multipleChoiceSeparator), out.multipleChoiceSeparator); else buttonsHtml = renderSingleChoice(buttons); buf.append(span(buttonsHtml, "class", "chat_msg_item chat_msg_item_admin chat_buttons" + stringIf(!out.multipleChoice, " single-choice"))); } public String renderMultipleChoice(List buttons, Collection selections, String multipleChoiceSeparator) { Set selectionSet = asCISet(selections); String rand = randomID(); String className = "chat_multiplechoice_" + rand; String allCheckboxes = "$(\"." + className + "\")"; return joinWithBR(map(buttons, name -> hcheckbox("", contains(selectionSet, name), "value", name, "class", className) + " " + name)) + "
" + hbuttonOnClick_returnFalse("OK", "submitMsg()", "class", "btn btn-ok") + hscript(allCheckboxes + ".change(function() {" + " var theList = $('." + className + ":checkbox:checked').map(function() { return this.value; }).get();" + " console.log('theList: ' + theList);" + " $('#chat_message').val(theList.join(" + jsQuote(multipleChoiceSeparator) + "));" + "});"); } } public String replaceButtonText(String s) { if (standardButtonsAsSymbols) { if (eqicOneOf(s, "back", "zurück")) return unicode_undoArrow(); if (eqicOneOf(s, "cancel", "Abbrechen")) return unicode_crossProduct(); } return s; } public void appendDate(StringBuilder buf, String date) { buf.append("\r\n
\r\n DATE\r\n
".replace("DATE", date)); } public boolean lastUserMessageWas(Conversation conv, String message) { Msg m = last(conv.msgs); return m != null && m.fromUser && eq(m.text, message); } public String formatTime(long time) { return timeInTimeZoneWithOptionalDate_24(timeZone, time); } public String formatDialog(String id, List msgs) { List lc = new ArrayList(); for (Msg m : msgs) lc.add(htmlencode((m.fromUser ? "> " : "< ") + m.text)); return id + ul(lc); } public Conversation getConv(final String cookie) { return uniq(Conversation.class, "cookie", cookie); } public String errorMsg(String msg) { return hhtml(hhead_title("Error") + hbody(hfullcenter(msg + "

" + ahref(jsBackLink(), "Back")))); } public String defaultUserName() { return "You"; } public boolean botOn() { return true; } public boolean botAutoOpen(Domain domain) { return getDomainValue(domain, d -> d.autoOpenBot, false); } public File workerImageFile(long id) { return id == 0 ? null : javaxDataDir("adaptive-bot/images/" + id + ".jpg"); } public long activeConversationTimeout() { return longPollMaxWait + activeConversationSafetyMargin; } public AuthedDialogID authObject(String cookie) { AuthedDialogID auth = empty(cookie) ? null : conceptWhere(AuthedDialogID.class, "cookie", cookie); printVars_str("cookie", cookie, "auth", auth); return auth; } public boolean anyInterestingMessages(List msgs, boolean workerMode) { return any(msgs, m -> m.fromUser == workerMode); } public boolean shouldHtmlEncodeMsg(Msg msg) { return msg.fromUser; } public void calcCountry(Conversation c) { cset(c, "country", ""); getCountry(c); } public String getCountry(Conversation c) { if (empty(c.country) && nempty(c.ip)) cset(c, "country", ipToCountry2020_safe(c.ip)); return or2(c.country, "?"); } public void initAvatar(Conversation c) { if (enableAvatars && !c.avatar.has() && c.domainObj.has()) { AbstractAvatar a = c.domainObj.get().avatar.get(); Avatar avatar = a == null ? null : a.getActualAvatar(); cset(c, "avatar", avatar); } } public void noteConversationChange() { lastConversationChange = now(); } public String template(String hashtag, Object... params) { return replaceSquareBracketVars(getCannedAnswer(hashtag), params); } public String getCannedAnswer(String hashTag) { return getCannedAnswer(hashTag, null); } public String getCannedAnswer(String hashTag, Conversation conv) { return hashTag; } public List text_multipleChoiceSplit(String input, String multipleChoiceSeparator) { return trimAll(splitAt(input, dropSpaces(multipleChoiceSeparator))); } public Msg lastBotMsg(List l) { return lastThat(l, msg -> !msg.fromUser); } public File uploadedImagesDir() { return programDir("uploadedImages"); } public File uploadedSoundsDir() { return programDir("uploadedSounds"); } public File uploadedFilesDir() { return programDir("uploadedFiles"); } public String defaultNotificationSound() { return "https://botcompany.de/files/1400403/notification.mp3"; } public String convertToAbsoluteURL(String url) { if (isURL(url)) return url; String domain = settings().mainDomainName; return empty(domain) ? url : "https://" + domain + addSlashPrefix(url); } public String absoluteAdminURL() { return convertToAbsoluteURL(baseLink); } public void editMasterPassword() { if (!confirmOKCancel("Are you sure? This will reveal the password.")) return; JTextField tf = jtextfield(realPW()); showFormTitled2(botName + " master password", "Password", tf, new Runnable() { public void run() { try { String pw = gtt(tf); if (empty(pw)) infoBox("Empty password, won't save"); else { saveTextFile(realPWFile(), pw); infoBox("Saved new password for " + adminName); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String pw = gtt(tf);\r\n if (empty(pw)) infoBox(\"Empty password, won't s..."; } }); } public void editMailSenderInfo() { JTextField tf = jtextfield(realPW()); inputText("Mail sender info", mailSenderInfo, new VF1() { public void get(String mailSenderInfo) { try { setField("mailSenderInfo", mailSenderInfo); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "setField(+mailSenderInfo);"; } }); } public Object handleAuth(Req req, String cookie) { String pw = trim(req.params.get("pw")); if (nempty(pw) && nempty(cookie)) { Domain authDomain; if (eq(pw, realPW())) cset(uniq(AuthedDialogID.class, "cookie", cookie), "restrictedToDomain", null, "master", true); else if ((authDomain = conceptWhere(Domain.class, "password", pw)) != null) cset(uniq(AuthedDialogID.class, "cookie", cookie), "restrictedToDomain", authDomain, "master", false); else return errorMsg("Bad password, please try again"); String redirect = req.params.get("redirect"); if (nempty(redirect)) return hrefresh(redirect); } return null; } public String loggedInUserDesc(Req req) { return req.masterAuthed ? "super user" : htmlEncode2(req.authDomain); } public Object redirectToHttps(Req req) { if (!req.webRequest.isHttps()) return subBot_serveRedirect("https://" + req.webRequest.domain() + req.uri + htmlQuery(req.params)); return null; } public void startMainScript(Conversation conv) { initAvatar(conv); Domain domain = conv.domainObj.get(); if (domain == null) { botMod().addReplyToConvo(conv, () -> "Error: No domain set"); return; } BotStep seq = getConcept(BotStep.class, parseLong(mapGet(conv.botConfig, "mainScript"))); if (seq == null) seq = domain.mainScript.get(); if (seq == null) { botMod().addReplyToConvo(conv, () -> "Error: No main script set for " + htmlEncode2(str(domain))); return; } conv.callSubroutine(seq); if (enableUndoStates) conv.addUndoState(); conv.scheduleNextStep(); } public boolean isRequestFromBot(Req req) { return false; } public String modifyTemplateBeforeDelivery(String html, Req req) { return html; } public String headingForReq(Req req) { return null; } public Object serveHomePage() { return null; } public void possiblyTriggerNewDialog(Conversation conv) { if (empty(conv.msgs) && conv.newDialogTriggered < conv.archiveSize()) { cset(conv, "newDialogTriggered", conv.archiveSize()); addScheduledAction(new OnNewDialog(conv)); } } public String rewriteBotMessage(Conversation conv, String text) { if (!enableVars || conv == null) return text; text = html_evaluateIfTags(text, var -> eqic("true", print("if " + var + ": ", calcVar(conv, dropDollarPrefix(var))))); print("text", text); text = replaceDollarVars_dyn(text, var -> print("calcVar " + var, calcVar(conv, var))); return text; } public String calcVar(Conversation conv, String var) { if (conv == null) return null; { String val = syncGet(conv.answers, var); if (val != null) return val; } if (eqic(var, "botName") && conv.avatar.has()) return conv.avatar.get().name; return null; } public String cssURL() { return serveSnippetURL(cssID); } public class RenderDialogTree { public Set seen = new HashSet(); public String render(BotStep step) { if (!seen.add(step)) return "[see above] " + htmlEncode2(str(step)); List children = new ArrayList(); if (step instanceof Sequence) for (Pair __0 : iterateWithIndex1(((Sequence) step).steps)) { int i = pairA(__0); BotStep step2 = pairB(__0); children.add("Step " + i + ": " + renderDialogTree(step2)); } if (step instanceof BotOutgoingQuestion) for (Pair __1 : ((BotOutgoingQuestion) step).buttonsWithActions()) { String input = pairA(__1); BotStep step2 = pairB(__1); children.add("If user says " + b(htmlEncode2(quote(last(splitAtVerticalBar(input))))) + "

=> " + (step2 == null ? "no action defined" : renderDialogTree(step2))); } return stepToHTMLFull(step) + ulIfNempty(children, "class", "dialogTree"); } } public String stepToHTMLFull(BotStep step) { if (step == null) return "-"; String link = conceptLink(step, currentReq.get()); return ahref_unstyled(link, prependSquareBracketed(step.id)) + ahref(link, htmlEncode2_nlToBr(step.fullToString())); } public String renderDialogTree(BotStep step) { return new RenderDialogTree().render(step); } public ChatRenderer makeChatRenderer(Req req) { String botLayout = req.params.get("botLayout"); String layout = or2(botLayout, defaultBotLayout()); return eqic(layout, "sahil") ? new ChatRendererSahilStyle() : new ChatRendererHusainStyle(); } public String defaultBotLayout() { return "husain"; } public boolean allowedTemplateID(String id) { return false; } public double typingDelayForText(String text) { double perWord = settings().botTypingDelayPerWord; double x = settings().botTypingDelay; if (perWord != 0) x += countWords(dropHTMLTags(text)) * settings().botTypingDelayPerWord; double max = settings().botTypingMaxDelay; if (max != 0) x = min(x, max); return x; } public String nameOfBotSide(Conversation conv) { String __9 = calcVar(conv, "botName"); if (!empty(__9)) return __9; return "Representative"; } public void addThingsAboveCRUDTable(Req req, Class c, List aboveTable) { } public boolean checkPhoneNumber(String s) { return isValidInternationalPhoneNumber(s); } public void onNewLead(Lead lead) { for (String address : splitAtComma_trim(settings().mailLeadsTo)) try { String text = formatColonProperties(lead.answers); sendMailThroughScript(mailSenderInfo, "auto@botcompany.de", address, settings().leadMailSubject, text); } catch (Throwable e) { printStackTrace(e); appendToFile(programFile("mail-errors"), getStackTrace(e)); } } public void doUndo(Conversation conv) { UndoState undoState = syncNextToLast(conv.undoStates); print("Undo state: " + undoState); if (undoState != null) { syncRemoveLast(2, conv.undoStates); conv.dropScheduledActions(); syncReplaceCollection(conv.stack, undoState.stack); print("Stack after undo: " + conv.stack); conv.scheduleNextStep(); } } public Object serveCRUD(Req req) { String uri = req.uri(); List classes = crudClasses(req); List cmdClasses = req.masterAuthed ? botCmdClasses() : null; printVars_str("serveCRUD", "uri", uri, "classes", classes, "baseLink", baseLink); for (Class c : (Set) asSet(flattenList2(classes, DeliveredDomain.class, cmdClasses))) if (eq(uri, dropUriPrefix(baseLink, crudLink(c)))) { HCRUD crud = makeCRUD(c, req); return serveCRUD(req, c, crud); } return null; } public Object serveCRUD(Req req, Class c, HCRUD crud) { HTMLFramer1 framer = req.framer; Map params = req.params(); String help = mapGet(crudHelp(), c); if (nempty(help)) framer.add(p(help)); String json = crud.handleComboSearch(params); if (nempty(json)) return serveText(json); List aboveTable = new ArrayList(); if (c == UserKeyword.class) { Scorer scorer = consistencyCheckResults(); framer.add(p("Consistency check results: " + nTests(scorer.successes) + " OK, " + nErrors(scorer.errors))); if (nempty(scorer.errors)) framer.add(ul(map(scorer.errors, e -> "Error: " + e))); } addThingsAboveCRUDTable(req, c, aboveTable); String baseTitle = framer.title; crud.makeFrame = (title, contents) -> { framer.title = joinNemptiesWithVBar(hTitleClean(title), baseTitle); return h1(title) + lines(aboveTable) + contents; }; crud.processSortParameter(params); framer.add(crud.renderPage(params)); framer.add(hjs_markRowMagic()); return completeFrame(req); } public IF1, Collection> crudSearchFilter(Req req, HCRUD_Concepts data, String query) { if (empty(query)) return null; boolean debug = eq(req.get("searchDebug"), "1"); HTMLFramer1 framer = req.framer; return objects -> { ScoredSearcher searcher = new ScoredSearcher<>(query); if (debug) { if (framer != null) framer.add(hcomment(renderVars_struct("searcher", searcher))); } for (A a : unnull(objects)) { List fields = allToString(values(allConceptFieldsAsMap(a))); fields.add(str(a.id)); if (debug) { if (framer != null) framer.add(hcomment(renderVars_str("a", a, "fields", fields))); } searcher.put(a, fields); } return searcher.get(); }; } public boolean requestAuthed() { return currentReq.get() != null && currentReq.get().requestAuthed(); } public String webSocketHeadStuff(Req req) { return hreconnectingWebSockets() + hjs("\r\n var webSocketQuery = \"\";\r\n var ws;\r\n $(document).ready(function() {\r\n ws = new ReconnectingWebSocket(((window.location.protocol === \"https:\") ? \"wss://\" : \"ws://\") + window.location.host + " + jsQuote(baseLink + req.uri) + " + webSocketQuery);\r\n var wsReady = false;\r\n ws.onopen = function(event) {\r\n wsReady = true;\r\n console.log(\"WebSocket ready!\");\r\n ws.onmessage = " + js_evalOnWebSocketMessage() + ";\r\n };\r\n });\r\n "); } } static public class ExecutedStep extends Concept { static final public String _fieldOrder = "step conversation msg"; public Ref step = new Ref(); public Ref conversation = new Ref(); public Msg msg; } static public class InputHandled extends Concept { static final public String _fieldOrder = "input conversation msg inputHandler handled"; public String input; public Ref conversation = new Ref(); public Msg msg; public Ref inputHandler = new Ref(); public boolean handled = false; } abstract static public class BotStep extends Concept { public String comment; public boolean run(Conversation conv) { return false; } public ScheduledAction nextStepAction(Conversation conv) { return new Action_NextStep(conv, conv.executedSteps); } public String fullToString() { return toString(); } public double preTypingDelay() { return 0; } public boolean isUndoBoundary() { return false; } } static public class Sequence extends BotStep { public RefL steps = new RefL(); public String toString() { return "Sequence " + quoteOr(comment, "(unnamed)") + spaceRoundBracketed(nSteps(steps)); } public boolean run(Conversation conv) { syncAdd(conv.stack, new ActiveSequence(this)); conv.change(); return true; } } static public class BotRandomAction extends BotStep { public RefL actions = new RefL(); public String toString() { return "Random Action " + appendBracketed(comment) + (empty(actions) ? " [empty]" : ": " + first(actions) + (l(actions) == 1 ? "" : " + " + n2(l(actions) - 1) + " more")); } public boolean run(Conversation conv) { BotStep step = random(actions); if (step == null) return true; return step.run(conv); } } static public class BotMessage extends BotStep { public String text; public String specialPurpose; public boolean disableInput = false; static public String _fieldOrder = "text specialPurpose"; public String toString() { return toString(40); } public String toString(int shorten) { return "Message" + spacePlusRoundBracketedIfNempty(comment) + ": " + newLinesToSpaces2(shorten(text, shorten)); } public String fullToString() { return toString(Integer.MAX_VALUE); } public boolean run(Conversation conv) { Msg msg = new Msg(false, text); msg.out = new Out(); msg.out.disableInput = disableInput; conv.add(msg); return true; } public double preTypingDelay() { return botMod().typingDelayForText(text); } } abstract static public class AbstractBotImage extends BotStep { public String altText; public boolean run(Conversation conv) { botMod().addReplyToConvo(conv, () -> himgsrc(imageURL(), "title", altText, "alt", altText, "class", "chat_contentImage")); return true; } abstract public String imageURL(); public double preTypingDelay() { return botMod().settings().botTypingDelay; } } static public class BotImage extends AbstractBotImage { public String imageURL, altText; static public String _fieldOrder = "imageURL"; public String imageURL() { return imageURL; } public String toString() { return "Image" + spacePlusRoundBracketedIfNempty(comment) + ": " + imageURL; } } static public class UploadedImage extends AbstractBotImage { public String imageURL() { return botMod().convertToAbsoluteURL(botMod().baseLink + "/uploaded-image/" + id); } public File imageFile() { return newFile(botMod().uploadedImagesDir(), id + ".png"); } public String toString() { return "Image" + spacePlusRoundBracketedIfNempty(altText) + spacePlusRoundBracketedIfNempty(comment); } public void delete() { if (concepts() == db_mainConcepts()) deleteFile(imageFile()); super.delete(); } } static public class UploadedSound extends Concept { public String comment; public String soundURL() { return botMod().convertToAbsoluteURL(botMod().baseLink + "/uploaded-sound/" + id); } public File soundFile() { return newFile(botMod().uploadedSoundsDir(), id + ".mp3"); } public String toString() { return "Sound" + spacePlusRoundBracketedIfNempty(comment); } public void delete() { if (concepts() == db_mainConcepts()) deleteFile(soundFile()); super.delete(); } } static public class UploadedFile extends Concept { static final public String _fieldOrder = "name comment mimeType liveURI"; public String name, comment, mimeType, liveURI; public String downloadURL() { return downloadURL(null); } public String downloadURL(String contentType) { return botMod().convertToAbsoluteURL(appendQueryToURL(botMod().baseLink + "/uploaded-file/" + id + (empty(name) ? "" : "/" + urlencode(name)), "ct", contentType)); } public File theFile() { return newFile(botMod().uploadedFilesDir(), id + ".png"); } public String toString() { return "File " + spacePlusRoundBracketedIfNempty(name) + spacePlusRoundBracketedIfNempty(comment); } public void delete() { if (concepts() == db_mainConcepts()) deleteFile(theFile()); super.delete(); } } static public class BotDoNothing extends BotStep { public boolean run(Conversation conv) { return false; } public String toString() { return "Do nothing"; } } static public class BotSendTyping extends BotStep { public boolean run(Conversation conv) { conv.botTyping = print("Bot typing", now()); return true; } } static public class BotGoBack extends BotStep { public boolean run(Conversation conv) { botMod().doUndo(conv); return false; } public String toString() { return "Go back one step"; } } static public class BotNewDialog extends BotStep { public boolean run(Conversation conv) { conv.newDialog(); return false; } public String toString() { return "New dialog"; } } static public class BotPause extends BotStep { public double seconds; public BotPause() { } public BotPause(double seconds) { this.seconds = seconds; } public boolean run(Conversation conv) { botMod().addScheduledAction(nextStepAction(conv), toMS(seconds)); return false; } public String toString() { return "Pause for " + (seconds == 1 ? "1 second" : formatDouble(seconds, 1) + " seconds"); } } static public class BotOutgoingQuestion extends BotStep implements IInputHandler { public String displayText; public String key; public String defaultValue; public String placeholder; public List buttons; public boolean allowFreeText = true; public boolean multipleChoice = false; public boolean radioButtons = false; public String multipleChoiceSeparator = ", "; public boolean optional = false; public String answerCheck; public RefL buttonActions = new RefL(); static public String _fieldOrder = "displayText key defaultValue placeholder buttons buttonActions allowFreeText multipleChoice optional answerCheck"; public String toString() { return "Question: " + orEmptyQuotes(displayText); } public List> buttonsWithActions() { return zipTwoListsToPairs_longer(buttons, buttonActions); } public boolean run(Conversation conv) { String text = botMod().rewriteBotMessage(conv, displayText); Msg msg = new Msg(false, text); msg.out = makeMsgOut(); conv.add(msg); cset(conv, "inputHandler", this); return false; } public Out makeMsgOut() { Out out = new Out(); out.placeholder = or(placeholder, displayText); out.defaultInput = defaultValue; out.buttons = cloneList(buttons); out.multipleChoice = multipleChoice; out.multipleChoiceSeparator = multipleChoiceSeparator; out.radioButtons = radioButtons; if (eqic(answerCheck, "phone number") && botMod().phoneNumberSpecialInputField) out.javaScript = "$(\"#chat_message\").hide(); $(\"#chat_telephone, .iti\").show(); $(\"#chat_telephone\").val(\"\").focus();"; else if (!allowFreeText) { out.javaScript = jsDisableInputField(); if (empty(out.placeholder)) out.placeholder = " "; } return out; } public boolean handleInput(String s, Conversation conv) { print("BotOutgoingQuestion handleInput " + s); s = trim(s); String theKey = or2(key, htmldecode_dropAllTags(trim(displayText))); if (nempty(theKey) && !eq(theKey, "-")) syncPut(conv.answers, theKey, s); conv.change(); if (eqic(answerCheck, "email address") && !isValidEmailAddress_simple(s)) { handleValidationFail(conv, "bad email address"); return true; } if (eqic(answerCheck, "phone number") && !botMod().checkPhoneNumber(s)) { handleValidationFail(conv, "bad phone number"); return true; } conv.removeInputHandler(this); int idx = indexOfIC(trimAll(lmap(__62 -> dropStuffBeforeVerticalBar(__62), buttons)), s); print("Button index of " + quote(s) + " in " + sfu(buttons) + " => " + idx); BotStep target = get(buttonActions, idx); print("Button action: " + target); if (target != null) conv.callSubroutine(target); print("Scheduling next step in " + conv); conv.scheduleNextStep(); return true; } public double preTypingDelay() { return empty(displayText) ? 0 : botMod().typingDelayForText(displayText); } public void handleValidationFail(Conversation conv, String purpose) { BotMessage msg = botMod().messageForPurpose(purpose); String text = or2(or2(msg == null ? null : msg.text, getOrKeep(botMod().specialPurposes, purpose)), "Invalid input, please try again"); printVars_str("handleValidationFail", "purpose", purpose, "msg", msg, "text", text); Msg m = new Msg(); m.text = text; m.out = makeMsgOut(); conv.add(m); cset(conv, "inputHandler", this); return; } public boolean isUndoBoundary() { return true; } } static public class BotIdleMode extends BotStep { public String toString() { return "Idle Mode (wait indefinitely)"; } public boolean run(Conversation conv) { return false; } } static public class BotEndConversation extends BotStep { public String toString() { return "End Conversation (disable user input)"; } public boolean run(Conversation conv) { Msg msg = new Msg(false, ""); msg.out = new Out(); msg.out.javaScript = jsDisableInputField(); msg.out.placeholder = " "; conv.add(msg); return true; } } static public String jsDisableInputField() { return "$(\"#chat_message\").prop('disabled', true).attr('placeholder', '');"; } static public class BotSaveLead extends BotStep { public String toString() { return "Save Lead"; } public boolean run(Conversation conv) { Lead lead = cnew(Lead.class, "conversation", conv, "domain", conv.domainObj, "date", new Timestamp(now()), "answers", cloneMap(conv.answers)); botMod().onNewLead(lead); return true; } } static public class BotSaveFeedback extends BotStep { public String toString() { return "Save Conversation Feedback"; } public boolean run(Conversation conv) { cnew(ConversationFeedback.class, "conversation", conv, "domain", conv.domainObj, "date", new Timestamp(now()), "answers", filterKeys(conv.answers, swic$("Conversation Feedback:"))); return true; } } static public class BotClearStack extends BotStep { public boolean run(Conversation conv) { syncRemoveAllExceptLast(conv.stack); conv.change(); return true; } public String toString() { return "Clear Stack [forget all running procedures in conversation]"; } } static public class BotSwitchLanguage extends BotStep { public Ref language = new Ref(); public boolean run(Conversation conv) { cset(conv, "language", language); return true; } public String toString() { return "Switch to " + language; } } static public class UserKeyword extends Concept { static final public String _fieldOrder = "language pattern examples counterexamples action enabled priority precedence parsedPattern"; public Ref language = new Ref(); public String pattern; public List examples, counterexamples; public Ref action = new Ref(); public boolean enabled = true; public boolean priority = false; public int precedence; transient public MMOPattern parsedPattern; public void change() { parsedPattern = null; botMod().consistencyCheckResults = null; super.change(); } public MMOPattern parsedPattern() { if (parsedPattern == null) return parsedPattern = mmo2_parsePattern(pattern); return parsedPattern; } public String toString() { return "User Keyword: " + pattern; } public boolean matchWithTypos(String s) { return mmo2_matchWithTypos(parsedPattern(), s); } } static public class Language extends Concept { static final public String _fieldOrder = "languageName comment"; public String languageName; public String comment; public String toString() { return languageName + spaceRoundBracketed(comment); } } static public class Evt extends Concept { } static public class EvtMatchedUserKeyword extends Evt { static final public String _fieldOrder = "userKeyword msg"; public Ref userKeyword = new Ref(); public Msg msg; public EvtMatchedUserKeyword() { } public EvtMatchedUserKeyword(UserKeyword userKeyword, Msg msg) { this.userKeyword.set(userKeyword); this.msg = msg; } } static public class EvtJumpTo extends Evt { public Ref target = new Ref(); public EvtJumpTo() { } public EvtJumpTo(BotStep target) { this.target.set(target); } } static public class EvtCallSubroutine extends Evt { public Ref target = new Ref(); public EvtCallSubroutine() { } public EvtCallSubroutine(BotStep target) { this.target.set(target); } } abstract static public class AbstractAvatar extends Concept { abstract public Avatar getActualAvatar(); } static public class RandomAvatar extends AbstractAvatar { public Avatar getActualAvatar() { return random(filter(list(Avatar.class), a -> a.onShift())); } public String toString() { return "Choose a random avatar that is on shift"; } } static public class Avatar extends AbstractAvatar { static final public String _fieldOrder = "name comment shift image"; public String name, comment; public String shift; public Ref image = new Ref(); public Avatar getActualAvatar() { return this; } public boolean onShift() { List shifts = parseBusinessHours_pcall(shift); if (empty(shifts)) return true; shifts = splitBusinessHoursAtMidnight(shifts); int minute = minuteInDay(timeZone(botMod().timeZone)); return anyIntRangeContains(shifts, minute); } public String toString() { return empty(name) ? super.toString() : "Avatar " + name + appendBracketed(comment); } } static public class Out extends DynamicObject { public List buttons; public boolean multipleChoice, radioButtons; public String multipleChoiceSeparator; public String placeholder; public String defaultInput; public String javaScript; public boolean disableInput = false; } static public class Msg extends DynamicObject { public long time; public boolean fromUser = false; public Worker fromWorker; public String text; public Out out; public List labels; public Msg() { } public Msg(boolean fromUser, String text) { this.text = text; this.fromUser = fromUser; time = now(); } public Msg(String text, boolean fromUser) { this.fromUser = fromUser; this.text = text; time = now(); } public String toString() { return (fromUser ? "User" : "Bot") + ": " + text; } } static public class AuthedDialogID extends Concept { static final public String _fieldOrder = "cookie master restrictedToDomain loggedIn"; public String cookie; public boolean master = false; public Ref restrictedToDomain = new Ref(); public Worker loggedIn; public String domain() { return !restrictedToDomain.has() ? null : restrictedToDomain.get().domainAndPath; } public Ref user = new Ref(); public boolean userMode = false; public User user() { return user.get(); } } static public class ActiveSequence { public Sequence originalSequence; public List steps; public int stepIndex; public ActiveSequence() { } public ActiveSequence(BotStep step) { if (step instanceof Sequence) { steps = cloneList(((Sequence) step).steps); originalSequence = ((Sequence) step); } else steps = ll(step); steps = botMod().addTypingDelays(steps); } public boolean done() { return stepIndex >= l(steps); } public BotStep currentStep() { return get(steps, stepIndex); } public void nextStep() { ++stepIndex; } public String toString() { return (stepIndex >= l(steps) ? "DONE " : "Step " + (stepIndex + 1) + "/" + l(steps) + " of ") + (originalSequence != null ? str(originalSequence) : squareBracket(joinWithComma(steps))); } } static public class UndoState { public List stack; public UndoState() { } public UndoState(List stack) { this.stack = stack; } public String toString() { return "UndoState " + stack; } } static public class Conversation extends Concept { static final public String _fieldOrder = "cookie ip country domain domainObj oldDialogs msgs lastPing botOn notificationsOn worker userTyping botTyping testMode nextActionTime userMessageProcessed newDialogTriggered dryRun avatar stack undoStates executedSteps inputHandler language answers botConfig events reloadCounter"; public String cookie, ip, country, domain; public Ref domainObj = new Ref(); public List> oldDialogs = new ArrayList(); public List msgs = new ArrayList(); public long lastPing; public boolean botOn = true; public boolean notificationsOn = true; public Worker worker; transient volatile public long userTyping, botTyping; public boolean testMode = false; public long nextActionTime = Long.MAX_VALUE; public long userMessageProcessed; public int newDialogTriggered = -1; transient public boolean dryRun = false; public Ref avatar = new Ref(); public List stack = new ArrayList(); public List undoStates; public int executedSteps; public IInputHandler inputHandler; public Ref language = new Ref(); public Map answers = litcimap(); public Map botConfig; public RefL events = new RefL(); public int reloadCounter; public void add(Msg m) { m.text = trim(m.text); syncAdd(msgs, m); botMod().noteConversationChange(); change(); vmBus_send("chatBot_messageAdded", mc(), this, m); } public int allCount() { return archiveSize() + syncL(msgs); } public int archiveSize() { return syncLengthLevel2(oldDialogs) + syncL(oldDialogs); } public List allMsgs() { return concatLists_syncIndividual(syncListPlus(oldDialogs, msgs)); } public long lastMsgTime() { Msg m = last(msgs); return m == null ? 0 : m.time; } public void incReloadCounter() { cset(this, "reloadCounter", reloadCounter + 1); } public void turnBotOff() { cset(this, "botOn", false); botMod().noteConversationChange(); } public void turnBotOn() { cset(this, "botOn", true, "worker", null); String backMsg = botMod().getCannedAnswer("#botBack", this); if (empty(msgs) || lastMessageIsFromUser() || !eq(last(msgs).text, backMsg)) add(new Msg(backMsg, false)); botMod().noteConversationChange(); } public boolean lastMessageIsFromUser() { return nempty(msgs) && last(msgs).fromUser; } public void newDialog() { if (syncNempty(msgs)) syncAdd(oldDialogs, msgs); cset(this, "msgs", new ArrayList()); syncClear(answers); syncClear(stack); syncClear(undoStates); dropScheduledActions(); change(); print("newDialog " + archiveSize() + "/" + allCount()); vmBus_send("chatBot_clearedSession", mc(), this); } public void dropScheduledActions() { deleteConcepts(ScheduledActionOnConversation.class, "conv", this); } public void jumpTo(BotStep step) { syncPopLast(stack); print("Jumping to " + step); noteEvent(new EvtJumpTo(step)); if (step == null) return; syncAdd(stack, new ActiveSequence(step)); change(); } public void callSubroutine(BotStep step) { if (step == null) return; noteEvent(new EvtCallSubroutine(step)); print("Calling subroutine " + step); syncAdd(stack, new ActiveSequence(step)); change(); } public void removeInputHandler(IInputHandler h) { if (inputHandler == h) cset(this, "inputHandler", null); } public void scheduleNextStep() { botMod().addScheduledAction(new Action_NextStep(this)); } public void noteEvent(Concept event) { events.add(event); } public boolean isActive() { return lastPing + botMod().activeConversationTimeout() >= now(); } public String botImg() { if (avatar.has()) return avatar.get().image.get().imageURL(); else return botMod().botImageForDomain(domainObj.get()); } public void addUndoState() { UndoState state = new UndoState(syncShallowCloneElements(stack)); print("Made undo state: " + state); undoStates = syncAddOrCreate(undoStates, state); change(); } public Ref mirrorPost = new Ref(); public Ref detailedMirrorPost = new Ref(); public void change() { super.change(); ((DynGazelleRocks) botMod()).rstUpdateMirrorPosts.add(this); } public void updateMirrorPost() { if (isDeleted()) return; if (!mirrorPost.has() && syncNempty(msgs)) cset(Conversation.this, "mirrorPost", cnew(UserPost.class, "title", "Conversation " + id, "type", "Conversation Mirror", "creator", ((DynGazelleRocks) botMod()).internalUser(), "botInfo", "Conversation Mirror Bot")); cset(mirrorPost.get(), "text", lines_rtrim(msgs)); if (!detailedMirrorPost.has() && syncNempty(msgs)) cset(Conversation.this, "detailedMirrorPost", cnew(UserPost.class, "title", "Conversation " + id + " with details", "type", "Detailed Conversation Mirror", "creator", ((DynGazelleRocks) botMod()).internalUser(), "botInfo", "Conversation Mirror Bot")); cset(detailedMirrorPost.get(), "text", indentedStructure(msgs)); } public void delete() { cdelete(mirrorPost.get()); super.delete(); } } abstract static public class ScheduledAction extends Concept implements Runnable { public long time; } abstract static public class ScheduledActionOnConversation extends ScheduledAction { public Ref conv = new Ref(); } static public class Action_NextStep extends ScheduledActionOnConversation { public int executedSteps = -1; public Action_NextStep() { } public Action_NextStep(Conversation conv) { this.conv.set(conv); } public Action_NextStep(Conversation conv, int executedSteps) { this.conv.set(conv); this.executedSteps = executedSteps; } public void run() { nextStep(conv.get(), executedSteps); } } static public class OnNewDialog extends ScheduledActionOnConversation { public OnNewDialog() { } public OnNewDialog(Conversation conv) { this.conv.set(conv); } public void run() { botMod().startMainScript(conv.get()); } } static public void nextStep(Conversation conv) { nextStep(conv, -1); } static public void nextStep(Conversation conv, int expectedExecutedSteps) { if (expectedExecutedSteps >= 0 && conv.executedSteps != expectedExecutedSteps) return; while (licensed()) { if (empty(conv.stack)) return; ActiveSequence seq = syncLast(conv.stack); boolean done = seq.done(); printVars_str("Active sequence", "conv", conv, "seq", seq, "done", done, "stackSize", syncL(conv.stack)); if (done) { syncPopLast(conv.stack); continue; } BotStep step = seq.currentStep(); if (botMod().enableUndoStates && step.isUndoBoundary()) conv.addUndoState(); seq.nextStep(); ++conv.executedSteps; conv.change(); if (!executeStep(step, conv)) { print("Step returned false: " + step); break; } } } static public boolean executeStep(BotStep step, Conversation conv) { if (step == null || conv == null) return false; print("Executing step " + step + " in " + conv); ExecutedStep executed = null; if (botMod().recordExecutionsAndInputs) executed = cnew(ExecutedStep.class, "step", step, "conversation", conv); Msg lastMsg = syncLast(conv.msgs); boolean result = step.run(conv); Msg newMsg = syncLast(conv.msgs); if (newMsg != null && !newMsg.fromUser && newMsg != lastMsg) cset(executed, "msg", newMsg); return result; } static public class OnUserMessage extends ScheduledActionOnConversation { public OnUserMessage() { } public OnUserMessage(Conversation conv) { this.conv.set(conv); } public void run() { Conversation conv = this.conv.get(); Msg msg = syncLast(conv.msgs); if (msg == null || !msg.fromUser) return; print("OnUserMessage: " + msg); if (eqic(msg.text, "!back")) { botMod().doUndo(conv); return; } if (botMod().handleGeneralUserInput(conv, msg, true)) return; IInputHandler inputHandler = conv.inputHandler; if (inputHandler != null) { InputHandled rec = null; String input = msg.text; if (botMod().recordExecutionsAndInputs) rec = cnew(InputHandled.class, "inputHandler", inputHandler, "conversation", conv, "msg", msg, "input", input); boolean result = conv.inputHandler.handleInput(input, conv); cset(rec, "handled", result); if (result) return; } botMod().handleGeneralUserInput(conv, msg, false); } } static public class Domain extends Concept { public String domainAndPath; public String tenantID; public Ref botImage = new Ref(); public String botName; public Ref avatar = new Ref(); public String headerColorLeft, headerColorRight; public Boolean autoOpenBot; public Ref mainScript = new Ref(); public String password = aGlobalID(); static public String _fieldOrder = "domainAndPath botImage mainScript"; public String toString() { return domainAndPath; } } static public class Form extends Concept { public String name; public RefL steps = new RefL(); public String toString() { return name; } } static public class DeliveredDomain extends Concept { public String domain; } static public class CannedAnswer extends Concept { public String hashTag, text; } static public String text(CannedAnswer a) { return a == null ? null : a.text; } static public class Lead extends Concept { static final public String _fieldOrder = "domain conversation date answers"; public Ref domain = new Ref(); public Ref conversation = new Ref(); public Timestamp date; public Map answers; } static public class ConversationFeedback extends Concept { static final public String _fieldOrder = "domain conversation date answers"; public Ref domain = new Ref(); public Ref conversation = new Ref(); public Timestamp date; public Map answers; } static public class Settings extends Concept { static final public String _fieldOrder = "mainDomainName botTypingDelay botTypingDelayPerWord botTypingMaxDelay preferredCountryCodes multiLanguageMode notificationSound talkToBotOnlyWithAuth enableWorkerChat defaultLanguage mailLeadsTo leadMailSubject"; public String mainDomainName; public double botTypingDelay; public double botTypingDelayPerWord; public double botTypingMaxDelay; public String preferredCountryCodes; public boolean multiLanguageMode = false; public Ref notificationSound = new Ref(); public boolean talkToBotOnlyWithAuth = false; public boolean enableWorkerChat = false; public Ref defaultLanguage = new Ref(); public String mailLeadsTo; public String leadMailSubject = "A new lead occurred in your chat bot"; } static public interface IInputHandler { public boolean handleInput(String s, Conversation conv); } static public DynNewBot2 botMod() { return (DynNewBot2) db_mainConcepts().miscMapGet(DynNewBot2.class); } static public class And implements IFieldsToList, Transformable, Visitable { public A a; public A b; public And() { } public And(A a, A b) { this.b = b; this.a = a; } public String toString() { return shortClassName(this) + "(" + a + ", " + b + ")"; } public boolean equals(Object o) { if (!(o instanceof And)) return false; And __0 = (And) o; return eq(a, __0.a) && eq(b, __0.b); } public int hashCode() { int h = 65975; h = boostHashCombine(h, _hashCode(a)); h = boostHashCombine(h, _hashCode(b)); return h; } public Object[] _fieldsToList() { return new Object[] { a, b }; } public Object transformUsing(IF1 f) { return new And((A) f.get(a), (A) f.get(b)); } public void visitUsing(IVF1 f) { f.get(a); f.get(b); } } static public class ReliableSingleThread implements Runnable { public boolean _isTransient() { return true; } public Object runnable; public String name = "Single Thread"; public boolean cancelBeforeTrigger = false; public F0 enter; public int cancelTimeOut = 10000; public boolean trigger = false; public Thread thread; public WeakReference threadBeingCancelled; public ReliableSingleThread(Object runnable) { this.runnable = runnable; } public void trigger() { go(); } synchronized public void go() { if (cancelBeforeTrigger) cancel(); trigger = true; if (!running()) { AutoCloseable __1 = callF(enter); try { thread = startThread(name, new Runnable() { public void run() { try { AutoCloseable __2 = callF(enter); try { _run(); } finally { _close(__2); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp callF(enter);\r\n _run();"; } }); } finally { _close(__1); } } } public void run() { go(); } public void get() { go(); } synchronized public boolean running() { return thread != null; } public void triggerAndWait() { trigger(); waitUntilDone(); } public void waitUntilDone() { while (running()) sleep(1); } public void _run() { try { while (licensed()) { Thread oldThread; synchronized (this) { if (!trigger) { thread = null; break; } oldThread = getWeakRef(threadBeingCancelled); trigger = false; } if (oldThread != null && oldThread != currentThread()) oldThread.join(cancelTimeOut); pcallF(runnable); } } catch (Exception __e) { throw rethrow(__e); } } synchronized public void cancel() { if (thread == null) return; threadBeingCancelled = new WeakReference(thread); cancelAndInterruptThread(thread); thread = null; } public void cancelAndTrigger() { cancel(); trigger(); } synchronized public boolean triggered() { return trigger; } public void cleanMeUp() { cancel(); } public ReliableSingleThread cancelBeforeTrigger() { cancelBeforeTrigger = true; return this; } } static public class HasIndex implements Comparable { public int idx; public HasIndex() { } public HasIndex(int idx) { this.idx = idx; } public int compareTo(HasIndex h) { return idx - h.idx; } } static public class Cache { public Object maker; public A value; public long loaded; static public boolean debug = false; public long changeCount; public Lock lock = lock(); public Cache() { } public Cache(Object maker) { this.maker = maker; } public Cache(IF0 maker) { this.maker = maker; } public A get() { if (hasLock(lock)) return value; Lock __0 = lock; lock(__0); try { if (loaded == 0) { value = make(); changeCount++; loaded = sysNow(); } return value; } finally { unlock(__0); } } public void clear() { Lock __1 = lock; lock(__1); try { if (debug && loaded != 0) print("Clearing cache"); value = null; changeCount++; loaded = 0; } finally { unlock(__1); } } public void clear(double seconds) { Lock __2 = lock; lock(__2); try { if (seconds != 0 && loaded != 0 && sysNow() >= loaded + seconds * 1000) clear(); } finally { unlock(__2); } } public void set(A a) { Lock __3 = lock; lock(__3); try { value = a; ++changeCount; loaded = sysNow(); } finally { unlock(__3); } } public A make() { return (A) callF(maker); } } static public class CountryDialCode implements IFieldsToList { public String country; public String countryCode; public String dialCode; public CountryDialCode() { } public CountryDialCode(String country, String countryCode, String dialCode) { this.dialCode = dialCode; this.countryCode = countryCode; this.country = country; } public String toString() { return shortClassName(this) + "(" + country + ", " + countryCode + ", " + dialCode + ")"; } public boolean equals(Object o) { if (!(o instanceof CountryDialCode)) return false; CountryDialCode __1 = (CountryDialCode) o; return eq(country, __1.country) && eq(countryCode, __1.countryCode) && eq(dialCode, __1.dialCode); } public int hashCode() { int h = 240284435; h = boostHashCombine(h, _hashCode(country)); h = boostHashCombine(h, _hashCode(countryCode)); h = boostHashCombine(h, _hashCode(dialCode)); return h; } public Object[] _fieldsToList() { return new Object[] { country, countryCode, dialCode }; } } static public interface IWebRequest { public String uri(); public Map params(); public Map headers(); public Map files(); default public String clientIP() { return unnull(getClientIPFromHeaders(headers())); } default public String domain() { return mapGet(headers(), "host"); } public String cookie(); public boolean isHttps(); default public void noSpam() { } default public String get(String param) { return mapGet(params(), param); } } static public class StringTree2 { public A leafValue; public HashMap> children = new HashMap(); public A get() { return leafValue; } public StringTree2 get(String s) { return children.get(s); } public StringTree2 getOrAdd(String s) { StringTree2 t = children.get(s); if (t == null) children.put(s, t = new StringTree2()); return t; } } static public interface Visitable { public void visitUsing(IVF1 f); } static public class IntRange { public int start, end; public IntRange() { } public IntRange(int start, int end) { this.end = end; this.start = start; } public IntRange(IntRange r) { start = r.start; end = r.end; } public boolean equals(Object o) { return stdEq2(this, o); } public int hashCode() { return stdHash2(this); } final public int length() { return end - start; } final public boolean empty() { return start >= end; } final public boolean isEmpty() { return start >= end; } static public String _fieldOrder = "start end"; public String toString() { return "[" + start + ";" + end + "]"; } } static public interface Transformable { public Object transformUsing(IF1 f); } static public class Scorer { public double score, total; public List successes, errors; public boolean verboseFailures, verboseAll; public void addZeroToOne(double score) { ++total; this.score += clamp(score, 0, 1); } public void addZeroToOneError(double error) { addZeroToOne(1 - error); } public void addError() { add(false); } public void addError(A info) { add(false, info); } public void error(A info) { addError(info); } public void addOK() { add(true); } public void addOK(A info) { add(true, info); } public void ok() { addOK(); } public void ok(A info) { addOK(info); } public boolean add(boolean correct) { ++total; if (correct) ++score; return correct; } public boolean add(boolean correct, A info) { main.add(correct ? successes : errors, info); if (verboseAll || verboseFailures && !correct) _print((correct ? "[GOOD] " : "[BAD] ") + info); return add(correct); } public void eq(Object a, Object b) { if (_eq(a, b)) add(true); else add(false, (A) (a + " != " + b)); } public void print() { main.print(toString()); } public String toString() { return formatDouble(ratioToPercent(score, total), 1) + "% correct (n=" + formatDouble(total, 1) + ")"; } public double get() { return ratioToPercent(score, total); } public double percentScore() { return get(); } public double score() { return get(); } public boolean allCorrect() { return score == total; } public void add(Scorer scorer) { if (scorer == null) return; total += scorer.total; score += scorer.score; addAll(successes, scorer.successes); addAll(errors, scorer.errors); } public void collectErrors() { errors = new ArrayList(); } } static public class Timestamp implements IFieldsToList { public long date; public Timestamp() { } public Timestamp(long date) { this.date = date; } public boolean equals(Object o) { if (!(o instanceof Timestamp)) return false; Timestamp __1 = (Timestamp) o; return date == __1.date; } public int hashCode() { int h = 2059094262; h = boostHashCombine(h, _hashCode(date)); return h; } public Object[] _fieldsToList() { return new Object[] { date }; } public String toString() { return formatLocalDateWithSeconds(date); } } abstract static public class DynPrintLogAndEnabled extends DynPrintLog { public JComponent visualize() { return dm_visualizeWithEnabled(super.visualize()); } volatile public boolean enabled = true; transient public JPanel buttons; public JComponent visualizeWithoutEnabled() { return super.visualize(); } public JComponent dm_visualizeWithEnabled(JComponent main) { return centerAndSouthWithMargins(main, makeControlArea()); } public JPanel makeControlArea() { return buttons = jrightalignedline(makeEnabledCheckBox()); } static public JCheckBox makeEnabledCheckBox() { return dm_fieldCheckBox("enabled"); } public void setEnabled(boolean b) { setField("enabled", b); } public void addToControlArea(Component... components) { addComponentsFirst(buttons, components); } } static public class ScoredSearcher { public int maxResults = 1000; public List preparedTerms; public Map scores = new HashMap(); public ScoredSearcher() { } public ScoredSearcher(String query, Object... __) { maxResults = optPar("maxResults", __, maxResults); setQuery(query); } public void setQuery(String query) { preparedTerms = scoredSearch_prepare(query); } public void put(A object, String s) { putUnlessZero(scores, object, scoredSearch_score(s, preparedTerms)); } public void put(A object, Collection fields) { add(object, scoreFields(fields)); } public int scoreFields(Collection fields) { return scoredSearch_score(fields, preparedTerms); } public int score(String text) { return scoredSearch_score(text, preparedTerms); } public void add(A object) { put(object, str(object)); } public void add(A object, Collection fields) { put(object, fields); } public void add(A object, double score) { putUnlessZero(scores, object, score); } public List get() { return takeFirst(maxResults, keysSortedByValuesDesc(scores)); } public A best() { return keyWithHighestValue(scores); } } static public B pairB(Pair p) { return p == null ? null : p.b; } static public String nConcepts(long n) { return n2(n, "concept"); } static public String nConcepts(Collection l) { return nConcepts(l(l)); } static public Object firstElementNotSubclassing(Iterable l, Class c) { return firstThat(l, o -> !isInstanceOf(o, c)); } static public boolean allUnique(List l) { return l(uniquify(l)) == l(l); } static public List nonNulls(List l) { return withoutNulls(l); } static public List nonNulls(A[] l) { return withoutNulls(l); } static public Map nonNulls(Map map) { return withoutNulls(map); } static public Collection scanConceptForRefs(Concept c) { Set refs = new HashSet(); if (c != null) for (Object o : values(objectToMap(c))) { if (o instanceof Concept.Ref) refs.add(((Concept.Ref) o)); else if (o instanceof Concept.RefL) addAll(refs, ((Concept.RefL) o).l); } return refs; } static public List listMinusSet(Iterable l, Collection stuff) { if (l == null) return null; if (empty(stuff)) return asList(l); Set set = asSet(stuff); List l2 = new ArrayList(); for (A a : l) if (!set.contains(a)) l2.add(a); return l2; } static public List listMinusSet(Iterable l, Collection stuff, Collection stuff2) { return listMinusSet(listMinusSet(l, stuff), stuff2); } static public List cloneAndClear(List l) { return cloneAndClearList(l); } static public MultiSetMap treeMultiSetMap() { return new MultiSetMap(true); } static public MultiSetMap treeMultiSetMap(Comparator comparator) { return new MultiSetMap(new TreeMap>(comparator)); } static public Comparator reverseOrder() { return new Comparator() { public int compare(Object a, Object b) { return cmp(b, a); } }; } static public List getAll(Map map, Collection l) { return lookupAllOpt(map, l); } static public List getAll(Collection l, Map map) { return lookupAllOpt(map, l); } static public List cloneKeys_noSync(Map map) { return cloneList_noSync(keys(map)); } static public IterableIterator navigableMultiSetMapValuesIterator_concurrent(final MultiSetMap mm) { return navigableMultiSetMapValuesIterator_concurrent(mm, mm.data); } static public IterableIterator navigableMultiSetMapValuesIterator_concurrent(final MultiSetMap mm, Object mutex) { return iteratorFromFunction(new F0() { public Iterator> it = concurrentlyIterateValues((NavigableMap) mm.data, mutex); public Iterator it2; public B get() { while (it2 == null || !it2.hasNext()) { if (!it.hasNext()) return null; it2 = iterator(asList(it.next())); } return it2.next(); } }); } static public MultiSet multiSetMapToMultiSet(MultiSetMap mm) { MultiSet ms = new MultiSet(); for (A a : keys(mm)) ms.add(a, l(mm.get(a))); return ms; } static public Collection allConcepts() { return db_mainConcepts().allConcepts(); } static public Collection allConcepts(Concepts concepts) { return concepts.allConcepts(); } static public String defaultTimerName_name; static public String defaultTimerName() { if (defaultTimerName_name == null) defaultTimerName_name = "A timer by " + programID(); return defaultTimerName_name; } static public Set _registerTimer_list = newWeakHashSet(); static public void _registerTimer(java.util.Timer timer) { _registerTimer_list.add(timer); } static public void cleanMeUp__registerTimer() { cancelTimers(getAndClearList(_registerTimer_list)); } static public UnsupportedOperationException unsupportedOperation() { throw new UnsupportedOperationException(); } static public long sysTime() { return sysNow(); } static public void change() { callOpt(getOptMC("mainConcepts"), "allChanged"); } static public void put(Map map, A a, B b) { if (map != null) map.put(a, b); } static public void put(List l, int i, A a) { if (l != null && i >= 0 && i < l(l)) l.set(i, a); } static public Set> entrySet(Map map) { return _entrySet(map); } static public Set keySet(Map map) { return map == null ? new HashSet() : map.keySet(); } static public Set keySet(Object map) { return keys((Map) map); } static public Set keySet(MultiSet ms) { return ms.keySet(); } static public Set keySet(MultiMap mm) { return mm.keySet(); } static public MultiSetMap ciMultiSetMap() { MultiSetMap mm = new MultiSetMap(); mm.data = ciMap(); return mm; } static public IterableIterator navigableMultiSetMapValuesIterator(final MultiSetMap mm) { return iteratorFromFunction(new F0() { public Iterator> it = concurrentlyIterateValues((NavigableMap) mm.data); public Iterator it2; public B get() { while (it2 == null || !it2.hasNext()) { if (!it.hasNext()) return null; it2 = iterator(asList(it.next())); } return it2.next(); } }); } static public boolean isAbstract(Class c) { return (c.getModifiers() & Modifier.ABSTRACT) != 0; } static public boolean isAbstract(Method m) { return (m.getModifiers() & Modifier.ABSTRACT) != 0; } static public boolean reflection_isForbiddenMethod(Method m) { return m.getDeclaringClass() == Object.class && eqOneOf(m.getName(), "finalize", "clone", "registerNatives"); } static public void multiMapPut(Map> map, A a, B b) { List l = map.get(a); if (l == null) map.put(a, l = new ArrayList()); l.add(b); } static public void multiMapPut(MultiMap mm, A key, B value) { if (mm != null && key != null && value != null) mm.put(key, value); } static public Set allInterfacesImplementedBy(Class c) { if (c == null) return null; HashSet set = new HashSet(); allInterfacesImplementedBy_find(c, set); return set; } static public void allInterfacesImplementedBy_find(Class c, Set set) { if (c.isInterface() && !set.add(c)) return; do { for (Class intf : c.getInterfaces()) allInterfacesImplementedBy_find(intf, set); } while ((c = c.getSuperclass()) != null); } static public boolean call_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) print("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) { Object arg = args[i]; if (!(arg == null ? !types[i].isPrimitive() : isInstanceX(types[i], arg))) { if (debug) print("Bad parameter " + i + ": " + arg + " vs " + types[i]); return false; } } return true; } static public Method findStaticMethod(Class c, String method, Object... args) { Class _c = c; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (!m.getName().equals(method)) continue; if ((m.getModifiers() & Modifier.STATIC) == 0 || !findStaticMethod_checkArgs(m, args)) continue; return m; } c = c.getSuperclass(); } return null; } static public boolean findStaticMethod_checkArgs(Method m, Object[] args) { Class[] types = m.getParameterTypes(); if (types.length != args.length) return false; for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) return false; return true; } static public File programSecretFile(String progID, String fileName) { return secretProgramFile(progID, fileName); } static public File programSecretFile(String fileName) { return secretProgramFile(fileName); } static public String loadTextFileOrCreateWithRandomID(File f) { String id = trim(loadTextFile(f)); if (empty(id)) saveTextFile(f, id = aGlobalID()); return id; } static public SecretValue aSecretGlobalID() { return secretValueOrNull(aGlobalID()); } static public boolean syncNempty(Collection l) { return !syncEmpty(l); } static public String lines_rtrim(Collection lines) { return rtrim_fromLines(lines); } static public String indentedStructure(Object o) { return indentStructureString(struct(o)); } static public String escapeNewLines(String s) { return s == null ? null : fixNewLines(s).replace("\n", " | "); } static public List> zipTwoListsToPairs_lengthOfFirst(List l1, List l2) { int n = l(l1); List> out = emptyList(n); for (int i = 0; i < n; i++) addPair(out, l1.get(i), get(l2, i)); return out; } static public List pairsAWhereB(Iterable> c, IF1 pred) { return pairsA(filter(c, p -> pred.get(p.b))); } static public boolean eqic_unnull(String a, String b) { return eqic(unnull(a), unnull(b)); } static public List syncInstancesOf(Iterable i, Class c) { if (i == null) return new ArrayList(); synchronized (i) { return collectInstances(i, c); } } static public List syncInstancesOf(Class c, Iterable i) { return syncInstancesOf(i, c); } static public boolean eqicOrSwicPlusSpace(String a, String b) { return swic(a, b) && (l(a) == l(b) || a.charAt(l(b)) == ' '); } static public String dm_require(String moduleLibID) { return dm_makeModule(moduleLibID); } static public AutoCloseable dm_vmBus_onMessage(final String msg, final VF1 onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static public AutoCloseable dm_vmBus_onMessage(final String msg, final IVF1 onMessage) { return dm_ownResource(vmBus_onMessage(msg, ivf1ToVF1(onMessage))); } static public AutoCloseable dm_vmBus_onMessage(final String msg, final IVF2 onMessage) { return dm_ownResource(vmBus_onMessage(msg, ivf2ToVF2(onMessage))); } static public AutoCloseable dm_vmBus_onMessage(String msg, final VF2 onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static public AutoCloseable dm_vmBus_onMessage(String msg, Runnable onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static public double systemLoad() { double load = osMXBean().getSystemLoadAverage(); if (load < 0) return systemCPULoad(); return load; } static public void printConceptIndices() { printConceptIndices(db_mainConcepts()); } static public void printConceptIndices(Concepts cc) { if (cc == null) return; Set> classes = joinSets(keys(cc.fieldIndices), keys(cc.ciFieldIndices)); print(n2(classes, "indexed class", "indexed classes") + "."); for (Class c : classes) { print("Indices on " + c + ":"); for (Map.Entry __1 : _entrySet(cc.fieldIndices.get(c))) { String field = __1.getKey(); IFieldIndex idx = __1.getValue(); print(" " + field + ": " + idx); } for (Map.Entry __0 : _entrySet(cc.ciFieldIndices.get(c))) { String field = __0.getKey(); IFieldIndex idx = __0.getValue(); print(" " + field + " [case-insensitive]: " + idx); } } } static public void onConceptsChange(Runnable r) { onConceptsChange(db_mainConcepts(), r); } static public void onConceptsChange(Concepts cc, Runnable r) { cc.addConceptIndex(simpleConceptIndex(r)); cc.onAllChanged.add(r); } static public Map syncWeakHashMap() { return newWeakHashMap(); } static public void closeAllKeysAndClear(Map map) { closeAllAndClear(keys(map)); } static public Object rcall(String method, Object o, Object... args) { return call_withVarargs(o, method, args); } static public void setFieldToIVF1Proxy(Object o, String field, IVF1 target) { if (o == null || target == null) return; Class type = fieldType(o, field); if (type == null) throw fail("Field " + field + " not found in " + className(o)); set(o, field, singleObjectMethodProxy(type, target, "get")); } static public String rcall_string(String method, Object o, Object... args) { return (String) rcall(method, o, args); } static public boolean syncAdd(Collection c, A b) { if (c == null) return false; synchronized (collectionMutex(c)) { return c.add(b); } } static public void syncAdd(List l, int idx, A b) { if (l != null) synchronized (collectionMutex(l)) { l.add(idx, b); } } static public String dropParamFromURL(String url, String key) { Map params = paramsFromURL(url); if (!containsKey(params, key)) return url; params.remove(key); return addAnchorToURL(appendParamsToURL(urlWithoutQueryAndAnchor(url), params), anchorFromURL(url)); } static public Lock dbLock() { return db_mainConcepts().lock; } static public Lock dbLock(Concepts cc) { return cc == null ? null : cc.lock; } static public Lock dbLock(Concept c) { return dbLock(c == null ? null : c._concepts); } static public boolean hasConceptIC(Class c, Object... params) { return hasConceptWhereIC(c, params); } static public boolean hasConceptIC(Concepts cc, Class c, Object... params) { return hasConceptWhereIC(cc, c, params); } static public boolean regexpContainsIC(String pat, String s) { return regexpFindsIC(pat, s); } static public String hresponstable() { return hcss_responstable(); } static public String hfullcenter(Object contents, Object... __) { return tag("table", tr(td(contents, "align", "center")), paramsPlus(__, "width", "100%", "height", "100%")); } static public String h3_htmlEncode(Object contents, Object... params) { return h3(htmlEncode2(str(contents)), params); } static public String td(Object contents, Object... params) { return hfulltag("td", contents, params); } static public String td() { return td(""); } static public String td_valignTop(Object contents, Object... params) { return tdTop(contents, params); } static public String hpassword(String name, Object... params) { return hpasswordfield(name, params); } static public String hpassword(String name) { return hpasswordfield(name); } static public Object serve404() { return subBot_serve404(); } static public Object serve404(String msg) { return subBot_serve404(msg); } static public Object serveWithContentType(String text, String contentType) { return serveByteArray(toUtf8(text), contentType); } static public Object addHeader(String header, String value, Object response) { call(response, "addHeader", header, value); return response; } static public Object serveJSON(Object... data) { return serveJSON_shallowLineBreaks(jsonPrepareData(data)); } static public long conceptID(Concept c) { return c == null ? 0 : c.id; } static public String dropSlashPrefix(String s) { return dropLeadingSlash(s); } static public String renderConceptDate(Concept cc) { if (cc == null) return ""; String c = formatLocalDateWithSeconds(cc.created); String m = formatLocalDateWithSeconds(cc._modified); String s = "Created " + c; if (neq(c, m)) s += ", modified " + m; return s; } static public String p_vbar(String... items) { return p_vbar(asList(items)); } static public String p_vbar(Collection items, Object... __) { return pUnlessEmpty(joinNemptiesWithVBar(items), __); } static public String html_showLineFeedsForPRE(String html) { return replace(html, "\n", unicode_newLineArrow() + "\n"); } static public String sourceCodeToHTML_noEncode(String html) { return "
" + html + "
"; } static public String hstyle_sourceCodeLikeInRepo() { return "padding-left: 1em; padding-top: 0.5em; padding-bottom: 0.5em; background-color: #EEEEEE; border-style: solid; border-color: #666666; border-width: 1px 0px 1px 0px;"; } static public
Pair, List> filterAntiFilter(Iterable c, Object pred) { List yes = new ArrayList(); List no = new ArrayList(); if (c != null) for (A o : c) (isTrue(callF(pred, o)) ? yes : no).add(o); return pair(yes, no); } static public Pair, List> filterAntiFilter(Iterable c, IF1 pred) { return filterAntiFilter(c, (Object) pred); } static public Pair, List> filterAntiFilter(IF1 pred, Iterable c) { return filterAntiFilter(c, pred); } static public Pair, List> filterAntiFilter(Object pred, Iterable c) { return filterAntiFilter(c, pred); } static public A highestBy(Iterable l, Object f) { return highestByFunction(l, f); } static public A highestBy(Object f, Iterable l) { return highestByFunction(f, l); } static public A highestBy(Iterable l, IF1 f) { return highestByFunction(f, l); } static public A highestBy(IF1 f, Iterable l) { return highestByFunction(f, l); } static public String squareBracketIfNempty(String s) { return empty(s) ? "" : squareBracket(s); } static public boolean cic(Collection l, String s) { return containsIgnoreCase(l, s); } static public boolean cic(String[] l, String s) { return containsIgnoreCase(l, s); } static public boolean cic(String s, char c) { return containsIgnoreCase(s, c); } static public boolean cic(String a, String b) { return containsIgnoreCase(a, b); } static public String hbuttonLink(String url, String text, Object... params) { return hbuttonOnClick(text, "location.href=" + jsQuote(url) + ";", params); } static public String nLines(long n) { return n2(n, "line"); } static public String nLines(Collection l) { return nLines(l(l)); } static public String nLines(String s) { return nLines(countLines(s)); } static public String p_alignRight(String s, Object... params) { return p(s, params_stylePlus(params, "text-align: right")); } static public String small(Object contents, Object... params) { return tag("small", contents, params); } static public String span_title(String title, Object contents) { return spanTitle(title, contents); } static public String regexpReplace(String s, String pat, Object f) { return regexReplace(s, pat, f); } static public String regexpReplace(String s, String pat, IF1 f) { return regexReplace(s, pat, f); } static public String gazelle_postMentionRegexp() { return regexpCaseInsensitivePrefix() + "\\bpost\\s+(\\d+)"; } static public List allBackRefs(Concept c) { IdentityHashMap l = new IdentityHashMap(); if (c != null && c.backRefs != null) for (Concept.Ref r : cloneList(c.backRefs)) l.put(r.concept(), true); return keysList(l); } static public String hInitWebSocket(Object... __) { String wsVar = optPar("wsVar", __, "ws"); String onOpen = (String) (optPar("onOpen", __)); String onMessage = (String) (optPar("onMessage", __)); String readyMsg = optPar("readyMsg", __, "WebSocket ready!"); return hreconnectingWebSockets() + hscript("\r\n var wsReady = false;\r\n var wsInitialMsgs = [];\r\n var wsVerbose = false;\r\n var " + wsVar + " = new ReconnectingWebSocket(((window.location.protocol === \"https:\") ? \"wss://\" : \"ws://\") + window.location.host + \"/\");\r\n \r\n " + wsVar + ".onopen = function(event) {\r\n wsReady = true;\r\n console.log(" + jsQuote(readyMsg) + ");\r\n wsInitialMsgs.forEach(function(msg) {\r\n if (wsVerbose) console.log(\"Sending initial msg: \" + msg);\r\n ws.send(msg);\r\n });\r\n " + jsDropTrailingComments(onOpen) + " };\r\n \r\n " + wsVar + ".onmessage = function(event) {\r\n " + unnull(onMessage) + "\r\n };\r\n \r\n // add an initial message to send when websocket opens\r\n // also send it now if ws is open already\r\n function wsInitialMsg(msg) {\r\n wsInitialMsgs.push(msg);\r\n if (wsReady) {\r\n if (wsVerbose) console.log(\"Sending initial msg: \" + msg);\r\n ws.send(msg);\r\n }\r\n }\r\n "); } static public String div_vbar(String... items) { return div_vbar(asList(items)); } static public String div_vbar(Collection items, Object... params) { return divUnlessEmpty(joinNemptiesWithVBar(items), params); } static public A getVar(IF0 v) { return v == null ? null : v.get(); } static public A uniq(Class c, Object... params) { return uniqueConcept(c, params); } static public A uniq(Concepts cc, Class c, Object... params) { return uniqueConcept(cc, c, params); } static public List itemPlus(A a, Collection l) { return itemPlusList(a, l); } static public Map applyFunctionToValue(IF1 f, A key, Map map) { return applyFunctionToMapValue(key, f, map); } static public Map applyFunctionToValue(IF1 f, Map map, A... keys) { for (A key : unnull(keys)) applyFunctionToValue(f, key, map); return map; } static public String joinWithBR(Iterable l) { return join("
\n", l); } static public String joinWithBR(String... l) { return joinWithBR(asList(l)); } static public
void listSet(List l, int i, A a, A emptyElement) { if (i < 0) return; while (i >= l(l)) l.add(emptyElement); l.set(i, a); } static public void listSet(List l, int i, A a) { listSet(l, i, a, null); } static public Map cgetAll_cloneLists(Concept c, Collection fields) { return mapToValues(fields, f -> cloneIfList(cget(c, f))); } static public MetaTransformer defaultMetaTransformer() { return metaTransformer_transformableAndList(); } static public A printStruct(String prefix, A a) { printStructure(prefix, a); return a; } static public A printStruct(A a) { printStructure(a); return a; } static public void logStructure(File logFile, Object o) { logQuoted(logFile, structure(o)); } static public void logStructure(String fileName, Object o) { logStructure(getProgramFile(fileName), o); } static public void logStructure(String progID, String fileName, Object o) { logStructure(getProgramFile(progID, fileName), o); } static public int indexOfPred(List l, Object pred) { for (int i = 0; i < l(l); i++) if (checkCondition(pred, l.get(i))) return i; return -1; } static public int indexOfPred(List l, IF1 pred) { return indexOfPred(l, (Object) pred); } static public String hcrud_mergeTables(String table1, String table2, String connector) { List tok1 = htmlTok(table1), tok2 = htmlTok(table2); List tbl1 = first(findContainerTag(tok1, "table")); List tbl2 = first(findContainerTag(tok2, "table")); List> rows1 = findContainerTag(tbl1, "tr"); List> rows2 = findContainerTag(tbl2, "tr"); print("rows1: " + l(rows1) + ", rows2: " + l(rows2)); int nRows = max(l(rows1), l(rows2)); List rows = new ArrayList(); for (int i = 0; i < nRows; i++) { List row1 = dropFirstTwoAndLastTwo(get(rows1, i)); List row2 = dropFirstTwoAndLastTwo(get(rows2, i)); row2 = dropFirst(row2, indexOfIC(row2, "") + 1); rows.add(tr(join(concatLists(row1, ll(td(connector)), row2)))); } replaceTokens(tbl1, 2, l(tbl1) - 2, lines(rows)); return join(tok1); } static public String firstWhereFirstLongIs(Collection l, long i) { return firstThat(l, s -> parseFirstLong(s) == i); } static public String himgsnippet(String imageID, Object... params) { return hsnippetimg(imageID, params); } static public String hjssrc(String src) { return hjavascript_src(src); } static public String renderHowLongAgoPlusModified(long timestamp, long timestamp2, Object... __) { String spacer = optPar("spacer", __, ", modified "); if (timestamp2 == 0) timestamp2 = timestamp; String s = renderHowLongAgo(timestamp); String s2 = renderHowLongAgo(timestamp2); return eq(s, s2) ? s : s + ", modified " + s2; } static public List gazelle_navLinks(String baseLink, String searchQuery, Object... __) { boolean withTeam = optPar("withTeam", __, true); boolean withStats = optPar("withStats", __, true); boolean flat = boolPar("flat", __); List more = ll(ahref(baseLink + "/deletedPosts", "Deleted Posts")); return llNonNulls(flattenStringArray2(ahref(baseLink + "/crud/UserPost?cmd=new", "New Post"), searchQuery != null ? hform(hinputfield("q", searchQuery, "style", "width: 75px") + " " + hsubmit("Search"), "style", "display: inline", "action", baseLink + "/search") : ahref(baseLink + "/search", "Search"), ahref(baseLink + "/rootPosts", "Root Posts"), ahref(baseLink + "/allPosts", "All Posts"), ahref(baseLink + "/latestPosts", "Latest Posts"), ahref(baseLink + "/latestModifiedPosts", "Latest Changes"), ahref(baseLink + "/mainPosts", "Main Posts"), !withTeam ? null : ahref(baseLink + "/team", "Team"), flat ? more : hPopDownButton(flattenStringArray2(!withStats ? null : ahref(baseLink + "/stats", "Stats"), more)))); } static public Map mapToValues(Iterable l, Object f) { return mapKeyAndFunction(l, f); } static public Map mapToValues(Object f, Iterable l) { return mapKeyAndFunction(f, l); } static public Map mapToValues(Iterable l, IF1 f) { return mapKeyAndFunction(f, l); } static public Map mapToValues(IF1 f, Iterable l) { return mapKeyAndFunction(f, l); } static public Map mapToValues(Map map, IF2 f) { return mapKeyAndFunction(map, f); } static public File programFile(String name) { return prepareProgramFile(name); } static public File programFile(String progID, String name) { return prepareProgramFile(progID, name); } static public String regexpFirstGroupIC(String pat, String s) { Matcher m = regexpIC(pat, s); if (m.find()) return m.group(1); else return null; } static public Map safeUnstructMapAllowingClasses(String s, Class... allowedClasses) { return (Map) safeUnstructureAllowingClasses(s, allowedClasses); } static public List uniquifyAndSortAlphaNum(Collection l) { return sortedAlphaNum(uniquify(l)); } static public List allToUpper(Collection l) { List x = new ArrayList(l(l)); if (l != null) for (String s : l) x.add(upper(s)); return x; } static public Object dm_call(Object moduleOrID, String method, Object... args) { Object mod = dm_getModule(moduleOrID); if (mod == null) return null; AutoCloseable __1 = dm_enter(mod); try { return call_withVarargs(mod, method, args); } finally { _close(__1); } } static public List asForPairsWithB(B b, Iterable> l) { List out = new ArrayList(); for (Pair p : unnull(l)) if (eq(pairB(p), b)) out.add(pairA(p)); return out; } static public List asForPairsWithB(Iterable> l, B b) { return asForPairsWithB(b, l); } static public String nPosts(long n) { return n2(n, "post"); } static public String nPosts(Collection l) { return nPosts(l(l)); } static public String nPosts(Map map) { return nPosts(l(map)); } static public String formatDoubleX(double d, int digits) { return formatDoubleFull(d, digits); } static public String str_toM(long l) { return n2(toM(l)) + " MB"; } static public List listToTopTenCI(Collection l) { return asCIMultiSet(l).highestFirst(); } static public boolean fileNempty(File f) { return fileNotEmpty(f); } static public Map decodeHQuery(String query) { Map map = new HashMap(); for (String s : splitAtAmpersand(query)) { int i = s.indexOf('='); if (i >= 0) map.put(urldecode(s.substring(0, i)), urldecode(s.substring(i + 1))); } return map; } static public A firstThat(Iterable l, Object pred) { if (l != null) for (A a : l) if (checkCondition(pred, a)) return a; return null; } static public A firstThat(A[] l, IF1 pred) { if (l != null) for (A a : l) if (pred.get(a)) return a; return null; } static public A firstThat(Iterable l, IF1 pred) { return firstThat(l, (Object) pred); } static public A firstThat(IF1 pred, Iterable l) { return firstThat(l, pred); } static public Map parseColonPropertyCIMap(String text) { return parseColonProperties(text, ciMap()); } static public Object serveFile(File file) { return subBot_serveFile(file); } static public Object serveFile(File file, String mimeType) { return subBot_serveFile(file, mimeType); } static public String faviconMimeType() { return "image/x-icon"; } static public String gazelle_textURL(long postID) { return gazelle_server() + "text/" + postID; } static public Object postJSONPage(String url, Object... params) { return jsonDecode(postPage(url, params)); } static public boolean hasLock(Lock lock) { return ((ReentrantLock) lock).isHeldByCurrentThread(); } static public String mL_raw(String name) { return mechList_raw(name); } static public boolean eqOrSame(Object a, Object b) { return a == null ? b == null : a == b || b != null && a.equals(b); } static public void clear(Collection c) { if (c != null) c.clear(); } static public void clear(Map map) { if (map != null) map.clear(); } static public A reverseGet(List l, int idx) { if (l == null || idx < 0) return null; int n = l(l); return idx < n ? l.get(n - 1 - idx) : null; } static public List mapToLines(Map map) { List l = new ArrayList(); for (Object key : keys(map)) l.add(str(key) + " = " + str(map.get(key))); return l; } static public String mapToLines(Map map, Object f) { return lines(map(map, f)); } static public String mapToLines(Object f, Map map) { return lines(map(map, f)); } static public String mapToLines(Object f, Iterable l) { return lines(map(f, l)); } static public String mapToLines(Iterable l, IF1 f) { return mapToLines((Object) f, l); } static public String mapToLines(IF1 f, Iterable l) { return mapToLines((Object) f, l); } static public String mapToLines(Map map, IF2 f) { return lines(map(map, f)); } static public String stringIf(boolean b, String s) { return stringIfTrue(b, s); } static public float score(Scored s) { return s == null ? 0 : s.score(); } static public String formatDouble_significant2(double d, int digits) { try { digits -= max(0, Math.floor(Math.log10(abs(d)) + 1)); return formatDouble(d, digits); } catch (Throwable _e) { print("Had number: " + d + ", digits: " + digits); throw rethrow(_e); } } static public File pathToJavaxJar() { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.pathToJavaXJar(); return pathToJavaxJar_noResourceLoader(); } static public File pathToJavaxJar_noResourceLoader() { try { int x = latestInstalledJavaX(); File xfile = new File(userHome(), ".javax/x" + Math.max(x, 30) + ".jar"); if (!xfile.isFile()) { print("Saving " + f2s(xfile)); String url = x30JarServerURL(); byte[] data = loadBinaryPage(url); if (data.length < 1000000) throw fail("Could not load " + url); saveBinaryFile(xfile.getPath(), data); } return xfile; } catch (Exception __e) { throw rethrow(__e); } } static public A popFirst(List l) { if (empty(l)) return null; A a = first(l); l.remove(0); return a; } static public A popFirst(Collection l) { if (empty(l)) return null; A a = first(l); l.remove(a); return a; } static public List popFirst(int n, List l) { List part = cloneSubList(l, 0, n); removeSubList(l, 0, n); return part; } static public boolean isA(Either e) { return eitherIsA(e); } static public Object process(String processorID, Object in) { return process(processorID, in, "in"); } static public Object process(String processorID, Object in, String outVar) { try { Class processor = hotwire(processorID); set(processor, "in", in); call(processor, "main", new Object[] { new String[0] }); return get(processor, outVar); } catch (Exception e) { throw new RuntimeException("Error in #" + parseSnippetID(processorID), e); } } static public List syncCloneAndClearList(Collection l) { if (l == null) return emptyList(); synchronized (collectionMutex(l)) { List l2 = cloneList(l); l.clear(); return l2; } } static public List findMainClass(List tok) { for (List c : reversedList(allClasses(tok))) { String name = getClassDeclarationName(c); if (eq(name, "main") || name.startsWith("x")) return c; } return findBlock("m {", tok); } static public boolean useDummyMainClasses() { return true; } static public boolean tok_classHasModifier(List classDecl, String modifier) { if (classDecl == null) return false; int i = classDecl.indexOf("class"); return subList(classDecl, 0, i).contains(modifier); } static public boolean javaCompileToJar_useRAMDisk = false; static public File javaCompileToJar_optionalRename(String src, File destJar, String progIDForRename) { return javaCompileToJar_optionalRename(src, "", destJar, progIDForRename); } static synchronized public File javaCompileToJar_optionalRename(String src, String dehlibs, File destJar, String progIDForRename) { return javaCompileToJar_optionalRename(src, dehlibs, destJar, progIDForRename, null); } static synchronized public File javaCompileToJar_optionalRename(String src, String dehlibs, File destJar, String progIDForRename, String progID) { String javaTarget = null; String dummyClass = "main"; if (progIDForRename != null) { dummyClass = dummyMainClassName(progIDForRename); src += "\nclass " + dummyClass + "{}"; } String md5 = md5(src); File jar = destJar; Class j = getJavaX(); if (javaTarget != null) setOpt(j, "javaTarget", javaTarget); File srcDir = tempDir(); String className = "main"; String fileName = dummyClass + ".java"; List tok = javaTok(src); String packageName = tok_packageName(tok); if (packageName != null) fileName = packageName.replace(".", "/") + "/" + tok_firstClassName(tok) + ".java"; File mainJava = new File(srcDir, fileName); saveTextFile(mainJava, src); File classesDir = javaCompileToJar_useRAMDisk ? tempDirPossiblyInRAMDisk() : tempDir(); try { List libraries = new ArrayList(); Matcher m = Pattern.compile("\\d+").matcher(dehlibs); while (m.find()) { String libID = m.group(); assertTrue(isSnippetID(libID)); libraries.add(loadLibraryOrSrcLib(libID)); } libraries.add(pathToJavaxJar()); String compilerOutput; try { compilerOutput = (String) call(j, "compileJava", srcDir, libraries, classesDir); } catch (Throwable e) { compilerOutput = (String) get(getJavaX(), "javaCompilerOutput"); compilerOutput = indentx("> ", cleanJavaCompilerOutput(compilerOutput)); if (!swic(e.getMessage(), "Java compiler returned errors.")) compilerOutput = appendWithNewLine(compilerOutput, str(e)); throw fail(compilerOutput, e); } compilerOutput = cleanJavaCompilerOutput("Annotation processing got disabled, since it requires a 1.6 compliant JVM"); if (nempty(compilerOutput)) { print("Compiler said: " + compilerOutput); } if (!anyFileWithExtensionInDir(classesDir, ".class")) { printWithIndent("SRC> ", src); throw fail("No classes generated (was compiling " + nChars(src) + ")"); } saveTextFile(new File(classesDir, "main.java"), src); if (nempty(dehlibs)) saveTextFile(new File(classesDir, "libraries"), dehlibs); saveTextFile(new File(classesDir, "progID"), progID); dir2zip_recurse_verbose = false; int n = dir2zip_recurse(classesDir, jar); return jar; } finally { if (isInRAMDisk(classesDir)) deleteDirectory(classesDir); } } static public void touchFile(File file) { try { closeRandomAccessFile(newRandomAccessFile(mkdirsForFile(file), "rw")); } catch (Exception __e) { throw rethrow(__e); } } static public File actualUserDir() { return new File(actualUserHome()); } static public File actualUserDir(String path) { return new File(actualUserHome(), path); } static public int hashCodeFor(Object a) { return a == null ? 0 : a.hashCode(); } static public String joinWithVBar(Iterable l) { return join(" | ", l); } static public String joinWithVBar(String... l) { return joinWithVBar(asList(l)); } static public String ahref_possiblyTargetBlank(String link, Object contents, boolean targetBlank, Object... params) { return ahref(link, contents, targetBlank ? paramsPlus(params, "target", "_blank") : params); } static public A setAll(A o, Map fields) { if (fields == null) return o; for (String field : keys(fields)) set(o, field, fields.get(field)); return o; } static public A setAll(A o, Object... values) { failIfOddCount(values); for (int i = 0; i + 1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i + 1]; set(o, field, value); } return o; } static public Object[] filterParams(Object[] params, Object... keys) { Set set = asSet(keys); List l = new ArrayList(); for (int i = 0; i < l(params); i += 2) if (contains(set, params[i])) { l.add(params[i]); l.add(params[i + 1]); } return asObjectArray(l); } static public void addIfNempty(Collection l, String s) { if (nempty(s)) l.add(s); } static public void addIfNempty(Collection l, Map m) { if (nempty(m)) l.add(m); } static public void addIfNempty(Collection l, Collection c) { if (nempty(c)) l.add(c); } static public void fixACCInClassLoader(Object o) { try { AccessControlContext acc = vm_globalACC(); if (acc != null) replaceACCInClassLoader(o, acc); } catch (Throwable __e) { _handleException(__e); } } static public String systemHashCodeHex(Object o) { return intToHex(identityHashCode(o)); } static public LinkedHashMap cloneLinkedHashMap(Map map) { return map == null ? new LinkedHashMap() : new LinkedHashMap(map); } static public Set emptySet() { return new HashSet(); } static public Map.Entry firstEntry(Map map) { return empty(map) ? null : first(map.entrySet()); } static public StringTree2 stringTree2_javaTok(Map entries) { StringTree2 tree = new StringTree2(); for (String key : keys(entries)) addToStringTree(tree, javaTokC(key), entries.get(key)); return tree; } static public void putMultipleKeys(Map map, Collection keys, B value) { if (map == null || keys == null) return; for (A key : keys) map.put(key, value); } static public List allPlus(final int x, List l) { return map(l, new F1() { public Integer get(Integer i) { try { return i + x; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "i+x"; } }); } static public List jfindAll(List tok, String pat) { return jfindAll(tok, pat, null); } static public List jfindAll(List tok, String pat, ITokCondition condition) { return jfindAll(tok, jfind_preprocess(javaTok(pat)), condition); } static public List jfindAll(List tok, List tokPat) { return jfindAll(tok, tokPat, null); } static public List jfindAll(List tok, List tokPat, ITokCondition condition) { TokCondition cond = toTokCondition(condition); String[] toks = toStringArray(codeTokensOnly(tokPat)); int i = -1; List l = new ArrayList(); while ((i = findCodeTokens(tok, i + 1, false, toks, cond)) >= 0) l.add(i); return l; } static public List tok_subListWithoutBorderNTokens(List tok, int i, int j) { List tok2 = cloneSubList(tok, i & (~1), j | 1); tok2.set(0, ""); tok2.set(l(tok2) - 1, ""); return tok2; } static public String tok_expandIfQuoted(String s) { return applyTranspilationFunction(__103 -> tok_expandIfQuoted(__103), s); } static public void tok_expandIfQuoted(List tok) { jreplace(tok, "if || ", "if (matchOneOf(s, m, $2, $5))"); jreplace_dyn(tok, "if ", new F2, Integer, String>() { public String get(List tok, Integer cIdx) { try { String s = unquote(tok.get(cIdx + 2)); List l = new ArrayList(); for (String pat : splitAtJavaToken(s, "|")) { if (pat.contains("...")) l.add("matchX(" + quote(trim(pat)) + ", s, m)"); else if (javaTok(pat).contains("*")) l.add("match(" + quote(trim(pat)) + ", s, m)"); else l.add("match(" + quote(trim(pat)) + ", s)"); } return "if (" + join(" || ", l) + ")"; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S s = unquote(tok.get(cIdx+2));\r\n //print(\"multimatch: \" + quote(s));\r\n ..."; } }, new TokCondition() { public boolean get(final List tok, final int i) { return javaTokC(unquote(tok.get(i + 3))).contains("|"); } }); tok_transpileIfQuoted_dollarVars(tok); jreplace(tok, "if ", "if (find3plusRestsX($2, s, m))", new TokCondition() { public boolean get(final List tok, final int i) { return startsAndEndsWith(unquote(tok.get(i + 3)), "..."); } }); jreplace(tok, "if ", "if (matchStartX($2, s, m))", new TokCondition() { public boolean get(final List tok, final int i) { return unquote(tok.get(i + 3)).endsWith("..."); } }); jreplace(tok, "if ", "if (match($2, s))", new TokCondition() { public boolean get(final List tok, final int i) { return !javaTokC(unquote(tok.get(i + 3))).contains("*"); } }); jreplace(tok, "if ", "if (match($2, s, m))"); jreplace(tok, "if match ", "if (match($3, s, m))"); } static public void doublePut(Map map, A key1, A key2, B value) { map.put(key1, value); map.put(key2, value); } static public boolean isSingleQuoteIdentifier(String s) { if (l(s) < 2 || s.charAt(0) != '\'' || !Character.isJavaIdentifierStart(s.charAt(1))) return false; for (int i = 2; i < l(s); i++) if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; return true; } static public String fromSingleQuoteIdentifier(String s) { return isSingleQuoteIdentifier(s) ? substring(s, 1) : s; } static public boolean tok_tokenBeforeLonelyReturnValue(List tok, int i) { String t = get(tok, i); if (l(t) == 1 && "{};".contains(t) || eq(t, "else")) return true; if (!eq(t, ")")) return false; int level = 0; while (i > 0) { if (eq(tok.get(i), ")")) ++level; if (eq(tok.get(i), "(")) --level; if (level == 0) return eq(get(tok, i - 2), "if"); i -= 2; } return false; } static public Pair stringTreeLeafValue2(StringTree2 tree, List items) { int i = 0; while (tree != null && i < l(items)) { if (tree.leafValue != null) return pair(tree.leafValue, i); tree = tree.children.get(items.get(i)); ++i; } return null; } static public void mapPutInRange(Map map, int start, int end, A value) { if (map != null && value != null) for (int i = start; i < end; i++) map.put(i, value); } static public String neatMechListURL(String listName) { return "http://botcompany.de/mech/raw/list/" + urlencode(listName); } static public boolean getSnippetTitles_verbose = false; static public Map getSnippetTitles(Collection ids) { try { if (empty(ids)) return new HashMap(); String url = tb_mainServer() + "/tb-int/get-titles.php"; String ids2 = join(" ", parseSnippetIDs(ids)); return trimValues(transformKeys(jsonDecodeMap(doPost(mapPlus(standardCredentialsMap(), "ids", ids2), url)), new F1() { public Object get(String id) { try { return fsI(id); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "fsI(id)"; } })); } catch (Exception __e) { throw rethrow(__e); } } static public String dottedSpan(String contents, String title) { return span(contents, "title", title, "style", "border-bottom: dotted 1px"); } static public ThreadLocal dynamize_linkParams = new ThreadLocal(); static public String dynamize_noEncode(String html) { List tok = htmlTok(html); Pattern p = Pattern.compile(regexp_findSnippetIDs()); for (int i = 0; i < l(tok); i += 2) { Matcher m = p.matcher(tok.get(i).replace("&#", "&~~~")); StringBuffer buf = new StringBuffer(); while (m.find()) { String id = m.group(1); String link = m.group(); try { link = ahref(snippetLink(id), link, concatArrays(new Object[] { "title", getSnippetTitle_cached(id) }, dynamize_linkParams.get())); } catch (Throwable __e) { _handleException(__e); } mreplace(m, buf, link); } m.appendTail(buf); String s = str(buf).replace("&~~~", "&#"); tok.set(i, s); } dynamize_linkParams.set(null); return join(tok); } static public String longSnippetLink(String id) { return tb_mainServer() + "/tb/show-snippet.php?id=" + parseSnippetID(id); } static public Map standardClassesMap() { String sc = loadSnippet("#1003674"); Map map = new HashMap(); for (String line : tlft_j(sc)) { int idx = line.indexOf('/'); map.put(line.substring(0, idx), line.substring(idx + 1)); } return map; } static public Boolean not(Boolean b) { return b == null ? null : !b; } static public String ukTimeZone_string() { return "Europe/London"; } static public ReliableSingleThread dm_rst(Runnable r) { return dm_rst(dm_current_mandatory(), r); } static public ReliableSingleThread dm_rst(DynModule mod, Runnable r) { return dm_rst(mod, new ReliableSingleThread(r)); } static public ReliableSingleThread dm_rst(DynModule mod, ReliableSingleThread rst) { rst.enter = dm_rEnter(mod); return rst; } static public void dm_setModuleName(Object module, String name) { dm_callModule(module, "setModuleName", name); } static public void dm_setModuleName(String name) { dm_setModuleName(dm_current_mandatory_generic(), name); } static public void dm_assertFirstSibling() { if (!dm_isFirstSiblingModule(dm_current_mandatory_generic())) throw fail("Don't start this module multiple times. This instance will exit."); } static public String dbProgramID() { return getDBProgramID(); } static public void ensureConceptClassesAreIndexed(Collection classes) { for (Class c : unnull(classes)) ensureConceptClassIsIndexed(c); } static public JButton jPopDownButton_noText(final Object... menuParams) { return toolTip("Additional commands", jPopDownButton("", menuParams)); } static public Runnable runnableThread(final Runnable r) { return new Runnable() { public void run() { try { startThread(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "startThread(r)"; } }; } static public Object serve500() { return subBot_serve500(); } static public Object serve500(String msg) { return subBot_serve500(msg); } static public void htmlencode_forParams_useV2() { htmlencode_forParams_useV2.set(true); } static public AutoCloseable temp_printPrefix(String prefix) { Object oldValue = print_byThread(); print_setPrefixForThread(prefix); return new AutoCloseable() { public String toString() { return "print_byThread().set(oldValue);"; } public void close() throws Exception { print_byThread().set(oldValue); } }; } static public Map decodeURIParams(String query) { return decodeHQuery(query); } static public boolean cset_trueIfChanged(Concept c, Object... values) { try { return cset(c, values) != 0; } catch (Exception __e) { throw rethrow(__e); } } static public Object subBot_serveFile_maxCache(File file) { return subBot_maxCacheHeaders(subBot_serveFile(file)); } static public Object subBot_serveFile_maxCache(File file, String mimeType) { return subBot_maxCacheHeaders(subBot_serveFile(file, mimeType)); } static public String mp3mimeType() { return "audio/mpeg"; } static public String dropAfterSlash(String s) { if (s == null) return null; int i = s.indexOf('/'); return i < 0 ? s : rtrim(substring(s, 0, i)); } static public String binaryMimeType() { return "application/octet-stream"; } static public Object subBot_maxCacheHeaders(Object response) { return callMainBot("maxCacheHeaders", response); } static public Object serveInputStream(InputStream in, String mimeType) { return subBot_serveInputStream(in, mimeType); } static public BufferedInputStream bufferedFileInputStream(File f) { return bufferedInputStream(f); } static public BufferedInputStream bufferedFileInputStream(File f, int bufSize) { try { return new BufferedInputStream(new FileInputStream(f), bufSize); } catch (Exception __e) { throw rethrow(__e); } } static public String rawLink(String pageName) { return "/" + parseSnippetID(getProgramID()) + "/raw" + addPrefix("/", pageName); } static public String rawLink() { return "/" + parseSnippetID(getProgramID()) + "/raw"; } static public String rawLink(String pageName, String contents) { return ahref(rawLink(pageName), contents); } static public String webChatBotLogsHTML2(final String baseLink, final Map params) { return withDBLock(new F0() { public String get() { try { List l = new ArrayList(); for (Conversation conv : sortByCalculatedFieldDesc(list(Conversation.class), new F1() { public Object get(Conversation c) { try { return empty(c.msgs) ? c.created : last(c.msgs).time; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "empty(c.msgs) ? c.created : last(c.msgs).time"; } })) { List> dialogs = reversed(unnull(conv.oldDialogs)); if (l(conv.msgs) > 1) l.add(webChatBotLogsHTML_formatDialog(str(conv.id), conv.msgs)); int i = 2; for (List msgs : dialogs) if (l(msgs) > 1) l.add(webChatBotLogsHTML_formatDialog(conv.id + "/" + (i++), msgs)); } int perPage = 50, n = parseIntOpt(params.get("n")); return h3_htitle("Chat Logs") + pageNav2(baseLink, l(l), n, perPage, "n") + ul(subList(l, n, n + perPage), null, "style", "margin-top: 1em"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new L l;\r\n for (Conversation conv : sortByCalculatedFieldDesc(list Conv..."; } }); } static public String fileInfo(File f) { return renderFileInfo(f); } static public String fileInfo(String f) { return renderFileInfo(newFile(f)); } static public File backupConceptsNow() { return backupConceptsNow(db_mainConcepts()); } static public File backupConceptsNow(Concepts cc) { if (cc == null) return null; File f1 = cc.conceptsFile(); File f2 = fileInSameDir(f1, "backups/concepts.structure" + (cc.useGZIP ? ".gz" : "") + ".backup" + ymd_minus_hms()); return copyFile(f1, f2); } static public String hhtml_title_body(String title, Object bodyContents, Object... bodyParams) { return hhtml_head_title_body(title, bodyContents, bodyParams); } static public String nMessages(long n) { return n2(n, "message"); } static public String nMessages(Collection l) { return nMessages(l(l)); } static public String hstylesheetsrc(String src) { return tag("link", "", "rel", "stylesheet", "href", src); } static public Boolean trueOrNull(boolean b) { return b ? Boolean.TRUE : null; } static public String or2_trim(String a, String b) { a = trim(a); if (nempty(a)) return a; return trim(b); } static public String or2_trim(String a, String b, String c) { return or2_trim(or2_trim(a, b), c); } static public String hexColorToCSSRGB(String hex) { return empty(hex) ? null : "rgb(" + joinWithComma(rgbToIntList(new RGB(hex))) + ")"; } static public String loadSnippet_cached(String id) { return loadSnippet_simpleCache(id); } static public String lower(String s) { return s == null ? null : s.toLowerCase(); } static public char lower(char c) { return Character.toLowerCase(c); } static public String psI_str(String snippetID) { return str(psI(snippetID)); } static public String jsBool(boolean b) { return b ? "true" : "false"; } static public String hreplaceTitle(String html, String newTitle) { return hreplacetag(html, "title", htitle(newTitle)); } static public Object subBot_serveJavaScript(String html) { return subBot_serveWithContentType(html, "text/javascript"); } static public A conceptWhere(Class c, Object... params) { return findConceptWhere(c, params); } static public A conceptWhere(Concepts cc, Class c, Object... params) { return findConceptWhere(cc, c, params); } static public Object subBot_serveFile(File file) { return call(getMainBot(), "serveFile", file); } static public Object subBot_serveFile(File file, String mimeType) { return call(getMainBot(), "serveFile", file, mimeType); } static public Map guessMimeTypeFromFileName_map = litmap(".css", "text/css", ".js", "text/javascript"); static public String guessMimeTypeFromFileName(String name) { return guessMimeTypeFromFileName(name, binaryMimeType()); } static public String guessMimeTypeFromFileName(String name, String defaultMimeType) { String __1 = guessMimeTypeFromFileName_map.get(fileExtension(name)); if (!empty(__1)) return __1; return or2(URLConnection.guessContentTypeFromName(name), defaultMimeType); } static public String afterLastSlash(String s) { if (s == null) return null; int i = s.lastIndexOf('/'); return i < 0 ? s : substring(s, i + 1); } static public String hhtml_head_title_body(String title, Object bodyContents, Object... bodyParams) { return hhtml(hhead(htitle(title)) + "\n" + hbody(bodyContents, bodyParams)); } static public String hcss_linkColorInherit() { return hcss("a { color: inherit; }"); } static public Collection conceptsWhere(Class c, Object... params) { return findConceptsWhere(c, params); } static public Collection conceptsWhere(String c, Object... params) { return findConceptsWhere(c, params); } static public Collection conceptsWhere(Concepts concepts, Class c, Object... params) { return findConceptsWhere(concepts, c, params); } static public List replace(List l, A a, A b) { for (int i = 0; i < l(l); i++) if (eq(l.get(i), a)) l.set(i, b); return l; } static public List replace(A a, A b, List l) { return replace(l, a, b); } static public String replace(String s, String a, String b) { return s == null ? null : a == null || b == null ? s : s.replace(a, b); } static public String replace(String s, char a, char b) { return s == null ? null : s.replace(a, b); } static public String ymd_minus_hm() { return ymd() + "-" + hhmm(); } static public Object serveCSVWithFileName(String fileName, String text) { Object response = serveWithContentType(text, "text/csv"); call(response, "addHeader", "Content-Disposition", "inline; filename=\"" + fileName + "\""); return response; } static public NavigableMap emojiShortNameMap_cache; static public NavigableMap emojiShortNameMap() { if (emojiShortNameMap_cache == null) emojiShortNameMap_cache = emojiShortNameMap_load(); return emojiShortNameMap_cache; } static public NavigableMap emojiShortNameMap_load() { NavigableMap map = ciMap(); for (Map m : rawEmojisList()) { String shortName = (String) (m.get("shortname")); String emoji = (String) (m.get("emoji")); if (startsWith(shortName, ":")) map.put(shortName, emoji); } return map; } static public String hjavascript_src_withType(String src, Object... __) { return hfulltag("script", "", paramsPlus_inFront(__, "src", src, "type", "text/javascript")); } static public String htableRaw2(List data, List paramsTable, List paramsTR, List paramsTD) { StringBuilder buf = new StringBuilder(); for (List row : data) { buf.append(hopeningTag("tr", toObjectArray(paramsTR))); for (Object cell : row) buf.append(htd(cell, toObjectArray(paramsTD))).append("\n"); buf.append("\n"); } return htag("table", buf, toObjectArray(paramsTable)); } static public List llNonNulls(A... a) { List l = new ArrayList(); for (A x : a) if (x != null) l.add(x); return l; } static public int conceptCount(Concepts concepts, Class c, Object... params) { return countConcepts(concepts, c, params); } static public int conceptCount(Class c, Object... params) { return countConcepts(c, params); } static public int conceptCount() { return countConcepts(); } static public int conceptCount(String className) { return countConcepts(className); } static public int conceptCount(Concepts concepts, String className) { return countConcepts(concepts, className); } static public int conceptCount(Concepts concepts) { return countConcepts(concepts); } static public String toK_str(long l) { return str_toK(l); } static public File conceptsFile(String progID) { return getProgramFile(progID, conceptsFileName()); } static public File conceptsFile() { return conceptsFile(dbProgramID()); } static public String renderDBLoadTime() { return renderDBLoadTime(db_mainConcepts()); } static public String renderDBLoadTime(Concepts cc) { if (cc == null) return null; return cc.loadTook < 0 ? "unknown" : n2(cc.loadTook) + " ms"; } static public String renderDBSaveTime() { return renderDBSaveTime(db_mainConcepts()); } static public String renderDBSaveTime(Concepts cc) { if (cc == null) return null; return cc.lastSaveTook < 0 ? "unknown" : n2(cc.lastSaveTook) + " ms"; } static public String renderHowLongAgo(long timestamp) { if (timestamp == 0) return "never"; int seconds = howManySecondsAgo(timestamp); if (seconds <= 0) return "just now"; if (seconds < 60) return n2(seconds, "second") + " ago"; int minutes = iround(seconds / 60.0); if (minutes < 60) return n2(minutes, "minute") + " ago"; int hours = iround(minutes / 60.0); if (hours < 24) return n2(hours, "hour") + " ago"; int days = iround(hours / 24.0); return n2(days, "day") + " ago"; } static public List listZIP(File inZip) { return listZip(inZip); } static public String appendSlash(String s) { return addSlash(s); } static public byte[] loadBinaryFromZip(File inZip, String fileName) { try { ZipFile zip = new ZipFile(inZip); try { ZipEntry entry = zip.getEntry(fileName); if (entry == null) return null; InputStream fin = zip.getInputStream(entry); ByteArrayOutputStream baos = new ByteArrayOutputStream(); copyStream(fin, baos); fin.close(); return baos.toByteArray(); } finally { zip.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean fileContentsIs(File f, byte[] data) { try { if (isFile(f) != (data != null)) return false; int l = l(data); if (fileSize(f) != l) return false; BufferedInputStream in = bufferedFileInputStream(f); try { for (int ofs = 0; ofs < l; ofs++) if (data[ofs] != (byte) in.read()) return false; return true; } finally { _close(in); } } catch (Exception __e) { throw rethrow(__e); } } static public void touchConcept(Concept c) { if (c != null) c.change(); } static public String nChanges(long n) { return n2(n, "change"); } static public String nChanges(Collection l) { return nChanges(l(l)); } static public String squareBracket(String s) { return "[" + s + "]"; } static public String hcss_responstableForForms() { return hcss("\r\n .responstableForForms {\r\n margin: 1em 0;\r\n /*width: 100%;*/\r\n overflow: hidden;\r\n background: #FFF;\r\n color: #024457;\r\n border-radius: 10px;\r\n border: 1px solid #167F92;\r\n }\r\n \r\n .responstableForForms tr {\r\n border: 1px solid #D9E4E6;\r\n }\r\n .responstableForForms tr:nth-child(odd) {\r\n background-color: #EAF3F3;\r\n }\r\n .responstableForForms th {\r\n display: none;\r\n border: 1px solid #FFF;\r\n background-color: #167F92;\r\n color: #FFF;\r\n padding: 1em;\r\n }\r\n .responstableForForms th:first-child {\r\n display: table-cell;\r\n text-align: center;\r\n }\r\n .responstableForForms th:nth-child(2) {\r\n display: table-cell;\r\n }\r\n .responstableForForms th:nth-child(2) span {\r\n display: none;\r\n }\r\n .responstableForForms th:nth-child(2):after {\r\n content: attr(data-th);\r\n }\r\n @media (min-width: 480px) {\r\n .responstableForForms th:nth-child(2) span {\r\n display: block;\r\n }\r\n .responstableForForms th:nth-child(2):after {\r\n display: none;\r\n }\r\n }\r\n .responstableForForms td {\r\n display: block;\r\n word-wrap: break-word;\r\n /*max-width: 7em;*/\r\n }\r\n .responstableForForms td:first-child {\r\n display: table-cell;\r\n text-align: center;\r\n border-right: 1px solid #D9E4E6;\r\n }\r\n @media (min-width: 480px) {\r\n .responstableForForms td {\r\n border: 1px solid #D9E4E6;\r\n }\r\n }\r\n .responstableForForms th, .responstableForForms td {\r\n text-align: left;\r\n margin: .5em 1em;\r\n }\r\n @media (min-width: 480px) {\r\n .responstableForForms th, .responstableForForms td {\r\n display: table-cell;\r\n padding: 1em;\r\n }\r\n }\r\n "); } static public String hjs_selectize() { return "\r\n \r\n \r\n "; } static public boolean neqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return false; return true; } static public boolean isConceptList(Object o) { if (!(o instanceof List)) return false; List l = (List) o; for (Object x : l) if (!(x instanceof Concept)) return false; return true; } static public String htmlEncode_nlToBr_withIndents(String s) { return nlToBr_withIndents(htmlEncode(s)); } static public void addInFront(List c, A a) { addFirst(c, a); } static public String hjs_imgUploadBase64Encoder() { return hscript("\r\n var imgConverted = false;\r\n \r\n function submitWithImageConversion(form) {\r\n console.log(\"imgConverted: \" + imgConverted + \", form: \" + form);\r\n if (imgConverted) return true;\r\n imgConverted = true;\r\n var file = $('#imgUploader')[0].files[0];\r\n if (file == null) return true;\r\n var reader = new FileReader();\r\n\r\n // delay form submit until reader is done\r\n reader.onloadend = function () {\r\n var b64 = reader.result.replace(/^data:.+;base64,/, '');\r\n $(\"#f_img_base64\").val(b64);\r\n console.log(\"Got base64 data: \" + b64.length);\r\n setTimeout(function() {\r\n $(form).submit();\r\n }, 1000);\r\n };\r\n\r\n reader.readAsDataURL(file);\r\n return false;\r\n }\r\n "); } static public String himageupload(Object... params) { return hfileupload(paramsPlus(params, "accept", "image/png,image/jpeg,image/gif")); } static public String hhiddenWithIDAndName(String idAndName) { return hhiddenWithIDAndName(idAndName, null); } static public String hhiddenWithIDAndName(String idAndName, Object value, Object... params) { return tag("input", "", paramsPlus(params, "type", "hidden", "id", idAndName, "name", idAndName, "value", value)); } static public String hjs_fileUploadBase64Encoder() { return hscript("\r\n var fileConverted = false;\r\n \r\n function submitWithFileConversion(form) {\r\n if (fileConverted) return true;\r\n fileConverted = true;\r\n var file = $('#fileUploader')[0].files[0];\r\n if (file == null) return true;\r\n var reader = new FileReader();\r\n\r\n // delay form submit until reader is done\r\n reader.onloadend = function () {\r\n var b64 = reader.result.replace(/^data:.+;base64,/, '');\r\n $(\"#f_file_base64\").val(b64);\r\n console.log(\"Got base64 data: \" + b64.length);\r\n setTimeout(function() {\r\n $(form).submit();\r\n }, 1000);\r\n };\r\n\r\n reader.readAsDataURL(file);\r\n return false;\r\n }\r\n "); } static public String hmp3upload(Object... params) { return hfileupload(paramsPlus(params, "accept", mp3mimeType())); } static public Object[] litparams(Object... l) { int n = 0, n1 = l(l); for (int i = 0; i < n1; i += 2) if (l[i] != null && l[i + 1] != null) ++n; if (n == 0) return null; Object[] params = new Object[n * 2]; int j = 0; for (int i = 0; i < n1; i += 2) { Object key = l[i], value = l[i + 1]; if (key != null && value != null) { params[j++] = key; params[j++] = value; } } return params; } static public String hfileupload(Object... params) { return hinput("", paramsPlus_noOverwrite(params, "type", "file", "name", "thefile")); } static public List sortedByConceptID(Collection c) { return sortedByCalculatedField("conceptID", c); } static public Set joinSets(Collection... l) { Set set = similarEmptySet(first(l)); for (Collection o : l) if (o != null) set.addAll(o); return set; } static public String shortName(Object o) { return shortClassName(o); } static public A replaceIfEquals(A a, A b, A c) { return replaceIfEqual(a, b, c); } static public Type type_LS() { return new ParameterizedTypeImpl(null, List.class, String.class); } static public String ol_htmlEncode(String... list) { return ol_htmlEncode(asList(list)); } static public String ol_htmlEncode(List list, Object... params) { return ol(lmap(__104 -> htmlEncode(__104), list), params); } static public void replaceMap(Map dest, Map src) { if (dest == src) return; dest.clear(); dest.putAll(src); } static public String formatLocalDateWithMinutes(long time) { return localDateWithMinutes(time); } static public String formatLocalDateWithMinutes() { return localDateWithMinutes(); } static public String renderColonProperties(Map map) { return formatColonProperties(map); } static public String renderColonProperties(List> l) { return formatColonProperties(l); } static public String pnlToStringWithEmptyLines_rtrim(Iterable l) { return rtrim(pnlToStringWithEmptyLines(l)); } static public String hcrud_imagePreviewStyle() { return "max-width: 200px; max-height: 100px; width: auto; height: auto"; } static public void saveFileVerbose(File f, byte[] data) { saveBinaryFileVerbose(f, data); } static public byte[] base64decode(String s) { byte[] alphaToInt = base64decode_base64toint; int sLen = s.length(); int numGroups = sLen / 4; if (4 * numGroups != sLen) throw new IllegalArgumentException("String length must be a multiple of four."); int missingBytesInLastGroup = 0; int numFullGroups = numGroups; if (sLen != 0) { if (s.charAt(sLen - 1) == '=') { missingBytesInLastGroup++; numFullGroups--; } if (s.charAt(sLen - 2) == '=') missingBytesInLastGroup++; } byte[] result = new byte[3 * numGroups - missingBytesInLastGroup]; int inCursor = 0, outCursor = 0; for (int i = 0; i < numFullGroups; i++) { int ch0 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); int ch1 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); int ch2 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); int ch3 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4)); result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2)); result[outCursor++] = (byte) ((ch2 << 6) | ch3); } if (missingBytesInLastGroup != 0) { int ch0 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); int ch1 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4)); if (missingBytesInLastGroup == 1) { int ch2 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2)); } } return result; } static public int base64decode_base64toint(char c, byte[] alphaToInt) { int result = alphaToInt[c]; if (result < 0) throw new IllegalArgumentException("Illegal character " + c); return result; } static final public byte[] base64decode_base64toint = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; static public String beforeColonOrAll(String s) { return takeFirst(smartIndexOf(s, ':'), s); } static public double elapsedSeconds_timestamp(long time) { return toSeconds(now() - time); } static public String div_floatRight(Object contents, Object... params) { return div(contents, params_stylePlus("float: right", params)); } static public String htmlEncode2_gen(Object o) { return htmlEncode2(str(o)); } static public String nConversations(long n) { return n2(n, "conversation"); } static public String nConversations(Collection l) { return nConversations(l(l)); } static public String nConversations(Map map) { return nConversations(l(map)); } static public File secretProgramFile(String progID, String fileName) { return new File(getSecretProgramDir(progID), fileName); } static public File secretProgramFile(String fileName) { return secretProgramFile(getProgramID(), fileName); } static public ContentsIndexedList ciContentsIndexedList() { return new ContentsIndexedList(ciMap()); } static public Map mapPlus_inFront(Map m, Object... data) { LinkedHashMap m2 = new LinkedHashMap(); litmap_impl(m2, data); putAll(m2, m); return m2; } static public int addAndReturnIndex(List l, A a) { if (l == null) return -1; int idx = l.size(); l.add(a); return idx; } static public String formatCSVFileForExcel2(List rows) { String sep = "|"; return windowsLineBreaks("sep=" + sep + "\n" + mapToLines_rtrim(rows, row -> join(sep, map(row, col -> replace(newLinesToSpaces(str(col)), sep, " "))))); } static public List itemPlusList(A a, Collection l) { return concatLists(ll(a), l); } static public Set putSetElementsFirst(Collection cl, Collection elements) { Set inputSet = asSet(cl); LinkedHashSet set = new LinkedHashSet(); for (A a : unnull(elements)) if (contains(inputSet, a)) set.add(a); addAll(set, cl); return set; } static public Set putSetElementsFirst(Collection cl, A... elements) { return putSetElementsFirst(cl, asList(elements)); } static public Cache> countryDialCodesMultiMap_cache = new Cache<>(() -> countryDialCodesMultiMap_load()); static public MultiMap countryDialCodesMultiMap() { return countryDialCodesMultiMap_cache.get(); } static public MultiMap countryDialCodesMultiMap_load() { return treeMultiMapIndexByField("dialCode", countryDialCodes()); } static public List splitAtComma_trim(String s) { return nempties(trimAll(splitAtComma(s))); } static public String dialCodeStringForCountryCode(String countryCode) { CountryDialCode cdc = countryDialCodeByCountryCode(countryCode); return cdc == null ? null : cdc.dialCode; } static public List collectSorted(Iterable c, String field) { return sorted(collect(c, field)); } static public List collectSorted(String field, Iterable c) { return collectSorted(c, field); } static public List concatMap(Object f, Iterable l) { return concatLists(map(f, l)); } static public List concatMap(Iterable l, Object f) { return concatMap(f, l); } static public List concatMap(Object f, Object[] l) { return concatLists(map(f, l)); } static public List concatMap(Object[] l, Object f) { return concatMap(f, l); } static public > List concatMap(Iterable l, IF1 f) { return concatMap(l, (Object) f); } static public > List concatMap(IF1 f, Iterable l) { return concatMap(l, f); } static public String dropPrefix_trim(String prefix, String s) { return dropPrefixTrim(prefix, s); } static public String formatLocalDateWithSeconds(long time) { return localDateWithSeconds(time); } static public String formatLocalDateWithSeconds() { return localDateWithSeconds(); } static public String imageSnippetURLOrEmptyGIF(String snippetID) { return empty(snippetID) ? smallestTransparentGIFDataURI() : snippetImageURL(snippetID); } static public Scorer scorerWithSuccessesAndErrors() { Scorer scorer = new Scorer(); scorer.successes = new ArrayList(); scorer.errors = new ArrayList(); return scorer; } static public List sortByFieldDesc(Collection c, final String field) { return sortedByFieldDesc(c, field); } static public List sortByFieldDesc(String field, Collection c) { return sortedByFieldDesc(field, c); } static public Object[] onlyNonNullParams(Object... params) { List out = new ArrayList(); for (int i = 0; i + 1 < l(params); i += 2) if (params[i] != null && params[i + 1] != null) { out.add(params[i]); out.add(params[i + 1]); } return toObjectArray(out); } static public A lowestConceptByField(Class c, String field) { return lowestConceptByField(db_mainConcepts(), c, field); } static public A lowestConceptByField(Concepts concepts, Class c, String field) { IFieldIndex index = concepts.getFieldIndex(c, field); if (index instanceof ConceptFieldIndexDesc) { Map.Entry e = ((NavigableMap) ((ConceptFieldIndexDesc) index).valueToObject.data).lastEntry(); return e == null ? null : (A) first((Collection) e.getValue()); } return lowestByField(field, concepts.list(c)); } static public java.util.Timer doAfter(long delay, Object r) { return doLater(delay, r); } static public java.util.Timer doAfter(double delaySeconds, Object r) { return doLater(delaySeconds, r); } static public void registerConcept(Concept c) { db_mainConcepts().register(c); } static public void registerConcept(Concepts cc, Concept c) { cc.register(c); } static public void db() { conceptsAndBot(); } static public void db(Integer autoSaveInterval) { conceptsAndBot(autoSaveInterval); } static public void indexConceptFields(Object... params) { int i = 0; Concepts concepts; if (first(params) instanceof Concepts) { concepts = (Concepts) first(params); ++i; } else concepts = db_mainConcepts(); for (; i < l(params); i += 2) indexConceptField(concepts, (Class) params[i], (String) params[i + 1]); } static public void indexSingletonConcept(Concepts cc, Class c) { indexConceptField(cc, c, "_dummy"); } static public void indexSingletonConcept(Class c) { indexSingletonConcept(db_mainConcepts(), c); } static public Object subBot_noCacheHeaders(Object r) { call(r, "addHeader", "Cache-Control", "no-cache, must-revalidate, max-age=0"); return r; } static public Object subBot_serveHTML(Object html) { return subBot_serveWithContentType(str(html), "text/html"); } static public String html_emojisToUnicode(String s) { return join(mapNonCodeTokens(__105 -> emojisToUnicode(__105), htmlTok(s))); } static public String fullRawLink(String pageName) { return (subBot_isHttps() ? "https" : "http") + "://" + domain() + rawLink(pageName); } static public String unicode_undoArrow() { return unicodeFromCodePoint(0x21B6); } static public String htmldecode_dropAllTags(String html) { return htmldecode(dropAllTags(html)); } static public List splitAtVerticalBar(String s) { return s == null ? new ArrayList() : trimAll(asList(s.split("\\|"))); } static public String hbuttonOnClick_returnFalse(String text, String onClick, Object... params) { return hfulltag("button", text, paramsPlus(params, "onclick", addSuffix(trim(onClick), ";") + " return false;")); } static public String stringUnless(boolean b, String s) { return b ? "" : s; } static public List text_multipleChoiceSplit(String input, String multipleChoiceSeparator) { return trimAll(splitAt(input, dropSpaces(multipleChoiceSeparator))); } static public TreeSet asCISet(Iterable c) { return toCaseInsensitiveSet(c); } static public TreeSet asCISet(String... x) { return toCaseInsensitiveSet(x); } static public String hcheckbox(String name, boolean checked, Object... params) { return tag("input", "", arrayPlus(params, "type", "checkbox", "name", name, checked ? "checked" : null, "1")); } static public String hcheckbox(String name) { return hcheckbox(name, false); } static public String unicode_crossProduct() { return unicodeFromCodePoint(0x2A2F); } static public String timeInTimeZoneWithOptionalDate_24(String timezone, long time) { return timeInTimeZoneWithOptionalDate_24(timeZone(timezone), time); } static public String timeInTimeZoneWithOptionalDate_24(TimeZone timezone, long time) { SimpleDateFormat format = simpleDateFormat("yyyy/MM/dd", timezone); String date = format.format(time); boolean needDate = neq(date, format.format(now())); return (needDate ? date + " " : "") + timeInTimeZone(timezone, time); } static public String hhead_title(String title) { return hhead(htitle(title)); } static public String jsBackLink() { return "javascript:history.go(-1)"; } static public String ipToCountry2020_safe(String ip) { try { return or2(ipToCountry2020(ip), "?"); } catch (Throwable __e) { _handleException(__e); } return "?"; } static public String replaceSquareBracketVars(String s, Object... params) { if (empty(params)) return s; Map vars = mapKeys(__106 -> deSquareBracket(__106), (Map) litcimap(params)); return regexpReplaceIC(s, "\\[(.+?)\\]", matcher -> { String var = matcher.group(1); Object val = vars.get(var); return val == null ? matcher.group() : str(val); }); } static public String dropSpaces(String s) { return unnull(s).replace(" ", ""); } static public A lastThat(List l, Object pred) { for (int i = l(l) - 1; i >= 0; i--) { A a = l.get(i); if (checkCondition(pred, a)) return a; } return null; } static public A lastThat(Object pred, List l) { return lastThat(l, pred); } static public A lastThat(IF1 pred, List l) { return lastThat((Object) pred, l); } static public A lastThat(List l, IF1 pred) { return lastThat(pred, l); } static public String addSlashPrefix(String s) { return addPrefix("/", s); } static public boolean confirmOKCancel(final Component owner, final String msg) { return isTrue(swingAndWait(new F0() { public Object get() { try { return JOptionPane.showConfirmDialog(owner, msg, "JavaX", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret JOptionPane.showConfirmDialog(owner,\r\n msg, \"JavaX\", JOptionPane.OK_..."; } })); } static public boolean confirmOKCancel(String msg) { return confirmOKCancel(null, msg); } static public JTextField jtextfield() { return jTextField(); } static public JTextField jtextfield(String text) { return jTextField(text); } static public JTextField jtextfield(Object o) { return jTextField(o); } static public JPanel showFormTitled2(String title, Object... parts) { return showFormTitled_customLayout(formLayouter1(), title, parts); } static public String gtt(JTextComponent c) { return getTextTrim(c); } static public String gtt(JComboBox cb) { return getTextTrim(cb); } static public JWindow infoBox(String text) { return infoMessage(text); } static public JWindow infoBox(String text, double seconds) { return infoMessage(text, seconds); } static public JWindow infoBox(Throwable e) { return infoMessage(e); } static public void inputText(final String msg, final Object action) { inputText(msg, "", action); } static public void inputText(final String msg, final String defaultText, final Object action) { final Object threadInfo = _threadInfo(); swingLater(new Runnable() { public void run() { try { final JTextField tf = jtextfield(defaultText); String title = joinStrings(" | ", msg, programName()); JComponent form = showFormTitled(title, unnull(msg), tf, new Runnable() { public void run() { try { vmBus_send("inputtingText_OK", threadInfo, msg, tf); callF_thread(action, getTextTrim(tf)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "vmBus_send(\"inputtingText_OK\", threadInfo, msg, tf);\r\n callF_thread(ac..."; } }); renameSubmitButton(form, "OK"); vmBus_send("inputtingText", threadInfo, msg, tf); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final JTextField tf = jtextfield(defaultText);\r\n String title = joinString..."; } }); } static public void inputText(String msg, String defaultText, IVF1 action) { inputText(msg, defaultText, (Object) action); } static public void inputText(String msg, IVF1 action) { inputText(msg, (Object) action); } static public Object subBot_serveRedirect(String url) { return call(getMainBot(), "serveRedirect", url); } static public String html_evaluateIfTags(String html, IF1 pred) { List tok = htmlTok(html); boolean anyChange = false; while (true) { ping(); List ifTag = first(findContainerTag(tok, "if")); if (ifTag == null) break; anyChange = true; int iElse = indexOfIC(ifTag, ""); boolean val = pred.get(htmlTagFullParamString(second(ifTag))); if (val) { if (iElse >= 0) clearTokens(ifTag, iElse, l(ifTag) - 2); } else { clearTokens(ifTag, 2, iElse < 0 ? l(ifTag) - 2 : iElse + 1); } clearToken(ifTag, 1); clearToken(ifTag, l(ifTag) - 2); } return anyChange ? join(tok) : html; } static public A syncGet(List l, int idx) { if (l == null || idx < 0) return null; synchronized (l) { return idx < l(l) ? l.get(idx) : null; } } static public B syncGet(Map map, A a) { if (map == null) return null; synchronized (map) { return map.get(a); } } static public String serveSnippetURL(String snippetID) { return "https://botcompany.de/serve/" + psI(snippetID); } static public IterableIterator> iterateWithIndex1(Collection l) { return iterateListWithIndex(l, 1); } static public A pairA(Pair p) { return p == null ? null : p.a; } static public String ulIfNempty(Collection list, Object... params) { return empty(list) ? "" : ul(list, params); } static public String prependSquareBracketed(Object o) { String s = str(o); return empty(s) ? "" : squareBracketed(s) + " "; } static public int countWords(String s) { return numberOfWords2(s); } static public List dropHTMLTags(List tok) { return dropAllTags(tok); } static public String dropHTMLTags(String html) { return dropAllTags(html); } static public boolean isValidInternationalPhoneNumber(String s) { InternationalPhoneValidator v = new InternationalPhoneValidator(s); v.run(); if (v.error != null) print(v.error); return v.valid; } static public String formatColonProperties(Map map) { return mapToLines("joinPairWithColon", mapToPairs(map)); } static public String formatColonProperties(List> l) { return mapToLines("joinPairWithColon", l); } static public void sendMailThroughScript(String senderInfo, String from, String to, String subject, String text) { List l = splitAt(senderInfo, "#"); if (l(l) != 2) throw fail("Bad mail sender info"); String url = first(l), pw = second(l); print("Sending mail through " + url); print("From: " + from); print("To: " + to); print("Subject: " + subject); print("Text:"); printIndent("> ", text); assertStartsWith("OK", postPage(url, "pw", pw, "from", from, "to", to, "subject", subject, "text", text)); } static public Lock appendToFile_lock = lock(); static public boolean appendToFile_keepOpen = false; static public HashMap appendToFile_writers = new HashMap(); static public void appendToFile(String path, String s) { try { Lock __0 = appendToFile_lock; lock(__0); try { mkdirsForFile(new File(path)); path = getCanonicalPath(path); Writer writer = appendToFile_writers.get(path); if (writer == null) { writer = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(path, true), "UTF-8")); if (appendToFile_keepOpen) appendToFile_writers.put(path, writer); } writer.write(s); if (!appendToFile_keepOpen) writer.close(); } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } static public void appendToFile(File path, String s) { if (path != null) appendToFile(path.getPath(), s); } static public void cleanMeUp_appendToFile() { AutoCloseable __3 = tempCleaningUp(); try { Lock __1 = appendToFile_lock; lock(__1); try { closeAllWriters(values(appendToFile_writers)); appendToFile_writers.clear(); } finally { unlock(__1); } } finally { _close(__3); } } static public A syncNextToLast(List l) { if (l == null) return null; synchronized (l) { return nextToLast(l); } } static public void syncRemoveLast(List l) { if (l != null) synchronized (l) { removeLast(l); } } static public void syncRemoveLast(List l, int n) { if (l != null) synchronized (l) { removeLast(l, n); } } static public void syncRemoveLast(int n, List l) { syncRemoveLast(l, n); } static public void syncReplaceCollection(Collection dest, Collection src) { if (dest == src) return; synchronized (collectionMutex(dest)) { dest.clear(); if (src != null) dest.addAll(src); } } static public Set asSet(Object[] array) { HashSet set = new HashSet(); for (Object o : array) if (o != null) set.add(o); return set; } static public Set asSet(String[] array) { TreeSet set = new TreeSet(); for (String o : array) if (o != null) set.add(o); return set; } static public Set asSet(Iterable l) { if (l instanceof Set) return (Set) l; HashSet set = new HashSet(); for (A o : unnull(l)) if (o != null) set.add(o); return set; } static public Set asSet(MultiSet ms) { return ms == null ? null : ms.asSet(); } static public List flattenList2(Object... a) { List l = new ArrayList(); if (a != null) for (Object x : a) if (x instanceof Collection) for (Object sub : (Collection) x) l.addAll(flattenList2(sub)); else if (x != null) l.add(x); return l; } static public String dropUriPrefix(String prefix, String uri) { prefix = dropTrailingSlash(prefix); if (empty(prefix)) return uri; if (eq(uri, prefix) || startsWith(uri, prefix + "/")) return substring(uri, l(prefix)); return uri; } static public String nTests(long n) { return n2(n, "test"); } static public String nTests(Collection l) { return nTests(l(l)); } static public String nErrors(long n) { return n2(n, "error"); } static public String nErrors(Collection l) { return nErrors(l(l)); } static public String nErrors(Map map) { return nErrors(l(map)); } static public String hTitleClean(String title) { return htmldecode(dropTagsAndHTMLComments(title)); } static public String hjs_markRowMagic(Object... __) { String color = optPar("color", __, "#99f"); return hjs(replaceDollarVars("\r\n var rowMagic_hash = window.location.hash.substr(1);\r\n if (rowMagic_hash)\r\n $(\"a[name=\" + rowMagic_hash + \"]\").closest('tr').css({ 'background-color' : '$color'});\r\n ", "color", color)); } static public String hcomment(String text) { return ""; } static public String renderVars_struct(Object... params) { return renderVars(params); } static public Map allConceptFieldsAsMap(Concept c) { Map map = new HashMap(); for (String field : unnull(conceptFields(c))) map.put(field, cget(c, field)); return map; } static public String hreconnectingWebSockets() { return hjavascript_src_snippet("#1013374"); } static public String js_evalOnWebSocketMessage() { return "\r\n function(event) {\r\n var data = JSON.parse(event.data);\r\n if (data.eval) {\r\n console.log(\"Evaluating: \" + data.eval);\r\n var geval = eval; // use global scope\r\n geval(data.eval);\r\n console.log(\"Evaluated.\");\r\n }\r\n }\r\n "; } static public String toString(Object o) { return strOrNull(o); } static public String quoteOr(String s, String whenEmpty) { return empty(s) ? whenEmpty : quote(s); } static public String spaceRoundBracketed(String s) { return spacePlusRoundBracketedIfNempty(s); } static public String nSteps(long n) { return n2(n, "step"); } static public String nSteps(Collection l) { return nSteps(l(l)); } static public String spacePlusRoundBracketedIfNempty(String s) { return nempty(s) ? " " + roundBracket(s) : ""; } static public String newLinesToSpaces2(String s) { return newLinesToSpaces_trim(s); } static public String himgsrc(String src, Object... params) { return tag("img", "", arrayPlus(params, "src", src)); } static public boolean deleteFile(File file) { return file != null && file.delete(); } static public String orEmptyQuotes(String s) { return or2(s, "\"\""); } static public List> zipTwoListsToPairs_longer(List l1, List l2) { int n = max(l(l1), l(l2)); List> out = emptyList(n); for (int i = 0; i < n; i++) addPair(out, _get(l1, i), _get(l2, i)); return out; } static public B syncPut(Map map, A key, B value) { if (map == null) return null; synchronized (map) { return map.put(key, value); } } static public boolean isValidEmailAddress_simple(String s) { return l(s) <= 254 && regexpMatches("^\\S+@\\S+(\\.[^\\.\\s]+)+$", s); } static public int indexOfIC(List a, String b) { return indexOfIgnoreCase(a, b); } static public int indexOfIC(List a, String b, int i) { return indexOfIgnoreCase(a, b, i); } static public int indexOfIC(String a, String b) { return indexOfIgnoreCase(a, b); } static public int indexOfIC(String a, String b, int i) { return indexOfIgnoreCase(a, b, i); } static public String dropStuffBeforeVerticalBar(String s) { int i = indexOf(s, '|'); return i < 0 ? s : substring(s, i + 1); } static public Map filterKeys(Map map, Object f) { return filterMapByFunctionOnKey(map, f); } static public Map filterKeys(Object f, Map map) { return filterMapByFunctionOnKey(f, map); } static public Map filterKeys(IF1 f, Map map) { return filterMapByFunctionOnKey((Object) f, map); } static public Map filterKeys(Map map, IF1 f) { return filterKeys(f, map); } static public IF1 swic$(String prefix) { return s -> swic(s, prefix); } static public void syncRemoveAllExceptLast(List l) { if (l == null) return; synchronized (collectionMutex(l)) { removeSubList(l, 0, l(l) - 1); } } static public boolean mmo2_matchWithTypos(String pattern, String s) { return mmo2_matchWithTypos(pattern, s, 1); } static public boolean mmo2_matchWithTypos(String pattern, String s, int maxTypos) { return mmo2_matchWithTypos(mmo2_parsePattern(pattern), s, maxTypos); } static public boolean mmo2_matchWithTypos(MMOPattern pattern, String s) { return mmo2_matchWithTypos(pattern, s, 1); } static public boolean mmo2_matchWithTypos(MMOPattern pattern, String s, int maxTypos) { if (maxTypos == 0) return mmo2_match(pattern, s); Integer score = mmo2_levenWithSwapsScore(pattern, s); return score != null && score <= maxTypos; } static public List parseBusinessHours_pcall(String s) { try { return parseBusinessHours(s); } catch (Throwable __e) { _handleException(__e); } return null; } static public List splitBusinessHoursAtMidnight(List l) { return concatLists(map(l, r -> r.end < r.start && r.start > 12 ? ll(intRange(r.start, 24 * 60), intRange(0, r.end)) : ll(r))); } static public int minuteInDay() { return minuteInDay(java.util.Calendar.getInstance()); } static public int minuteInDay(java.util.Calendar c) { return hours(c) * 60 + minutes(c); } static public int minuteInDay(long time) { return minuteInDay(calendarFromTime(time)); } static public int minuteInDay(TimeZone tz) { return minuteInDay(now(), tz); } static public int minuteInDay(long time, TimeZone tz) { return minuteInDay(calendarFromTime(time, tz)); } static public TimeZone timeZone(String name) { return TimeZone.getTimeZone(name); } static public boolean anyIntRangeContains(Iterable ranges, int i) { return any(ranges, r -> intRangeContains(r, i)); } static public int syncL(Collection l) { if (l == null) return 0; synchronized (l) { return l.size(); } } static public List syncL() { return syncList(); } static public int syncLengthLevel2(Collection l) { int sum = 0; for (Collection c : cloneList(l)) sum += syncL(c); return sum; } static public List concatLists_syncIndividual(Iterable... lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) syncAddAll(l, list); return l; } static public List concatLists_syncIndividual(Collection> lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) syncAddAll(l, list); return l; } static public List syncListPlus(Collection l, A... more) { if (l == null) return asList(more); synchronized (collectionMutex(l)) { return concatLists(l, asList(more)); } } static public void syncClear(Collection c) { if (c != null) synchronized (collectionMutex(c)) { c.clear(); } } static public void syncClear(Map map) { if (map != null) synchronized (collectionMutex(map)) { map.clear(); } } static public A syncPopLast(List l) { if (l == null) return null; synchronized (l) { return popLast(l); } } static public List syncPopLast(int n, List l) { if (l == null) return null; synchronized (l) { return popLast(n, l); } } static public List syncShallowCloneElements(List l) { return syncLambdaMap(__107 -> shallowClone(__107), l); } static public List syncAddOrCreate(List l, A a) { if (l == null) l = syncList(); l.add(a); return l; } static public A syncLast(List l) { if (l == null) return null; synchronized (l) { return last(l); } } static public Class _run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static public A getWeakRef(Reference ref) { return ref == null ? null : ref.get(); } static public String getClientIPFromHeaders(Map headers) { if (headers == null) return null; String remoteAddr = (String) (headers.get("remote-addr")); String client = (String) (headers.get("x-forwarded-for")); if (nempty(client)) remoteAddr += "," + client; return remoteAddr; } static public boolean stdEq2(Object a, Object b) { if (a == null) return b == null; if (b == null) return false; if (a.getClass() != b.getClass()) return false; for (String field : allFields(a)) if (neq(getOpt(a, field), getOpt(b, field))) return false; return true; } static public int stdHash2(Object a) { if (a == null) return 0; return stdHash(a, toStringArray(allFields(a))); } static public float clamp(float x, float a, float b) { return x < a ? a : x > b ? b : x; } static public double clamp(double x, double a, double b) { return x < a ? a : x > b ? b : x; } static public int clamp(int x, int a, int b) { return x < a ? a : x > b ? b : x; } static public A _print(String s, A a) { return print(s, a); } static public A _print(A a) { return print(a); } static public void _print() { print(); } static public boolean _eq(Object a, Object b) { return eq(a, b); } static public double ratioToPercent(double x, double y) { return x * 100 / y; } static public List scoredSearch_prepare(String query) { return map("replacePlusWithSpace", splitAtSpace(query)); } static public void putUnlessZero(Map map, A key, int value) { if (map != null && key != null && value != 0) map.put(key, value); } static public void putUnlessZero(Map map, A key, double value) { if (map != null && key != null && value != 0) map.put(key, value); } static public int scoredSearch_score(Iterable l, List words) { int score = 0; if (l != null) for (String s : l) score += scoredSearch_score(s, words); return score; } static public int scoredSearch_score(String s, List words) { int score = 0; if (nempty(s)) for (String word : words) score += scoredSearch_score_single(s, word); return score; } static public int scoredSearch_score(String s, String query) { return scoredSearch_score(s, scoredSearch_prepare(query)); } static public List keysSortedByValuesDesc(final Map map) { List l = new ArrayList(map.keySet()); sort(l, mapComparatorDesc(map)); return l; } static public A keyWithHighestValue(Map map) { return keyWithBiggestValue(map); } static public List uniquify(Collection l) { return uniquifyList(l); } static public List cloneAndClearList(Collection l) { List l2 = cloneList(l); l.clear(); return l2; } static public List lookupAllOpt(Map map, Collection l) { List out = new ArrayList(); if (l != null) for (A a : l) addIfNotNull(out, map.get(a)); return out; } static public List lookupAllOpt(Collection l, Map map) { return lookupAllOpt(map, l); } static public ArrayList cloneList_noSync(Iterable l) { return l instanceof Collection ? cloneList_noSync((Collection) l) : asList(l); } static public ArrayList cloneList_noSync(Collection l) { if (l == null) return new ArrayList(); return new ArrayList(l); } static public IterableIterator concurrentlyIterateValues(NavigableMap map) { return concurrentlyIterateValues(map, map); } static public IterableIterator concurrentlyIterateValues(final NavigableMap map, Object mutex) { return iteratorFromFunction(new F0() { public Iterator it = keys(map).iterator(); public A key; public B get() { synchronized (mutex) { try { if (!it.hasNext()) return null; return map.get(key = it.next()); } catch (ConcurrentModificationException e) { print("Re-iterating"); it = map.tailMap(key, false).keySet().iterator(); if (!it.hasNext()) return null; return map.get(key = it.next()); } } } }); } static public void cancelTimers(Collection timers) { for (Object timer : timers) cancelTimer(timer); } static public Object getOptMC(String field) { return getOpt(mc(), field); } static public SecretValue secretValueOrNull(A a) { return a == null ? null : new SecretValue(a); } static public boolean syncEmpty(Collection l) { if (l == null) return true; synchronized (l) { return l.isEmpty(); } } static public String rtrim_fromLines(Collection lines) { StringBuilder buf = new StringBuilder(); if (lines != null) { boolean first = true; for (Object line : lines) { if (first) first = false; else buf.append('\n'); buf.append(str(line)); } } return buf.toString(); } static public String indentStructureString(String s) { if (s == null) return null; List tok = javaTokForStructure(s); StringBuilder buf = new StringBuilder(); int indent = 0; for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (isOpeningBracket(t)) { int j = i + 5; if (containsClosingBracket(subList(tok, i + 2, i + 5))) { buf.append(joinSubList(tok, i, j)); i = j - 1; } else buf.append(t).append("\n").append(spaces(indent += 2)); } else if (isClosingBracket(t)) buf.append("\n").append(spaces(indent -= 2)).append(t); else if (eq(t, ",")) { buf.append(t).append("\n").append(spaces(indent)); i++; } else buf.append(t); } return str(buf); } static public void addPair(Collection> c, A a, B b) { if (c != null) c.add(pair(a, b)); } static public String dm_makeModule(String moduleLibID) { return (String) dm_callOS("makeModule", moduleLibID); } static public VF1 ivf1ToVF1(IVF1 f) { return f == null ? null : new VF1() { public void get(A a) { try { f.get(a); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.get(a)"; } }; } static public VF2 ivf2ToVF2(IVF2 f) { return f == null ? null : new VF2() { public void get(A a, B b) { try { f.get(a, b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.get(a, b)"; } }; } static public java.lang.management.OperatingSystemMXBean osMXBean() { return ManagementFactory.getOperatingSystemMXBean(); } static public double systemCPULoad() { return advancedOSMXBean().getSystemCpuLoad(); } static public IConceptIndex simpleConceptIndex(final Runnable r) { return new IConceptIndex() { public void update(Concept c) { pcallF(r); } public void remove(Concept c) { pcallF(r); } }; } static public void closeAllAndClear(Collection l) { if (l == null) return; for (AutoCloseable c : cloneList(l)) { try { close(c); } catch (Throwable __e) { _handleException(__e); } } l.clear(); } static public A singleObjectMethodProxy(Class intrface, Object object, String methodName) { return proxyFromInvocationHandler(intrface, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { String mname = method.getName(); if (mname.equals(methodName)) return call(object, methodName, unnull(args)); if (mname.equals("toString")) return "proxy for " + methodName; return null; } }); } static public Map paramsFromURL(String url) { return decodeHQuery(getQueryFromURL(url)); } static public boolean containsKey(Map map, A key) { return map != null && map.containsKey(key); } static public String addAnchorToURL(String url, String anchor) { int i = smartIndexOf(url, '#'); url = takeFirst(url, i); if (nempty(anchor)) url += "#" + anchor; return url; } static public String urlWithoutQueryAndAnchor(String url) { return takeFirst(url, min(smartIndexOf(url, "?"), smartIndexOf(url, "#"))); } static public String anchorFromURL(String url) { return substring(url, smartIndexOf(url, "#")); } static public boolean hasConceptWhereIC(Class c, Object... params) { return conceptWhereIC(c, params) != null; } static public boolean hasConceptWhereIC(Concepts cc, Class c, Object... params) { return conceptWhereIC(cc, c, params) != null; } static public boolean regexpFindsIC(String pat, String s) { return regexpIC(pat, s).find(); } static public String hcss_responstable() { return hcss("\r\n .responstable {\r\n margin: 1em 0;\r\n width: 100%;\r\n overflow: visible;\r\n background: #FFF;\r\n color: #024457;\r\n border-radius: 10px;\r\n border: 1px solid #167F92;\r\n }\r\n \r\n .responstable tr {\r\n border: 1px solid #D9E4E6;\r\n }\r\n .responstable tr:nth-child(odd) {\r\n background-color: #EAF3F3;\r\n }\r\n .responstable th {\r\n display: none;\r\n border: 1px solid #FFF;\r\n background-color: #167F92;\r\n color: #FFF;\r\n padding: 1em;\r\n }\r\n .responstable th:first-child {\r\n display: table-cell;\r\n text-align: center;\r\n }\r\n .responstable th:nth-child(2) {\r\n display: table-cell;\r\n }\r\n .responstable th:nth-child(2) span {\r\n display: none;\r\n }\r\n .responstable th:nth-child(2):after {\r\n content: attr(data-th);\r\n }\r\n @media (min-width: 480px) {\r\n .responstable th:nth-child(2) span {\r\n display: block;\r\n }\r\n .responstable th:nth-child(2):after {\r\n display: none;\r\n }\r\n }\r\n .responstable td {\r\n display: block;\r\n word-wrap: break-word;\r\n max-width: 7em;\r\n }\r\n .responstable td:first-child {\r\n display: table-cell;\r\n text-align: center;\r\n border-right: 1px solid #D9E4E6;\r\n }\r\n @media (min-width: 480px) {\r\n .responstable td {\r\n border: 1px solid #D9E4E6;\r\n }\r\n }\r\n .responstable th, .responstable td {\r\n text-align: left;\r\n margin: .5em 1em;\r\n }\r\n @media (min-width: 480px) {\r\n .responstable th, .responstable td {\r\n display: table-cell;\r\n padding: 1em;\r\n }\r\n }\r\n "); } static public String tdTop(Object contents, Object... params) { return tag("td", contents, arrayPlus(params, "valign", "top")); } static public String hpasswordfield(String name, Object... params) { Object value = ""; if (odd(l(params))) { value = params[0]; params = dropFirst(params); } params = html_massageAutofocusParam(params); return tag("input", "", concatArrays(new Object[] { "type", "password", "name", name, "value", value }, params)); } static public String hpasswordfield(String name) { return hpasswordfield(name, ""); } static public Object subBot_serve404() { return call(getMainBot(), "serve404"); } static public Object subBot_serve404(String msg) { return call(getMainBot(), "serve404", msg); } static public Object serveByteArray(byte[] data, String mimeType) { return subBot_serveByteArray(data, mimeType); } static public Object serveJSON_shallowLineBreaks(Object data) { return serveText(jsonEncode_shallowLineBreaks(data)); } static public String dropLeadingSlash(String s) { return dropPrefix("/", s); } static public String pUnlessEmpty(String s, Object... __) { return empty(s) ? "" : p(s, __); } static public String unicode_newLineArrow() { return charToString(0x21b5); } static public A highestByFunction(Iterable l, Object f) { A best = null; Object bestValue = null; if (l != null) for (A a : l) { Object val = callF(f, a); if (best == null || cmp(val, bestValue) > 0) { best = a; bestValue = val; } } return best; } static public A highestByFunction(Object f, Iterable l) { return highestByFunction(l, f); } static public A highestByFunction(IF1 f, Iterable l) { return highestByFunction(l, (Object) f); } static public A highestByFunction(Iterable l, IF1 f) { return highestByFunction(f, l); } static public String hbuttonOnClick(String text, String onClick, Object... params) { return hfulltag("button", text, paramsPlus(params, "onClick", onClick)); } static public String spanTitle(String title, Object contents) { return empty(title) ? str(contents) : span(contents, "title", title); } static public String regexpCaseInsensitivePrefix() { return "(?i)"; } static public String jsDropTrailingComments(String s) { return javaTokDropTrailingN(s); } static public String divUnlessEmpty(String s, Object... params) { return empty(s) ? "" : div(s, params); } static public Map applyFunctionToMapValue(A key, Object f, Map map) { if (map.containsKey(key)) map.put(key, (B) callF(f, map.get(key))); return map; } static public Object cloneIfList(Object o) { return o instanceof List ? cloneList((List) o) : o; } static public MetaTransformer metaTransformer_transformableAndList() { return new MetaTransformer(new MetaTransformer.StructureHandler() { public Object transform(Object o, IF1 recurse) { if (o instanceof Transformable) return ((Transformable) o).transformUsing(recurse); if (o instanceof List) return map_ping(recurse, ((List) o)); return null; } public void visit(Object o, IVF1 recurse) { if (o instanceof Visitable) ((Visitable) o).visitUsing(recurse); else if (o instanceof List) for (Object x : ((List) o)) { ping(); recurse.get(x); } } }); } static public A printStructure(String prefix, A o) { if (endsWithLetter(prefix)) prefix += ": "; print(prefix + structureForUser(o)); return o; } static public A printStructure(A o) { print(structureForUser(o)); return o; } static public void logQuoted(String logFile, String line) { logQuoted(getProgramFile(logFile), line); } static public void logQuoted(File logFile, String line) { appendToFile(logFile, quote(line) + "\n"); } static public List dropFirstTwoAndLastTwo(List l) { return dropFirstAndLast(2, l); } static public String hjavascript_src(String src) { return tag("script", "", "src", src); } static public String[] flattenStringArray2(Object... a) { List l = new ArrayList(); if (a != null) for (Object x : a) if (x instanceof String[]) l.addAll(asList(((String[]) x))); else if (x instanceof Collection) l.addAll(((Collection) x)); else l.add(x); return asStringArray(l); } static public Map mapKeyAndFunction(Iterable l, Object f) { return mapKeyAndFunction(f, l); } static public Map mapKeyAndFunction(Object f, Iterable l) { HashMap map = new HashMap(); if (l != null) for (Object o : l) map.put(o, callF(f, o)); return map; } static public Map mapKeyAndFunction(Map map, IF2 f) { HashMap map2 = new HashMap(); if (map != null) for (Map.Entry __0 : _entrySet(map)) { A key = __0.getKey(); B value = __0.getValue(); map2.put(key, callF(f, key, value)); } return map2; } static public Map mapKeyAndFunction(Iterable l, IF1 f) { return mapKeyAndFunction(f, l); } static public File prepareProgramFile(String name) { return mkdirsForFile(getProgramFile(name)); } static public File prepareProgramFile(String progID, String name) { return mkdirsForFile(getProgramFile(progID, name)); } static public Matcher regexpIC(Pattern pat, String s) { return pat.matcher(unnull(s)); } static public Matcher regexpIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static public Pattern regexpIC(String pat) { return compileRegexpIC(pat); } static public Object safeUnstructureAllowingClasses(String s, Class... allowedClasses) { final Set allowedClassesSet = mapToSet(__108 -> className(__108), allowedClasses); Object classFinder = new F1() { public Object get(String name) { try { if (!allowedClassesSet.contains(name)) throw fail("Class not allowed to unstructure: " + name); return classForName(name); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!allowedClassesSet.contains(name)) fail(\"Class not allowed to unstructure..."; } }; return unstructure(s, false, classFinder); } static public List sortedAlphaNum(Collection c) { return sorted(c, new AlphanumComparator()); } static public Object dm_getModule(Object moduleOrID) { if (moduleOrID == null || eq(moduleOrID, "")) return null; if (isString(moduleOrID) && isIdentifier(((String) moduleOrID))) return dm_getService(((String) moduleOrID)); if (isStringOrIntOrLong(moduleOrID)) return dm_callOS("getDynModuleByID", str(moduleOrID)); return dm_resolveModule(moduleOrID); } static public AutoCloseable dm_enter(Object mod) { return (AutoCloseable) callOpt(dm_getModule(mod), "enter"); } static public String formatDoubleFull(double d, int digits) { String format = digits <= 0 ? "0" : "0." + rep(digits, '0'); return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d); } static public long toM(long l) { return (l + 1024 * 1024 - 1) / (1024 * 1024); } static public String toM(long l, int digits) { return formatDouble(toM_double(l), digits); } static public boolean fileNotEmpty(File f) { return isFile(f) && fileSize(f) > 0; } static public List splitAtAmpersand(String s) { return s == null ? emptyList() : asList(s.split("&")); } static public Map parseColonProperties(String text) { return parseColonProperties(text, new LinkedHashMap()); } static public Map parseColonProperties(String text, Map map) { for (String s : tlft(text)) { int i = indexOf(s, ':'); if (i > 0) map.put(trimSubstring(s, 0, i), trimSubstring(s, i + 1)); } return map; } static public String gazelle_server() { return "https://gazelle.rocks/"; } static public String postPage(String url, Object... params) { return doPost(litmap(params), url); } static public String stringIfTrue(boolean b, String s) { return b ? s : ""; } static public float abs(float f) { return Math.abs(f); } static public int abs(int i) { return Math.abs(i); } static public double abs(double d) { return Math.abs(d); } static public int latestInstalledJavaX() { File[] files = new File(userHome(), ".javax").listFiles(); int v = 0; if (files != null) for (File f : files) { Matcher m = regexpMatcher("x(\\d\\d\\d?)\\.jar", f.getName()); if (m.matches()) v = Math.max(v, Integer.parseInt(m.group(1))); } return v; } static public String x30JarServerURL() { return "http://botcompany.de:8081/x30.jar"; } static public boolean eitherIsA(Either e) { return e != null && e.isA(); } static public HashSet allClasses_keywords = lithashset("class", "interface", "enum", "sclass", "sinterface", "record", "srecord", "strecord", "asclass", "concept"); static public List> allClasses(List tok) { List> l = new ArrayList(); int n = tok.size(); HashSet _allClasses_keywords = allClasses_keywords; for (int i = 1; i < n; i += 2) { String t = tok.get(i); if ("{".equals(t)) i = findEndOfBlock(tok, i) - 1; else if (_allClasses_keywords.contains(t) && (tok_isJavaxMetaCommandLeftOf(tok, i) || !eqGetOneOf(tok, i - 2, ".", "include"))) { int j = i; while (j < n && !tok.get(j).equals("{")) j += 2; j = findEndOfBlock(tok, j) + 1; i = leftScanModifiers(tok, i); l.add(tok.subList(i - 1, Math.min(n, j))); i = j - 2; } } return l; } static public List> allClasses(String text) { return allClasses(javaTok(text)); } static public String getClassDeclarationName(List tok) { if (tok != null) for (int i = 1; i + 2 < tok.size(); i += 2) if (allClasses_keywords.contains(tok.get(i)) && isIdentifier(tok.get(i + 2))) { if (eqGet(tok, i + 2, "noeq")) i += 2; return tok.get(i + 2); } return null; } static public List findBlock(String pat, List tok) { List tokpat = javaTok(pat); int i = findCodeTokens(tok, toStringArray(codeTokensOnly(tokpat))); if (i < 0) return null; int bracketIdx = i + tokpat.size() - 3; assertEquals("{", tok.get(bracketIdx)); int endIdx = findEndOfBlock(tok, bracketIdx); return subList(tok, i - 1, endIdx + 1); } static public String dummyMainClassName(String progID) { return "m" + psI(progID); } static public File tempDir() { return makeTempDir(); } static public String tok_packageName(List tok) { int i = jfind(tok, "package"); if (i < 0) return ""; i += 2; int j = jfind(tok, i, ";"); if (j < 0) return ""; return join(codeTokensOnly(subList(tok, i - 1, j))); } static public String tok_firstClassName(List tok) { int i = jfind(tok, "class "); return i < 0 ? null : tok.get(i + 2); } static public File tempDirPossiblyInRAMDisk() { File f = linux_fileInRamDisk(aGlobalID()); if (f != null) { f.mkdirs(); return f; } return makeTempDir(); } static public boolean loadLibraryOrSrcLib_srcLibsEnabled = true; static public ThreadLocal> loadLibraryOrSrcLib_tempCache = new ThreadLocal(); static public File loadLibraryOrSrcLib(String snippetID) { try { vmBus_send("loadLibraryOrSrcLib", snippetID); long id = parseSnippetID(snippetID); if (loadLibraryOrSrcLib_tempCache.get() != null) { File f = loadLibraryOrSrcLib_tempCache.get().get(id); if (f != null) return f; } boolean srcLib = loadLibraryOrSrcLib_srcLibsEnabled && isMarkedAsSrcLib(snippetID); if (srcLib) { File f = pairA(hotwire_compile(snippetID)); mapPut(loadLibraryOrSrcLib_tempCache.get(), id, f); return f; } File f = DiskSnippetCache_getLibrary(id); if (fileSize(f) != 0) return f; try { return loadDataSnippetToFile(snippetID); } catch (Throwable e) { if (loadLibraryOrSrcLib_srcLibsEnabled && nempty(loadSnippet(snippetID))) { markAsSrcLib(snippetID); return pairA(hotwire_compile(snippetID)); } throw rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static public String cleanJavaCompilerOutput(String s) { return dropPrefixTrim("Annotation processing got disabled, since it requires a 1.6 compliant JVM", s); } static public String appendWithNewLine(String a, String b) { if (empty(b)) return a; if (empty(a)) return b; return addSuffix(a, "\n") + b; } static public boolean anyFileWithExtensionInDir(File dir, String ext) { return nempty(filesWithExtension(ext, findAllFiles_noDirs(dir))); } static public String nChars(long n) { return n2(n, "char"); } static public String nChars(String s) { return nChars(l(s)); } static public boolean dir2zip_recurse_verbose = false; static public int dir2zip_recurse(File inDir, File zip) { return dir2zip_recurse(inDir, zip, ""); } static public int dir2zip_recurse(File inDir, File zip, String outPrefix) { try { mkdirsForFile(zip); FileOutputStream fout = newFileOutputStream(zip); ZipOutputStream outZip = new ZipOutputStream(fout); try { return dir2zip_recurse(inDir, outZip, outPrefix, 0); } finally { outZip.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public int dir2zip_recurse(File inDir, ZipOutputStream outZip) { return dir2zip_recurse(inDir, outZip, "", 0); } static public int dir2zip_recurse(File inDir, ZipOutputStream outZip, String outPrefix, int level) { try { if (++level >= 20) throw fail("woot? 20 levels in zip?"); List files = new ArrayList(); for (File f : listFiles(inDir)) files.add(f); int n = 0; sortFilesByName(files); for (File f : files) { if (f.isDirectory()) { print("dir2zip_recurse: Scanning " + f.getAbsolutePath()); n += dir2zip_recurse(f, outZip, outPrefix + f.getName() + "/", level); } else { if (dir2zip_recurse_verbose) print("Copying " + f.getName()); outZip.putNextEntry(new ZipEntry(outPrefix + f.getName())); InputStream fin = new FileInputStream(f); copyStream(fin, outZip); fin.close(); ++n; } } return n; } catch (Exception __e) { throw rethrow(__e); } } static public boolean isInRAMDisk(File f) { return startsWithOneOf(f2s(f), "/dev/shm/", "/run/shm/"); } static public void deleteDirectory(File dir) { deleteDirectory(dir, false, false); } static public void deleteDirectory(File dir, boolean verbose, boolean testRun) { deleteAllFilesInDirectory(dir, verbose, testRun); if (verbose) print((testRun ? "Would delete " : "Deleting ") + dir.getAbsolutePath()); if (!testRun) dir.delete(); } static public void closeRandomAccessFile(RandomAccessFile f) { if (f != null) try { f.close(); callJavaX("dropIO", f); } catch (Throwable e) { printStackTrace(e); } } static public RandomAccessFile newRandomAccessFile(File path, String mode) { try { boolean forWrite = mode.indexOf('w') >= 0; if (forWrite) mkdirsForFile(path); RandomAccessFile f = new RandomAccessFile(path, mode); callJavaX("registerIO", f, path, forWrite); return f; } catch (Exception __e) { throw rethrow(__e); } } static public void failIfOddCount(Object... list) { if (odd(l(list))) throw fail("Odd list size: " + list); } static public Object[] asObjectArray(Collection l) { return toObjectArray(l); } static public AccessControlContext vm_globalACC() { return (AccessControlContext) vm_generalMap_get("Global ACC"); } static public void replaceACCInClassLoader(Object o, AccessControlContext newACC) { ClassLoader cl = getClassLoaderOrSame(o); if (cl instanceof URLClassLoader) { try { setOpt(cl, "acc", newACC); try { setOpt((Object) getOpt(cl, "ucp"), "acc", newACC); } catch (Throwable e) { printShortException("replaceACCInClassLoader: ", e); if (java10OrHigher()) if (addDefaultVMOption("--add-opens java.base/jdk.internal.loader=ALL-UNNAMED")) print("Please restart the OS"); } } catch (Throwable __e) { _handleException(__e); } } } static public String intToHex(int i) { return bytesToHex(intToBytes(i)); } static public int identityHashCode(Object o) { return System.identityHashCode(o); } static public void addToStringTree(StringTree2 tree, List tokC, A leafValue) { if (leafValue == null) return; if (empty(tokC)) { tree.leafValue = leafValue; return; } String s = first(tokC); StringTree2 t = tree.getOrAdd(s); addToStringTree(t, dropFirst(tokC), leafValue); } static public String applyTranspilationFunction(IVF1> f, String s) { if (f == null) return s; List tok = javaTok(s); f.get(tok); return join(tok); } static public String jreplace_dyn(String s, String in, Object out) { return jreplace_dyn(s, in, out, null); } static public String jreplace_dyn(String s, String in, Object out, Object condition) { List tok = javaTok(s); jreplace_dyn(tok, in, out, condition); return join(tok); } static public boolean jreplace_dyn(List tok, String in, Object out) { return jreplace_dyn(tok, in, out, false, true, null); } static public boolean jreplace_dyn(List tok, String in, IF2, Integer, String> out) { return jreplace_dyn(tok, in, (Object) out); } static public boolean jreplace_dyn(List tok, String in, IF2, Integer, String> out, IF2, Integer, Boolean> condition) { return jreplace_dyn(tok, in, (Object) out, (Object) condition); } static public boolean jreplace_dyn(List tok, String in, Object out, Object condition) { return jreplace_dyn(tok, in, out, false, true, condition); } static public boolean jreplace_dyn(List tok, String in, Object out, boolean ignoreCase, boolean reTok, Object condition) { List tokin = javaTok(in); jfind_preprocess(tokin); String[] toks = toStringArray(codeTokensOnly(tokin)); boolean anyChange = false; for (int n = 0; n < 10000; n++) { int i = findCodeTokens(tok, 1, ignoreCase, toks, condition); if (i < 0) return anyChange; String expansion = (String) (callF(out, tok, i)); int end = i + l(tokin) - 2; clearAllTokens(tok, i, end); tok.set(i, expansion); if (reTok) reTok(tok, i, end); anyChange = true; } throw fail("woot? 10000! " + quote(in) + " => " + quote(out)); } static public List splitAtJavaToken(String s, String splitToken) { return splitByJavaToken(s, splitToken); } static public void tok_transpileIfQuoted_dollarVars(List tok) { jreplace_dyn(tok, "if ", new F2, Integer, String>() { public String get(List tok, Integer cIdx) { try { String pat = unquote(tok.get(cIdx + 2)); List vars = new ArrayList(); String pat2 = dollarVarsToStars(pat, vars); int iCurly = cIdx + 4; tok_statementToBlock(tok, iCurly); tokAppend_reTok(tok, iCurly, joinWithSpace(mapWithIndexStartingAt1(vars, (i, var) -> ("S " + var + " = $" + i + ";")))); return ("if (match(" + (quote(pat2)) + ", s, m))"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S pat = unquote(tok.get(cIdx+2));\r\n new LS vars;\r\n S pat2 = dollarVarsT..."; } }, new TokCondition() { public boolean get(final List tok, final int i) { return containsDollarVars(unquote(tok.get(i + 3))); } }); } static public boolean startsAndEndsWith(String a, char c) { return startsWith(a, c) && endsWith(a, c) && l(a) >= 2; } static public boolean startsAndEndsWith(String a, String b) { return startsWith(a, b) && endsWith(a, b) && l(a) >= l(b) * 2; } public static List parseSnippetIDs(Collection snippetIDs) { List l = new ArrayList(); for (String id : snippetIDs) l.add(str(parseSnippetID(id))); return l; } static public Map trimValues(Map map) { Map map2 = similarEmptyMap(map); for (A key : keys(map)) map2.put(key, trim(map.get(key))); return map2; } static public Map transformKeys(Map map, Object f) { HashMap m = new HashMap(); for (Object key : keys(map)) m.put(callF(f, key), map.get(key)); return m; } static public Map standardCredentialsMap() { String user = standardCredentialsUser(); String pass = standardCredentialsPass(); if (nempty(user) && nempty(pass)) return litmap("_user", user, "_pass", pass); return litmap(); } static public String regexp_findSnippetIDs() { return "(?:#|\\blib\\s+|(?:^|\\n)\\s*!)([0-9]+)"; } static public String snippetLink(String id) { return empty(id) ? id : "https://code.botcompany.de/" + parseSnippetID(id); } static public SnippetTitles getSnippetTitle_cached_cache = new SnippetTitles(); static public String getSnippetTitle_cached(String id) { return getSnippetTitle_cached_cache.get(id); } static public void getSnippetTitle_cached_put(String id, String title) { getSnippetTitle_cached_cache.put(id, title); } static public boolean getSnippetTitle_cached_has(String id) { return getSnippetTitle_cached_cache.has(id); } static public String getSnippetTitle_cached_probe(String id) { return getSnippetTitle_cached_cache.probe(id); } static public void mreplace(Matcher m, StringBuffer buf, String s) { m.appendReplacement(buf, Matcher.quoteReplacement(s)); } static public List tlft_j(String text) { return toLinesFullTrim_java(text); } static public Object dm_callModule(Object moduleOrID, String method, Object... args) { Object mod = dm_getModule(moduleOrID); if (mod == null) return null; AutoCloseable __1 = dm_enter(mod); try { return call(mod, method, args); } finally { _close(__1); } } static public boolean dm_isFirstSiblingModule(Object mod) { String libID = dm_moduleLibID(mod); if (libID == null) return false; List siblings = dm_modulesWithLibID(libID); return eq(dm_moduleID(mod), lowestByAlphaNum(siblings)); } static public void ensureConceptClassIsIndexed(Class c) { if (c != null && !isConceptClassIndexed(c)) indexRandomConceptField(c); } static public A toolTip(A c, final Object toolTip) { return setToolTipText(c, toolTip); } static public A toolTip(Object toolTip, A c) { return setToolTipText(toolTip, c); } static public JButton jPopDownButton(String text, final Object... menuParams) { return jbutton((empty(text) ? "" : text + " ") + unicode_downPointingTriangle(), new Runnable() { public void run() { try { JPopupMenu menu = new JPopupMenu(); int emptyCount = menu.getComponentCount(); String position = (String) (optPar_ignoreOddLength("position", menuParams)); fillJPopupMenu(menu, paramsWithout(menuParams, "position")); if (menu.getComponentCount() != emptyCount) { JButton btn = heldInstance(JButton.class); int x = 0; if (eq(position, "center")) x = (btn.getWidth() - getPreferredWidth(menu)) / 2; else if (eq(position, "right")) x = btn.getWidth() - getPreferredWidth(menu); menu.show(btn, x, btn.getHeight()); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new JPopupMenu menu;\r\n int emptyCount = menu.getComponentCount();\r\n Str..."; } }); } static public void print_setPrefixForThread(final String prefix) { interceptPrintInThisThread(empty(prefix) ? null : new _PrintIndent(prefix)); } static public Object callMainBot(String method, Object... args) { return call(mainBot(), method, args); } static public Object subBot_serveInputStream(InputStream in, String mimeType) { return call(mainBot(), "serveInputStream", in, mimeType); } static public int bufferedInputStream_bufferSize = 65536; static public BufferedInputStream bufferedInputStream(int bufSize, File f) { try { return bufferedInputStream(bufSize, newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static public BufferedInputStream bufferedInputStream(File f) { try { return bufferedInputStream(newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static public BufferedInputStream bufferedInputStream(InputStream in) { return new BufferedInputStream(in, bufferedInputStream_bufferSize); } static public BufferedInputStream bufferedInputStream(int bufSize, InputStream in) { return new BufferedInputStream(in, bufSize); } static public String addPrefix(String prefix, String s) { return s.startsWith(prefix) ? s : prefix + s; } static public String webChatBotLogsHTML() { return withDBLock(new F0() { public String get() { try { List l = new ArrayList(); for (Conversation conv : sortByCalculatedFieldDesc(list(Conversation.class), new F1() { public Object get(Conversation c) { try { return empty(c.msgs) ? c.created : last(c.msgs).time; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "empty(c.msgs) ? c.created : last(c.msgs).time"; } })) { List> dialogs = reversed(unnull(conv.oldDialogs)); l.add(webChatBotLogsHTML_formatDialog(str(conv.id + "/" + (l(dialogs) + 1)), conv.msgs)); int i = l(dialogs); for (List msgs : dialogs) l.add(webChatBotLogsHTML_formatDialog(conv.id + "/" + (i--), msgs)); } return h3_htitle("Chat Logs") + ul(l, null, "style", "margin-top: 1em"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new L l;\r\n for (Conversation conv : sortByCalculatedFieldDesc(list Conv..."; } }); } static public String webChatBotLogsHTML_formatDialog(String id, List msgs) { long startTime = collectMinLong(msgs, "time"); long endTime = collectMaxLong(msgs, "time"); List lc = new ArrayList(); for (Msg m : msgs) if (m.fromUser) lc.add("U: " + i(htmlencode(m.text))); else lc.add("B: " + htmlencode(m.text)); String time1 = formatDateAndTime(startTime); String time2 = formatDateAndTime(endTime); time2 = shortenEndTime(time2, time1); return id + " [" + htmlencode(time1) + " - " + htmlencode(time2) + "]" + ul(lc); } static public int parseIntOpt(String s) { return isInteger(s) ? parseInt(s) : 0; } static public String h3_htitle(String s) { return htitle(s) + h3(s); } static public String pageNav2(String baseLink, int count, int value, int step, String nVar, Object... __) { List l = new ArrayList(); baseLink = unnull(baseLink) + (contains(baseLink, "?") ? "&" : "?") + urlencode(nVar) + "="; if (value > 0) l.add(ahref(baseLink + max(0, value - step), stringPar("leftArrow", __, htmlencode(unicode_leftPointingTriangle())))); for (int i = 0; i < count; i += step) { int n = i / step + 1; if (pageNav2_showPage(value, i, step, count)) if (value == i) l.add(b(n)); else l.add(ahref(baseLink + i, n)); } if (value + step < count) l.add(ahref(baseLink + (value + step), stringPar("rightArrow", __, htmlencode(unicode_rightPointingTriangle())))); return p("Pages: " + lines(l)); } static public boolean pageNav2_showPage(int actual, int i, int step, int count) { int diff = abs(actual - i) / step; return i == 0 || i >= (count - 1) / step * step || diff <= 10 || diff < 100 && ((i / step) % 10) == 9 || ((i / step) % 100) == 99; } static public String renderFileInfo(File f) { return f == null ? "-" : f2s(f) + " " + (f.isFile() ? "(file, " + n2(fileSize(f)) + " bytes)" : f.isDirectory() ? "(dir)" : "(not found)"); } static public File fileInSameDir(File f, String newName) { return newFile(parentFile(f), newName); } static public String ymd_minus_hms() { return ymd() + "-" + hms(); } static public List rgbToIntList(RGB rgb) { return rgb == null ? null : ll(rgb.redInt(), rgb.greenInt(), rgb.blueInt()); } static public ExpiringMap2 loadSnippet_simpleCache_map = new ExpiringMap2(10000); static public Lock loadSnippet_simpleCache_lock = lock(); static public int loadSnippet_simpleCache_timeout = 60000; static public String loadSnippet_simpleCache(String id) { if (id == null) return null; Lock __0 = loadSnippet_simpleCache_lock; lock(__0); try { id = fsI(id); String src = loadSnippet_simpleCache_map.get(id); if (src != null) return src; Integer oldTimeout = setThreadLocal(loadPage_forcedTimeout_byThread, loadSnippet_simpleCache_timeout); try { src = loadSnippet(id); if (src != null) loadSnippet_simpleCache_map.put(id, src); return src; } finally { loadPage_forcedTimeout_byThread.set(oldTimeout); } } finally { unlock(__0); } } static public String hreplacetag(String html, String tag, String newTag) { List tok = htmlcoarsetok(html); List> tags = findContainerTag(tok, tag); if (empty(tags)) return html; List theTag = first(tags); List actualTag = subList(theTag, 1, l(theTag) - 1); return join(replaceSubList(cloneList(tok), actualTag, litlist(newTag))); } static public Object subBot_serveWithContentType(String text, String contentType) { return callMainBot("serveByteArray", toUtf8(text), contentType); } static public String fileExtension(File f) { if (f == null) return null; return fileExtension(f.getName()); } static public String fileExtension(String s) { return substring(s, smartLastIndexOf(s, '.')); } static public String ymd() { return ymd(now()); } static public String ymd(long now) { return year(now) + formatInt(month(now), 2) + formatInt(dayOfMonth(now), 2); } static public String ymd(long now, TimeZone tz) { return year(now, tz) + formatInt(month(now, tz), 2) + formatInt(dayOfMonth(now, tz), 2); } static public String hhmm() { return hhmm(now()); } static public String hhmm(long time) { return new SimpleDateFormat("HHmm").format(time); } static public List rawEmojisList() { return (List) jsonDecodeMap(loadTextFile(loadLibrary("#1400427"))).get("emojis"); } static public Object[] paramsPlus_inFront(Object[] a1, Object... a2) { return paramsPlus(a2, a1); } static public String htd(Object contents, Object... params) { return htag("td", contents, params); } static public String str_toK(long l) { return n2(toK(l)) + " K"; } static public String conceptsFileName() { return "concepts.structure.gz"; } static public int howManySecondsAgo(long timestamp) { return iround(toSeconds(now() - timestamp)); } static public List listZip(File inZip) { return listZipFile(inZip); } static public String addSlash(String s) { return empty(s) || s.endsWith("/") ? s : s + "/"; } static public boolean isFile(File f) { return f != null && f.isFile(); } static public boolean isFile(String path) { return isFile(newFile(path)); } static public String nlToBr_withIndents(String s) { s = nlToBr(s); StringBuilder buf = new StringBuilder(); int i = 0; while (i < l(s)) { while (charAt(s, i) == ' ') { ++i; buf.append(" "); } int j = smartIndexOf(s, i, '\n') + 1; buf.append(substring(s, i, j)); i = j; } return str(buf); } static public void addFirst(List c, A a) { if (c != null) c.add(0, a); } static public String hinput(Object contents, Object... params) { return htag("input", contents, params); } static public Object[] paramsPlus_noOverwrite(Object[] a1, Object... a2) { if (a2 == null) return a1; if (a1 == null) return a2; if (l(a1) == 1 && a1[0] instanceof Map) return new Object[] { mapPlus((Map) a1[0], a2) }; assertEvenLength(a1); assertEvenLength(a2); Map map = paramsToOrderedMap(a1); int n = l(a2); for (int i = 0; i < n; i += 2) mapPut_noOverwrite(map, a2[i], a2[i + 1]); return mapToParams(map); } static public Set similarEmptySet(Iterable m) { if (m instanceof TreeSet) return new TreeSet(((TreeSet) m).comparator()); if (m instanceof LinkedHashSet) return new LinkedHashSet(); return new HashSet(); } static public Set similarEmptySet(Map m) { if (m instanceof TreeMap) return new TreeSet(((TreeMap) m).comparator()); if (m instanceof LinkedHashMap) return new LinkedHashSet(); return new HashSet(); } static public A replaceIfEqual(A a, A b, A c) { return eq(a, b) ? c : a; } static public String localDateWithMinutes(long time) { SimpleDateFormat format = simpleDateFormat_local("yyyy/MM/dd HH:mm"); return format.format(time); } static public String localDateWithMinutes() { return localDateWithMinutes(now()); } static public String pnlToStringWithEmptyLines(Iterable l) { return pnlToString(map(l, o -> o + "\n")); } static public void saveBinaryFileVerbose(File f, byte[] data) { boolean exists = f.exists(); saveBinaryFile(f, data); print((!exists ? "Created" : "Updated") + " file " + f2s(f) + " (" + f.length() + " bytes)"); } static public File getSecretProgramDir() { return getSecretProgramDir(actualProgramID()); } static public File getSecretProgramDir(String snippetID) { if (empty(snippetID)) return javaxSecretDir(); return newFile(javaxSecretDir(), formatSnippetID(snippetID)); } static public String windowsLineBreaks(String s) { return s == null ? null : s.replaceAll("(? String mapToLines_rtrim(Iterable l, IF1 f) { return mapToLines_rtrim(f, l); } static public String newLinesToSpaces(String s) { return s == null ? null : fixNewLines(s).replace("\n", " "); } static public MultiMap treeMultiMapIndexByField(Collection c, String field) { MultiMap map = treeMultiMap(); for (Object a : c) { Object val = getOpt(a, field); if (val != null) map.put(val, a); } return map; } static public MultiMap treeMultiMapIndexByField(String field, Collection c) { return treeMultiMapIndexByField(c, field); } static public Cache> countryDialCodes_cache = new Cache<>(() -> countryDialCodes_load()); static public List countryDialCodes() { return countryDialCodes_cache.get(); } static public List countryDialCodes_load() { return sortedByField("dialCode", filter(c -> nempty(c.dialCode), map((List>) loadJSONFile(loadLibrary("#1400429")), m -> new CountryDialCode(m.get("name"), m.get("code"), m.get("dial_code"))))); } static public List nempties(Collection c) { return filterNempty(c); } static public List splitAtComma(String s) { return empty(s) ? emptyList() : asList(s.split(",")); } static public CountryDialCode countryDialCodeByCountryCode(String countryCode) { return objectWhere(countryDialCodes(), "countryCode", upper(countryCode)); } static public String dropPrefixTrim(String prefix, String s) { return trim(dropPrefix(prefix, s)); } static public String localDateWithSeconds(long time) { SimpleDateFormat format = simpleDateFormat_local("yyyy/MM/dd HH:mm:ss"); return format.format(time); } static public String localDateWithSeconds() { return localDateWithSeconds(now()); } static public String smallestTransparentGIFDataURI() { return "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; } static public List sortedByFieldDesc(Collection c, String field) { List l = new ArrayList(c); sort(l, descFieldComparator(field)); return l; } static public List sortedByFieldDesc(String field, Collection c) { return sortedByFieldDesc(c, field); } static public A lowestByField(Iterable l, String field) { A lowest = null; Object lowestValue = null; for (A a : unnull(l)) { Object val = getOpt(a, field); if (lowest == null || cmp(val, lowestValue) < 0) { lowest = a; lowestValue = val; } } return lowest; } static public A lowestByField(String field, Iterable l) { return lowestByField(l, field); } static public java.util.Timer doLater(long delay, final Object r) { ping(); final java.util.Timer timer = new java.util.Timer(); timer.schedule(timerTask(r, timer), delay); return vmBus_timerStarted(timer); } static public java.util.Timer doLater(double delaySeconds, final Object r) { return doLater(toMS(delaySeconds), r); } volatile static public boolean conceptsAndBot_running = false; static public boolean conceptsAndBot_thinOnStart = true; static public void conceptsAndBot() { conceptsAndBot(null); } static public void conceptsAndBot(Integer autoSaveInterval) { if (conceptsAndBot_running) return; conceptsAndBot_running = true; Concepts cc = db_mainConcepts(); try { if (cc.useFileLock) { if (!cc.fileLock().tryToLock()) { ensureDBNotRunning(dbBotStandardName()); cc.fileLock().forceLock(); } } else ensureDBNotRunning(dbBotStandardName()); } catch (Throwable _e) { cc.dontSave = true; throw rethrow(_e); } cc.persist(autoSaveInterval); dbBot(false); if (conceptsAndBot_thinOnStart) { try { thinAProgramsBackups(getDBProgramID(), true); } catch (Throwable __e) { _handleException(__e); } } } static public List mapNonCodeTokens(Object f, List l) { List out = emptyList(l); for (int i = 0; i < l(l); i++) { Object o = l.get(i); out.add(even(i) ? callF(f, o) : o); } return out; } static public List mapNonCodeTokens(List l, Object f) { return mapNonCodeTokens(f, l); } static public List mapNonCodeTokens(List tok, IF1 f) { return mapNonCodeTokens(tok, (Object) f); } static public List mapNonCodeTokens(IF1 f, List tok) { return mapNonCodeTokens(tok, f); } static public String emojisToUnicode(String s) { return regexReplace(s, ":(\\w+):", matcher -> lookupOrKeep(emojiShortNameMap(), matcher.group())); } static public boolean subBot_isHttps() { Object httpd = subBot_httpd(); return eqOneOf(httpd, getOpt(mainBot(), "serveHttps_server"), getOpt(mainBot(), "serveHttpsWithWebsockets_server")) || contains((Collection) getOpt(mainBot(), "serveHttpsWithWebsockets_multiplePorts_servers"), httpd); } static public String domain() { return domainName(); } static public String unicodeFromCodePoint(int codePoint) { return codePointToString(codePoint); } static public String htmldecode(final String input) { if (input == null) return null; final int MIN_ESCAPE = 2; final int MAX_ESCAPE = 6; StringWriter writer = null; int len = input.length(); int i = 1; int st = 0; while (true) { while (i < len && input.charAt(i - 1) != '&') i++; if (i >= len) break; int j = i; while (j < len && j < i + MAX_ESCAPE + 1 && input.charAt(j) != ';') j++; if (j == len || j < i + MIN_ESCAPE || j == i + MAX_ESCAPE + 1) { i++; continue; } if (input.charAt(i) == '#') { int k = i + 1; int radix = 10; final char firstChar = input.charAt(k); if (firstChar == 'x' || firstChar == 'X') { k++; radix = 16; } try { int entityValue = Integer.parseInt(input.substring(k, j), radix); if (writer == null) writer = new StringWriter(input.length()); writer.append(input.substring(st, i - 1)); if (entityValue > 0xFFFF) { final char[] chrs = Character.toChars(entityValue); writer.write(chrs[0]); writer.write(chrs[1]); } else { writer.write(entityValue); } } catch (NumberFormatException ex) { i++; continue; } } else { CharSequence value = htmldecode_lookupMap.get(input.substring(i, j)); if (value == null) { i++; continue; } if (writer == null) writer = new StringWriter(input.length()); writer.append(input.substring(st, i - 1)); writer.append(value); } st = j + 1; i = st; } if (writer != null) { writer.append(input.substring(st, len)); return writer.toString(); } return input; } static final public String[][] htmldecode_ESCAPES = { { "\"", "quot" }, { "&", "amp" }, { "<", "lt" }, { ">", "gt" }, { "\u00A0", "nbsp" }, { "\u00A1", "iexcl" }, { "\u00A2", "cent" }, { "\u00A3", "pound" }, { "\u00A4", "curren" }, { "\u00A5", "yen" }, { "\u00A6", "brvbar" }, { "\u00A7", "sect" }, { "\u00A8", "uml" }, { "\u00A9", "copy" }, { "\u00AA", "ordf" }, { "\u00AB", "laquo" }, { "\u00AC", "not" }, { "\u00AD", "shy" }, { "\u00AE", "reg" }, { "\u00AF", "macr" }, { "\u00B0", "deg" }, { "\u00B1", "plusmn" }, { "\u00B2", "sup2" }, { "\u00B3", "sup3" }, { "\u00B4", "acute" }, { "\u00B5", "micro" }, { "\u00B6", "para" }, { "\u00B7", "middot" }, { "\u00B8", "cedil" }, { "\u00B9", "sup1" }, { "\u00BA", "ordm" }, { "\u00BB", "raquo" }, { "\u00BC", "frac14" }, { "\u00BD", "frac12" }, { "\u00BE", "frac34" }, { "\u00BF", "iquest" }, { "\u00C0", "Agrave" }, { "\u00C1", "Aacute" }, { "\u00C2", "Acirc" }, { "\u00C3", "Atilde" }, { "\u00C4", "Auml" }, { "\u00C5", "Aring" }, { "\u00C6", "AElig" }, { "\u00C7", "Ccedil" }, { "\u00C8", "Egrave" }, { "\u00C9", "Eacute" }, { "\u00CA", "Ecirc" }, { "\u00CB", "Euml" }, { "\u00CC", "Igrave" }, { "\u00CD", "Iacute" }, { "\u00CE", "Icirc" }, { "\u00CF", "Iuml" }, { "\u00D0", "ETH" }, { "\u00D1", "Ntilde" }, { "\u00D2", "Ograve" }, { "\u00D3", "Oacute" }, { "\u00D4", "Ocirc" }, { "\u00D5", "Otilde" }, { "\u00D6", "Ouml" }, { "\u00D7", "times" }, { "\u00D8", "Oslash" }, { "\u00D9", "Ugrave" }, { "\u00DA", "Uacute" }, { "\u00DB", "Ucirc" }, { "\u00DC", "Uuml" }, { "\u00DD", "Yacute" }, { "\u00DE", "THORN" }, { "\u00DF", "szlig" }, { "\u00E0", "agrave" }, { "\u00E1", "aacute" }, { "\u00E2", "acirc" }, { "\u00E3", "atilde" }, { "\u00E4", "auml" }, { "\u00E5", "aring" }, { "\u00E6", "aelig" }, { "\u00E7", "ccedil" }, { "\u00E8", "egrave" }, { "\u00E9", "eacute" }, { "\u00EA", "ecirc" }, { "\u00EB", "euml" }, { "\u00EC", "igrave" }, { "\u00ED", "iacute" }, { "\u00EE", "icirc" }, { "\u00EF", "iuml" }, { "\u00F0", "eth" }, { "\u00F1", "ntilde" }, { "\u00F2", "ograve" }, { "\u00F3", "oacute" }, { "\u00F4", "ocirc" }, { "\u00F5", "otilde" }, { "\u00F6", "ouml" }, { "\u00F7", "divide" }, { "\u00F8", "oslash" }, { "\u00F9", "ugrave" }, { "\u00FA", "uacute" }, { "\u00FB", "ucirc" }, { "\u00FC", "uuml" }, { "\u00FD", "yacute" }, { "\u00FE", "thorn" }, { "\u00FF", "yuml" }, { "\u2013", "ndash" }, { "\u2018", "lsquo" }, { "\u2019", "rsquo" }, { "\u201D", "rdquo" }, { "\u201C", "ldquo" }, { "\u2014", "mdash" }, { "'", "apos" } }; static final public HashMap htmldecode_lookupMap; static { htmldecode_lookupMap = new HashMap(); for (final CharSequence[] seq : htmldecode_ESCAPES) htmldecode_lookupMap.put(seq[1].toString(), seq[0]); } static public TreeSet toCaseInsensitiveSet(Iterable c) { if (isCISet(c)) return (TreeSet) c; TreeSet set = caseInsensitiveSet(); addAll(set, c); return set; } static public TreeSet toCaseInsensitiveSet(String... x) { TreeSet set = caseInsensitiveSet(); addAll(set, x); return set; } static public java.text.SimpleDateFormat simpleDateFormat(String format, TimeZone timeZone) { java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(format); sdf.setTimeZone(timeZone); return sdf; } static public String timeInTimeZone(String timeZone) { return timeInTimeZone(timeZone, now()); } static public String timeInTimeZone(String timeZone, long time) { return simpleDateFormat_timeZone("HH:mm", timeZone).format(time); } static public String timeInTimeZone(TimeZone timeZone, long time) { return simpleDateFormat("HH:mm", timeZone).format(time); } static public String ipToCountry2020_dataSnippetID = "#1400400"; static public Lock ipToCountry2020_lock = lock(); static public File ipToCountry2020_dataDir() { return javaxCachesDir("ipToCountry2020"); } static public String ipToCountry2020(String ip) { return ipToCountry2020(ipToInt(ip)); } static public String ipToCountry2020(long ipNum) { { Lock __0 = ipToCountry2020_lock; lock(__0); try { if (directoryEmpty(ipToCountry2020_dataDir())) unzipSnippet(ipToCountry2020_dataSnippetID, ipToCountry2020_dataDir()); } finally { unlock(__0); } } String line = pairB(binarySearchForLineInTextFile(newFile(ipToCountry2020_dataDir(), "IP2LOCATION-LITE-DB1.CSV"), s -> { List l = tok_splitAtComma_unquote(s); long a = parseLongOpt(first(l)), b = parseLongOpt(second(l)); return ipNum > b ? 1 : ipNum < a ? -1 : 0; })); return get(tok_splitAtComma_unquote(line), 2); } static public String deSquareBracket(String s) { if (startsWith(s, "[") && endsWith(s, "]")) return substring(s, 1, l(s) - 1); return s; } static public JTextField jTextField() { return jTextField(""); } static public JTextField jTextField(final String text) { return swing(new F0() { public JTextField get() { try { JTextField tf = new JTextField(unnull(text)); standardTextFieldPopupMenu(tf); jenableUndoRedo(tf); tf.selectAll(); return tf; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JTextField tf = new JTextField(unnull(text));\r\n standardTextFieldPopupMenu..."; } }); } static public JTextField jTextField(Object o) { return jTextField(strOrEmpty(o)); } static public JPanel showFormTitled_customLayout(final F1 layouter, final String title, final Object... parts) { return showFormTitled_customArrangement(false, new F1, JPanel>() { public JPanel get(List components) { try { return customLayoutPanel(layouter, components); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "customLayoutPanel(layouter, components)"; } }, title, parts); } static public int formLayouter1_yPlus = 5; static public int formLayouter1_fixer2 = 0; static public F1 formLayouter1() { final int yplus = formLayouter1_yPlus, fixer2 = formLayouter1_fixer2; return new F1() { public Dimension get(Container parent) { try { List l = getComponents(parent); BitSet bigOnes = new BitSet(); for (int i = 0; i < l(l); i++) if (containsATextArea(l.get(i))) add(bigOnes, i); int nBigOnes = bigOnes.cardinality(); int mandatoryHeight = totalPreferredHeight(listWithoutIndicesInBitSet(l, bigOnes)); int gap = 4, outerSpacing = 5; Dimension size = parent.getSize(); int gapsAndMargins = outerSpacing * 2 - (l(l) - 1) * gap; int totalSpace = size.height - gapsAndMargins - fixer2; int liberalSpace = totalSpace - mandatoryHeight; double perBigOne = doubleRatio(liberalSpace, nBigOnes); double y = outerSpacing; for (int i = 0; i < l(l); i++) { Component c = l.get(i); boolean big = contains(bigOnes, i); double h = big ? perBigOne : c.getPreferredSize().height; int actualY = iround(y); c.setBounds(10, actualY, size.width - outerSpacing * 2, iround(y + h) - actualY); y += h + gap; } Dimension pref = componentsBoundingSize(parent, outerSpacing); if (parent.getHeight() <= 0) { int tph = totalPreferredHeight(l); pref.height = tph + gapsAndMargins + yplus; } return pref; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "L l = getComponents(parent);\r\n new BitSet bigOnes;\r\n for i o..."; } }; } static public String getTextTrim(JTextComponent c) { return trim(getText(c)); } static public String getTextTrim(JComboBox cb) { return trim(getText(cb)); } static public String getTextTrim(JComponent c) { if (c instanceof JLabel) return trim(((JLabel) c).getText()); if (c instanceof JComboBox) return getTextTrim((JComboBox) c); return getTextTrim((JTextComponent) c); } static public boolean infoMessage_alwaysOnTop = true; static public double infoMessage_defaultTime = 5.0; static public JWindow infoMessage(String text) { return infoMessage(text, infoMessage_defaultTime); } static public JWindow infoMessage(final String text, final double seconds) { printHidingCredentials(text); return infoMessage_noprint(text, seconds); } static public JWindow infoMessage_noprint(String text) { return infoMessage_noprint(text, infoMessage_defaultTime); } static public JWindow infoMessage_noprint(final String _text, final double seconds) { final String text = hideCredentials(_text); if (empty(text)) return null; logQuotedWithDate(infoBoxesLogFile(), text); if (isHeadless()) return null; return (JWindow) swingAndWait(new F0() { public Object get() { try { final JWindow window = showWindow(infoMessage_makePanel(text)); window.setSize(300, 150); moveToTopRightCorner(window); if (infoMessage_alwaysOnTop) window.setAlwaysOnTop(true); if (vmBus_noObjections("shouldShowInfoBox", window, text)) window.setVisible(true); if (seconds != 0) disposeWindowAfter(iround(seconds * 1000), window); return window; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final JWindow window = showWindow(infoMessage_makePanel(text));\r\n window.s..."; } }); } static public JWindow infoMessage(Throwable e) { printStackTrace(e); return infoMessage(exceptionToStringShort(e)); } static public String programName() { return getProgramName(); } static public int showForm_defaultGap = 4; static public int showForm_gapBetweenColumns = 10; static public JPanel showFormTitled(final String title, final Object... _parts) { JDesktopPane desktop = mainDesktopPane(); if (desktop != null) return showInternalFrameFormTitled(desktop, title, _parts); return swing(new F0() { public JPanel get() { try { final Var frame = new Var(); JPanel panel = showForm_makePanel(false, _parts); frame.set(showForm_makeFrame(title, panel)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final new Var frame;\r\n JPanel panel = showForm_makePanel(false, _p..."; } }); } static public JPanel showForm_makePanel(Boolean internalFrame, Object... _parts) { List out = showForm_arrange1(showForm_makeComponents(internalFrame, _parts)); return vstackWithSpacing(out, showForm_defaultGap); } static public void callF_thread(final Object f, final Object... args) { if (f != null) { startThread(new Runnable() { public void run() { try { callF(f, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(f, args);"; } }); } } static public A renameSubmitButton(A form, String newName) { renameButton(form, showFormSubmitButtonName(), newName); return form; } static public A renameSubmitButton(String newName, A form) { return renameSubmitButton(form, newName); } static public String htmlTagFullParamString(String tag) { int i = indexOfSpaceEtc(tag); return trimSubstring(i, dropSuffix(">", tag)); } static public void clearToken(List tok, int i) { tok.set(i, ""); } static public IterableIterator> iterateListWithIndex(Collection l) { return iterateListWithIndex(l, 0); } static public IterableIterator> iterateListWithIndex(Collection l, int startAt) { return iff(new Object() { public Iterator it = iterator(l); public int i = startAt; public Object get() { if (!it.hasNext()) return endMarker(); return pair(i++, it.next()); } }); } static public String squareBracketed(String s) { return "[" + s + "]"; } static public int numberOfWords2(String s) { return l(words2(s)); } static public String joinPairWithColon(Pair p) { return p == null ? "" : str(p.a) + ": " + str(p.b); } static public void assertStartsWith(List a, List b) { if (!startsWith(a, b)) throw fail(a + " does not start with " + b); } static public void assertStartsWith(String a, String b) { if (!startsWith(a, b)) throw fail(quote(a) + " does not start with " + quote(b)); } static public String getCanonicalPath(File f) { try { return f == null ? null : f.getCanonicalPath(); } catch (Exception __e) { throw rethrow(__e); } } static public String getCanonicalPath(String path) { return getCanonicalPath(newFile(path)); } static public AutoCloseable tempCleaningUp() { return tempSetTL(ping_isCleanUpThread, true); } static public void closeAllWriters(Collection l) { for (Writer w : unnull(l)) { try { w.close(); } catch (Throwable __e) { _handleException(__e); } } } static public A nextToLast(List l) { return get(l, l(l) - 2); } static public String dropTrailingSlash(String s) { return dropSuffix("/", s); } static public List dropTagsAndHTMLComments(List tok) { return dropHTMLComments(dropTags(tok)); } static public String dropTagsAndHTMLComments(String html) { return join(dropTagsAndHTMLComments(htmlTok(html))); } static public String renderVars(Object... params) { List l = new ArrayList(); for (int i = 0; i + 1 < l(params); i += 2) l.add(params[i] + "=" + struct(params[i + 1]) + ". "); return trim(join(l)); } static public String[] conceptFields_drop = { "className", "fieldValues", "id", "created", "_modified", "refs", "backRefs", "_concepts" }; static public Set conceptFields(Concept c) { return setMinus(mergeSets(allNonStaticNonTransientFields(c), keys(c.fieldValues)), conceptFields_drop); } static public Set conceptFields(Class c) { return setMinus(allNonStaticNonTransientFields(c), conceptFields_drop); } static public String hjavascript_src_snippet(String snippetID) { return hfulltag("script", "", "src", snippetRawURL(snippetID, "text/javascript")); } static public String newLinesToSpaces_trim(String s) { return s == null ? null : trim(s).replaceAll("\\s*\r?\n\\s*", " "); } static public boolean regexpMatches(String pat, String s) { return pat != null && s != null && regexp(pat, s).matches(); } static public Map filterMapByFunctionOnKey(Map map, Object f) { Map m2 = similarEmptyMap(map); for (A a : keys(map)) { if (isTrue(callF(f, a))) m2.put(a, map.get(a)); } return m2; } static public Map filterMapByFunctionOnKey(Object f, Map map) { return filterMapByFunctionOnKey(map, f); } static public Integer mmo2_levenWithSwapsScore(MMOPattern pattern, String s) { return mmo2_levenWithSwapsScore(pattern, s, false, false); } static public Integer mmo2_levenWithSwapsScore(MMOPattern pattern, String s, boolean startOfLine, boolean endOfLine) { String s2 = trim(s); if (pattern == null) return null; if (startsWith(s2, "#")) return null; if (pattern instanceof MMOPattern.StartOfLine) return mmo2_levenWithSwapsScore(((MMOPattern.StartOfLine) pattern).p, s2, true, endOfLine); if (pattern instanceof MMOPattern.EndOfLine) return mmo2_levenWithSwapsScore(((MMOPattern.EndOfLine) pattern).p, s2, startOfLine, true); if (pattern instanceof MMOPattern.Phrase) { if (((MMOPattern.Phrase) pattern).quoted) return mmo2_match(((MMOPattern.Phrase) pattern), s2) ? (Integer) 0 : null; String p = ((MMOPattern.Phrase) pattern).phrase; if (startsWith(p, "#")) return null; if (endsWith(p, "!")) return find3(p, s) ? 0 : null; else return find3_levenWithSwapsDistance(p, s2); } if (pattern instanceof MMOPattern.And) { int score = 0; for (MMOPattern pat : ((MMOPattern.And) pattern).l) { Integer score2 = mmo2_levenWithSwapsScore(pat, s2, startOfLine, endOfLine); if (score2 == null) return null; score += score2; } return score; } if (pattern instanceof MMOPattern.Or) { Integer min = null; for (MMOPattern pat : ((MMOPattern.Or) pattern).l) min = min_withNull(min, mmo2_levenWithSwapsScore(pat, s2, startOfLine, endOfLine)); return min; } if (pattern instanceof MMOPattern.Not) return mmo2_match(pattern, s2) ? 0 : null; throw fail("what. " + pattern); } static public Integer mmo2_levenWithSwapsScore(String pattern, String s) { return mmo2_levenWithSwapsScore(mmo2_parsePattern(pattern), s, false, false); } static public List parseBusinessHours(String s) { List parts = nempties(tok_splitAtComma(s)); return map(parts, part -> { List l = splitAtMinus(part); IntRange r = intRange(parseHourAndOptionalMinutesToMinutes(first(l)), parseHourAndOptionalMinutesToMinutes(second(l))); if (r.end < r.start && r.start <= 12 * 60 && r.end < 12 * 60) r.end += 12 * 60; return r; }); } static public IntRange intRange(int start, int end) { return new IntRange(start, end); } static public int hours() { return hours(java.util.Calendar.getInstance()); } static public int hours(java.util.Calendar c) { return c.get(java.util.Calendar.HOUR_OF_DAY); } static public int hours(long time) { return hours(calendarFromTime(time)); } static public int hours(long time, TimeZone tz) { return hours(calendarFromTime(time, tz)); } static public int minutes() { return minutes(Calendar.getInstance()); } static public int minutes(Calendar c) { return c.get(Calendar.MINUTE); } static public java.util.Calendar calendarFromTime(long time, TimeZone tz) { java.util.Calendar c = java.util.Calendar.getInstance(tz); c.setTimeInMillis(time); return c; } static public java.util.Calendar calendarFromTime(long time) { java.util.Calendar c = java.util.Calendar.getInstance(); c.setTimeInMillis(time); return c; } static public boolean intRangeContains(IntRange r, int i) { return r != null && i >= r.start && i < r.end; } static public List syncList() { return synchroList(); } static public List syncList(List l) { return synchroList(l); } static public boolean syncAddAll(Collection c, Iterable b) { if (c == null || b == null) return false; synchronized (c) { return c.addAll(asCollection(b)); } } static public List syncLambdaMap(IF1 f, Collection l) { if (l == null) return emptyList(); synchronized (collectionMutex(l)) { return map(l, f); } } static public A shallowClone(A o) { return (A) shallowClone_impl(o); } static public A shallowClone(A o, A emptyClone) { return copyFields(o, emptyClone); } static public Object shallowClone_impl(Object o) { if (o == null) return o; if (o instanceof List) return cloneList((List) o); if (o instanceof Map) return cloneMap(((Map) o)); if (o instanceof String || o instanceof Number || o instanceof Boolean) return o; if (o instanceof Object[]) { Object[] l = (Object[]) o; return l.clone(); } Class c = o.getClass(); final Object clone = nuEmptyObject(c); copyFields(o, clone); return clone; } static public Set allFields(Object o) { TreeSet fields = new TreeSet(); Class _c = _getClass(o); do { for (Field f : _c.getDeclaredFields()) fields.add(f.getName()); _c = _c.getSuperclass(); } while (_c != null); return fields; } static public int stdHash(Object a, String... fields) { if (a == null) return 0; int hash = getClassName(a).hashCode(); for (String field : fields) hash = boostHashCombine(hash, hashCode(getOpt(a, field))); return hash; } static public String replacePlusWithSpace(String s) { return replace(s, '+', ' '); } static public List splitAtSpace(String s) { return empty(s) ? emptyList() : asList(s.split("\\s+")); } static public int scoredSearch_score_single(String s, String query) { int i = indexOfIC_underscore(s, query); if (i < 0) return 0; if (i > 0) return 1; return l(s) == l(query) ? 3 : 2; } static public Comparator mapComparatorDesc(final Map map) { return new Comparator() { public int compare(A a, A b) { return cmp(map.get(b), map.get(a)); } }; } static public A keyWithBiggestValue(Map map) { A best = null; Number bestScore = null; for (A key : keys(map)) { Number score = map.get(key); if (best == null || cmp(score, bestScore) > 0) { best = key; bestScore = score; } } return best; } static public void cancelTimer(javax.swing.Timer timer) { if (timer != null) timer.stop(); } static public void cancelTimer(java.util.Timer timer) { if (timer != null) timer.cancel(); } static public void cancelTimer(Object o) { if (o instanceof java.util.Timer) cancelTimer((java.util.Timer) o); else if (o instanceof javax.swing.Timer) cancelTimer((javax.swing.Timer) o); else if (o instanceof AutoCloseable) { try { ((AutoCloseable) o).close(); } catch (Throwable __e) { _handleException(__e); } } } static public Object dm_callOS(String functionName, Object... args) { return call(dm_os(), functionName, args); } static public com.sun.management.OperatingSystemMXBean advancedOSMXBean() { return optCast(com.sun.management.OperatingSystemMXBean.class, osMXBean()); } static public void close(AutoCloseable c) { _close(c); } static public A proxyFromInvocationHandler(Class intrface, InvocationHandler handler) { return (A) java.lang.reflect.Proxy.newProxyInstance(intrface.getClassLoader(), new Class[] { intrface }, handler); } static public String getQueryFromURL(String url) { return dropAfterSubstring(substring(url, smartIndexOf(url, "?") + 1), "#"); } static public Object subBot_serveByteArray(byte[] data, String mimeType) { return call(mainBot(), "serveByteArray", data, mimeType); } static public String jsonEncode_shallowLineBreaks(Object o) { return jsonEncode_breakAtLevel1(o); } static public void jsonEncode_shallowLineBreaks(Object o, StringBuilder buf, int level) { jsonEncode_breakAtLevel1(o, buf, level); } static public String javaTokDropTrailingN(String s) { List tok = javaTok(s); return empty(last(tok)) ? unnull(s) : join(dropLast(tok)); } static public List map_ping(Iterable l, Object f) { return map_ping(f, l); } static public List map_ping(Object f, Iterable l) { List x = emptyList(l); if (l != null) for (Object o : l) x.add(callF(f, o)); return x; } static public List map_ping(Iterable l, F1 f) { return map_ping(f, l); } static public List map_ping(F1 f, Iterable l) { List x = emptyList(l); if (l != null) for (A o : l) x.add(callF(f, o)); return x; } static public List map_ping(IF1 f, Iterable l) { return map_ping(l, f); } static public List map_ping(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static public List map_ping(IF1 f, A[] l) { return map_ping(l, f); } static public List map_ping(A[] l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static public List map_ping(Object f, Object[] l) { return map_ping(f, asList(l)); } static public List map_ping(Object[] l, Object f) { return map_ping(f, l); } static public List map_ping(Object f, Map map) { return map_ping(map, f); } static public List map_ping(Map map, Object f) { List x = new ArrayList(); if (map != null) for (Object _e : map.entrySet()) { ping(); Map.Entry e = (Map.Entry) _e; x.add(callF(f, e.getKey(), e.getValue())); } return x; } static public List map_ping(Map map, IF2 f) { return map_ping(map, (Object) f); } static public boolean endsWithLetter(String s) { return nempty(s) && isLetter(last(s)); } static public HashSet mapToSet(Object f, Iterable l) { return mapToHashSet(f, l); } static public HashSet mapToSet(IF1 f, Iterable l) { return mapToSet((Object) f, l); } static public HashSet mapToSet(IF1 f, A[] l) { return mapToSet(f, asList(l)); } static public HashSet mapToSet(Iterable l, IF1 f) { return mapToSet((Object) f, l); } static public Object unstructure(String text) { return unstructure(text, false); } static public Object unstructure(String text, boolean allDynamic) { return unstructure(text, allDynamic, null); } static public Object unstructure(String text, IF1 classFinder) { return unstructure(text, false, classFinder); } static public int structure_internStringsLongerThan = 50; static public int unstructure_unquoteBufSize = 100; static public int unstructure_tokrefs; abstract static public class unstructure_Receiver { abstract public void set(Object o); } static public Object unstructure(String text, boolean allDynamic, Object classFinder) { if (text == null) return null; return unstructure_tok(javaTokC_noMLS_iterator(text), allDynamic, classFinder); } static public Object unstructure_reader(BufferedReader reader) { return unstructure_tok(javaTokC_noMLS_onReader(reader), false, null); } static public Object unstructure_tok(final Producer tok, final boolean allDynamic, final Object _classFinder) { final boolean debug = unstructure_debug; final class X { public int i = -1; final public Object classFinder = _classFinder != null ? _classFinder : _defaultClassFinder(); public HashMap refs = new HashMap(); public HashMap tokrefs = new HashMap(); public HashSet concepts = new HashSet(); public HashMap classesMap = new HashMap(); public List stack = new ArrayList(); public Map baseClassMap = new HashMap(); public String curT; public char[] unquoteBuf = new char[unstructure_unquoteBufSize]; public Class findAClass(String fullClassName) { return classFinder != null ? (Class) callF(classFinder, fullClassName) : findClass_fullName(fullClassName); } public String unquote(String s) { return unquoteUsingCharArray(s, unquoteBuf); } public String t() { return curT; } public String tpp() { String t = curT; consume(); return t; } public void parse(final unstructure_Receiver out) { String t = t(); int refID; if (structure_isMarker(t, 0, l(t))) { refID = parseInt(t.substring(1)); consume(); } else refID = -1; final int tokIndex = i; parse_inner(refID, tokIndex, new unstructure_Receiver() { public void set(Object o) { if (refID >= 0) refs.put(refID, o); if (o != null) tokrefs.put(tokIndex, o); out.set(o); } }); } public void parse_inner(int refID, int tokIndex, unstructure_Receiver out) { String t = t(); Class c = classesMap.get(t); if (c == null) { if (t.startsWith("\"")) { String s = internIfLongerThan(unquote(tpp()), structure_internStringsLongerThan); out.set(s); return; } if (t.startsWith("'")) { out.set(unquoteCharacter(tpp())); return; } if (t.equals("bigint")) { out.set(parseBigInt()); return; } if (t.equals("d")) { out.set(parseDouble()); return; } if (t.equals("fl")) { out.set(parseFloat()); return; } if (t.equals("sh")) { consume(); t = tpp(); if (t.equals("-")) { t = tpp(); out.set((short) (-parseInt(t))); return; } out.set((short) parseInt(t)); return; } if (t.equals("-")) { consume(); t = tpp(); out.set(isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t))); return; } if (isInteger(t) || isLongConstant(t)) { consume(); if (isLongConstant(t)) { out.set(parseLong(t)); return; } long l = parseLong(t); boolean isInt = l == (int) l; out.set(isInt ? (Object) Integer.valueOf((int) l) : (Object) Long.valueOf(l)); return; } if (t.equals("false") || t.equals("f")) { consume(); out.set(false); return; } if (t.equals("true") || t.equals("t")) { consume(); out.set(true); return; } if (t.equals("-")) { consume(); t = tpp(); out.set(isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t))); return; } if (isInteger(t) || isLongConstant(t)) { consume(); if (isLongConstant(t)) { out.set(parseLong(t)); return; } long l = parseLong(t); boolean isInt = l == (int) l; out.set(isInt ? (Object) Integer.valueOf((int) l) : (Object) Long.valueOf(l)); return; } if (t.equals("File")) { consume(); File f = new File(unquote(tpp())); out.set(f); return; } if (t.startsWith("r") && isInteger(t.substring(1))) { consume(); int ref = Integer.parseInt(t.substring(1)); Object o = refs.get(ref); if (o == null) throw fail("unsatisfied back reference " + ref); out.set(o); return; } if (t.startsWith("t") && isInteger(t.substring(1))) { consume(); int ref = Integer.parseInt(t.substring(1)); Object o = tokrefs.get(ref); if (o == null) throw fail("unsatisfied token reference " + ref + " at " + tokIndex); out.set(o); return; } if (t.equals("hashset")) { parseHashSet(out); return; } if (t.equals("lhs")) { parseLinkedHashSet(out); return; } if (t.equals("treeset")) { parseTreeSet(out); return; } if (t.equals("ciset")) { parseCISet(out); return; } if (eqOneOf(t, "hashmap", "hm")) { consume(); parseMap(new HashMap(), out); return; } if (t.equals("lhm")) { consume(); parseMap(new LinkedHashMap(), out); return; } if (t.equals("tm")) { consume(); parseMap(new TreeMap(), out); return; } if (t.equals("cimap")) { consume(); parseMap(ciMap(), out); return; } if (t.equals("ll")) { consume(); LinkedList l = new LinkedList(); if (refID >= 0) refs.put(refID, l); { parseList(l, out); return; } } if (t.equals("syncLL")) { consume(); { parseList(synchroLinkedList(), out); return; } } if (t.equals("sync")) { consume(); { parse(new unstructure_Receiver() { public void set(Object value) { if (value instanceof Map) { if (value instanceof NavigableMap) { out.set(Collections.synchronizedNavigableMap((NavigableMap) value)); return; } if (value instanceof SortedMap) { out.set(Collections.synchronizedSortedMap((SortedMap) value)); return; } { out.set(Collections.synchronizedMap((Map) value)); return; } } else { out.set(Collections.synchronizedList((List) value)); return; } } }); return; } } if (t.equals("{")) { parseMap(out); return; } if (t.equals("[")) { ArrayList l = new ArrayList(); if (refID >= 0) refs.put(refID, l); this.parseList(l, out); return; } if (t.equals("bitset")) { parseBitSet(out); return; } if (t.equals("array") || t.equals("intarray") || t.equals("dblarray")) { parseArray(out); return; } if (t.equals("ba")) { consume(); String hex = unquote(tpp()); out.set(hexToBytes(hex)); return; } if (t.equals("boolarray")) { consume(); int n = parseInt(tpp()); String hex = unquote(tpp()); out.set(boolArrayFromBytes(hexToBytes(hex), n)); return; } if (t.equals("class")) { out.set(parseClass()); return; } if (t.equals("l")) { parseLisp(out); return; } if (t.equals("null")) { consume(); out.set(null); return; } if (eq(t, "c")) { consume(); t = t(); assertTrue(isJavaIdentifier(t)); concepts.add(t); } if (eq(t, "cu")) { consume(); t = tpp(); assertTrue(isJavaIdentifier(t)); String fullClassName = "main$" + t; Class _c = findAClass(fullClassName); if (_c == null) throw fail("Class not found: " + fullClassName); parse(new unstructure_Receiver() { public void set(Object value) { out.set(call(_c, "_deserialize", value)); } }); return; } } if (eq(t, "j")) { consume(); out.set(parseJava()); return; } if (eq(t, "bc")) { consume(); String c1 = tpp(); String c2 = tpp(); baseClassMap.put(c1, c2); { parse_inner(refID, i, out); return; } } if (c == null && !isJavaIdentifier(t)) throw new RuntimeException("Unknown token " + (i + 1) + ": " + quote(t)); consume(); String className, fullClassName; if (eq(t(), ".")) { consume(); className = fullClassName = t + "." + assertIdentifier(tpp()); } else { className = t; fullClassName = "main$" + t; } if (c == null && !allDynamic) { c = findAClass(fullClassName); if (c != null) classesMap.put(className, c); } if (c == null && !allDynamic) { String baseName = baseClassMap.get(className); if (baseName != null) { c = findAClass("main$" + baseName); if (c != null) classesMap.put(className, c); } } boolean hasBracket = eq(t(), "("); if (hasBracket) consume(); boolean hasOuter = hasBracket && eq(t(), "this$1"); DynamicObject dO = null; Object o = null; final String thingName = t; if (c != null) { o = hasOuter ? nuStubInnerObject(c, classFinder) : nuEmptyObject(c); if (o instanceof DynamicObject) dO = (DynamicObject) o; } else { if (concepts.contains(t) && (c = findAClass("main$Concept")) != null) o = dO = (DynamicObject) nuEmptyObject(c); else dO = new DynamicObject(); dO.className = className; } if (refID >= 0) refs.put(refID, o != null ? o : dO); tokrefs.put(tokIndex, o != null ? o : dO); HashMap fields = new HashMap(); Object _o = o; DynamicObject _dO = dO; if (hasBracket) { stack.add(new Runnable() { public void run() { try { if (eq(t(), ",")) consume(); if (eq(t(), ")")) { consume(")"); objRead(_o, _dO, fields, hasOuter); out.set(_o != null ? _o : _dO); } else { final String key = unquote(tpp()); String t = tpp(); if (!eq(t, "=")) throw fail("= expected, got " + t + " after " + quote(key) + " in object " + thingName); stack.add(this); parse(new unstructure_Receiver() { public void set(Object value) { fields.put(key, value); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef unstructure_debug\r\n print(\"in object values, token: \" + t())..."; } }); } else { objRead(o, dO, fields, hasOuter); out.set(o != null ? o : dO); } } public void objRead(Object o, DynamicObject dO, Map fields, boolean hasOuter) { if (o != null) { if (dO != null) { setOptAllDyn_pcall(dO, fields); } else { setOptAll_pcall(o, fields); } if (hasOuter) fixOuterRefs(o); } else for (Map.Entry e : fields.entrySet()) setDynObjectValue(dO, intern(e.getKey()), e.getValue()); if (o != null) pcallOpt_noArgs(o, "_doneLoading"); } public void parseSet(final Set set, final unstructure_Receiver out) { this.parseList(new ArrayList(), new unstructure_Receiver() { public void set(Object o) { set.addAll((List) o); out.set(set); } }); } public void parseLisp(final unstructure_Receiver out) { throw fail("class Lisp not included"); } public void parseBitSet(final unstructure_Receiver out) { consume("bitset"); consume("{"); final BitSet bs = new BitSet(); stack.add(new Runnable() { public void run() { try { if (eq(t(), "}")) { consume("}"); out.set(bs); } else { stack.add(this); parse(new unstructure_Receiver() { public void set(Object o) { bs.set((Integer) o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"}\")) {\r\n consume(\"}\");\r\n out.set(bs);\r\n ..."; } }); } public void parseList(final List list, final unstructure_Receiver out) { tokrefs.put(i, list); consume("["); stack.add(new Runnable() { public void run() { try { if (eq(t(), "]")) { consume(); out.set(list); } else { stack.add(this); parse(new unstructure_Receiver() { public void set(Object o) { list.add(o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"]\")) {\r\n consume();\r\n ifdef unstructure_debug\r..."; } }); } public void parseArray(final unstructure_Receiver out) { final String type = tpp(); consume("{"); final List list = new ArrayList(); stack.add(new Runnable() { public void run() { try { if (eq(t(), "}")) { consume("}"); out.set(type.equals("intarray") ? toIntArray(list) : type.equals("dblarray") ? toDoubleArray(list) : list.toArray()); } else { stack.add(this); parse(new unstructure_Receiver() { public void set(Object o) { list.add(o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"}\")) {\r\n consume(\"}\");\r\n out.set(\r\n ..."; } }); } public Object parseClass() { consume("class"); consume("("); String name = unquote(tpp()); consume(")"); Class c = allDynamic ? null : findAClass(name); if (c != null) return c; DynamicObject dO = new DynamicObject(); dO.className = "java.lang.Class"; name = dropPrefix("main$", name); dO.fieldValues.put("name", name); return dO; } public Object parseBigInt() { consume("bigint"); consume("("); String val = tpp(); if (eq(val, "-")) val = "-" + tpp(); consume(")"); return new BigInteger(val); } public Object parseDouble() { consume("d"); consume("("); String val = unquote(tpp()); consume(")"); return Double.parseDouble(val); } public Object parseFloat() { consume("fl"); String val; if (eq(t(), "(")) { consume("("); val = unquote(tpp()); consume(")"); } else { val = unquote(tpp()); } return Float.parseFloat(val); } public void parseHashSet(unstructure_Receiver out) { consume("hashset"); parseSet(new HashSet(), out); } public void parseLinkedHashSet(unstructure_Receiver out) { consume("lhs"); parseSet(new LinkedHashSet(), out); } public void parseTreeSet(unstructure_Receiver out) { consume("treeset"); parseSet(new TreeSet(), out); } public void parseCISet(unstructure_Receiver out) { consume("ciset"); parseSet(ciSet(), out); } public void parseMap(unstructure_Receiver out) { parseMap(new TreeMap(), out); } public Object parseJava() { String j = unquote(tpp()); Matches m = new Matches(); if (jmatch("java.awt.Color[r=*,g=*,b=*]", j, m)) return nuObject("java.awt.Color", parseInt(m.unq(0)), parseInt(m.unq(1)), parseInt(m.unq(2))); else { warn("Unknown Java object: " + j); return null; } } public void parseMap(final Map map, final unstructure_Receiver out) { consume("{"); stack.add(new Runnable() { public boolean v = false; public Object key; public void run() { if (v) { v = false; stack.add(this); if (!eq(tpp(), "=")) throw fail("= expected, got " + t() + " in map of size " + l(map)); parse(new unstructure_Receiver() { public void set(Object value) { map.put(key, value); if (eq(t(), ",")) consume(); } }); } else { if (eq(t(), "}")) { consume("}"); out.set(map); } else { v = true; stack.add(this); parse(new unstructure_Receiver() { public void set(Object o) { key = o; } }); } } } }); } public void consume() { curT = tok.next(); ++i; } public void consume(String s) { if (!eq(t(), s)) { throw fail(quote(s) + " expected, got " + quote(t())); } consume(); } public void parse_initial(unstructure_Receiver out) { consume(); parse(out); while (nempty(stack)) popLast(stack).run(); } } ThreadLocal tlLoading = dynamicObjectIsLoading_threadLocal(); Boolean b = tlLoading.get(); tlLoading.set(true); try { final Var v = new Var(); X x = new X(); x.parse_initial(new unstructure_Receiver() { public void set(Object o) { v.set(o); } }); unstructure_tokrefs = x.tokrefs.size(); return v.get(); } finally { tlLoading.set(b); } } static public boolean unstructure_debug = false; static public boolean isString(Object o) { return o instanceof String; } static public Object dm_getService(String serviceName) { return empty(serviceName) ? null : dm_getModule(vmBus_query(assertIdentifier(serviceName))); } static public boolean isStringOrIntOrLong(Object o) { return o instanceof String || o instanceof Integer || o instanceof Long; } static public Object dm_resolveModule(Object moduleOrStem) { return dm_callOS("resolveModule", moduleOrStem); } static public double toM_double(long l) { return l / (1024 * 1024.0); } static public int findEndOfBlock(List cnc, int i) { int j = i + 2, level = 1, n = cnc.size(); while (j < n) { String t = cnc.get(j); if ("{".equals(t)) ++level; else if ("}".equals(t)) --level; if (level == 0) return j + 1; j += 2; } return n; } static public boolean tok_isJavaxMetaCommandLeftOf(List tok, int i) { int j = i - 2 * 4 - 1; if (j >= 0 && jfind(subList(tok, j, i), "set flag .") == 1) return true; return false; } static public boolean eqGetOneOf(List l, int i, A... options) { return eqOneOf(get(l, i), options); } static public int leftScanModifiers(List tok, int i) { List mod = getJavaModifiers(); while (i > 1 && mod.contains(tok.get(i - 2))) i -= 2; return i; } static public A assertEquals(Object x, A y) { return assertEquals(null, x, y); } static public A assertEquals(String msg, Object x, A y) { if (assertVerbose()) return assertEqualsVerbose(msg, x, y); if (!(x == null ? y == null : x.equals(y))) throw fail((msg != null ? msg + ": " : "") + y + " != " + x); return y; } static public File makeTempDir() { return (File) call(getJavaX(), "TempDirMaker_make"); } static public File linux_fileInRamDisk(String name) { if (!isLinux()) return null; File dir = newFile("/dev/shm"); if (dir.isDirectory()) return newFile(dir, name); return null; } static public boolean isMarkedAsSrcLib(String snippetID) { if (snippetID == null) return false; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return isJavaxCompilableSnippetType(rl.getSnippetType(snippetID)); return fileExists(javaxCodeDir("srclibs/" + psI(snippetID))); } static public Object hotwire_onCompile; static public boolean hotwire_serially = false; static public Lock hotwire_overInternalBot_lock = lock(); static public boolean hotwire_compileOnServer = false; static public Class hotwire_overInternalBot(String progID) { return hotwire_overInternalBot(progID, "main"); } static public Class hotwire_overInternalBot(String progID, String mainClass) { try { Pair p; try { p = hotwire_compile(progID); } catch (Throwable e) { throw rethrow("Error hotwiring " + progID, e); } File jar = p.a; assertTrue(jar.getAbsolutePath(), jar.isFile()); List files = hotwire_collectJars(jar); JavaXClassLoader classLoader = hotwire_makeClassLoader(files); classLoader.progID = progID; return hotwire_finish(classLoader, progID, p.b, mainClass); } catch (Exception __e) { throw rethrow(__e); } } static public Pair hotwire_compile(String progID) { Pair p = hotwire_compileOnServer && !isLocalSnippetID(progID) ? compileSnippetThroughServer(progID) : CompilerBot.compileSnippet2(progID); Lock __0 = hotwire_serially ? hotwire_overInternalBot_lock : null; lock(__0); try { callF(hotwire_onCompile, p); return p; } finally { unlock(__0); } } static public void markAsSrcLib(String snippetID) { saveTextFile(javaxCodeDir("srclibs/" + psI(snippetID)), ""); } static public List filesWithExtension(String ext, List files) { return filesEndingWith(files, addPrefixIfNotEmpty2(".", ext)); } static public List findAllFiles_noDirs(List dirs) { return findAllFiles_noDirs(asObjectArray(dirs)); } static public List findAllFiles_noDirs(Object... dirs) { List l = new ArrayList(); for (Object dir : dirs) { if (dir instanceof String && ((String) dir).endsWith("/.")) { for (File f : listFiles(dropSuffix("/.", (String) dir))) if (f.isFile()) l.add(f); } else findAllFiles_noDirs_impl(toFile(dir), l); } return l; } static public void findAllFiles_noDirs_impl(File dir, List l) { for (File f : listFiles(dir)) { if (f.isDirectory()) findAllFiles_noDirs_impl(f, l); else l.add(f); } } static public File[] listFiles(File dir) { File[] files = dir.listFiles(); return files == null ? new File[0] : files; } static public File[] listFiles(String dir) { return listFiles(new File(dir)); } static public List sortFilesByName(List l) { sort(l, (a, b) -> stdcompare(a.getName(), b.getName())); return l; } static public int deleteAllFilesInDirectory_minPathLength = 10; static public void deleteAllFilesInDirectory(File dir) { deleteAllFilesInDirectory(dir, false, false); } static public void deleteAllFilesInDirectory(File dir, boolean verbose, boolean testRun) { dir = getCanonicalFile(dir); assertTrue(f2s(dir), l(f2s(dir)) >= deleteAllFilesInDirectory_minPathLength); File[] files = dir.listFiles(); if (files == null) return; for (File f : files) { if (!isSymLink(f) && f.isDirectory()) deleteDirectory(f, verbose, testRun); else { if (verbose) print((testRun ? "Would delete " : "Deleting ") + f.getAbsolutePath()); if (!testRun) f.delete(); } } } static public Object callJavaX(String method, Object... args) { return callOpt(getJavaX(), method, args); } static public ClassLoader getClassLoaderOrSame(Object o) { return o instanceof ClassLoader ? (ClassLoader) o : getClassLoader(o); } static public void printShortException(Throwable e) { print(exceptionToStringShort(e)); } static public void printShortException(String s, Throwable e) { print(s, exceptionToStringShort(e)); } static public boolean java10OrHigher() { return parseFirstInt(javaVersion()) >= 10; } static public boolean addDefaultVMOption(String option) { String s = defaultVMArgs(), old = s; if (!s.contains(option)) s = trim(s + " " + option); if (eq(old, s)) return false; { setDefaultVMArgs(s); return true; } } static public byte[] intToBytes(int i) { return new byte[] { (byte) (i >>> 24), (byte) (i >>> 16), (byte) (i >>> 8), (byte) i }; } static public List splitByJavaToken(String s, String splitToken) { List tok = javaTok(s); List l = new ArrayList(); int i = 1; while (i < l(tok)) { int j = smartIndexOf(tok, splitToken, i); l.add(join(subList(tok, i, j - 1))); i = j + 2; } return l; } static public String dollarVarsToStars(String s) { return dollarVarsToStars(s, null); } static public String dollarVarsToStars(String s, List varNames_out) { List tok = javaTok(s); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (isDollarVar(t)) { listAdd(varNames_out, t); tok.set(i, "*"); } else if (eq(t, "*")) listAdd(varNames_out, "*"); } return join(tok); } static public void tok_statementToBlock(List tok, int i) { if (neqGet(tok, i, "{")) { int iEnd = tok_findEndOfStatement(tok, i) - 1; tokAppend_reTok(tok, iEnd, " }"); tokPrepend_reTok(tok, i, "{ "); } } static public void tokAppend_reTok(List tok, int i, String s) { tok.set(i, tok.get(i) + s); reTok(tok, i, i + 1); } static public List mapWithIndexStartingAt1(List l, IF2 f) { List out = emptyList(l); for (int i = 0; i < l(l); i++) out.add(f.get(i + 1, l.get(i))); return out; } static public boolean containsDollarVars(String s) { for (String t : javaTokC(s)) if (isDollarVar(t)) return true; return false; } static public List toLinesFullTrim_java(String text) { return tlft(joinLines(map("javaDropComments", tlft(text)))); } static public String dm_moduleLibID() { return programID() + "/" + shortClassName(dm_current_mandatory_generic()); } static public String dm_moduleLibID(Object mod) { if (mod == null) return null; mod = dm_getModule(mod); if (hasSuperclassShortNamed(mod, "DynModule")) return programID(mod) + "/" + shortClassName(mod); return null; } static public List dm_modulesWithLibID(final String moduleLibID) { return filter(dm_moduleIDs(), new F1() { public Boolean get(String m) { try { return eq(dm_moduleLibID(m), moduleLibID); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "eq(dm_moduleLibID(m), moduleLibID)"; } }); } static public String dm_moduleID(Object module) { return strOrNull(getOpt(dm_getStem(module), "id")); } static public String dm_moduleID() { return dm_moduleID(dm_current_mandatory_generic()); } static public String lowestByAlphaNum(Collection c) { String best = null; for (String s : unnull(c)) if (best == null || alphaNumComparator().compare(s, best) < 0) best = s; return best; } static public boolean isConceptClassIndexed(Class c) { return isConceptClassIndexed(db_mainConcepts(), c); } static public boolean isConceptClassIndexed(Concepts concepts, Class c) { return concepts.conceptCounterForClass(c) != null; } static public void indexRandomConceptField(Class c) { indexRandomConceptField(db_mainConcepts(), c); } static public void indexRandomConceptField(Concepts cc, Class c) { String field = or(first(conceptFields(c)), "_dummy"); print("Indexing " + c + "." + field); indexConceptField(cc, c, field); } static public A setToolTipText(final A c, final Object toolTip) { if (c == null) return null; { swing(new Runnable() { public void run() { try { String s = nullIfEmpty(str(toolTip)); if (neq(s, c.getToolTipText())) c.setToolTipText(s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String s = nullIfEmpty(str(toolTip));\r\n if (neq(s, c.getToolTipText()))\r\n ..."; } }); } return c; } static public A setToolTipText(Object toolTip, A c) { return setToolTipText(c, toolTip); } static public JButton jbutton(String text, Object action) { return newButton(text, action); } static public JButton jbutton(String text) { return newButton(text, null); } static public JButton jbutton(Action action) { return swingNu(JButton.class, action); } static public String unicode_downPointingTriangle() { return charToString(0x25BC); } static public A optPar_ignoreOddLength(Object[] opt, String name, A defaultValue) { int n = l(opt); if (n == 1 && opt[0] instanceof Map) { Map map = (Map) (opt[0]); return map.containsKey(name) ? (A) map.get(name) : defaultValue; } for (int i = 0; i + 1 < l(opt); i += 2) if (eq(opt[i], name)) return (A) opt[i + 1]; return defaultValue; } static public Object optPar_ignoreOddLength(Object[] opt, String name) { return optPar_ignoreOddLength(opt, name, null); } static public Object optPar_ignoreOddLength(String name, Object[] params) { return optPar_ignoreOddLength(params, name); } static public void fillJPopupMenu(JPopupMenu m, Object... x) { if (x == null) return; for (int i = 0; i < l(x); i++) { Object o = x[i], y = get(x, i + 1); if (o instanceof IVF1) callF(o, m); else if (o instanceof List) fillJPopupMenu(m, asArray((List) o)); else if (isMenuSeparatorIndicator(o)) m.addSeparator(); else if (o instanceof LiveValue && ((LiveValue) o).getType() == String.class && isRunnableX(y)) { final LiveValue lv = (LiveValue) o; final JMenuItem mi = jmenuItem("", y); bindLiveValueListenerToComponent(mi, lv, new Runnable() { public void run() { try { String s = lv.get(); if (isCurlyBracketed(s)) { setEnabled(mi, false); s = unCurlyBracket(s); } else setEnabled(mi, true); setText(mi, s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String s = lv.get();\r\n if (isCurlyBracketed(s)) {\r\n setEnable..."; } }); m.add(mi); } else if (o instanceof String && isRunnableX(y)) { m.add(jmenuItem((String) o, y)); ++i; } else if (o instanceof JMenuItem) m.add((JMenuItem) o); else if (o instanceof String || o instanceof Action || o instanceof Component) call(m, "add", o); else if (o != null) print("Unknown menu item: " + o); } } static public int getPreferredWidth(Component c) { return preferredWidth(c); } static public Object interceptPrintInThisThread(Object f) { Object old = print_byThread().get(); print_byThread().set(f); return old; } static public Object mainBot() { return getMainBot(); } static public long collectMinLong(Collection c, String field) { long x = Long.MAX_VALUE; for (Object o : unnull(c)) { Long l = (Long) (getOpt(o, field)); if (l != null) x = min(x, l); } return x; } static public long collectMaxLong(Collection c, String field) { long x = Long.MIN_VALUE; for (Object o : unnull(c)) { Long l = (Long) (getOpt(o, field)); if (l != null) x = max(x, l); } return x; } static public String i(String s, Object... params) { return tag("i", s, params); } static public String formatDateAndTime(long timestamp) { return formatDate(timestamp); } static public String formatDateAndTime() { return formatDate(); } static public String shortenEndTime(String endTime, String startTime) { int i = endTime.lastIndexOf(' ') + 1; if (i > 0 && eq(substring(startTime, 0, i), substring(endTime, 0, i))) return trim(substring(endTime, i)); return endTime; } static public String unicode_leftPointingTriangle() { return unicodeFromCodePoint(0x25C2); } static public String unicode_rightPointingTriangle() { return charToString(0x25B8); } static public File parentFile(File f) { return dirOfFile(f); } static public String hms() { return hms(now()); } static public String hms(long time) { return new SimpleDateFormat("HHmmss").format(time); } static public int smartLastIndexOf(String s, char c) { if (s == null) return 0; int i = s.lastIndexOf(c); return i >= 0 ? i : l(s); } static public int smartLastIndexOf(List l, A sub) { int i = lastIndexOf(l, sub); return i < 0 ? l(l) : i; } static public int year() { return localYear(); } static public int year(long now) { return localYear(now); } static public int year(long now, TimeZone tz) { return parseInt(simpleDateFormat("y", tz).format(now)); } static public String formatInt(int i, int digits) { return padLeft(str(i), '0', digits); } static public String formatInt(long l, int digits) { return padLeft(str(l), '0', digits); } static public int month() { return localMonth(); } static public int month(long now) { return localMonth(now); } static public int month(long now, TimeZone tz) { return parseInt(simpleDateFormat("M", tz).format(now)); } static public int dayOfMonth() { return localDayOfMonth(); } static public int dayOfMonth(long now) { return localDayOfMonth(now); } static public int dayOfMonth(long now, TimeZone tz) { return parseInt(simpleDateFormat("d", tz).format(now)); } static public long toK(long l) { return (l + 1023) / 1024; } static public List listZipFile(File inZip) { try { ZipFile zipFile = new ZipFile(inZip); try { return listZipFile(zipFile); } finally { zipFile.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public List listZipFile(ZipFile zipFile) { try { List list = new ArrayList(); Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry) entries.nextElement(); if (!entry.isDirectory()) list.add(entry.getName()); } return list; } catch (Exception __e) { throw rethrow(__e); } } static public List listZipFile(String name) { if (isSnippetID(name)) return listZipFile(loadLibrary(name)); return listZipFile(getProgramFile(name)); } static public void mapPut_noOverwrite(Map map, A key, B value) { if (map != null && key != null && value != null && !map.containsKey(key)) map.put(key, value); } static public String pnlToString(String prefix, Iterable l) { return hijackPrint(new Runnable() { public void run() { try { pnl(prefix, l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pnl(prefix, l)"; } }); } static public String pnlToString(final Iterable l) { return hijackPrint(new Runnable() { public void run() { try { pnl(l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pnl(l)"; } }); } static public String pnlToString(final A[] l) { return hijackPrint(new Runnable() { public void run() { try { pnl(l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pnl(l)"; } }); } static public String pnlToString(final Map map) { return hijackPrint(new Runnable() { public void run() { try { pnl(map); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pnl(map)"; } }); } static public String pnlToString(MultiMap map) { return pnlToString(multiMapToMap(map)); } static public String actualProgramID() { return programID(); } static public MultiMap treeMultiMap() { return new MultiMap(true); } static public MultiMap treeMultiMap(Comparator comparator) { return new MultiMap(new TreeMap>(comparator)); } static public List sortedByField(Collection c, final String field) { List l = new ArrayList(c); sort(l, new Comparator() { public int compare(A a, A b) { return cmp(getOpt(a, field), getOpt(b, field)); } }); return l; } static public List sortedByField(String field, Collection c) { return sortedByField(c, field); } static public Object loadJSONFile(File f) { return jsonDecode(loadTextFile(f)); } static public List filterNempty(Collection c) { List l = new ArrayList(); for (String x : unnull(c)) if (nempty(x)) l.add(x); return l; } static public A objectWhere(Collection c, Object... data) { return findWhere(c, data); } static public Comparator descFieldComparator(final String field) { return new Comparator() { public int compare(A a, A b) { return cmp(getOpt(b, field), getOpt(a, field)); } }; } static public TimerTask timerTask(final Object r, final java.util.Timer timer) { return new TimerTask() { public void run() { if (!licensed()) timer.cancel(); else pcallF(r); } }; } static public void ensureDBNotRunning(String name) { if (hasBot(name)) { try { String framesBot = dropSuffix(".", name) + " Frames"; print("Trying to activate frames of running DB: " + framesBot); if (isOK(sendOpt(framesBot, "activate frames")) && isMainProgram()) cleanKill(); } catch (Throwable __e) { _handleException(__e); } throw fail("Already running: " + name); } } static public void ensureDBNotRunning() { ensureDBNotRunning(dbBotStandardName()); } static public String dbBotStandardName() { String home = userHome(); String name = dbBotName(getDBProgramID()); if (neq(home, actualUserHome())) name += " " + quote(home); return name + "."; } static volatile public Android3 dbBot_instance; static public Android3 dbBot() { return dbBot(true); } static public Android3 dbBot(boolean ensureNotRunning) { return dbBot(dbBotStandardName(), ensureNotRunning); } static public Android3 dbBot(String name) { return dbBot(name, true); } static public Android3 dbBot(String name, boolean ensureNotRunning) { if (ensureNotRunning) ensureDBNotRunning(name); return dbBot_instance = methodsBot2(name, assertNotNull(db_mainConcepts()), db_standardExposedMethods(), db_mainConcepts().lock); } static public void thinAProgramsBackups(String progID, boolean doIt) { List files = new ArrayList(); Map ageMap = new HashMap(); java.util.regex.Pattern pat = regexp("^(.*)\\.backup(20\\d\\d)(\\d\\d)(\\d\\d)-(\\d\\d)$"); File dir = programDir(progID); for (File f : listFilesNotDirs(dir, newFile(dir, "backups"))) { String s = f.getName(); java.util.regex.Matcher matcher = pat.matcher(s); { if (!(matcher.find())) continue; } String originalName = matcher.group(1); { if (!(eq(originalName, "concepts.structure.gz"))) continue; } int year = matcherInt(matcher, 2); int month = matcherInt(matcher, 3); int day = matcherInt(matcher, 4); int hour = matcherInt(matcher, 5); long time = timestampFromYMDH(year, month, day, hour); double age = ((now() - time) / 1000.0 / 60 / 60 / 24); ageMap.put(f, age); files.add(f); } int numDeleted = 0; sortByMap_inPlace(files, ageMap); double lastAge = -1; for (File f : files) { double age = ageMap.get(f); if (!thinAProgramsBackups_shouldKeep(age, lastAge)) { ++numDeleted; if (doIt) { print("Deleting: " + f); f.delete(); } } else { lastAge = age; } } if (numDeleted != 0) print((doIt ? "Deleted: " : "Would delete: ") + n(numDeleted, "file")); } static public boolean thinAProgramsBackups_shouldKeep(double age, double lastAge) { return defaultAgeBasedBackupRetentionStrategy_shouldKeep(age, lastAge); } static public A lookupOrKeep(Map map, A key) { return map != null && map.containsKey(key) ? map.get(key) : key; } static public Object subBot_httpd() { Object httpd = getThreadLocal((ThreadLocal) getOpt(mainBot(), "MyHTTPD_current")); if (httpd == null) httpd = getThreadLocal((ThreadLocal) getOpt(mainBot(), "WebSocketHTTPD_current")); return httpd; } static public String domainName() { Object session = call(getMainBot(), "getSession"); Map headers = (Map) (call(session, "getHeaders")); String host = (String) (headers.get("host")); if (host == null) return null; return dropFrom(host, ":"); } static public String codePointToString(int codePoint) { return new String(Character.toChars(codePoint)); } static public SimpleDateFormat simpleDateFormat_timeZone(String format, String timeZone) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(timeZone(timeZone)); return sdf; } static public long ipToInt(String ip) { Matches m = new Matches(); assertTrue(jmatch("*.*.*.*", ip, m)); return parseLong(m.unq(3)) | parseLong(m.unq(2)) << 8 | parseLong(m.unq(1)) << 16 | parseLong(m.unq(0)) << 24; } static public boolean directoryEmpty(File f) { return directoryIsEmpty(f); } static public void unzipSnippet(String snippetID, File toDir) { print("Unzipping snippet " + snippetID + " to " + toDir); zip2dir(loadLibrary(snippetID), toDir); } static public Pair binarySearchForLineInTextFile(File file, IF1 nav) { long length = l(file); int bufSize = 1024; RandomAccessFile raf = randomAccessFileForReading(file); try { long min = 0, max = length; int direction = 0; Pair possibleResult = null; while (min < max) { ping(); long middle = (min + max) / 2; long lineStart = raf_findBeginningOfLine(raf, middle, bufSize); long lineEnd = raf_findEndOfLine(raf, middle, bufSize); String line = fromUtf8(raf_readFilePart(raf, lineStart, (int) (lineEnd - 1 - lineStart))); direction = nav.get(line); possibleResult = pair(new LongRange(lineStart, lineEnd), line); if (direction == 0) return possibleResult; if (direction < 0) max = assertLessThan(max, lineStart); else min = assertBiggerThan(min, lineEnd); } if (direction >= 0) return possibleResult; long lineStart = raf_findBeginningOfLine(raf, min - 1, bufSize); String line = fromUtf8(raf_readFilePart(raf, lineStart, (int) (min - 1 - lineStart))); return pair(new LongRange(lineStart, min), line); } finally { _close(raf); } } static public List tok_splitAtComma_unquote(String s) { List tok = javaTok(s); List out = new ArrayList(); for (int i = 0; i < l(tok); i++) { int j = smartIndexOf(tok, ",", i); out.add(unquote(trimJoinSubList(tok, i, j))); i = j; } return out; } static public long parseLongOpt(String s) { return isInteger(s) ? parseLong(s) : 0; } static public JTextField standardTextFieldPopupMenu(final JTextField tf) { final WeakReference ref = weakRef(tf); componentPopupMenuItem(tf, "Copy text to clipboard", new Runnable() { public void run() { try { copyTextToClipboard(ref.get().getText()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyTextToClipboard(ref.get().getText())"; } }); componentPopupMenuItem(tf, "Paste", new Runnable() { public void run() { try { ref.get().paste(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ref.get().paste()"; } }); return tf; } static public A jenableUndoRedo(final A textcomp) { { swing(new Runnable() { public void run() { try { final UndoManager undo = new UndoManager(); vm_generalWeakSet("Undo Managers").add(undo); textcomp.getDocument().addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); textcomp.getActionMap().put("Undo", abstractAction("Undo", new Runnable() { public void run() { try { if (undo.canUndo()) undo.undo(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canUndo()) undo.undo()"; } })); textcomp.getActionMap().put("Redo", abstractAction("Redo", new Runnable() { public void run() { try { if (undo.canRedo()) undo.redo(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canRedo()) undo.redo()"; } })); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo"); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final new UndoManager undo;\r\n vm_generalWeakSet(\"Undo Managers\").add(undo)..."; } }); } return textcomp; } static public JPanel showFormTitled_customArrangement(final boolean internalFrame, final F1, JPanel> arrange, final String title, final Object... _parts) { return swing(new F0() { public JPanel get() { try { List out = showForm_arrange1(showForm_makeComponents(internalFrame, _parts)); JPanel panel = callF(arrange, out); showForm_makeFrame(title, panel); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "L out = showForm_arrange1(showForm_makeComponents(internalFrame, ..."; } }); } static public JPanel customLayoutPanel(final Object layouter) { return jpanel(layoutManagerFromFunction(layouter)); } static public JPanel customLayoutPanel(final Object layouter, final List components) { return addAllComponents(customLayoutPanel(layouter), components); } static public List getComponents(final Component c) { return !(c instanceof Container) ? emptyList() : asList(swing(new F0() { public Component[] get() { try { return ((Container) c).getComponents(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret ((Container) c).getComponents();"; } })); } static public boolean containsATextArea(Component c) { return childOfType(c, JTextArea.class) != null; } static public int totalPreferredHeight(List l) { int h = 0; for (Component c : unnull(l)) h += c.getPreferredSize().height; return h; } static public List listWithoutIndicesInBitSet(List l, BitSet bs) { List out = new ArrayList(); for (int i = 0; i < l(l); i++) if (!bs.get(i)) out.add(l.get(i)); return out; } static public Dimension componentsBoundingSize(Container container, int insetBottomRight) { Rectangle r = new Rectangle(0, 0, 0, 0); for (Component c : container.getComponents()) r = rectangleUnion(r, c.getBounds()); return new Dimension(r.x + r.width + insetBottomRight, r.y + r.height + insetBottomRight); } static public String getText(final AbstractButton c) { return c == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return c.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getText();"; } }); } static public String getText(final JTextComponent c) { return c == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return c.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getText();"; } }); } static public String getText(final JLabel l) { return l == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return l.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret l.getText();"; } }); } static public String getText(final JComboBox cb) { if (cb == null) return null; if (isEditableComboBox(cb)) return unnull((String) cb.getEditor().getItem()); else return str(cb.getSelectedItem()); } static public A printHidingCredentials(A o) { print(hideCredentials(str(o))); return o; } static public void logQuotedWithDate(String s) { logQuotedWithTime(s); } static public void logQuotedWithDate(String logFile, String s) { logQuotedWithTime(logFile, s); } static public void logQuotedWithDate(File logFile, String s) { logQuotedWithTime(logFile, s); } static public File infoBoxesLogFile() { return new File(javaxDataDir(), "Logs/infoBoxes.txt"); } static public JWindow showWindow(Component c) { JWindow w = new JWindow(); w.add(wrap(c)); return w; } static public JPanel infoMessage_makePanel(String text) { final JTextArea ta = wrappedTextArea(text); onClick(ta, new Runnable() { public void run() { try { disposeWindow(ta); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "disposeWindow(ta)"; } }); int size = 14; if (l(text) <= 50) size *= 2; else if (l(text) < 100) size = iround(size * 1.5); ta.setFont(typeWriterFont(size)); JScrollPane sp = jscroll(ta); return withMargin(sp); } static public boolean vmBus_noObjections(String msg, Object... args) { return !vmBus_anyFalse(msg, args); } static public String getProgramName_cache; static public String getProgramName() { Lock __0 = downloadLock(); lock(__0); try { if (getProgramName_cache == null) getProgramName_cache = getSnippetTitleOpt(programID()); return getProgramName_cache; } finally { unlock(__0); } } static public void _onLoad_getProgramName() { { startThread(new Runnable() { public void run() { try { getProgramName(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getProgramName();"; } }); } } static public JDesktopPane mainDesktopPane_value; static public JDesktopPane mainDesktopPane() { return mainDesktopPane_value; } static public JPanel showInternalFrameFormTitled(final JDesktopPane desktop, final String title, final Object... _parts) { JPanel panel = showForm_makePanel(true, _parts); showForm_makeInternalFrame(desktop, title, panel); return panel; } static public JFrame showForm_makeFrame(String title, JPanel panel) { return handleEscapeKey(minFrameWidth(showPackedFrame(title, withMargin(panel)), 400)); } static public List showForm_arrange1(List> l) { int minW = showForm_leftWidth(l); List out = new ArrayList(); for (List row : l) out.add(westAndCenter(withRightMargin(showForm_gapBetweenColumns, jMinWidthAtLeast(minW, first(row))), second(row))); return out; } static public List> showForm_makeComponents(final Boolean internalFrame, Object... _parts) { List> l = new ArrayList(); List parts = asList(_parts); JButton submitButton = null; for (int i = 0; i < l(parts); i++) { final Object o = parts.get(i), next = get(parts, i + 1); if (o instanceof String && next instanceof Component) setComponentID((Component) next, (String) o); if (o instanceof Component || o instanceof String || next instanceof Component) { l.add(mapLL("wrapForSmartAdd", o == null ? new JPanel() : o instanceof String ? humanizeFormLabel((String) o) : o, next)); if (next instanceof JButton && submitButton == null) submitButton = (JButton) next; i++; } else if (isRunnable(o)) l.add(mapLL("wrapForSmartAdd", null, submitButton = jbutton(showFormSubmitButtonName(), new Runnable() { public void run() { try { Object result = call(o); print("Result of form runnable: " + result + ". Button: " + heldInstance(JButton.class)); if (neq(Boolean.FALSE, result)) { if (isTrue(internalFrame)) disposeInternalFrame(heldInstance(JButton.class)); else if (isFalse(internalFrame)) disposeFrame(heldInstance(JButton.class)); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Object result = call(o);\r\n print(\"Result of form runnable: \" + result ..."; } }))); else print("showForm: Unknown element type: " + getClassName(o)); } if (submitButton != null) { final JButton _submitButton = submitButton; onEnterInAllTextFields(concatLists(l), new Runnable() { public void run() { try { clickButton(_submitButton); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "clickButton(_submitButton)"; } }); } for (List row : l) { JComponent left = first(row); if (left instanceof JLabel) makeBold((JLabel) left).setVerticalAlignment(JLabel.TOP); } return l; } static public int vstackWithSpacing_default = 10; static public JPanel vstackWithSpacing(final List parts) { return vstackWithSpacing(parts, vstackWithSpacing_default); } static public JPanel vstackWithSpacing(final List parts, final int spacing) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets = new Insets(spacing / 2, 0, spacing / 2, 0); smartAddWithLayout(panel, gbc, toObjectArray(nonNulls(parts))); gbc.weighty = 1; gbc.insets = new Insets(0, 0, 0, 0); panel.add(jrigid(), gbc); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new GridBagLayout);\r\n new GridBagConstraints gbc..."; } }); } static public JPanel vstackWithSpacing(Component... parts) { return vstackWithSpacing(asList(parts), vstackWithSpacing_default); } static public JPanel vstackWithSpacing(int spacing, Component... parts) { return vstackWithSpacing(asList(parts), spacing); } static public JButton renameButton(JComponent c, String name) { JButton b = first(childrenOfType(c, JButton.class)); if (b != null) b.setText(name); return b; } static public JButton renameButton(JComponent c, String oldName, String newName) { JButton b = findButton(c, oldName); if (b != null) b.setText(newName); return b; } static public String showFormSubmitButtonName() { return "Submit"; } static public int indexOfSpaceEtc(String s) { int n = l(s); for (int i = 0; i < n; i++) if (isSpace(s.charAt(i))) return i; return -1; } static public List words2(String s) { List l = new ArrayList(); int n = l(s); for (int i = 0; i < n; ) { int j = i; while (j < n && isLetterOrDigit(s.charAt(j))) ++j; if (j > i) l.add(substring(s, i, j)); while (j < n && !isLetterOrDigit(s.charAt(j))) ++j; i = j; } return l; } static public List dropHTMLComments(List tok) { List l = new ArrayList(); for (int idx = 0; idx < l(tok); idx++) { String t = tok.get(idx); if (even(idx)) { int i; while ((i = t.indexOf("", i + 4); t = substring(t, 0, i) + substring(t, j + 3); } } l.add(t); } return l; } static public Set setMinus(Set set, Object... stuff) { Set s2 = cloneSet(set); for (Object o : stuff) s2.remove(o); return s2; } static public Set mergeSets(Collection... l) { return joinSets(l); } static public Set allNonStaticNonTransientFields(Object o) { TreeSet fields = new TreeSet(); Class _c = _getClass(o); do { for (Field f : _c.getDeclaredFields()) if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) fields.add(f.getName()); _c = _c.getSuperclass(); } while (_c != null); return fields; } static public String snippetRawURL(String snippetID) { return snippetRawURL(snippetID, null); } static public String snippetRawURL(String snippetID, String contentType) { return "https://botcompany.de/serve/" + psI(snippetID) + htmlQuery("ct", contentType); } static public Matcher regexp(String pat, String s) { return regexp(compileRegexp(pat), unnull(s)); } static public Matcher regexp(java.util.regex.Pattern pat, String s) { return pat.matcher(unnull(s)); } static public java.util.regex.Pattern regexp(String pat) { return compileRegexp(pat); } static public Integer find3_levenWithSwapsDistance(String pat, String input) { List tokPat = parse3_cachedPattern(pat); List tok = parse3_cachedInput(input); int end = tok.size() - tokPat.size() + 1; Integer min = null; for (int idx = 0; idx < end; idx += 2) { int score = 0; for (int i = 1; i < tokPat.size(); i += 2) { String p = tokPat.get(i), t = tok.get(idx + i); score += levenWithSwapsIC(p, t); } min = min_withNull(min, score); } return min; } static public Integer min_withNull(Integer a, Integer b) { return a == null ? b : b == null ? a : (Integer) min(a, b); } static public List splitAtMinus(String s) { return trimAll(asList(s.split("\\-"))); } static public Integer parseHourAndOptionalMinutesToMinutes(String s) { List l = trimAll(splitAtColon(s)); if (empty(l)) return null; int minute = parseInt(first(l)) * 60; if (l(l) > 1) minute += parseInt(second(l)); return minute; } static public Collection asCollection(Iterable l) { return l == null ? null : l instanceof Collection ? ((Collection) l) : asList(l); } static public A copyFields(Object x, A y, String... fields) { if (empty(fields)) { Map map = objectToMap(x); for (String field : map.keySet()) setOpt(y, field, map.get(field)); } else for (String field : fields) { Object o = getOpt(x, field); if (o != null) setOpt(y, field, o); } return y; } static public A copyFields(Object x, A y, Collection fields) { return copyFields(x, y, asStringArray(fields)); } static public Map nuEmptyObject_cache = newDangerousWeakHashMap(); static public A nuEmptyObject(Class c) { try { Constructor ctr; synchronized (nuEmptyObject_cache) { ctr = nuEmptyObject_cache.get(c); if (ctr == null) { nuEmptyObject_cache.put(c, ctr = nuEmptyObject_findConstructor(c)); makeAccessible(ctr); } } try { return (A) ctr.newInstance(); } catch (InstantiationException e) { if (empty(e.getMessage())) if ((c.getModifiers() & Modifier.ABSTRACT) != 0) throw fail("Can't instantiate abstract class " + className(c), e); else throw fail("Can't instantiate " + className(c), e); else throw rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static public Constructor nuEmptyObject_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (m.getParameterTypes().length == 0) return m; throw fail("No default constructor declared in " + c.getName()); } static public int hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static public int indexOfIC_underscore(String a, String b) { int la = l(a), lb = l(b); if (la < lb) return -1; int n = la - lb; elsewhere: for (int i = 0; i <= n; i++) { for (int j = 0; j < lb; j++) { char c2 = b.charAt(j); if (c2 == '_' || eqic(c2, a.charAt(i + j))) { } else continue elsewhere; } return i; } return -1; } static public Object dm_os() { { Object __1 = vm_generalMap_get("stefansOS"); if (__1 != null) return __1; } return creator(); } static public String dropAfterSubstring(String s, String b) { return substring(s, 0, smartIndexOf(s, b)); } static public String jsonEncode_breakAtLevel1(Object o) { StringBuilder buf = new StringBuilder(); jsonEncode_breakAtLevel1(o, buf, 1); return str(buf); } static public void jsonEncode_breakAtLevel1(Object o, StringBuilder buf, int level) { if (o == null) buf.append("null"); else if (o instanceof String) buf.append(quote((String) o)); else if (o instanceof Number || o instanceof Boolean) buf.append(o); else if (o instanceof Map) { Map map = (Map) o; buf.append("{"); boolean first = true; for (Object key : keys(map)) { if (first) first = false; else buf.append(","); if (level == 1) buf.append("\n "); buf.append(quote((String) key)); buf.append(":"); jsonEncode_breakAtLevel1(map.get(key), buf, level + 1); } if (level == 1) buf.append("\n"); buf.append("}"); } else if (o instanceof Collection) { Collection l = (Collection) o; buf.append("["); boolean first = true; for (Object element : l) { if (first) first = false; else buf.append(","); if (level == 1) buf.append("\n "); jsonEncode_breakAtLevel1(element, buf, level + 1); } if (level == 1) buf.append("\n"); buf.append("]"); } else throw fail("Unknown object for JSON encoding: " + className(o)); } static public HashSet mapToHashSet(Object f, Iterable l) { HashSet x = new HashSet(l(l)); if (l != null) for (Object o : l) x.add(callF(f, o)); return x; } static public HashSet mapToHashSet(IF1 f, Iterable l) { return mapToHashSet((Object) f, l); } static public Producer javaTokC_noMLS_iterator(final String s) { return javaTokC_noMLS_iterator(s, 0); } static public Producer javaTokC_noMLS_iterator(final String s, final int startIndex) { return new Producer() { final public int l = s.length(); public int i = startIndex; public String next() { if (i >= l) return null; int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) return null; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else ++j; String t = quickSubstring(s, i, j); i = j; return t; } }; } static public Producer javaTokC_noMLS_onReader(final BufferedReader r) { final class X implements Producer { public StringBuilder buf = new StringBuilder(); public char c, d, e = 'x'; public X() { nc(); nc(); nc(); } public void nc() { try { c = d; d = e; if (e == '\0') return; int i = r.read(); e = i < 0 ? '\0' : i == '\0' ? '_' : (char) i; } catch (Exception __e) { throw rethrow(__e); } } public void ncSave() { if (c != '\0') { buf.append(c); nc(); } } public String next() { while (c != '\0') { if (c == ' ' || c == '\t' || c == '\r' || c == '\n') nc(); else if (c == '/' && d == '*') { do nc(); while (c != '\0' && !(c == '*' && d == '/')); nc(); nc(); } else if (c == '/' && d == '/') { do nc(); while (c != '\0' && "\r\n".indexOf(c) < 0); } else break; } if (c == '\0') return null; if (c == '\'' || c == '"') { char opener = c; ncSave(); while (c != '\0') { if (c == opener || c == '\n') { ncSave(); break; } else if (c == '\\') { ncSave(); ncSave(); } else ncSave(); } } else if (Character.isJavaIdentifierStart(c)) do ncSave(); while (Character.isJavaIdentifierPart(c) || c == '\''); else if (Character.isDigit(c)) { do ncSave(); while (Character.isDigit(c)); if (c == 'L') ncSave(); } else ncSave(); String t = buf.toString(); buf.setLength(0); return t; } } return new X(); } static public String unquoteUsingCharArray(String s, char[] buf) { if (s == null) return null; if (startsWith(s, '[')) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i + 1, s.length() - i - 1); } } if (s.length() > 1) { char c = s.charAt(0); if (c == '\"' || c == '\'') { int l = endsWith(s, c) ? s.length() - 1 : s.length(); if (l > buf.length) return unquote(s); int n = 0; for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } buf[n++] = (char) Integer.parseInt(code, 8); continue; } switch(nextChar) { case '\"': ch = '\"'; break; case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\'': ch = '\''; break; case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt("" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); char[] x = Character.toChars(code); int lx = x.length; for (int j = 0; j < lx; j++) buf[n++] = x[j]; i += 5; continue; default: ch = nextChar; } i++; } buf[n++] = ch; } return new String(buf, 0, n); } } return s; } static public boolean structure_isMarker(String s, int i, int j) { if (i >= j) return false; if (s.charAt(i) != 'm') return false; ++i; while (i < j) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static public String internIfLongerThan(String s, int l) { return s == null ? null : l(s) >= l ? intern(s) : s; } static public char unquoteCharacter(String s) { assertTrue(s.startsWith("'") && s.length() > 1); return unquote("\"" + s.substring(1, s.endsWith("'") ? s.length() - 1 : s.length()) + "\"").charAt(0); } static public BigInteger parseBigInt(String s) { return new BigInteger(s); } static public float parseFloat(String s) { return Float.parseFloat(s); } static public boolean isLongConstant(String s) { if (!s.endsWith("L")) return false; s = s.substring(0, l(s) - 1); return isInteger(s); } static public List parseList(String s) { return (List) safeUnstructure(s); } static public List synchroLinkedList() { return Collections.synchronizedList(new LinkedList()); } static public boolean[] boolArrayFromBytes(byte[] a, int n) { boolean[] b = new boolean[n]; int m = min(n, l(a) * 8); for (int i = 0; i < m; i++) b[i] = (a[i / 8] & 1 << (i & 7)) != 0; return b; } static public A nuStubInnerObject(Class c) { return nuStubInnerObject(c, null); } static public A nuStubInnerObject(Class c, Object classFinder) { try { Class outerType = getOuterClass(c, classFinder); Constructor m = c.getDeclaredConstructor(outerType); makeAccessible(m); return (A) m.newInstance(new Object[] { null }); } catch (Exception __e) { throw rethrow(__e); } } static public void setOptAllDyn_pcall(DynamicObject o, Map fields) { if (fields == null || o == null) return; HashMap fieldMap = instanceFieldsMap(o); for (Map.Entry e : fields.entrySet()) { try { String field = e.getKey(); Object val = e.getValue(); Field f = fieldMap.get(field); if (f != null) smartSet(f, o, val); else { o.fieldValues = syncMapPut2_createLinkedHashMap(o.fieldValues, intern(field), val); } } catch (Throwable __e) { _handleException(__e); } } } static public void setOptAll_pcall(Object o, Map fields) { if (fields == null) return; for (String field : keys(fields)) try { setOpt(o, field, fields.get(field)); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } static public void setOptAll_pcall(Object o, Object... values) { warnIfOddCount(values); for (int i = 0; i + 1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i + 1]; try { setOpt(o, field, value); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } } static public void fixOuterRefs(Object o) { try { if (o == null) return; Field[] l = thisDollarOneFields(o.getClass()); if (l.length <= 1) return; Object father = null; for (Field f : l) { father = f.get(o); if (father != null) break; } if (father == null) return; for (Field f : l) f.set(o, father); } catch (Exception __e) { throw rethrow(__e); } } static public void setDynObjectValue(DynamicObject o, String field, Object value) { o.fieldValues = syncMapPut2_createLinkedHashMap(o.fieldValues, field, value); } static public String intern(String s) { return fastIntern(s); } static public void pcallOpt_noArgs(Object o, String method) { try { callOpt_noArgs(o, method); } catch (Throwable __e) { _handleException(__e); } } static public int[] toIntArray(Collection l) { int[] a = new int[l(l)]; int i = 0; if (a.length != 0) for (int x : l) a[i++] = x; return a; } static public double[] toDoubleArray(Collection l) { double[] a = new double[l(l)]; int i = 0; if (a.length != 0) for (double x : l) a[i++] = x; return a; } static public boolean jmatch(String pat, String s) { return jmatch(pat, s, null); } static public boolean jmatch(String pat, String s, Matches matches) { if (s == null) return false; return jmatch(pat, javaTok(s), matches); } static public boolean jmatch(String pat, List toks) { return jmatch(pat, toks, null); } static public boolean jmatch(String pat, List toks, Matches matches) { List tokpat = javaTok(pat); String[] m = match2(tokpat, toks); if (m == null) return false; else { if (matches != null) matches.m = m; return true; } } static public boolean warn_on = true; static public ThreadLocal> warn_warnings = new ThreadLocal(); static public void warn(String s) { if (warn_on) print("Warning: " + s); } static public void warn(String s, List warnings) { warn(s); if (warnings != null) warnings.add(s); addToCollection(warn_warnings.get(), s); } static public Object vmBus_query(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); { Object __1 = pcallFAll_returnFirstNotNull(vm_busListeners_live(), msg, arg); if (__1 != null) return __1; } return pcallFAll_returnFirstNotNull(vm_busListenersByMessage_live().get(msg), msg, arg); } static public Object vmBus_query(String msg) { return vmBus_query(msg, (Object) null); } static public List getJavaModifiers_list = litlist("static", "abstract", "public", "private", "protected", "final", "native", "volatile", "synchronized", "transient"); static public List getJavaModifiers() { return getJavaModifiers_list; } static public ThreadLocal assertVerbose_value = new ThreadLocal(); static public void assertVerbose(boolean b) { assertVerbose_value.set(b); } static public boolean assertVerbose() { return isTrue(assertVerbose_value.get()); } static public A assertEqualsVerbose(Object x, A y) { assertEqualsVerbose((String) null, x, y); return y; } static public A assertEqualsVerbose(String msg, Object x, A y) { if (!eq(x, y)) { throw fail((msg != null ? msg + ": " : "") + "expected: " + x + ", got: " + y); } else print("OK" + (empty(msg) ? "" : " " + msg) + ": " + (x)); return y; } static public void assertEqualsVerbose(Scorer scorer, Object x, Object y) { if (scorer == null) { assertEqualsVerbose(x, y); return; } if (!eq(x, y)) { print((y) + " != " + (x)); scorer.add(false); } else { print("OK: " + (x)); scorer.add(true); } } static public Cache isLinux_cache = new Cache<>(() -> isLinux_load()); static public boolean isLinux() { return isLinux_cache.get(); } static public Boolean isLinux_load() { return !isWindows() && !isMac() && !isAndroid(); } static public boolean isJavaxCompilableSnippetType(int type) { return isJavaxCompilableSnippetTypeExceptInclude(type) || type == javaxIncludeSnippetType(); } static public List hotwire_collectJars(File jar) { List libIDs = hotwire_libraryIDsFromJar_deleteJarOnFail(jar); List files = ll(jar); for (String libID : libIDs) files.add(loadLibraryOrSrcLib(libID)); return files; } static public Pair compileSnippetThroughServer(String progID) { String transpiledSrc = getServerTranspiled2(progID); String md5 = md5(transpiledSrc + "\n" + progID); File jar = CompilerBot.getJarFile(md5); if (jar == null || jar.length() <= 22) { byte[] jarData = null; boolean dontLoad = false; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) { dontLoad = true; File jar2 = rl.getSnippetJar(progID, transpiledSrc); if (jar2 != null) return pair(jar2, transpiledSrc); } if (!dontLoad) { try { jarData = loadBinaryPage("http://www.botcompany.de/jar/" + psI(progID) + "?md5=" + md5(transpiledSrc)); } catch (Throwable __e) { _handleException(__e); } } if (!isJAR(jarData)) { if (jarData != null) { print(bytesToHex(takeFirstOfByteArray(8, jarData))); print("fallback to CompilerBot: " + fromUtf8(takeFirstOfByteArray(80, jarData))); } return CompilerBot.compileSnippet2(progID); } saveBinaryFile(jar, jarData); } return pair(jar, transpiledSrc); } static public List filesEndingWith(File dir, String suffix) { return listFilesWithSuffix(dir, suffix); } static public List filesEndingWith(List l, String suffix) { List out = new ArrayList(); for (File f : unnull(l)) if (!f.isDirectory() && (empty(suffix) || endsWithIgnoreCase(f.getName(), suffix))) out.add(f); return out; } static public List filesEndingWith(String suffix, File dir) { return filesEndingWith(dir, suffix); } static public String addPrefixIfNotEmpty2(String prefix, String s) { return empty(s) ? "" : addPrefix(prefix, s); } static public File toFile(Object o) { if (o instanceof File) return (File) o; if (o instanceof String) return new File((String) o); throw fail("Not a file: " + o); } static public File getCanonicalFile(File f) { try { return f == null ? null : f.getCanonicalFile(); } catch (Exception __e) { throw rethrow(__e); } } static public boolean isSymLink(File f) { return f != null && Files.isSymbolicLink(toPath(f)); } static public ClassLoader getClassLoader(Object o) { return o == null ? null : _getClass(o).getClassLoader(); } static public int parseFirstInt(String s) { return parseInt(jextract("", s)); } static public int parseFirstInt(Iterable l) { return parseInt(firstIntegerString(l)); } static public String javaVersion() { return System.getProperty("java.version"); } static public String defaultVMArgs() { return javaxDefaultVMArgs(); } static public void setDefaultVMArgs(String args) { String oldArgs = javaxDefaultVMArgs(); args = trim(args); if (neq(unnull(oldArgs), unnull(args))) { print(); print("Changing default VM arguments from"); print(" " + oldArgs); print("to"); print(" " + args); print(); saveTextFile(javaxDataDir("default-vm-args"), nullIfEmpty(args)); } } static public boolean isDollarVar(String s) { return startsWith(s, '$') && l(s) > 1; } static public void listAdd(Collection c, A a) { if (c != null) c.add(a); } static public boolean neqGet(List l, int i, Object o) { return neq(get(l, i), o); } static public int tok_findEndOfStatement(List tok, int i) { if (eq(get(tok, i), "{")) return findEndOfBlock(tok, i); int j = i; boolean special = false; while (j < l(tok) && neq(tok.get(j), ";")) { String t = get(tok, j); if (eqOneOf(t, "for", "if")) special = true; if (eqOneOf(t, "{", "(")) { j = findEndOfBracketPart(tok, j) + 1; if (special && eq(t, "{")) return j - 1; } else j += 2; } return j + 1; } static public void tokPrepend_reTok(List tok, int i, String s) { tokPrepend(tok, i, s); reTok(tok, i, i + 1); } static public String joinLines(List lines) { return fromLines(lines); } static public String joinLines(String glue, String text) { return join(glue, toLines(text)); } static public String javaDropComments(String s) { return javaDropAllComments(s); } static public boolean hasSuperclassShortNamed(Object o, String name) { Class c = _getClass(o); while (c != null) if (shortClassNameIs(c, name)) return true; else c = c.getSuperclass(); return false; } static public List dm_moduleIDs() { return dm_listModuleIDs(); } static public Object dm_getStem(Object moduleOrID) { if (isString(moduleOrID) && isIdentifier(((String) moduleOrID))) moduleOrID = dm_getService(((String) moduleOrID)); if (isStringOrIntOrLong(moduleOrID)) return dm_getStemByID(moduleOrID); return or(getOpt(dm_getModule(moduleOrID), "_host"), moduleOrID); } static public AlphanumComparator alphaNumComparator_instance; static public Comparator alphaNumComparator() { if (alphaNumComparator_instance == null) alphaNumComparator_instance = new AlphanumComparator(); return alphaNumComparator_instance; } static public String nullIfEmpty(String s) { return isEmpty(s) ? null : s; } static public Map nullIfEmpty(Map map) { return isEmpty(map) ? null : map; } static public List nullIfEmpty(List l) { return isEmpty(l) ? null : l; } static public boolean newButton_autoToolTip = true; static public JButton newButton(final String text, final Object action) { return swing(new F0() { public JButton get() { try { String text2 = dropPrefix("[disabled] ", text); final JButton btn = new JButton(text2); if (l(text2) < l(text)) btn.setEnabled(false); if (newButton_autoToolTip) { btn.setToolTipText(btn.getText()); } if (action != null) btn.addActionListener(actionListener(action, btn)); return btn; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S text2 = dropPrefix(\"[disabled] \", text);\r\n final JButton btn = new JButt..."; } }); } static public A swingNu(final Class c, final Object... args) { return swingConstruct(c, args); } static public Object[] asArray(List l) { return toObjectArray(l); } static public A[] asArray(Class type, List l) { return (A[]) l.toArray((Object[]) Array.newInstance(type, l.size())); } static public boolean isMenuSeparatorIndicator(Object o) { return eqOneOf(o, "***", "---", "===", ""); } static public boolean isRunnableX(Object o) { if (o == null) return false; if (o instanceof String) return hasMethod(mc(), (String) o); return o instanceof Runnable || hasMethod(o, "get"); } static public boolean jmenuItem_newThreads = false; static public JMenuItem jmenuItem(final String text) { return jMenuItem(text, null); } static public JMenuItem jmenuItem(final String text, final Object r) { return swing(new F0() { public JMenuItem get() { try { Pair p = jmenu_autoMnemonic(dropPrefix("[disabled] ", text)); JMenuItem mi = new JMenuItem(p.a); if (startsWith(text, "[disabled] ")) disableMenuItem(mi); if (p.b != 0) mi.setMnemonic(p.b); mi.addActionListener(jmenuItem_newThreads ? actionListenerInNewThread(r) : actionListener(r)); return mi; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Pair p = jmenu_autoMnemonic(dropPrefix(\"[disabled] \", text));\r\n JM..."; } }); } static public A bindLiveValueListenerToComponent(A component, final LiveValue lv, final Runnable listener) { if (lv != null) bindToComponent(component, new Runnable() { public void run() { try { lv.onChangeAndNow(listener); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef bindLiveValueListenerToComponent_debug\r\n print(\"bindLiveValueL..."; } }, new Runnable() { public void run() { try { lv.removeOnChangeListener(listener); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "lv.removeOnChangeListener(listener)"; } }); return component; } static public boolean isCurlyBracketed(String s) { return isCurlyBraced(s); } static public A setEnabled(A c, boolean enable) { if (c != null) { swing(new Runnable() { public void run() { try { c.setEnabled(enable); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setEnabled(enable);"; } }); } return c; } static public A setEnabled(boolean enable, A c) { return setEnabled(c, enable); } static public String unCurlyBracket(String s) { return tok_unCurlyBracket(s); } static public boolean setText_opt = true; static public A setText(A c, Object text) { setText((JComponent) c, text); return c; } static public A setText(final A c, Object text) { final String s = strUnnull(text); { swing(new Runnable() { public void run() { try { c.getEditor().setItem(s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.getEditor().setItem(s);"; } }); } return c; } static public void setText(JLabel c, Object text) { setText((JComponent) c, text); } static public JButton setText(JButton c, Object text) { setText((JComponent) c, jlabel_textAsHTML_center_ifNeeded(strUnnull(text))); return c; } static public A setText(final A c, Object text) { if (c == null) return null; final String s = strUnnull(text); { swing(new Runnable() { public void run() { try { if (!setText_opt || neq(callOpt(c, "getText"), s)) call(c, "setText", s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!setText_opt || neq(callOpt(c, \"getText\"), s))\r\n call(c, \"setText\", s);"; } }); } return c; } static public int preferredWidth(Component c) { return c == null ? 0 : getPreferredSize(c).width; } static public String formatDate() { return formatDate(now()); } static public String formatDate(long timestamp) { return timestamp == 0 ? "-" : str(new Date(timestamp)); } static public String formatDate(long timestamp, String format, TimeZone tz) { return simpleDateFormat(format, tz).format(timestamp); } static public File dirOfFile(File f) { return f == null ? null : f.getParentFile(); } static public int localYear() { return localYear(now()); } static public int localYear(long time) { return parseInt(simpleDateFormat_local("yyyy").format(time)); } static public String padLeft(String s, char c, int n) { return rep(c, n - l(s)) + s; } static public String padLeft(String s, int n) { return padLeft(s, ' ', n); } static public int localMonth(long time) { return parseInt(simpleDateFormat_local("MM").format(time)); } static public int localMonth() { return localMonth(now()); } static public int localDayOfMonth(long time) { return parseInt(simpleDateFormat_local("dd").format(time)); } static public int localDayOfMonth() { return localDayOfMonth(now()); } static public String hijackPrint(Object r) { final StringBuilder buf = new StringBuilder(); Object old = interceptPrintInThisThread(new F1() { public Boolean get(String s) { buf.append(s); return false; } }); try { callF(r); return str(buf); } finally { interceptPrintInThisThread(old); } } static public A pnl(String prefix, A l) { printNumberedLines(prefix, l); return l; } static public A pnl(A l) { printNumberedLines(l); return l; } static public A pnl(A map) { printNumberedLines(map); return map; } static public A pnl(String prefix, A map) { printNumberedLines(prefix, map); return map; } static public A[] pnl(A[] a) { printNumberedLines(a); return a; } static public String pnl(String s) { printNumberedLines(lines(s)); return s; } static public MultiSet pnl(MultiSet ms) { pnl(ms == null ? null : ms.asMap()); return ms; } static public MultiMap pnl(MultiMap mm) { pnl(mm == null ? null : mm.asMap()); return mm; } static public Map> multiMapToMap(MultiMap m) { return m == null ? null : m.data; } static public A findWhere(Collection c, Object... data) { if (c != null) for (A x : c) if (checkFields(x, data)) return x; return null; } static public boolean isOK(String s) { s = trim(s); return swic(s, "ok ") || eqic(s, "ok") || matchStart("ok", s); } static public String sendOpt(String bot, String text, Object... args) { return sendToLocalBotOpt(bot, text, args); } static public boolean isMainProgram() { return creator() == null; } static public void cleanKill() { cleanKillVM(); } static public String dbBotName(String progIDWithCase) { return fsI_flex(progIDWithCase) + " Concepts"; } static public Android3 methodsBot2(String name, final Object receiver, final List exposedMethods) { return methodsBot2(name, receiver, exposedMethods, null); } static public Android3 methodsBot2(String name, final Object receiver, final List exposedMethods, final Lock lock) { Android3 android = new Android3(); android.greeting = name; android.console = false; android.responder = new Responder() { public String answer(String s, List history) { return exposeMethods2(receiver, s, exposedMethods, lock); } }; return makeBot(android); } static public List db_standardExposedMethods_list = ll("xlist", "xnew", "xset", "xdelete", "xget", "xclass", "xfullgrab", "xshutdown", "xchangeCount", "xcount"); static public List db_standardExposedMethods() { return db_standardExposedMethods_list; } static public List listFilesNotDirs(String dir) { return listFilesOnly(dir); } static public List listFilesNotDirs(File... dirs) { return listFilesOnly(dirs); } static public int matcherInt(Matcher m, int i) { return parseInt(m.group(i)); } static public long timestampFromYMDH(int y, int m, int d, int h) { return new GregorianCalendar(y, m - 1, d, h, 0).getTimeInMillis(); } static public List sortByMap_inPlace(List l, Map map) { sort(l, mapComparator(map)); return l; } static public boolean defaultAgeBasedBackupRetentionStrategy_shouldKeep(double age, double lastAge) { if (age <= 0.5) return true; if (age <= 7 && age >= lastAge + 1) return true; if (age <= 28 && age >= lastAge + 7) return true; if (age >= lastAge + 365.0 / 12) return true; return false; } static public String dropFrom(String s, String x) { if (s == null) return null; int i = s.indexOf(x); if (i < 0) return s; return substring(s, 0, i); } static public boolean directoryIsEmpty(File f) { return !fileExists(f) || isDirectory(f) && empty(listFiles(f)); } static public void zip2dir(File inZip, File outDir) { zip2dir(inZip, outDir, ""); } static public void zip2dir(File inZip, File outDir, String prefix) { try { if (prefix.length() != 0 && !prefix.endsWith("/")) prefix += "/"; ZipFile zipFile = new ZipFile(inZip); try { Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry) entries.nextElement(); if (entry.isDirectory()) continue; if (!entry.getName().startsWith(prefix)) continue; File outFile = new File(outDir, entry.getName()); System.out.println("Unzipping " + entry.getName() + " to " + outFile.getAbsolutePath()); stream2file(zipFile.getInputStream(entry), outFile); } } finally { _close(zipFile); } } catch (Exception __e) { throw rethrow(__e); } } static public RandomAccessFile randomAccessFileForReading(File path) { try { return newRandomAccessFile(path, "r"); } catch (Exception __e) { throw rethrow(__e); } } static public long raf_findBeginningOfLine(RandomAccessFile raf, long pos, int bufSize) { try { byte[] buf = new byte[bufSize]; while (pos > 0) { long start = Math.max(pos - bufSize, 0); raf.seek(start); raf.readFully(buf, 0, (int) Math.min(pos - start, bufSize)); int idx = lastIndexOf_byteArray(buf, (byte) '\n'); if (idx >= 0) return start + idx + 1; pos = start; } return 0; } catch (Exception __e) { throw rethrow(__e); } } static public long raf_findEndOfLine(RandomAccessFile raf, long pos, int bufSize) { try { byte[] buf = new byte[bufSize]; long length = raf.length(); while (pos < length) { raf.seek(pos); raf.readFully(buf, 0, (int) Math.min(length - pos, bufSize)); int idx = indexOf_byteArray(buf, (byte) '\n'); if (idx >= 0) return pos + idx + 1; pos += bufSize; } return length; } catch (Exception __e) { throw rethrow(__e); } } static public byte[] raf_readFilePart(RandomAccessFile raf, long start, int l) { try { byte[] buf = new byte[l]; raf.seek(start); raf.readFully(buf); return buf; } catch (Exception __e) { throw rethrow(__e); } } static public A assertLessThan(A a, A b) { assertTrue(cmp(b, a) < 0); return b; } static public A assertBiggerThan(A a, A b) { assertTrue(cmp(b, a) > 0); return b; } static public String trimJoinSubList(List l, int i, int j) { return trim(join(subList(l, i, j))); } static public String trimJoinSubList(List l, int i) { return trim(join(subList(l, i))); } static public A componentPopupMenuItem(A c, final String name, final Object action) { componentPopupMenu(c, new VF1() { public void get(JPopupMenu menu) { try { addMenuItem(menu, name, action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, name, action);"; } }); return c; } static public void componentPopupMenuItem(JComponent c, final JMenuItem menuItem) { componentPopupMenu(c, new VF1() { public void get(JPopupMenu menu) { try { addMenuItem(menu, menuItem); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, menuItem);"; } }); } static public Set vm_generalWeakSet(Object name) { synchronized (get(javax(), "generalMap")) { Set set = (Set) (vm_generalMap_get(name)); if (set == null) vm_generalMap_put(name, set = newWeakHashSet()); return set; } } static public JPanel jpanel(LayoutManager layout) { return swingNu(JPanel.class, layout); } static public JPanel jpanel() { return swingNu(JPanel.class); } static public LayoutManager layoutManagerFromFunction(final Object layouter) { return new AbstractLayoutManager() { public void layoutContainer(Container parent) { Object size = pcallF(layouter, parent); if (size instanceof Dimension) preferredSize = ((Dimension) size); else if (size instanceof Pair) { preferredSize = (Dimension) ((Pair) size).a; minimumSize = (Dimension) ((Pair) size).b; } } }; } static public A addAllComponents(final A c, final List components) { if (nempty(components)) { swing(new Runnable() { public void run() { try { for (Component x : components) c.add(x); revalidate(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (Component x : components)\r\n c.add(x);\r\n revalidate(c);"; } }); } return c; } static public A childOfType(Component c, Class theClass) { return first(childrenOfType(c, theClass)); } static public A childOfType(Class theClass, Component c) { return childOfType(c, theClass); } static public Rectangle rectangleUnion(Rectangle a, Rectangle b) { return a == null ? b : b == null ? a : a.union(b); } static public boolean isEditableComboBox(final JComboBox cb) { return cb != null && swing(new F0() { public Boolean get() { try { return cb.isEditable(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret cb.isEditable();"; } }); } static public void logQuotedWithTime(String s) { logQuotedWithTime(standardLogFile(), s); } static public void logQuotedWithTime(File logFile, String s) { logQuoted(logFile, logQuotedWithTime_format(s)); } static public void logQuotedWithTime(String logFile, String s) { logQuoted(logFile, logQuotedWithTime_format(s)); } static public String logQuotedWithTime_format(String s) { return (now()) + " " + s; } static public JComponent wrap(Object swingable) { return _recordNewSwingComponent(wrap_2(swingable)); } static public JComponent wrap_2(Object swingable) { if (swingable == null) return null; JComponent c; if (swingable instanceof Component) c = componentToJComponent(((Component) swingable)); else c = componentToJComponent((Component) callOpt(swingable, "swing")); if (c instanceof JTable || c instanceof JList || c instanceof JTextArea || c instanceof JEditorPane || c instanceof JTextPane || c instanceof JTree) return jscroll(c); return c == null ? jlabel(str(swingable)) : c; } static public JTextArea wrappedTextArea(final JTextArea ta) { enableWordWrapForTextArea(ta); return ta; } static public JTextArea wrappedTextArea() { return wrappedTextArea(jtextarea()); } static public JTextArea wrappedTextArea(String text) { JTextArea ta = wrappedTextArea(); setText(ta, text); return ta; } static public JScrollPane jscroll(final Component c) { return swing(new F0() { public JScrollPane get() { try { return new JScrollPane(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret new JScrollPane(c);"; } }); } static public int withMargin_defaultWidth = 6; static public JPanel withMargin(Component c) { return withMargin(withMargin_defaultWidth, c); } static public JPanel withMargin(int w, Component c) { return withMargin(w, w, c); } static public JPanel withMargin(int w, int h, Component c) { return withMargin(w, h, w, h, c); } static public JPanel withMargin(final int top, final int left, final int bottom, final int right, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static public boolean vmBus_anyFalse(String msg, Object... args) { return contains(vmBus_queryAll(msg, args), false); } static public String getSnippetTitleOpt(String s) { return isSnippetID(s) ? getSnippetTitle(s) : s; } static public JInternalFrame showForm_makeInternalFrame(JDesktopPane desktop, String title, JPanel panel) { JInternalFrame f = addInternalFrame(desktop, title, withMargin(panel)); minInternalFrameWidth(f, 400); packInternalFrameVertically(f); centerInternalFrame(f); return f; } static public JFrame handleEscapeKey(final JFrame frame) { KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); frame.getRootPane().registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { frame.dispose(); } }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); return frame; } static public JFrame minFrameWidth(JFrame frame, int w) { if (frame != null && frame.getWidth() < w) frame.setSize(w, frame.getHeight()); return frame; } static public JFrame minFrameWidth(int w, JFrame frame) { return minFrameWidth(frame, w); } static public JFrame showPackedFrame(String title, Component contents) { return packFrame(showFrame(title, contents)); } static public JFrame showPackedFrame(Component contents) { return packFrame(showFrame(contents)); } static public int showForm_leftWidth_safetyMargin = 10; static public int showForm_leftWidth(List> l) { forEachLevel2(l, x -> vmBus_send("updateLayoutNow", x)); int minW = 0; for (List row : l) minW = max(minW, getMinimumSize(first(row)).width); return minW + or((Integer) vmBus_query("formSafetyMargin"), showForm_leftWidth_safetyMargin); } static public JPanel westAndCenter(final Component w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.WEST, wrap(w)); panel.add(BorderLayout.CENTER, wrap(c)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.WEST..."; } }); } static public int withRightMargin_defaultWidth = 6; static public JPanel withRightMargin(Component c) { return withRightMargin(withRightMargin_defaultWidth, c); } static public JPanel withRightMargin(final int w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, w)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static public A jMinWidthAtLeast(int w, final A c) { if (c == null) return null; return swing(new F0() { public A get() { try { Dimension size = c.getMinimumSize(); Dimension d = new Dimension(max(w, size.width), size.height); c.setMinimumSize(d); return jPreferWidth(d.width, c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Dimension size = c.getMinimumSize();\r\n Dimension d = new Dimension(max(w, ..."; } }); } static public void setComponentID(Component c, String id) { if (c != null) componentID_map.put(c, id); } static public List mapLL(Object f, Object... data) { return map(f, ll(data)); } static public Component wrapForSmartAdd(Object o) { if (o == null) return jpanel(); if (o instanceof String) return jlabel((String) o); return wrap(o); } static public Map humanizeFormLabel_replacements = litmap("id", "ID", "md5", "MD5"); static public String humanizeFormLabel(String s) { if (containsSpace(s)) return s; return firstToUpper(joinWithSpace(replaceElementsUsingMap(splitCamelCase(s), humanizeFormLabel_replacements)).replace("I D", "ID")); } static public boolean isRunnable(Object o) { return o instanceof Runnable || hasMethod(o, "get"); } static public void disposeInternalFrame(Component c) { final JInternalFrame f = getInternalFrame(c); if (f != null) { swing(new Runnable() { public void run() { try { vmBus_send("disposingInternalFrame", f); f.dispose(); setOpt(f, "lastFocusOwner", null); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "vmBus_send disposingInternalFrame(f);\r\n f.dispose();\r\n setOpt(f, lastFo..."; } }); } } static public void disposeFrame(final Component c) { disposeWindow(c); } static public void onEnterInAllTextFields(JComponent c, Object action) { if (action == null) return; for (Component tf : allChildren(c)) onEnterIfTextField(tf, action); } static public void onEnterInAllTextFields(List c, Object action) { for (Object o : unnull(c)) if (o instanceof JComponent) onEnterInAllTextFields((JComponent) o, action); } static public void clickButton(final JButton b) { if (b != null) { swing(new Runnable() { public void run() { try { if (b.isEnabled()) b.doClick(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (b.isEnabled())\r\n b.doClick();"; } }); } } static public A makeBold(final A c) { if (c != null) { swing(new Runnable() { public void run() { try { c.setFont(c.getFont().deriveFont(java.awt.Font.BOLD)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setFont(c.getFont().deriveFont(java.awt.Font.BOLD));"; } }); } return c; } static public JPanel smartAddWithLayout(JPanel panel, Object layout, List parts) { for (Object o : parts) panel.add(wrapForSmartAdd(o), layout); return panel; } static public JPanel smartAddWithLayout(JPanel panel, Object layout, Object... parts) { return smartAddWithLayout(panel, layout, asList(flattenArray2(parts))); } static public Component jrigid() { return javax.swing.Box.createRigidArea(new Dimension(0, 0)); } static public List childrenOfType(Component c, Class theClass) { List l = new ArrayList(); scanForComponents(c, theClass, l); return l; } static public List childrenOfType(Class theClass, Component c) { return childrenOfType(c, theClass); } static public JButton findButton(Component c, String name) { for (JButton b : childrenOfType(c, JButton.class)) if (eq(b.getText(), name)) return b; for (JButton b : childrenOfType(getFrame(c), JButton.class)) if (eq(b.getText(), name)) return b; return null; } static public JButton findButton(Component c) { return childOfType(c, JButton.class); } static public boolean isSpace(char c) { return " \t\r\n".indexOf(c) >= 0; } static public boolean isLetterOrDigit(char c) { return Character.isLetterOrDigit(c); } static public Set cloneSet(Set set) { if (set == null) return new HashSet(); synchronized (collectionMutex(set)) { Set s = similarEmptySet(set); s.addAll(set); return s; } } static public int levenWithSwapsIC(String s, String t) { if (s.equals(t)) return 0; int ls = s.length(), lt = t.length(); if (ls == 0) return lt; if (lt == 0) return ls; int[] vx = new int[lt + 1]; int[] v0 = new int[lt + 1]; int[] v1 = new int[lt + 1]; for (int i = 0; i < v0.length; i++) v0[i] = i; for (int i = 0; i < ls; i++) { v1[0] = i + 1; for (int j = 0; j < lt; j++) { int cost = equalsIgnoreCase(s.charAt(i), t.charAt(j)) ? 0 : 1; int d = min3(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost); if (i > 0 && j > 0 && equalsIgnoreCase(s.charAt(i), t.charAt(j - 1)) && equalsIgnoreCase(s.charAt(i - 1), t.charAt(j))) d = min(d, vx[j - 1] + 1); v1[j + 1] = d; } int[] v = vx; vx = v0; v0 = v1; v1 = v; } return v0[lt]; } static public Map componentID_map = weakHashMap(); static public String componentID(Component c) { return c == null ? null : componentID_map.get(c); } static public Object safeUnstructure(String s) { return unstructure(s, true); } static public Class getOuterClass(Class c) { return getOuterClass(c, null); } static public Class getOuterClass(Class c, Object classFinder) { try { String s = c.getName(); int i = s.lastIndexOf('$'); String name = substring(s, 0, i); if (classFinder != null) return (Class) callF(classFinder, name); return Class.forName(name); } catch (Exception __e) { throw rethrow(__e); } } static public HashMap instanceFieldsMap(Object o) { Class c = o.getClass(); HashMap map; synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } return map; } static public LinkedHashMap syncMapPut2_createLinkedHashMap(LinkedHashMap map, A key, B value) { if (key != null) if (value != null) { if (map == null) map = new LinkedHashMap(); synchronized (collectionMutex(map)) { map.put(key, value); } } else if (map != null) synchronized (collectionMutex(map)) { map.remove(key); } return map; } static public Map thisDollarOneFields_cache = newDangerousWeakHashMap(); static public Field[] thisDollarOneFields(Class c) { synchronized (thisDollarOneFields_cache) { Field[] l = thisDollarOneFields_cache.get(c); if (l == null) thisDollarOneFields_cache.put(c, l = thisDollarOneFields_uncached(c)); return l; } } static public Field[] thisDollarOneFields_uncached(Class c) { List fields = new ArrayList(); do { for (Field f : c.getDeclaredFields()) if (f.getName().equals("this$1")) fields.add(makeAccessible(f)); c = c.getSuperclass(); } while (c != null); return toArray(new Field[l(fields)], fields); } static public Method fastIntern_method; static public String fastIntern(String s) { try { if (s == null) return null; if (fastIntern_method == null) { fastIntern_method = findMethodNamed(javax(), "internPerProgram"); if (fastIntern_method == null) upgradeJavaXAndRestart(); } return (String) fastIntern_method.invoke(null, s); } catch (Exception __e) { throw rethrow(__e); } } static public Map> callOpt_noArgs_cache = newDangerousWeakHashMap(); static public Object callOpt_noArgs(Object o, String method) { try { if (o == null) return null; if (o instanceof Class) return callOpt(o, method); Class c = o.getClass(); HashMap map; synchronized (callOpt_noArgs_cache) { map = callOpt_noArgs_cache.get(c); if (map == null) map = callOpt_noArgs_makeCache(c); } Method m = map.get(method); return m != null ? m.invoke(o) : null; } catch (Exception __e) { throw rethrow(__e); } } static public HashMap callOpt_noArgs_makeCache(Class c) { HashMap map = new HashMap(); Class _c = c; do { for (Method m : c.getDeclaredMethods()) if (m.getParameterTypes().length == 0 && !reflection_isForbiddenMethod(m)) { makeAccessible(m); String name = m.getName(); if (!map.containsKey(name)) map.put(name, m); } _c = _c.getSuperclass(); } while (_c != null); callOpt_noArgs_cache.put(c, map); return map; } static public boolean addToCollection(Collection c, A a) { return c != null && c.add(a); } static public Object pcallFAll_returnFirstNotNull(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) { Object __1 = pcallF(f, args); if (__1 != null) return __1; } return null; } static public Object pcallFAll_returnFirstNotNull(Iterator it, Object... args) { while (it.hasNext()) { Object __2 = pcallF(it.next(), args); if (__2 != null) return __2; } return null; } public static boolean isWindows() { return System.getProperty("os.name").contains("Windows"); } static public boolean isMac() { return System.getProperty("os.name").toLowerCase().contains("mac"); } static public boolean isJavaxCompilableSnippetTypeExceptInclude(int type) { return isJavaxApplicationSnippetType(type) || isJavaxModuleSnippetType(type) || type == snippetType_dynModule(); } static public int javaxIncludeSnippetType() { return 42; } static public List hotwire_libraryIDsFromJar_deleteJarOnFail(File jar) { try { return hotwire_libraryIDsFromJar(jar); } catch (Throwable _e) { jar.delete(); throw rethrow(_e); } } static public byte[] isJAR_magic = bytesFromHex("504B0304"); static public boolean isJAR(byte[] data) { return byteArrayStartsWith(data, isJAR_magic); } static public boolean isJAR(File f) { return isJAR(loadBeginningOfBinaryFile(f, l(isJAR_magic))); } static public byte[] takeFirstOfByteArray(byte[] b, int n) { return subByteArray(b, 0, n); } static public byte[] takeFirstOfByteArray(int n, byte[] b) { return takeFirstOfByteArray(b, n); } static public List listFilesWithSuffix(File dir, String suffix) { List l = new ArrayList(); for (File f : listFiles(dir)) if (!f.isDirectory() && (empty(suffix) || endsWithIgnoreCase(f.getName(), suffix))) l.add(f); return l; } static public Path toPath(File f) { return f == null ? null : f.toPath(); } static public String firstIntegerString(Iterable c) { Iterator it = c.iterator(); while (it.hasNext()) { String s = it.next(); if (isInteger(s)) return s; } return null; } static public String javaxDefaultVMArgs() { File fileNew, fileOld; String text = loadTextFile(fileNew = javaxDataDir("default-vm-args")); if (text == null) { text = loadTextFile(fileOld = programFile("#1005850", "default-vm-args")); if (text != null) moveFile(fileOld, fileNew); } return trim(unnull(text)); } static public void tokPrepend(List tok, String s) { tokPrepend(tok, 0, s); } static public void tokPrepend(List tok, int i, String s) { tok.set(i, s + tok.get(i)); } static public String javaDropAllComments(String s) { return join(javaDropAllComments(javaTok(s))); } static public List javaDropAllComments(List tok) { for (int i = 0; i < l(tok); i += 2) tok.set(i, tok_javaDropCommentsFromWhitespace(tok.get(i))); return tok; } static public boolean shortClassNameIs(Object o, String name) { return eq(shortClassName(o), name); } static public boolean shortClassNameIs(String name, Object o) { return shortClassNameIs(o, name); } static public List dm_listModuleIDs() { return map("dm_moduleID", dm_listStems()); } static public Object dm_getStemByID(Object id) { return dm_callOS("getModuleByID", str(id)); } static public boolean isEmpty(Collection c) { return c == null || c.isEmpty(); } static public boolean isEmpty(CharSequence s) { return s == null || s.length() == 0; } static public boolean isEmpty(Object[] a) { return a == null || a.length == 0; } static public boolean isEmpty(byte[] a) { return a == null || a.length == 0; } static public boolean isEmpty(Map map) { return map == null || map.isEmpty(); } static public A swingConstruct(final Class c, final Object... args) { return swing(new F0() { public A get() { try { return nuObject(c, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret nuObject(c, args);"; } }); } static public JMenuItem jMenuItem(final String text) { return jmenuItem(text); } static public JMenuItem jMenuItem(String text, Object r) { return jmenuItem(text, r); } static public Pair jmenu_autoMnemonic(String s) { int i = indexOf(s, '&'); if (i >= 0 && i < l(s) && isLetterOrDigit(s.charAt(i + 1))) return pair(substring(s, 0, i) + substring(s, i + 1), (int) s.charAt(i + 1)); return pair(s, 0); } static public JMenuItem disableMenuItem(final JMenuItem mi) { if (mi != null) { swing(new Runnable() { public void run() { try { mi.setEnabled(false); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mi.setEnabled(false);"; } }); } return mi; } static public ActionListener actionListenerInNewThread(final Object runnable) { return actionListenerInNewThread(runnable, null); } static public ActionListener actionListenerInNewThread(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { startThread("Action Listener", new Runnable() { public void run() { try { AutoCloseable __1 = holdInstance(instanceToHold); try { callF(runnable); } finally { _close(__1); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "AutoCloseable __1 = holdInstance(instanceToHold); try {\r\n callF(runnable..."; } }); } catch (Throwable __e) { messageBox(__e); } } }; } static public String strUnnull(Object o) { return o == null ? "" : str(o); } static public String jlabel_textAsHTML_center_ifNeeded(String text) { if (swic(text, "") && ewic(text, "")) return text; if (!containsNewLines(text)) return text; return jlabel_textAsHTML_center(text); } static public Dimension getPreferredSize(final Component c) { return c == null ? null : swing(new F0() { public Dimension get() { try { return c.getPreferredSize(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getPreferredSize();"; } }); } static public void printNumberedLines(Map map) { printNumberedLines(mapToLines(map)); } static public void printNumberedLines(String prefix, Map map) { printNumberedLines(prefix, mapToLines(map)); } static public A printNumberedLines(A l) { int i = 0; if (l != null) for (Object a : l) print((++i) + ". " + str(a)); return l; } static public A printNumberedLines(String prefix, A l) { int i = 0; if (l != null) for (Object a : l) print(prefix + (++i) + ". " + str(a)); return l; } static public void printNumberedLines(Object[] l) { printNumberedLines(asList(l)); } static public void printNumberedLines(Object o) { printNumberedLines(lines(str(o))); } static public boolean checkFields(Object x, Object... data) { for (int i = 0; i < l(data); i += 2) if (neq(getOpt(x, (String) data[i]), data[i + 1])) return false; return true; } static public void cleanKillVM() { try { ping(); assertNotOnAWTThread(); cleanKillVM_noSleep(); Object o = new Object(); synchronized (o) { o.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static public void cleanKillVM_noSleep() { call(getJavaX(), "cleanKill"); } static public String fsI_flex(String s) { return startsWithDigit(s) ? "#" + s : s; } static public boolean exposeMethods2_debug = false; static public String exposeMethods2(Object receiver, String s, List methodNames) { return exposeMethods2(receiver, s, methodNames, null); } static public String exposeMethods2(Object receiver, String s, List methodNames, Lock lock) { Matches m = new Matches(); if (exposeMethods2_debug) print("Received: " + s); if (match("call *", s, m)) { List l; if (isIdentifier(m.unq(0))) l = ll(m.unq(0)); else l = (List) unstructure(m.unq(0)); String method = getString(l, 0); if (!contains(methodNames, method)) throw fail("Method not allowed: " + method); if (lock != null) lock.lock(); try { if (exposeMethods2_debug) print("Calling: " + method); Object o = call(receiver, method, asObjectArray(subList(l, 1))); if (exposeMethods2_debug) print("Got: " + getClassName(o)); return ok2(structure(o)); } finally { if (lock != null) lock.unlock(); } } if (match("list methods", s)) return ok2(structure(methodNames)); return null; } static public int makeBot(String greeting) { return makeAndroid3(greeting).port; } static public Android3 makeBot(Android3 a) { makeAndroid3(a); return a; } static public Android3 makeBot(String greeting, Object responder) { Android3 a = new Android3(greeting); a.responder = makeResponder(responder); makeBot(a); return a; } static public Android3 makeBot() { return makeAndroid3(defaultBotName()); } static public List listFilesOnly(String dir) { return listFilesOnly(new File(dir)); } static public List listFilesOnly(File... dirs) { return concatMap(rcurry("listFilesWithSuffix", ""), dirs); } static public Comparator mapComparator(final Map map) { return new Comparator() { public int compare(A a, A b) { return cmp(map.get(a), map.get(b)); } }; } static public boolean isDirectory(File f) { return f != null && f.isDirectory(); } static public boolean isDirectory(String path) { return path != null && isDirectory(newFile(path)); } static public void stream2file(InputStream in, File out) { try { mkdirsForFile(out); FileOutputStream fos = new FileOutputStream(out); copyStream(in, fos); in.close(); fos.close(); } catch (Exception __e) { throw rethrow(__e); } } static public int lastIndexOf_byteArray(byte[] a, byte b) { for (int i = l(a) - 1; i >= 0; i--) if (a[i] == b) return i; return -1; } static public int indexOf_byteArray(byte[] a, byte b) { int n = l(a); for (int i = 0; i < n; i++) if (a[i] == b) return i; return -1; } static public void addMenuItem(JPopupMenu menu, String text, Object action) { menu.add(jmenuItem(text, action)); } static public void addMenuItem(JPopupMenu menu, JMenuItem menuItem) { menu.add(menuItem); } static public void addMenuItem(JMenu menu, String text, Object action) { menu.add(jmenuItem(text, action)); } static public void addMenuItem(Menu menu, String text, Object action) { menu.add(menuItem(text, action)); } static public void addMenuItem(JMenu menu, JMenuItem menuItem) { menu.add(menuItem); } static public File standardLogFile() { return getProgramFile("log"); } static public A _recordNewSwingComponent(A c) { if (c != null) callF((Object) vm_generalMap_get("newSwingComponentRegistry"), (Object) c); return c; } static public JComponent componentToJComponent(Component c) { if (c instanceof JComponent) return (JComponent) c; if (c instanceof JFrame) return ((JFrame) c).getRootPane(); if (c == null) return null; throw fail("boohoo " + getClassName(c)); } static public JLabel jlabel(final String text) { return swingConstruct(BetterLabel.class, text); } static public JLabel jlabel() { return jlabel(" "); } static public JTextArea enableWordWrapForTextArea(JTextArea ta) { return enableWordWrapForTextArea(ta, true); } static public JTextArea enableWordWrapForTextArea(JTextArea ta, boolean enabled) { if (ta != null) { swing(new Runnable() { public void run() { try { ta.setLineWrap(enabled); ta.setWrapStyleWord(true); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ta.setLineWrap(enabled);\r\n ta.setWrapStyleWord(true);\r\n // Haven't foun..."; } }); } return ta; } static public JTextArea jtextarea() { return jTextArea(); } static public JTextArea jtextarea(String text) { return jTextArea(text); } static public List vmBus_queryAll(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); List out = new ArrayList(); for (Object o : unnull(vm_busListeners_live())) addIfNotNull(out, pcallF(o, msg, arg)); for (Object o : unnull(vm_busListenersByMessage_live().get(msg))) addIfNotNull(out, pcallF(o, msg, arg)); return out; } static public String getSnippetTitle(String id) { if (id == null) return null; if (!isSnippetID(id)) return "?"; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getSnippetTitle(id); return getSnippetTitle_noResourceLoader(id); } static public String getSnippetTitle_noResourceLoader(String id) { try { if (isLocalSnippetID(id)) return localSnippetTitle(id); long parsedID = parseSnippetID(id); String url; if (isImageServerSnippet(parsedID)) url = imageServerURL() + "title/" + parsedID + muricaCredentialsQuery(); else if (isGeneralFileServerSnippet(parsedID)) url = "http://butter.botcompany.de:8080/files/name/" + parsedID; else url = tb_mainServer() + "/tb-int/getfield.php?id=" + parsedID + "&field=title" + standardCredentials_noCookies(); String title = trim(loadPageSilently(url)); if (title != null) try { saveTextFileIfChanged(snippetTitle_cacheFile(id), title); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } return or(title, "?"); } catch (Exception __e) { throw rethrow(__e); } } static public String getSnippetTitle(long id) { return getSnippetTitle(fsI(id)); } static public ThreadLocal addInternalFrame_dontSelect = new ThreadLocal(); static public ThreadLocal addInternalFrame_layer = new ThreadLocal(); static public ThreadLocal addInternalFrame_toBack = new ThreadLocal(); static public JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final int x, final int y, final int w, final int h) { return addInternalFrame(desktop, title, x, y, w, h, null); } static public JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final int x, final int y, final int w, final int h, final Component contents) { return addInternalFrame(desktop, title, rect(x, y, w, h), contents); } static public JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final Component contents) { return addInternalFrame(desktop, title, null, contents); } static public JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final Rect r, final Component contents) { final boolean dontSelect = isTrue(optParam(addInternalFrame_dontSelect)); final boolean toBack = isTrue(optParam(addInternalFrame_toBack)); final Integer layer = optParam(addInternalFrame_layer); return swing(new F0() { public JInternalFrame get() { try { JInternalFrame frame; if (contents instanceof JInternalFrame) frame = (JInternalFrame) contents; else { frame = jInternalFrame(title); setInternalFrameContents(frame, contents); } frame.setVisible(true); desktop.add(frame, layer); if (r != null) setBounds(frame, r); else internalFrameDefaultPosition(frame); if (dontSelect) if (toBack) frame.toBack(); else frame.toFront(); else frame.setSelected(true); return fixInternalFrame(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JInternalFrame frame;\r\n if (contents instanceof JInternalFrame)\r\n fra..."; } }); } static public JInternalFrame addInternalFrame(JDesktopPane desktop, String title) { return addInternalFrame(desktop, title, jpanel()); } static public JInternalFrame minInternalFrameWidth(final JInternalFrame frame, final int w) { { swing(new Runnable() { public void run() { try { if (frame != null && frame.getWidth() < w) frame.setSize(w, frame.getHeight()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (frame != null && frame.getWidth() < w)\r\n frame.setSize(w, frame.getH..."; } }); } return frame; } static public JInternalFrame minInternalFrameWidth(int w, JInternalFrame frame) { return minInternalFrameWidth(frame, w); } static public A packInternalFrameVertically(A c) { return packInternalFrameVertically(-1, c); } static public A packInternalFrameVertically(int width, A c) { final JInternalFrame win = getInternalFrame(c); if (win == null) return c; final int w = width < 0 ? win.getWidth() : width; { swing(new Runnable() { public void run() { try { win.pack(); win.setSize(w, win.getHeight()); fixInternalFrame(win); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "win.pack();\r\n win.setSize(w, win.getHeight());\r\n fixInternalFrame(win);"; } }); } return c; } static public JInternalFrame centerInternalFrame(final JInternalFrame f) { { swing(new Runnable() { public void run() { try { Container c = f.getParent(); if (c != null) { f.setLocation((c.getWidth() - f.getWidth()) / 2, (c.getHeight() - f.getHeight()) / 2); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Container c = f.getParent();\r\n if (c != null) {\r\n //print(\"Container ..."; } }); } return f; } static public JInternalFrame centerInternalFrame(final int w, final int h, final JInternalFrame f) { { swing(new Runnable() { public void run() { try { f.setSize(w, h); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.setSize(w, h);"; } }); } return centerInternalFrame(f); } static public int packFrame_minw = 150, packFrame_minh = 50; static public A packFrame(final A c) { { swing(new Runnable() { public void run() { try { Window w = getWindow(c); if (w != null) { w.pack(); int maxW = getScreenWidth() - 50, maxH = getScreenHeight() - 50; w.setSize(min(maxW, max(w.getWidth(), packFrame_minw)), min(maxH, max(w.getHeight(), packFrame_minh))); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Window w = getWindow(c);\r\n if (w != null) {\r\n w.pack();\r\n int ma..."; } }); } return c; } static public JFrame packFrame(ButtonGroup g) { return packFrame(getFrame(g)); } static public JFrame showFrame() { return makeFrame(); } static public JFrame showFrame(Object content) { return makeFrame(content); } static public JFrame showFrame(String title) { return makeFrame(title); } static public JFrame showFrame(String title, Object content) { return makeFrame(title, content); } static public JFrame showFrame(final JFrame f) { if (f != null) { swing(new Runnable() { public void run() { try { if (frameTooSmall(f)) frameStandardSize(f); if (!f.isVisible()) f.setVisible(true); if (f.getState() == Frame.ICONIFIED) f.setState(Frame.NORMAL); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (frameTooSmall(f)) frameStandardSize(f);\r\n if (!f.isVisible()) f.setVis..."; } }); } return f; } static public JFrame showFrame(String title, Object content, JFrame frame) { if (frame == null) return showFrame(title, content); else { frame.setTitle(title); setFrameContents(frame, content); return frame; } } static public > void forEachLevel2(Iterable l, IVF1 f) { if (l != null) for (B b : l) forEach(b, f); } static public > void forEachLevel2(IVF1 f, Iterable l) { forEachLevel2(f, l); } static public Dimension getMinimumSize(final Component c) { return c == null ? null : swing(new F0() { public Dimension get() { try { return c.getMinimumSize(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getMinimumSize();"; } }); } static public A jPreferWidth(int w, A c) { Dimension size = c.getPreferredSize(); c.setPreferredSize(new Dimension(w, size.height)); return c; } static public boolean containsSpace(String s) { return containsSpaces(s); } static public List replaceElementsUsingMap(Iterable l, final Map map) { return map(l, new F1() { public A get(A a) { try { return getOrKeep(map, a); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getOrKeep(map, a)"; } }); } static public List splitCamelCase(String s) { return ai_splitCamelCase(s); } static public JInternalFrame getInternalFrame(final Object _o) { return _o == null ? null : swing(new F0() { public JInternalFrame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof JInternalFrame) return (JInternalFrame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n if (o instanceof ButtonGroup) o = first(buttonsInGroup((Button..."; } }); } static public List allChildren(Component c) { return childrenOfType(c, Component.class); } static public void onEnterIfTextField(Component c, Object action) { if (action == null) return; if (c instanceof JTextField) onEnter((JTextField) c, action); else if (c instanceof JComboBox) onEnter((JComboBox) c, action); } static public Object[] flattenArray2(Object... a) { List l = new ArrayList(); if (a != null) for (Object x : a) if (x instanceof Object[]) l.addAll(asList((Object[]) x)); else if (x instanceof Collection) l.addAll((Collection) x); else l.add(x); return asObjectArray(l); } static public void scanForComponents(final Component c, final Class theClass, final List l) { if (theClass.isInstance(c)) l.add((A) c); if (c instanceof Container) { swing(new Runnable() { public void run() { try { for (Component comp : ((Container) c).getComponents()) scanForComponents(comp, theClass, l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (Component comp : ((Container) c).getComponents())\r\n scanForComponen..."; } }); } } static public int min3(int a, int b, int c) { return min(min(a, b), c); } static public double min3(double a, double b, double c) { return min(min(a, b), c); } static public class getOpt_Map extends WeakHashMap { public getOpt_Map() { if (getOpt_special == null) getOpt_special = new HashMap(); clear(); } public void clear() { super.clear(); put(Class.class, getOpt_special); put(String.class, getOpt_special); } } static final public Map> getOpt_cache = _registerDangerousWeakMap(synchroMap(new getOpt_Map())); static public HashMap getOpt_special; static public Object getOpt_cached(Object o, String field) { try { if (o == null) return null; Class c = o.getClass(); HashMap map; synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } if (map == getOpt_special) { if (o instanceof Class) return getOpt((Class) o, field); if (o instanceof Map) return ((Map) o).get(field); } Field f = map.get(field); if (f != null) return f.get(o); if (o instanceof DynamicObject) return mapGet2(((DynamicObject) o).fieldValues, field); return null; } catch (Exception __e) { throw rethrow(__e); } } static public HashMap getOpt_makeCache(Class c) { HashMap map; if (isSubtypeOf(c, Map.class)) map = getOpt_special; else { map = new HashMap(); if (!reflection_classesNotToScan().contains(c.getName())) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) { makeAccessible(f); String name = f.getName(); if (!map.containsKey(name)) map.put(name, f); } _c = _c.getSuperclass(); } while (_c != null); } } if (getOpt_cache != null) getOpt_cache.put(c, map); return map; } static public Object[] toArray(Collection c) { return toObjectArray(c); } static public A[] toArray(Iterable c, Class type) { A[] a = arrayOfType(l(c), type); if (a.length == 0) return a; asList(c).toArray(a); return a; } static public A[] toArray(A[] array, Collection c) { if (array == null || c == null) return null; asList(c).toArray(array); return array; } static public Method findMethodNamed(Object obj, String method) { if (obj == null) return null; if (obj instanceof Class) return findMethodNamed((Class) obj, method); return findMethodNamed(obj.getClass(), method); } static public Method findMethodNamed(Class c, String method) { while (c != null) { for (Method m : c.getDeclaredMethods()) if (m.getName().equals(method)) { makeAccessible(m); return m; } c = c.getSuperclass(); } return null; } static public void upgradeJavaXAndRestart() { run("#1001639"); restart(); sleep(); } static public boolean isJavaxApplicationSnippetType(int type) { return type == snippetType_javaxSource() || type == snippetType_JavaXDesktop(); } static public boolean isJavaxModuleSnippetType(int type) { return type == snippetType_javaxModule() || type == snippetType_javaxDesktopModule(); } static public int snippetType_dynModule() { return 57; } static public List hotwire_libraryIDsFromJar(File jar) { String dehlibs = unnull(loadTextFileFromZip(jar, "libraries")); return regexpExtractAll("\\d+", dehlibs); } static public byte[] subByteArray(byte[] b, int start) { return subByteArray(b, start, l(b)); } static public byte[] subByteArray(byte[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new byte[0]; byte[] x = new byte[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public void moveFile(File a, File b) { if (!renameFile(a, b)) throw fail("File move failed: " + a + " to " + b); } static public String tok_javaDropCommentsFromWhitespace(String s) { int l = l(s), j = 0; StringBuilder buf = new StringBuilder(); while (j < l) { char c = s.charAt(j); char d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else { buf.append(c); ++j; } } return str(buf); } static public List dm_listStems() { return (List) dm_callOS("onModules"); } static public boolean containsNewLines(String s) { return containsNewLine(s); } static public String jlabel_textAsHTML_center(String text) { return "
" + replace(htmlencode(text), "\n", "
") + "
"; } static public void assertNotOnAWTThread() { assertFalse("Can't do this in AWT thread", isAWTThread()); } static public boolean startsWithDigit(String s) { return nempty(s) && isDigit(s.charAt(0)); } static public String ok2(String s) { return "ok " + s; } static public boolean makeAndroid3_disable = false; static public class Android3 implements AutoCloseable { public String greeting; public boolean publicOverride = false; public int startPort = 5000; public Responder responder; public boolean console = true; public boolean quiet = false; public boolean daemon = false; public boolean incomingSilent = false; public int incomingPrintLimit = 200; public boolean useMultiPort = true; public boolean recordHistory = false; public boolean verbose = false; public int answerPrintLimit = 500; public boolean newLineAboveAnswer, newLineBelowAnswer; public int port; public long vport; public DialogHandler handler; public ServerSocket server; public Android3(String greeting) { this.greeting = greeting; } public Android3() { } public void close() { dispose(); } synchronized public void dispose() { if (server != null) { try { server.close(); } catch (IOException e) { print("[internal] " + e); } server = null; } if (vport != 0) { try { print("Disposing " + this); removeFromMultiPort(vport); vport = 0; } catch (Throwable __e) { _handleException(__e); } } } public String toString() { return "Bot: " + greeting + " [vport " + vport + "]"; } } static abstract public class Responder { abstract public String answer(String s, List history); } static public Android3 makeAndroid3(final String greeting) { return makeAndroid3(new Android3(greeting)); } static public Android3 makeAndroid3(final String greeting, Responder responder) { Android3 android = new Android3(greeting); android.responder = responder; return makeAndroid3(android); } static public Android3 makeAndroid3(final Android3 a) { if (makeAndroid3_disable) return a; if (a.responder == null) a.responder = new Responder() { public String answer(String s, List history) { return callStaticAnswerMethod(s, history); } }; if (!a.quiet) print("[bot] " + a.greeting); if (a.console && (readLine_noReadLine || makeAndroid3_consoleInUse())) a.console = false; record(a); if (a.useMultiPort) a.vport = addToMultiPort(a.greeting, makeAndroid3_verboseResponder(a)); if (a.console) makeAndroid3_handleConsole(a); if (a.useMultiPort) return a; a.handler = makeAndroid3_makeDialogHandler(a); if (a.quiet) startDialogServer_quiet.set(true); try { a.port = a.daemon ? startDialogServerOnPortAboveDaemon(a.startPort, a.handler) : startDialogServerOnPortAbove(a.startPort, a.handler); } finally { startDialogServer_quiet.set(null); } a.server = startDialogServer_serverSocket; return a; } static public void makeAndroid3_handleConsole(final Android3 a) { if (!a.quiet) print("You may also type on this console."); { startThread(new Runnable() { public void run() { try { List history = new ArrayList(); while (licensed()) { String line; try { line = readLine(); } catch (Throwable e) { print(getInnerMessage(e)); break; } if (line == null) break; { history.add(line); history.add(makeAndroid3_getAnswer(line, history, a)); } } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "List history = new ArrayList();\r\n while (licensed()) {\r\n Stri..."; } }); } } static public DialogHandler makeAndroid3_makeDialogHandler(final Android3 a) { return new DialogHandler() { public void run(final DialogIO io) { if (!a.publicOverride && !(publicCommOn() || io.isLocalConnection())) { io.sendLine("Sorry, not allowed"); return; } String dialogID = randomID(8); io.sendLine(a.greeting + " / Your ID: " + dialogID); List history = new ArrayList(); while (io.isStillConnected()) { if (io.waitForLine()) { final String line = io.readLineNoBlock(); String s = dialogID + " at " + now() + ": " + quote(line); if (!a.incomingSilent) print(shorten(s, a.incomingPrintLimit)); if (eq(line, "bye")) { io.sendLine("bye stranger"); return; } Matches m = new Matches(); if (a.recordHistory) history.add(line); String answer; if (match3("this is a continuation of talk *", s, m) || match3("hello bot! this is a continuation of talk *", s, m)) { dialogID = unquote(m.m[0]); answer = "ok"; } else try { makeAndroid3_io.set(io); answer = makeAndroid3_getAnswer(line, history, a); } finally { makeAndroid3_io.set(null); } if (a.recordHistory) history.add(answer); io.sendLine(answer); } } } }; } static public String makeAndroid3_getAnswer(String line, List history, Android3 a) { String answer, originalAnswer; try { originalAnswer = a.responder.answer(line, history); answer = makeAndroid3_fallback(line, history, originalAnswer); } catch (Throwable e) { e = getInnerException(e); printStackTrace(e); originalAnswer = answer = e.toString(); } if (!a.incomingSilent) { if (originalAnswer == null) originalAnswer = "?"; if (a.newLineAboveAnswer) print(); print(">" + dropFirst(indentx(2, shorten(rtrim(originalAnswer), a.answerPrintLimit)))); if (a.newLineBelowAnswer) print(); } return answer; } static public String makeAndroid3_fallback(String s, List history, String answer) { if (answer == null && match3("what is your pid", s)) return getPID(); if (answer == null && match3("what is your program id", s)) return getProgramID(); if (match3("get injection id", s)) return getInjectionID(); if (answer == null) answer = "?"; if (answer.indexOf('\n') >= 0 || answer.indexOf('\r') >= 0) answer = quote(answer); return answer; } static public boolean makeAndroid3_consoleInUse() { if (isTrue(vm_generalMap_get("consoleInUse"))) return true; for (Object o : record_list) if (o instanceof Android3 && ((Android3) o).console) return true; return false; } static public Responder makeAndroid3_verboseResponder(final Android3 a) { return new Responder() { public String answer(String s, List history) { if (a.verbose) print("> " + shorten(s, a.incomingPrintLimit)); String answer = a.responder.answer(s, history); if (a.verbose) print("< " + shorten(answer, a.incomingPrintLimit)); return answer; } }; } static public ThreadLocal makeAndroid3_io = new ThreadLocal(); static public Android3 makeAndroid3() { return makeAndroid3(getProgramTitle() + "."); } static public String makeResponder_callAnswerMethod(Object bot, String s, List history) { String answer = (String) callOpt(bot, "answer", s, history); if (answer == null) answer = (String) callOpt(bot, "answer", s); return answer; } static public Responder makeResponder(final Object bot) { if (bot instanceof Responder) return (Responder) bot; if (bot instanceof String) { String f = (String) bot; return new Responder() { public String answer(String s, List history) { String answer = (String) callOptMC((String) bot, s, history); if (answer == null) answer = (String) callOptMC((String) bot, s); return answer; } }; } return new Responder() { public String answer(String s, List history) { return makeResponder_callAnswerMethod(bot, s, history); } }; } static public String defaultBotName() { return getProgramTitle() + "."; } static public Object rcurry(final Object f, final Object arg) { int n = numberOfFunctionArguments(f); if (n == 0) throw fail("function takes no arguments"); if (n == 1) return new F0() { public Object get() { return callF(f, arg); } }; if (n == 2) return new F1() { public Object get(Object a) { return callF(f, a, arg); } }; throw todo("currying a function with " + n + "arguments"); } static public MenuItem menuItem(String text, final Object r) { MenuItem mi = new MenuItem(text); mi.addActionListener(actionListener(r)); return mi; } static public JTextArea jTextArea() { return jTextArea(""); } static public JTextArea jTextArea(final String text) { return jTextAreaWithUndo(text); } static public String localSnippetTitle(String snippetID) { if (!isLocalSnippetID(snippetID)) return null; File f = localSnippetFile(snippetID); if (!f.exists()) return null; return or2(getFileInfoField(dropExtension(f), "Title"), "Unnamed"); } static public String muricaCredentialsQuery() { return htmlQuery(muricaCredentials()); } static public boolean isGeneralFileServerSnippet(long id) { return id >= 1400000 && id < 1500000; } static public boolean saveTextFileIfChanged(File f, String contents) { return saveTextFileIfDifferent(f, contents); } static public File snippetTitle_cacheFile(String snippetID) { return javaxCachesDir("Snippet Titles/" + psI(snippetID)); } static public Rect rect(int x, int y, int w, int h) { return new Rect(x, y, w, h); } static public boolean jInternalFrame_iconifiable = true; static public JInternalFrame jInternalFrame() { return jInternalFrame(""); } static public JInternalFrame jInternalFrame(final String title) { return swing(new F0() { public JInternalFrame get() { try { JInternalFrame f = new JInternalFrame(title, true, true, true, jInternalFrame_iconifiable); f.setVisible(true); return f; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JInternalFrame f = new JInternalFrame(title, true, true, true, jInternalFrame..."; } }); } static public void setInternalFrameContents(final Component c, final Object contents) { { swing(new Runnable() { public void run() { try { JInternalFrame frame = getInternalFrame(c); if (frame == null) return; frame.getContentPane().removeAll(); frame.getContentPane().setLayout(new BorderLayout()); if (contents != null) frame.getContentPane().add(wrap(contents)); revalidate(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JInternalFrame frame = getInternalFrame(c);\r\n if (frame == null) return;\r\n..."; } }); } } static public
A setBounds(final int x, final int y, final int w, final int h, final A a) { if (a != null) { swing(new Runnable() { public void run() { try { a.setBounds(x, y, w, h); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setBounds(x, y, w, h);"; } }); } return a; } static public A setBounds(A a, Rect r) { if (a != null && r != null) { swing(new Runnable() { public void run() { try { a.setBounds(toRectangle(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setBounds(toRectangle(r));"; } }); } return a; } static public A setBounds(Rect r, A a) { return setBounds(a, r); } static public A setBounds(A a, int x, int y, int w, int h) { return setBounds(x, y, w, h, a); } static public void internalFrameDefaultPosition(JInternalFrame f) { f.setSize(500, 300); centerInternalFrame(f); } static public int fixInternalFrame_borderTopLeft = 0; static public int fixInternalFrame_borderBottomRight = 40; static public JInternalFrame fixInternalFrame(final JInternalFrame f) { return swing(new F0() { public JInternalFrame get() { try { Container c = f.getParent(); if (c == null) return f; Rect r = toRect(f.getBounds()); int a = fixInternalFrame_borderTopLeft, b = fixInternalFrame_borderBottomRight; Rect outer = new Rect(a, a, c.getWidth() - b, c.getHeight() - b); if (!rectContains(outer, r)) f.setLocation(max(a, min(r.x, outer.x2())), max(a, min(r.y, outer.y2()))); if (r.w > c.getWidth() || r.h > c.getHeight()) f.setSize(c.getWidth() - a, c.getHeight() - a); return f; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Container c = f.getParent();\r\n if (c == null) ret f;\r\n Rect r = toRect(..."; } }); } static public int getScreenWidth() { return getScreenSize().width; } static public int getScreenHeight() { return getScreenSize().height; } static public String makeFrame_defaultIcon; static public boolean makeFrame_hideConsole = false; static public ThreadLocal> makeFrame_post = new ThreadLocal(); static public JFrame makeFrame() { return makeFrame((Component) null); } static public JFrame makeFrame(Object content) { return makeFrame(programTitle(), content); } static public JFrame makeFrame(String title) { return makeFrame(title, null); } static public JFrame makeFrame(String title, Object content) { return makeFrame(title, content, true); } static public JFrame makeFrame(final String title, final Object content, final boolean showIt) { final VF1 post = optParam(makeFrame_post); return swing(new F0() { public JFrame get() { try { if (getFrame(content) != null) return getFrame(setFrameTitle((Component) content, title)); final JFrame frame = new JFrame(title); if (makeFrame_defaultIcon != null) setFrameIconLater(frame, makeFrame_defaultIcon); _initFrame(frame); Component wrapped = wrap(content); if (wrapped != null) frame.getContentPane().add(wrapped); frame.setBounds(defaultNewFrameBounds()); callF(post, frame); if (showIt) frame.setVisible(true); if (showIt && makeFrame_hideConsole) { hideConsole(); makeFrame_hideConsole = false; } return frame; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (getFrame(content) != null)\r\n ret getFrame(setFrameTitle((Component) ..."; } }); } static public boolean frameTooSmall(JFrame frame) { return frame.getWidth() < 100 || frame.getHeight() < 50; } static public void frameStandardSize(JFrame frame) { frame.setBounds(300, 100, 500, 400); } static public void setFrameContents(final Component c, final Object contents) { swing(new Runnable() { public void run() { try { JFrame frame = getFrame(c); if (frame == null) return; frame.getContentPane().removeAll(); frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add(wrap(contents)); revalidate(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFrame frame = getFrame(c);\r\n if (frame == null) return;\r\n frame.getContent..."; } }); } static public void forEach(Iterable l, IVF1 f) { if (l != null) for (A a : l) callF(f, a); } static public void forEach(IVF1 f, Iterable l) { forEach(l, f); } static public boolean containsSpaces(String s) { return indexOf(s, ' ') >= 0; } static public List ai_splitCamelCase(String s) { int j = 0; List l = new ArrayList(); if (isAllUpperCase(s)) { l.add(s); return l; } for (int i = 0; i < l(s); i++) if (i > j && isUpperCaseLetter(s.charAt(i))) { l.add(substring(s, j, i)); j = i; } if (j < l(s)) l.add(substring(s, j)); return l; } static public List _registerDangerousWeakMap_preList; static public A _registerDangerousWeakMap(A map) { return _registerDangerousWeakMap(map, null); } static public A _registerDangerousWeakMap(A map, Object init) { callF(init, map); if (init instanceof String) { final String f = (String) init; init = new VF1() { public void get(Map map) { try { callMC(f, map); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callMC(f, map)"; } }; } if (javax() == null) { if (_registerDangerousWeakMap_preList == null) _registerDangerousWeakMap_preList = synchroList(); _registerDangerousWeakMap_preList.add(pair(map, init)); return map; } call(javax(), "_registerDangerousWeakMap", map, init); return map; } static public void _onLoad_registerDangerousWeakMap() { assertNotNull(javax()); if (_registerDangerousWeakMap_preList == null) return; for (Pair p : _registerDangerousWeakMap_preList) _registerDangerousWeakMap(p.a, p.b); _registerDangerousWeakMap_preList = null; } static public B mapGet2(Map map, A a) { return map == null ? null : map.get(a); } static public B mapGet2(A a, Map map) { return map == null ? null : map.get(a); } static public boolean isSubtypeOf(Class a, Class b) { return b.isAssignableFrom(a); } static public Set reflection_classesNotToScan_value = litset("jdk.internal.loader.URLClassPath"); static public Set reflection_classesNotToScan() { return reflection_classesNotToScan_value; } static public void restart() { Object j = getJavaX(); call(j, "cleanRestart", get(j, "fullArgs")); } static public int snippetType_javaxSource() { return 34; } static public int snippetType_JavaXDesktop() { return 55; } static public int snippetType_javaxModule() { return 54; } static public int snippetType_javaxDesktopModule() { return 58; } static public List regexpExtractAll(String pat, String s) { if (s == null) return null; Matcher m = regexpMatcher(pat, s); List out = new ArrayList(); while (m.find()) out.add(m.group()); return out; } static public boolean renameFile(File a, File b) { mkdirsForFile(b); return a.renameTo(b); } static public boolean renameFile(File a, String newName) { return renameFile(a, fileInSameDir(a, newName)); } static public boolean containsNewLine(String s) { return contains(s, '\n'); } static public boolean isDigit(char c) { return Character.isDigit(c); } static public void removeFromMultiPort(long vport) { if (vport == 0) return; for (Object port : getMultiPorts()) call(port, "removePort", vport); } static public String callStaticAnswerMethod(List bots, String s) { for (Object c : bots) try { String answer = callStaticAnswerMethod(c, s); if (!empty(answer)) return answer; } catch (Throwable e) { print("Error calling " + getProgramID(c)); e.printStackTrace(); } return null; } static public String callStaticAnswerMethod(Object c, String s) { String answer = (String) callOpt(c, "answer", s, litlist(s)); if (answer == null) answer = (String) callOpt(c, "answer", s); return emptyToNull(answer); } static public String callStaticAnswerMethod(String s) { return callStaticAnswerMethod(mc(), s); } static public String callStaticAnswerMethod(String s, List history) { return callStaticAnswerMethod(mc(), s, history); } static public String callStaticAnswerMethod(Object c, String s, List history) { String answer = (String) callOpt(c, "answer", s, history); if (answer == null) answer = (String) callOpt(c, "answer", s); return emptyToNull(answer); } static public List record_list = synchroList(); static public void record(Object o) { record_list.add(o); } static public Object addToMultiPort_responder; static public long addToMultiPort(final String botName) { return addToMultiPort(botName, new Object() { public String answer(String s, List history) { String answer = (String) (callOpt(getMainClass(), "answer", s, history)); if (answer != null) return answer; answer = (String) callOpt(getMainClass(), "answer", s); if (answer != null) return answer; if (match3("get injection id", s)) return getInjectionID(); return null; } }); } static public long addToMultiPort(final String botName, final Object responder) { addToMultiPort_responder = responder; startMultiPort(); List ports = getMultiPorts(); if (ports == null) return 0; if (ports.isEmpty()) throw fail("No multiports!"); if (ports.size() > 1) print("Multiple multi-ports. Using last one."); Object port = last(ports); Object responder2 = new Object() { public String answer(String s, List history) { if (match3("get injection id", s)) return getInjectionID(); if (match3("your name", s)) return botName; return (String) call(responder, "answer", s, history); } }; record(responder2); return (Long) call(port, "addResponder", botName, responder2); } static public AtomicInteger dialogServer_clients = new AtomicInteger(); static public boolean dialogServer_printConnects = false; static public ThreadLocal startDialogServer_quiet = new ThreadLocal(); static public Set dialogServer_knownClients = synchroTreeSet(); static public int startDialogServerOnPortAbove(int port, DialogHandler handler) { while (!forbiddenPort(port) && !startDialogServerIfPortAvailable(port, handler)) ++port; return port; } static public int startDialogServerOnPortAboveDaemon(int port, DialogHandler handler) { while (!forbiddenPort(port) && !startDialogServerIfPortAvailable(port, handler, true)) ++port; return port; } static public void startDialogServer(int port, DialogHandler handler) { if (!startDialogServerIfPortAvailable(port, handler)) throw fail("Can't start dialog server on port " + port); } static public boolean startDialogServerIfPortAvailable(int port, final DialogHandler handler) { return startDialogServerIfPortAvailable(port, handler, false); } static public ServerSocket startDialogServer_serverSocket; static public boolean startDialogServerIfPortAvailable(int port, final DialogHandler handler, boolean daemon) { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); } catch (IOException e) { return false; } final ServerSocket _serverSocket = serverSocket; startDialogServer_serverSocket = serverSocket; Thread thread = new Thread("Socket accept port " + port) { public void run() { try { while (true) { try { final Socket s = _serverSocket.accept(); String client = s.getInetAddress().toString(); if (!dialogServer_knownClients.contains(client) && neq(client, "/127.0.0.1")) { print("connect from " + client + " - clients: " + dialogServer_clients.incrementAndGet()); dialogServer_knownClients.add(client); } String threadName = "Handling client " + s.getInetAddress(); Thread t2 = new Thread(threadName) { public void run() { try { final Writer w = new OutputStreamWriter(s.getOutputStream(), "UTF-8"); final BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8")); DialogIO io = new DialogIO() { public boolean isLocalConnection() { return s.getInetAddress().isLoopbackAddress(); } public boolean isStillConnected() { return !(eos || s.isClosed()); } public void sendLine(String line) { try { w.write(line + "\n"); w.flush(); } catch (Exception __e) { throw rethrow(__e); } } public String readLineImpl() { try { return in.readLine(); } catch (Exception __e) { throw rethrow(__e); } } public void close() { try { s.close(); } catch (IOException e) { } } public Socket getSocket() { return s; } }; try { handler.run(io); } finally { if (!io.noClose) s.close(); } } catch (IOException e) { print("[internal] " + e); } finally { } } }; t2.setDaemon(true); t2.start(); } catch (SocketTimeoutException e) { } } } catch (IOException e) { print("[internal] " + e); } } }; if (daemon) thread.setDaemon(true); thread.start(); if (!isTrue(getAndClearThreadLocal(startDialogServer_quiet))) print("Dialog server on port " + port + " started."); return true; } static volatile public boolean readLine_noReadLine = false; static public String readLine_lastInput; static public String readLine_prefix = "[] "; static public String readLine() { if (readLine_noReadLine) return null; String s = readLineHidden(); if (s != null) { readLine_lastInput = s; print(readLine_prefix + s); } return s; } static public String getInnerMessage(Throwable e) { if (e == null) return null; return getInnerException(e).getMessage(); } static public boolean publicCommOn() { return "1".equals(loadTextFile(new File(userHome(), ".javax/public-communication"))); } static public String processID_cached; static public String getPID() { if (processID_cached == null) { String name = ManagementFactory.getRuntimeMXBean().getName(); processID_cached = name.replaceAll("@.*", ""); } return processID_cached; } static public String getInjectionID() { return (String) call(getJavaX(), "getInjectionID", getMainClass()); } static public String getProgramTitle() { return getProgramName(); } static public int numberOfFunctionArguments(Object f) { if (f instanceof F0) return 0; if (f instanceof F1) return 1; if (f instanceof F2) return 2; if (f instanceof VF1) return 1; if (f instanceof VF2) return 2; if (f instanceof String) return numberOfMethodArguments(mc(), (String) f); return numberOfMethodArguments(f, "get"); } static public JTextArea jTextAreaWithUndo() { return jTextAreaWithUndo(""); } static public JTextArea jTextAreaWithUndo(final String text) { return jenableUndoRedo(swingNu(JTextArea.class, text)); } static public File localSnippetFile(long snippetID) { return localSnippetsDir(snippetID + ".text"); } static public File localSnippetFile(String snippetID) { return localSnippetFile(parseSnippetID(snippetID)); } static public String getFileInfoField(File f, String field) { return getOneLineFileInfoField(f, field); } static public File dropExtension(File f) { return f == null ? null : fileInSameDir(f, dropExtension(f.getName())); } static public String dropExtension(String s) { return takeFirst(s, smartLastIndexOf(s, '.')); } static public boolean saveTextFileIfDifferent(File f, String contents) { if (eq(loadTextFile(f), contents)) return false; { saveTextFile(f, contents); return true; } } static public Rectangle toRectangle(Rect r) { return r == null ? null : r.getRectangle(); } static public Rect toRect(Rectangle r) { return r == null ? null : new Rect(r); } static public Rect toRect(RectangularShape r) { return r == null ? null : toRect(r.getBounds()); } static public Rect toRect(Rect r) { return r; } static public boolean rectContains(int x1, int y1, int w, int h, Pt p) { return p.x >= x1 && p.y >= y1 && p.x < x1 + w && p.y < y1 + h; } static public boolean rectContains(Rect a, Rect b) { return b.x >= a.x && b.y >= a.y && b.x2() <= a.x2() && b.y2() <= a.y2(); } static public boolean rectContains(Rect a, int x, int y) { return a != null && a.contains(x, y); } static public String programTitle() { return getProgramName(); } static public A setFrameTitle(A c, final String title) { final Frame f = getAWTFrame(c); if (f != null) { swing(new Runnable() { public void run() { try { f.setTitle(title); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.setTitle(title);"; } }); } return c; } static public A setFrameTitle(String title, A c) { return setFrameTitle(c, title); } static public JFrame setFrameTitle(String title) { Object f = getOpt(mc(), "frame"); if (f instanceof JFrame) return setFrameTitle((JFrame) f, title); return null; } static public JFrame setFrameIconLater(Component c, final String imageID) { final JFrame frame = getFrame(c); if (frame != null) startThread("Loading Icon", new Runnable() { public void run() { try { final Image i = imageIcon(or2(imageID, "#1005557")).getImage(); swingLater(new Runnable() { public void run() { try { frame.setIconImage(i); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setIconImage(i);"; } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final Image i = imageIcon(or2(imageID, \"#1005557\")).getImage();\r\n swingL..."; } }); return frame; } static public void _initFrame(JFrame f) { myFrames_list.put(f, Boolean.TRUE); standardTitlePopupMenu(f); } static public Rectangle defaultNewFrameBounds_r = new Rectangle(300, 100, 500, 400); static public Rectangle defaultNewFrameBounds() { return swing(new F0() { public Rectangle get() { try { defaultNewFrameBounds_r.translate(60, 20); if (!screenRectangle().contains(defaultNewFrameBounds_r)) defaultNewFrameBounds_r.setLocation(30 + random(30), 20 + random(20)); return new Rectangle(defaultNewFrameBounds_r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "defaultNewFrameBounds_r.translate(60, 20);\r\n if (!screenRectangle().contai..."; } }); } static public void hideConsole() { final JFrame frame = consoleFrame(); if (frame != null) { autoVMExit(); swingLater(new Runnable() { public void run() { try { frame.setVisible(false); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setVisible(false);"; } }); } } static public boolean isAllUpperCase(String s) { return hasLettersAllUpperCase(s); } static public boolean isUpperCaseLetter(char c) { return Character.isUpperCase(c); } static public List getMultiPorts() { return (List) callOpt(getJavaX(), "getMultiPorts"); } static public String emptyToNull(String s) { return eq(s, "") ? null : s; } static public Map emptyToNull(Map map) { return empty(map) ? null : map; } static public void startMultiPort() { List mp = getMultiPorts(); if (mp != null && mp.isEmpty()) { nohupJavax("#1001639"); throw fail("Upgrading JavaX, please restart this program afterwards."); } } static public Set synchroTreeSet() { return Collections.synchronizedSet(new TreeSet()); } static public Set synchroTreeSet(TreeSet set) { return Collections.synchronizedSet(set); } static public boolean forbiddenPort(int port) { return port == 5037; } static public String readLineHidden() { try { if (get(javax(), "readLine_reader") == null) set(javax(), "readLine_reader", new BufferedReader(new InputStreamReader(System.in, "UTF-8"))); try { return ((BufferedReader) get(javax(), "readLine_reader")).readLine(); } finally { consoleClearInput(); } } catch (Exception __e) { throw rethrow(__e); } } static public int numberOfMethodArguments(Object o, String method) { Class c; boolean mustBeStatic = false; if (o instanceof Class) { c = (Class) o; mustBeStatic = true; } else c = o.getClass(); Class _c = c; int n = -1; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (!m.getName().equals(method)) continue; if (mustBeStatic && !methodIsStatic(m)) continue; int nn = l(m.getParameterTypes()); if (n == -1) n = nn; else if (n != nn) throw fail("Variable number of method arguments: " + _c + "." + method); } c = c.getSuperclass(); } if (n == -1) throw fail("Method not found: " + _c + "." + method); return n; } static public File localSnippetsDir() { return javaxDataDir("Personal Programs"); } static public File localSnippetsDir(String sub) { return newFile(localSnippetsDir(), sub); } static public String getOneLineFileInfoField(File f, String field) { File infoFile = associatedInfosFile(f); List lines = lines(loadTextFile(infoFile)); return firstStartingWithIC_drop(lines, field + ": "); } static public Frame getAWTFrame(final Object _o) { return swing(new F0() { public Frame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof Frame) return (Frame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n /*\r\n ifdef HaveProcessing\r\n if (o instanceof PApplet) ..."; } }); } static public void standardTitlePopupMenu(final JFrame frame) { if (!isSubstanceLAF()) return; titlePopupMenu(frame, new VF1() { public void get(JPopupMenu menu) { try { boolean alwaysOnTop = frame.isAlwaysOnTop(); menu.add(jmenuItem("Restart Program", "restart")); menu.add(jmenuItem("Duplicate Program", "duplicateThisProgram")); menu.add(jmenuItem("Show Console", "showConsole")); menu.add(jCheckBoxMenuItem("Always On Top", alwaysOnTop, new Runnable() { public void run() { try { toggleAlwaysOnTop(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "toggleAlwaysOnTop(frame)"; } })); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "bool alwaysOnTop = frame.isAlwaysOnTop();\r\n ifndef standardTitlePopupMenu_..."; } }); } static public Rectangle screenRectangle() { return new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); } static public Rectangle screenRectangle(GraphicsDevice device) { if (device == null) return null; DisplayMode mode = device.getDisplayMode(); return new Rectangle(0, 0, mode.getWidth(), mode.getHeight()); } static public JFrame consoleFrame() { return (JFrame) getOpt(get(getJavaX(), "console"), "frame"); } static public void autoVMExit() { call(getJavaX(), "autoVMExit"); } static public boolean hasLettersAllUpperCase(String s) { return hasLetters(s) && !containsLowerCase(s); } static public void duplicateThisProgram() { nohupJavax(trim(programID() + " " + smartJoin((String[]) get(getJavaX(), "fullArgs")))); } static public void showConsole() { callOpt(get(javax(), "console"), "showConsole"); } static public void nohupJavax(final String javaxargs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs);"; } }); } } static public void nohupJavax(final String javaxargs, final String vmArgs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs, vmArgs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs, vmArgs);"; } }); } } static public void consoleClearInput() { consoleSetInput(""); } static public File associatedInfosFile(File f) { return replaceExtension(f, ".infos"); } static public String firstStartingWithIC_drop(Collection l, final String prefix) { for (String s : unnull(l)) if (swic(s, prefix)) return substring(s, l(prefix)); return null; } static public String firstStartingWithIC_drop(String prefix, Collection l) { return firstStartingWithIC_drop(l, prefix); } static public boolean isSubstanceLAF() { return substanceLookAndFeelEnabled(); } static public boolean titlePopupMenu(final Component c, final Object menuMaker) { JComponent titleBar = getTitlePaneComponent(getPossiblyInternalFrame(c)); if (titleBar == null) { print("Can't add title right click!"); return false; } else { componentPopupMenu(titleBar, menuMaker); return true; } } static public JCheckBoxMenuItem jCheckBoxMenuItem(String text, boolean checked, final Object r) { final JCheckBoxMenuItem mi = new JCheckBoxMenuItem(text, checked); addActionListener(mi, new Runnable() { public void run() { try { callF(r, isChecked(mi)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r, isChecked(mi))"; } }); return mi; } static public void toggleAlwaysOnTop(JFrame frame) { frame.setAlwaysOnTop(!frame.isAlwaysOnTop()); } static public boolean hasLetters(String s) { for (int i = 0; i < s.length(); i++) if (Character.isLetter(s.charAt(i))) return true; return false; } static public boolean containsLowerCase(String s) { for (int i = 0; i < l(s); i++) if (isLowerCase(s.charAt(i))) return true; return false; } static public String smartJoin(String[] args) { if (empty(args)) return ""; if (args.length == 1) return args[0]; String[] a = new String[args.length]; for (int i = 0; i < a.length; i++) a[i] = !isJavaIdentifier(args[i]) && !isQuoted(args[i]) ? quote(args[i]) : args[i]; return join(" ", a); } static public String smartJoin(List args) { return smartJoin(toStringArray(args)); } static public Class hotwireOnce(String programID) { return hotwireCached(programID, false); } static public void consoleSetInput(final String text) { if (headless()) return; setTextAndSelectAll(consoleInputField(), text); focusConsole(); } static public File replaceExtension(File f, String extOld, String extNew) { return newFile(replaceExtension(f2s(f), extOld, extNew)); } static public File replaceExtension(File f, String extNew) { return replaceExtension(f, fileExtension(f), extNew); } static public String replaceExtension(String s, String extOld, String extNew) { s = dropSuffixIC(addPrefixOptIfNempty(".", extOld), s); return s + addPrefixOptIfNempty(".", extNew); } static public String replaceExtension(String name, String extNew) { return replaceExtension(name, fileExtension(name), extNew); } static public boolean substanceLookAndFeelEnabled() { return startsWith(getLookAndFeel(), "org.pushingpixels."); } static public JComponent getTitlePaneComponent(RootPaneContainer window) { if (window instanceof JInternalFrame) return getInternalFrameTitlePaneComponent((JInternalFrame) window); if (!substanceLookAndFeelEnabled() || window == null) return null; JRootPane rootPane = window.getRootPane(); if (rootPane != null) { Object ui = rootPane.getUI(); return (JComponent) call(ui, "getTitlePane"); } return null; } static public RootPaneContainer getPossiblyInternalFrame(Component c) { JInternalFrame f = getInternalFrame(c); if (f != null) return f; return optCast(RootPaneContainer.class, getWindow(c)); } static public void addActionListener(JTextField tf, final Runnable action) { onEnter(tf, action); } static public void addActionListener(final JComboBox cb, final Runnable action) { if (cb != null) { swing(new Runnable() { public void run() { try { cb.addActionListener(actionListener(action)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.addActionListener(actionListener(action));"; } }); } } static public void addActionListener(final AbstractButton b, final Runnable action) { if (b != null) { swing(new Runnable() { public void run() { try { b.addActionListener(actionListener(action)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "b.addActionListener(actionListener(action));"; } }); } } static public boolean isChecked(final JCheckBox checkBox) { return checkBox != null && (boolean) swing(new F0() { public Boolean get() { try { return checkBox.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret checkBox.isSelected();"; } }); } static public boolean isChecked(final JCheckBoxMenuItem mi) { return mi != null && (boolean) swing(new F0() { public Boolean get() { try { return mi.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret mi.isSelected();"; } }); } static public boolean isLowerCase(char c) { return Character.isLowerCase(c); } static public TreeMap hotwireCached_cache = new TreeMap(); static public Lock hotwireCached_lock = lock(); static public Class hotwireCached(String programID) { return hotwireCached(programID, true); } static public Class hotwireCached(String programID, boolean runMain) { return hotwireCached(programID, runMain, false); } static public Class hotwireCached(String programID, boolean runMain, boolean dependent) { Lock __0 = hotwireCached_lock; lock(__0); try { programID = formatSnippetID(programID); Class c = hotwireCached_cache.get(programID); if (c == null) { c = hotwire(programID); if (dependent) makeDependent(c); if (runMain) callMain(c); hotwireCached_cache.put(programID, c); } return c; } finally { unlock(__0); } } static public JTextField setTextAndSelectAll(final JTextField tf, final String text) { if (tf != null) { swing(new Runnable() { public void run() { try { tf.setText(text); tf.selectAll(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tf.setText(text);\r\n tf.selectAll();"; } }); } return tf; } static public void focusConsole(String s) { setConsoleInput(s); focusConsole(); } static public void focusConsole() { JComponent tf = consoleInputFieldOrComboBox(); if (tf != null) { tf.requestFocus(); } } static public String dropSuffixIC(String suffix, String s) { return s == null ? null : ewic(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static public String addPrefixOptIfNempty(String prefix, String s) { return addPrefixIfNotEmpty2(prefix, s); } static public String getLookAndFeel() { return getClassName(UIManager.getLookAndFeel()); } static public JComponent getInternalFrameTitlePaneComponent(JInternalFrame f) { return (JComponent) childWithClassNameEndingWith(f, "InternalFrameTitlePane"); } static public void setConsoleInput(String text) { consoleSetInput(text); } static public JComponent consoleInputFieldOrComboBox() { Object console = get(getJavaX(), "console"); JComboBox cb = (JComboBox) (getOpt(console, "cbInput")); if (cb != null) return cb; return (JTextField) getOpt(console, "tfInput"); } static public Component childWithClassNameEndingWith(Component c, String suffix) { if (endsWith(className(c), suffix)) return c; Component x; for (Component comp : getComponents(c)) if ((x = childWithClassNameEndingWith(comp, suffix)) != null) return x; return null; } final static public class LongRange { public long start, end; public LongRange() { } public LongRange(long start, long end) { this.end = end; this.start = start; } public boolean equals(Object o) { if (o instanceof LongRange) return start == ((LongRange) o).start && end == ((LongRange) o).end; return false; } public int hashCode() { return boostHashCombine(hashOfLong(start), hashOfLong(end)); } public long length() { return end - start; } static public String _fieldOrder = "start end"; public String toString() { return "[" + start + ";" + end + "]"; } } static public interface Producer { public A next(); } static abstract public class DialogIO implements AutoCloseable { public String line; public boolean eos, loud, noClose; public Lock lock = lock(); abstract public String readLineImpl(); abstract public boolean isStillConnected(); abstract public void sendLine(String line); abstract public boolean isLocalConnection(); abstract public Socket getSocket(); public int getPort() { Socket s = getSocket(); return s == null ? 0 : s.getPort(); } public boolean helloRead = false; public int shortenOutputTo = 500; public String readLineNoBlock() { String l = line; line = null; return l; } public boolean waitForLine() { try { ping(); if (line != null) return true; line = readLineImpl(); if (line == null) eos = true; return line != null; } catch (Exception __e) { throw rethrow(__e); } } public String readLine() { waitForLine(); helloRead = true; return readLineNoBlock(); } public String ask(String s, Object... args) { if (loud) return askLoudly(s, args); if (!helloRead) readLine(); if (args.length != 0) s = format3(s, args); sendLine(s); return readLine(); } public String askLoudly(String s, Object... args) { if (!helloRead) readLine(); if (args.length != 0) s = format3(s, args); print("> " + shorten(s, shortenOutputTo)); sendLine(s); String answer = readLine(); print("< " + shorten(answer, shortenOutputTo)); return answer; } public void pushback(String l) { if (line != null) throw fail(); line = l; helloRead = false; } } static abstract public class DialogHandler { abstract public void run(DialogIO io); } static public class InternationalPhoneValidator { public String rawInput; public String filtered; public List dialCodes; public String countryPart, localPart; public boolean valid = false; public String error; public InternationalPhoneValidator() { } public InternationalPhoneValidator(String rawInput) { this.rawInput = rawInput; } public void run() { filtered = dropPrefix("+", dropSpecialChars(rawInput)); if (!isAllDigits(filtered)) { error = "Bad characters"; return; } splitLocal(); } public String dropSpecialChars(String s) { return replaceAll(s, "[\\s\\(\\)\\-]", ""); } public void splitLocal() { String countryPart = longestPrefixInNavigableSet(filtered, navigableKeys(countryDialCodes_rawNumbersTreeMultiMap())); if (countryPart == null) { error = "Invalid country code"; return; } dialCodes = countryDialCodes_rawNumbersTreeMultiMap().get(countryPart); localPart = dropPrefix(countryPart, filtered); if (l(filtered) < 7) { error = "Phone number too short"; return; } else if (l(filtered) > 15) { error = "Phone number too long"; return; } valid = true; } } static public class AlphanumComparator implements Comparator { public boolean ignoreCase = false; final public boolean isDigit(char ch) { return ((ch >= 48) && (ch <= 57)); } final public String getChunk(String s, int slength, int marker) { StringBuilder chunk = new StringBuilder(); char c = s.charAt(marker); chunk.append(c); marker++; if (isDigit(c)) while (marker < slength) { c = s.charAt(marker); if (!isDigit(c)) break; chunk.append(c); marker++; } else while (marker < slength) { c = s.charAt(marker); if (isDigit(c)) break; chunk.append(c); marker++; } return chunk.toString(); } public int compare(String s1, String s2) { if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return 1; int thisMarker = 0; int thatMarker = 0; int s1Length = s1.length(); int s2Length = s2.length(); while (thisMarker < s1Length && thatMarker < s2Length) { String thisChunk = getChunk(s1, s1Length, thisMarker); thisMarker += thisChunk.length(); String thatChunk = getChunk(s2, s2Length, thatMarker); thatMarker += thatChunk.length(); int result = 0; if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) { int thisChunkLength = thisChunk.length(); result = thisChunkLength - thatChunk.length(); if (result == 0) { for (int i = 0; i < thisChunkLength; i++) { result = thisChunk.charAt(i) - thatChunk.charAt(i); if (result != 0) { return result; } } } } else { result = thisChunk.compareTo(thatChunk); } if (result != 0) return result; } return s1Length - s2Length; } } static public class SnippetTitles { public Map titles = synchroHashMap(); public String get(String snippetID) { if (snippetID == null) return null; long id = parseSnippetID(snippetID); if (titles.containsKey(id)) return titles.get(id); else { String title = getSnippetTitle_safe(snippetID); titles.put(id, title); return title; } } public String probe(String id) { return titles.get(parseSnippetID(id)); } public void put(String id, String title) { titles.put(parseSnippetID(id), title); } public boolean has(String id) { return titles.containsKey(parseSnippetID(id)); } public void clear() { titles.clear(); } } static public class _PrintIndent extends F1 { public String prefix; public boolean beginningOfLine = true; public _PrintIndent() { } public _PrintIndent(String prefix) { this.prefix = prefix; } public Boolean get(String s) { if (empty(s)) return false; boolean nl = s.endsWith("\n"); if (nl) s = dropLast(s); s = s.replace("\n", "\n" + prefix); print_raw(beginningOfLine ? prefix + s : s); if (nl) print_raw("\n"); beginningOfLine = nl; return false; } } abstract static public class AbstractLayoutManager implements LayoutManager { public Dimension preferredSize = new Dimension(100, 100); public Dimension minimumSize = new Dimension(10, 10); public void addLayoutComponent(String name, Component comp) { } public void removeLayoutComponent(Component comp) { } public Dimension preferredLayoutSize(Container parent) { layoutContainer(parent); return preferredSize; } public Dimension minimumLayoutSize(Container parent) { return minimumSize; } } static abstract public class LiveValue { abstract public Class getType(); abstract public A get(); abstract public void onChange(Runnable l); abstract public void removeOnChangeListener(Runnable l); public void onChangeAndNow(Runnable l) { onChange(l); callF(l); } } static public class Scored extends Var { public float score; public Scored() { } public Scored(A a, float score) { super(a); this.score = score; } public Scored(A a, double score) { super(a); this.score = (float) score; } public float score() { return score; } public String toString() { return toIntPercent(score) + "%: " + str(get()); } } static final public class ParameterizedTypeImpl implements ParameterizedType { final public Type ownerType; final public Type rawType; final public Type[] typeArguments; public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) { this.typeArguments = typeArguments; this.rawType = rawType; this.ownerType = ownerType; } public Type[] getActualTypeArguments() { return typeArguments; } public Type getRawType() { return rawType; } public Type getOwnerType() { return ownerType; } @Override public boolean equals(Object other) { if (other instanceof ParameterizedType) return eq(ownerType, ((ParameterizedType) other).getOwnerType()) && eq(rawType, ((ParameterizedType) other).getRawType()) && eq(asList(typeArguments), asList(((ParameterizedType) other).getActualTypeArguments())); return false; } @Override public int hashCode() { return Arrays.hashCode(typeArguments) ^ rawType.hashCode() ^ _hashCode(ownerType); } @Override public String toString() { int length = typeArguments.length; if (length == 0) return typeToString(rawType); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(typeToString(rawType)).append("<").append(typeToString(typeArguments[0])); for (int i = 1; i < length; i++) { stringBuilder.append(", ").append(typeToString(typeArguments[i])); } return stringBuilder.append(">").toString(); } static public String typeToString(Type type) { return type instanceof Class ? ((Class) type).getName() : type.toString(); } } static public class MetaTransformer { static public interface StructureHandler { public Object transform(Object o, IF1 recurse); public void visit(Object o, IVF1 recurse); } public List structureHandlers; public MetaTransformer() { } public MetaTransformer(StructureHandler... handlers) { structureHandlers = asList(handlers); } public Object transform(IF1 f, Object o) { ping(); { Object __1 = f.get(o); if (__1 != null) return __1; } IF1 recurse = asFunction(f); for (StructureHandler h : unnull(structureHandlers)) { ping(); { Object __2 = h.transform(o, recurse); if (__2 != null) return __2; } } return o; } public void visit(IVF1 f, Object o) { ping(); f.get(o); IVF1 recurse = x -> visit(f, x); for (StructureHandler h : unnull(structureHandlers)) { ping(); h.visit(o, recurse); } } public IF1 asFunction(IF1 f) { return o -> transform(f, o); } public boolean any(IF1 pred, Object o) { Flag flag = new Flag(); withCancelPoint(cp -> visit(x -> { if (pred.get(x)) { flag.raise(); cancelTo(cp); } }, o)); return flag.isUp(); } } static public A highestConceptByField(Class c, String field) { return highestConceptByField(db_mainConcepts(), c, field); } static public A highestConceptByField(Concepts concepts, Class c, String field) { IFieldIndex index = concepts.getFieldIndex(c, field); if (index instanceof ConceptFieldIndexDesc) { Map.Entry e = ((NavigableMap) ((ConceptFieldIndexDesc) index).valueToObject.data).firstEntry(); return e == null ? null : (A) first((Collection) e.getValue()); } return highestByField(field, concepts.list(c)); } static public List sortedByConceptIDDesc(Collection c) { return sortedByCalculatedFieldDesc(__116 -> conceptID(__116), c); } static public String joinNemptiesWithColon(String... strings) { return joinNempties(": ", strings); } static public String joinNemptiesWithColon(Collection strings) { return joinNempties(": ", strings); } static public long parseLongOpt_pcall(String s) { try { return isInteger(s) ? parseLong(s) : 0; } catch (Throwable __e) { print(exceptionToStringShort(__e)); } return 0; } static public String addPlusToCount(long max, long n, String s) { if (n != max) return s; return insertString(s, smartIndexOfSpaceEtc(s), "+"); } static public Map withoutKey(Map map, A key) { return mapWithoutKey(map, key); } static public Map withoutKey(A key, Map map) { return withoutKey(map, key); } static public List stringToStringListOpt(IF1> f, Object o) { if (o instanceof String) return f.get(((String) o)); return (List) o; } static public List tok_identifiersInOrder(String s) { return filter(__117 -> isIdentifier(__117), javaTokC(s)); } static public Pair uniq2(Class c, Object... params) { return uniq2(db_mainConcepts(), c, params); } static public Pair uniq2(Concepts cc, Class c, Object... params) { AutoCloseable __1 = tempDBLock(cc); try { params = expandParams(c, params); A x = findConceptWhere(cc, c, params); if (x == null) { x = unlisted(c); csetAll(x, params); cc.register(x); return pair(x, true); } return pair(x, false); } finally { _close(__1); } } static public List allToLong(Collection l) { return lmap(__118 -> toLong(__118), l); } static public List tok_integersInOrder(String s) { return filter(__119 -> isInteger(__119), javaTokC(s)); } static public boolean isProperlyQuoted(String s) { return s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"") && (!s.endsWith("\\\"") || s.endsWith("\\\\\"")) && !containsNewLine(s); } static public Map safeUnstructureMap(String s) { return (Map) safeUnstructure(s); } static public Map onlyKeys(Map map, Collection keys) { Set keySet = asSet(keys); return filterKeys(map, a -> contains(keySet, a)); } static public Map onlyKeys(Map map, A... keys) { return onlyKeys(map, litset(keys)); } static public B getAndRemove(Map map, A a) { if (!containsKey(map, a)) return null; B b = map.get(a); map.remove(a); return b; } static public B getAndRemove(A a, Map map) { return getAndRemove(map, a); } static public String sortLinesAlphaNumIC(String s) { return lines_possiblyRTrim(s, sortedAlphanumIC(lines(s))); } static public String unquoteAllLines(String s) { return linesPreservingTrailingNewLine(s, unquoteAll(lines(s))); } static public Either eitherB(B b) { return new Either(2, b); } static public Either eitherA(A a) { return new Either(1, a); } static public GlobalID aGlobalIDObjUnlessLoading() { return dynamicObjectIsLoading() ? null : aGlobalIDObj(); } static public Map prependEmptyOptionForHSelect(Map map) { Map map2 = litorderedmap("", ""); putAll(map2, map); return map2; } static public LinkedHashMap mapToOrderedMap(Object f, Iterable l) { LinkedHashMap map = new LinkedHashMap(); for (Object o : unnull(l)) { Pair p = (Pair) (callF(f, o)); map.put(p.a, p.b); } return map; } static public LinkedHashMap mapToOrderedMap(IF1> f, Iterable l) { LinkedHashMap map = new LinkedHashMap(); for (A o : unnull(l)) { Pair p = callF(f, o); map.put(p.a, p.b); } return map; } static public LinkedHashMap mapToOrderedMap(Iterable l, IF1> f) { return mapToOrderedMap(f, l); } static public boolean conceptsSortedByFieldCI_verbose = false; static public Collection conceptsSortedByFieldCI(Class c, String field) { return conceptsSortedByFieldCI(db_mainConcepts(), c, field); } static public Collection conceptsSortedByFieldCI(Concepts concepts, Class c, String field) { IFieldIndex index = concepts.getCIFieldIndex(c, field); if (index instanceof ConceptFieldIndexCI) return (Collection) asList(((ConceptFieldIndexCI) index).objectIterator()); if (conceptsSortedByFieldCI_verbose) print("conceptsSortedByFieldCI_verbose: Manual sort of " + c + " for " + field); return sortedByFieldIC(field, concepts.list(c)); } static public String hselect(String name, Map map, Object... params) { return hselect(map, paramsPlus_skipFirst(params, "name", name)); } static public String hselect(Map map, Object... params) { StringBuilder buf = new StringBuilder(); String selected = null; if (odd(l(params))) { selected = str(first(params)); params = dropFirst(params); } int i = indexOf(params, "allowEmpty"); if (even(i)) { buf.append("\n"); params[i] = params[i + 1] = null; } if (nempty(map)) for (Object key : keys(map)) { Object value = map.get(key); String k = str(key); buf.append(tag("option", htmlencode(str(or(value, ""))), "value", k, "selected", eq(selected, k) ? "selected" : null)).append("\n"); } return tag("select", buf, params) + "\n"; } static public String hquery(Map params) { return htmlQuery(params); } static public String hquery(Object... data) { return htmlQuery(data); } static public String loadJQuery() { return ""; } static public String hscriptsrc(String src) { return hjavascript_src(src); } static public boolean conceptsWithFieldGreaterThan_verbose = false; static public Collection conceptsWithFieldGreaterThan(Class c, String field, Object value) { return conceptsWithFieldGreaterThan(db_mainConcepts(), c, field, value); } static public Collection conceptsWithFieldGreaterThan(Concepts concepts, Class c, String field, Object value) { IFieldIndex index = concepts.getFieldIndex(c, field); if (index instanceof ConceptFieldIndexDesc) return ((ConceptFieldIndexDesc) index).objectsWithValueGreaterThan(value); if (conceptsWithFieldGreaterThan_verbose) print("conceptsWithFieldGreaterThan: table scan of " + c + " for field " + field); return objectsWhereFieldGreaterThan(concepts.list(c), field, value); } static public String hhiddenWithID(String id) { return hhiddenWithID(id, null); } static public String hhiddenWithID(String id, Object value, Object... params) { return tag("input", "", paramsPlus(params, "type", "hidden", "id", id, "value", value)); } static public String hsimpletableheader(String... cols) { return tag("tr", join(lambdaMap(__120 -> th(__120), cols))); } static public List lastTwo(List l) { return takeLast(2, l); } static public String hscript_clickableRows() { return hscript("\r\n jQuery(document).ready(function($) {\r\n $(\".clickable-row\").click(function() {\r\n window.location = $(this).data(\"href\");\r\n });\r\n });\r\n "); } static public String hcheckboxWithText(String name, String text, boolean checked, Object... params) { String id = randomID(); return hcheckbox(name, checked, paramsPlus(params, "id", id)) + " " + hlabelFor(id, htmlEncode2(text)); } static public String hcheckboxWithText(String name, String text) { return hcheckboxWithText(name, text, false); } static public String hdivWithID(String id, Object contents, Object... params) { return hdiv(contents, paramsPlus(params, "id", id)); } static public String hdesktopNotifications() { return hscript("\r\n function sendDesktopNotification(text, options) {\r\n if (\"Notification\" in window && Notification.permission === \"granted\")\r\n new Notification(text, options);\r\n }\r\n window.sendDesktopNotification = sendDesktopNotification;\r\n \r\n function initDesktopNotifications() {\r\n if (!(\"Notification\" in window))\r\n $(\"#notiStatus\").html(\"Desktop notifications not supported in this browser\");\r\n else if (Notification.permission === \"granted\")\r\n $(\"#notiStatus\").html(\"Desktop notifications enabled\");\r\n else if (Notification.permission === \"denied\")\r\n $(\"#notiStatus\").html(\"Desktop notifications denied\");\r\n else {\r\n $(\"#notiStatus\").html(\"Requesting permission for desktop notifications\");\r\n Notification.requestPermission().then(function (permission) {\r\n initDesktopNotifications();\r\n sendDesktopNotification(\"Notifications will look like this!\");\r\n });\r\n }\r\n }\r\n \r\n $(document).ready(initDesktopNotifications);\r\n "); } static public String hframeset_cols(String cols, Object contents, Object... params) { return tag("frameset", contents, paramsPlus(params, "cols", cols)); } static public String hframeset_rows(String rows, Object contents, Object... params) { return tag("frameset", contents, paramsPlus(params, "rows", rows)); } static public String htmlEncode2If(boolean b, String s) { return b ? htmlEncode2(s) : s; } static public JPanel centerAndSouthWithMargins(Component c, Component s) { return applyDefaultMargin(centerAndSouth(c, withTopMargin(s))); } static public JPanel jrightalignedline(Component... components) { return jrightAlignedLine(components); } static public JPanel jrightalignedline(List components) { return jrightAlignedLine(components); } static public JCheckBox dm_fieldCheckBox(String field) { return dm_fieldCheckBox(humanizeFormLabel(field), field); } static public JCheckBox dm_fieldCheckBox(String text, String field) { if (isIdentifier(text) && !isIdentifier(field)) { String temp = field; field = text; text = temp; } return jLiveValueCheckBox(text, dm_fieldLiveValue(field)); } static public void addComponentsFirst(Container c, Component... l) { containerAddFirst(c, l); } static public int hashOfLong(long l) { return Long.hashCode(l); } static public int length(Object[] array) { return array == null ? 0 : array.length; } static public int length(List list) { return list == null ? 0 : list.size(); } static public int length(String s) { return s == null ? 0 : s.length(); } static public boolean isAllDigits(String s) { int n = l(s); for (int i = 0; i < n; i++) if (!isDigit(s.charAt(i))) return false; return true; } static public List replaceAll(List l, final A a, final A b) { return map(l, new F1() { public A get(A x) { try { return eq(x, a) ? b : x; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "eq(x, a) ? b : x"; } }); } static public String replaceAll(String s, String a, String b) { return s == null ? null : s.replaceAll(a, b); } static public String longestPrefixInNavigableSet(String s, NavigableSet set) { if (set == null || s == null) return null; while (licensed()) { String key = set.floor(s); if (key == null) break; int n = lCommonPrefix(key, s); if (n == l(key)) return key; s = takeFirst(s, n); } return null; } static public NavigableSet navigableKeys(NavigableMap map) { return map == null ? new TreeSet() : map.navigableKeySet(); } static public NavigableSet navigableKeys(MultiSet ms) { return ((NavigableMap) ms.map).navigableKeySet(); } static public NavigableSet navigableKeys(MultiMap mm) { return ((NavigableMap) mm.data).navigableKeySet(); } static public Cache> countryDialCodes_rawNumbersTreeMultiMap_cache = new Cache<>(() -> countryDialCodes_rawNumbersTreeMultiMap_load()); static public MultiMap countryDialCodes_rawNumbersTreeMultiMap() { return countryDialCodes_rawNumbersTreeMultiMap_cache.get(); } static public MultiMap countryDialCodes_rawNumbersTreeMultiMap_load() { return mapToMultiMap(mapKeys(__121 -> digitsOnly(__121), multiMapToMap(countryDialCodesMultiMap()))); } static public String getSnippetTitle_safe(String id) { if (isLocalSnippetID(id)) return localSnippetTitle(id); String title = or(loadTextFile(snippetTitle_cacheFile(id)), "?"); try { title = getSnippetTitle(id); } catch (Throwable __e) { _handleException(__e); } return title; } static public A onChange(A spinner, Object r) { { swing(new Runnable() { public void run() { try { spinner.addChangeListener(changeListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "spinner.addChangeListener(changeListener(r));"; } }); } return spinner; } static public A onChange(A b, Object r) { { swing(new Runnable() { public void run() { try { b.addItemListener(itemListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "b.addItemListener(itemListener(r));"; } }); } return b; } static public void onChange(JTextComponent tc, Object r) { onUpdate(tc, r); } static public A onChange(A slider, final Object r) { { swing(new Runnable() { public void run() { try { slider.addChangeListener(changeListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "slider.addChangeListener(changeListener(r));"; } }); } return slider; } static public JComboBox onChange(Object r, JComboBox cb) { return onChange(cb, r); } static public JComboBox onChange(JComboBox cb, final Object r) { if (isEditableComboBox(cb)) onChange(textFieldFromComboBox(cb), r); else onSelectedItem(cb, new VF1() { public void get(String s) { try { callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r)"; } }); return cb; } static public int toIntPercent(double ratio) { return roundToInt(ratio * 100); } static public int toIntPercent(float ratio) { return toIntPercent((double) ratio); } static public Type getRawType(Type t) { if (t instanceof ParameterizedType) return ((ParameterizedType) t).getRawType(); return t; } static public A highestByField(String field, Collection l) { A best = null; Object bestValue = null; if (l != null) for (A a : l) { Object val = getOpt(a, field); if (val != null && (bestValue == null || cmp(val, bestValue) > 0)) { best = a; bestValue = val; } } return best; } static public A highestByField(Collection l, String field) { return highestByField(field, l); } static public String insertString(String a, int idx, String b) { return spliceString(a, idx, idx, b); } static public int smartIndexOfSpaceEtc(String s) { int i = indexOfSpaceEtc(s); return i < 0 ? l(s) : i; } static public Map mapWithoutKey(Map map, A key) { if (map == null || !map.containsKey(key)) return map; Map m = cloneMap(map); m.remove(key); return m; } static public Map mapWithoutKey(A key, Map map) { return mapWithoutKey(map, key); } static public String lines_possiblyRTrim(String originalText, List lines) { return endsWithNewLine(originalText) ? lines(lines) : lines_rtrim(lines); } static public String lines_possiblyRTrim(List lines, String originalText) { return lines_possiblyRTrim(originalText, lines); } static public List sortedAlphanumIC(Collection c) { List l = cloneList(c); Collections.sort(l, alphaNumComparatorIC()); return l; } static public String linesPreservingTrailingNewLine(String original, List lines) { String s = lines(lines); return endsWith(original, "\n") ? s : dropSuffix("\n", s); } static public List unquoteAll(List l) { List t = cloneList(l); for (int i = 0; i < l(t); i++) if (isQuoted(t.get(i))) t.set(i, unquote(t.get(i))); return t; } static public GlobalID aGlobalIDObj() { return asGlobalID(randomID(16)); } static public GlobalID aGlobalIDObj(Random random) { return asGlobalID(randomID(random, 16)); } static public List sortedByFieldIC(Collection c, final String field) { List l = new ArrayList(c); sort(l, new Comparator() { public int compare(A a, A b) { return compareIC((String) getOpt(a, field), (String) getOpt(b, field)); } }); return l; } static public List sortedByFieldIC(String field, Collection c) { return sortedByFieldIC(c, field); } static public Object[] paramsPlus_skipFirst(Object[] a1, Object... a2) { if (odd(l(a1))) return itemPlusArray(first(a1), paramsPlus(dropFirst(a1), a2)); return paramsPlus(a1, a2); } static public String th(Object contents, Object... params) { return tag("th", contents, params); } static public String hlabelFor(String id, Object contents) { return htag("label", contents, "for", id); } static public A applyDefaultMargin(final A c) { if (c != null) { swing(new Runnable() { public void run() { try { c.setBorder(BorderFactory.createEmptyBorder(withMargin_defaultWidth, withMargin_defaultWidth, withMargin_defaultWidth, withMargin_defaultWidth)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setBorder(BorderFactory.createEmptyBorder(withMargin_defaultWidth, withMarg..."; } }); } return c; } static public JPanel centerAndSouth(final Component c, final Component s) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.CENTER, wrap(c)); if (s != null) panel.add(BorderLayout.SOUTH, wrap(s)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.CENT..."; } }); } static public int withTopMargin_defaultWidth = 6; static public JPanel withTopMargin(Component c) { return withTopMargin(withTopMargin_defaultWidth, c); } static public JPanel withTopMargin(final int w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(w, 0, 0, 0)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static public JPanel jrightAlignedLine(final Component... components) { return swing(new F0() { public RightAlignedLine get() { try { return new RightAlignedLine(components); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret RightAlignedLine(components);"; } }); } static public JPanel jrightAlignedLine(List components) { return jrightAlignedLine(asArray(Component.class, components)); } static public JCheckBox jLiveValueCheckBox(String text, final SimpleLiveValue lv) { final JCheckBox cb = jCheckBox(text); bindCheckBoxToLiveValue(cb, lv); return cb; } static public SimpleLiveValue dm_fieldLiveValue(String fieldName) { return dm_fieldLiveValue(dm_current_mandatory(), fieldName); } static public SimpleLiveValue dm_fieldLiveValue(final DynModule module, final String fieldName) { Lock __0 = module.lock; lock(__0); try { AutoCloseable __2 = module.enter(); try { Class type = getFieldType(module, fieldName); final SimpleLiveValue value = new SimpleLiveValue(type, get(module, fieldName)); dm_watchField(fieldName, new Runnable() { public void run() { try { Object o = get(module, fieldName); value.set(o); ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef dm_fieldLiveValue_debug\r\n print(\"dm_fieldLiveValue: setting \" + fi..."; } }); value.onChange(new Runnable() { public void run() { try { module.setField(fieldName, value.get()); ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef dm_fieldLiveValue_debug\r\n print(\"dm_fieldLiveValue: setting 2 \" + ..."; } }); return value; } finally { _close(__2); } } finally { unlock(__0); } } static public void containerAddFirst(final Container c, final Component... l) { if (c != null) { swing(new Runnable() { public void run() { try { for (int i = 0; i < l(l); i++) c.add(l[i], i); revalidate(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (int i = 0; i < l(l); i++)\r\n c.add(l[i], i);\r\n revalidate(c);"; } }); } } static public int lCommonPrefix(String a, String b) { int i = 0, n = Math.min(l(a), l(b)); while (i < n && a.charAt(i) == b.charAt(i)) ++i; return i; } static public > MultiMap mapToMultiMap(Map map) { if (map == null) return null; MultiMap mm = similarEmptyMultiMap(map); for (Map.Entry> __0 : _entrySet(map)) { A key = __0.getKey(); Collection values = __0.getValue(); mm.putAll(key, values); } return mm; } static public String digitsOnly(String s) { return filterChars(__122 -> isDigit(__122), s); } static public ChangeListener changeListener(final Object r) { return new ChangeListener() { public void stateChanged(ChangeEvent e) { pcallF(r); } }; } static public ItemListener itemListener(final Object r) { return new ItemListener() { public void itemStateChanged(ItemEvent e) { pcallF(r); } }; } static public void onUpdate(JComponent c, final Object r) { if (c instanceof JTextComponent) ((JTextComponent) c).getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { call(r); } public void removeUpdate(DocumentEvent e) { call(r); } public void changedUpdate(DocumentEvent e) { call(r); } }); else if (c instanceof ItemSelectable) ((ItemSelectable) c).addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { call(r); } }); else print("Warning: onUpdate doesn't know " + getClassName(c)); } static public void onUpdate(List l, Object r) { for (JComponent c : l) onUpdate(c, r); } static public JTextField textFieldFromComboBox(JComboBox cb) { return (JTextField) cb.getEditor().getEditorComponent(); } static public JComboBox onSelectedItem(final JComboBox cb, final VF1 f) { addActionListener(cb, new Runnable() { public void run() { try { pcallF(f, selectedItem(cb)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(f, selectedItem(cb))"; } }); return cb; } static public int roundToInt(double d) { return (int) Math.round(d); } static public String spliceString(String a, int from, int to, String b) { return takeFirst(a, from) + b + substring(a, max(from, to)); } static public String spliceString(String a, int from, int to, char b) { return spliceString(a, from, to, str(b)); } static public boolean endsWithNewLine(String s) { return endsWith(s, "\n"); } static public AlphanumComparator alphaNumComparatorIC_instance; static public Comparator alphaNumComparatorIC() { if (alphaNumComparatorIC_instance == null) { AlphanumComparator ac = new AlphanumComparator(); ac.ignoreCase = true; alphaNumComparatorIC_instance = ac; } return alphaNumComparatorIC_instance; } static public GlobalID asGlobalID(String id) { return id == null ? null : new GlobalID(id); } static public int compareIC(String s1, String s2) { return compareIgnoreCase_jdk(s1, s2); } static public A[] itemPlusArray(A a, A[] l) { return singlePlusArray(a, l); } static public JCheckBox jCheckBox() { return swingNu(JCheckBox.class); } static public JCheckBox jCheckBox(boolean checked) { return swingNu(JCheckBox.class, "", checked); } static public JCheckBox jCheckBox(String text, boolean checked) { return swingNu(JCheckBox.class, text, checked); } static public JCheckBox jCheckBox(String text) { return swingNu(JCheckBox.class, text); } static public JCheckBox jCheckBox(String text, boolean checked, final Object onChange) { JCheckBox cb = jCheckBox(checked, onChange); cb.setText(text); return cb; } static public JCheckBox jCheckBox(boolean checked, final Object onChange) { final JCheckBox cb = jCheckBox(checked); cb.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { pcallF(onChange, cb.isSelected()); } }); return cb; } static public A bindCheckBoxToLiveValue(final A cb, final SimpleLiveValue lv) { bindLiveValueListenerToComponent(cb, lv, new Runnable() { public void run() { try { setChecked(cb, isTrue(lv.get())); ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef bindCheckBoxToLiveValue_debug\r\n print(\"bindCheckBoxToLiveValue: se..."; } }); onChange(cb, new Runnable() { public void run() { try { lv.set(isChecked(cb)); ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef bindCheckBoxToLiveValue_debug\r\n print(\"bindCheckBoxToLiveValue: se..."; } }); return cb; } static public Class getFieldType(Object o, String field) { return fieldType(o, field); } static public void dm_watchField(String field, Runnable onChange) { new Dyn_FieldWatcher(dm_current_mandatory(), field, onChange); } static public MultiMap similarEmptyMultiMap(MultiMap m) { return similarEmptyMultiMap(m == null ? null : m.data); } static public MultiMap similarEmptyMultiMap(Map m) { MultiMap mm = new MultiMap(); if (m != null) mm.data = similarEmptyMap(m); return mm; } static public String filterChars(IF1 pred, String s) { if (s == null) return null; StringBuilder buf = new StringBuilder(); int n = l(s); char c; for (int i = 0; i < n; i++) if (isTrue(callF(pred, c = s.charAt(i)))) buf.append(c); return str(buf); } static public String selectedItem(JList l) { return getSelectedItem(l); } static public String selectedItem(JComboBox cb) { return getSelectedItem(cb); } static public int compareIgnoreCase_jdk(String s1, String s2) { if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return 1; int n1 = s1.length(); int n2 = s2.length(); int min = Math.min(n1, n2); for (int i = 0; i < min; i++) { char c1 = s1.charAt(i); char c2 = s2.charAt(i); if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); if (c1 != c2) return c1 - c2; } } } return n1 - n2; } static public A[] singlePlusArray(A a, A[] l) { A[] out = newObjectArrayOfSameType(l, l(l) + 1); out[0] = a; arraycopy(l, 0, out, 1, l(l)); return out; } static public void setChecked(JCheckBox checkBox, boolean b) { if (checkBox != null) { swing(new Runnable() { public void run() { try { if (isChecked(checkBox) != b) checkBox.setSelected(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (isChecked(checkBox) != b)\r\n checkBox.setSelected(b);"; } }); } } static public void setChecked(JCheckBoxMenuItem mi, boolean b) { if (mi != null) { swing(new Runnable() { public void run() { try { mi.setSelected(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mi.setSelected(b);"; } }); } } static public class SimpleLiveValue extends LiveValue { public Class type; volatile public A value; transient public List onChange = synchroList(); public SimpleLiveValue(Class type) { this.type = type; } public SimpleLiveValue(Class type, A value) { this.value = value; this.type = type; } public Class getType() { return type; } public A get() { return value; } public void onChange(Runnable l) { onChange.add(l); } public void onChangeAndNow(Runnable l) { onChange(l); callF(l); } public void removeOnChangeListener(Runnable l) { onChange.remove(l); } public void fireChanged() { pcallFAll(onChange); } public void set(A a) { if (neq(value, a)) { value = a; fireChanged(); } } } static public class Dyn_FieldWatcher { public DynModule module; public String field; public Object value; public Runnable action; transient public IF1 cloneValue; public Object cloneValue(Object o) { return cloneValue != null ? cloneValue.get(o) : cloneValue_base(o); } final public Object cloneValue_fallback(IF1 _f, Object o) { return _f != null ? _f.get(o) : cloneValue_base(o); } public Object cloneValue_base(Object o) { return o; } public Dyn_FieldWatcher(DynModule module, String field, Runnable action) { this(module, field, action, null); } public Dyn_FieldWatcher(DynModule module, String field, Runnable action, IF1 cloneValue) { this.cloneValue = cloneValue; this.action = action; this.field = field; this.module = module; value = cloneValue(get(module, field)); module.onChange(new Runnable() { public void run() { try { check(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "check();"; } }); module.onFieldChange(new VF1() { public void get(String f) { try { if (eq(f, field)) check(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(f, field))\r\n check();"; } }); } public void check() { Object newValue = cloneValue(get(module, field)); if (eq(value, newValue)) return; value = newValue; dm_q(module, action); } } static public class RightAlignedLine extends JPanel { public RightAlignedLine(Component... components) { setLayout(LetterLayout.rightAlignedRow()); for (Component component : components) add(component); } public void add(String text) { add(new JLabel(text)); } } static public class LetterLayout implements LayoutManager { public String[] lines; public Map map = new TreeMap(); public RC[] rows; public RC[] cols; public Cell[][] cells; public int spacingX = 10, spacingY = 10; public int insetTop, insetBottom, insetLeft, insetRight; public int template; public boolean formWideLeftSide, formWideRightSide; static final public int STALACTITE = 1, LEFT_ALIGNED_ROW = 2, CENTERED_ROW = 3, FORM = 4, RIGHT_ALIGNED_ROW = 5; public boolean debug = false; public void setLeftBorder(int border) { insetLeft = border; } public void setRightBorder(int border) { insetRight = border; } public static JComponent withBorder(JComponent component, int border) { JPanel panel = new JPanel(new LetterLayout("C").setBorder(border)); panel.add("C", component); return panel; } public static JPanel panel(String... lines) { return new JPanel(new LetterLayout(lines)); } public static JPanel stalactitePanel() { return new JPanel(stalactite()); } static public class DummyComponent extends JComponent { } static public class Cell { public boolean aux = false; public int minWidth, minHeight; public Component component; public int colspan, rowspan; public double weightX, weightY; } static public class RC { public int min; public double weightSum; public int start; public int minEnd; } public LetterLayout(int template) { this.template = template; } public LetterLayout(String... lines) { this.lines = lines; } public void removeLayoutComponent(Component component) { map.values().remove(component); } public void layoutContainer(Container container) { prepareLayout(container); if (debug) System.out.println("Container size: " + container.getSize()); Insets insets = getInsets(container); for (int r = 0; r < rows.length; r++) { for (int i = 0; i < cols.length; ) { Cell cell = cells[i][r]; if (cell.aux) ++i; else { if (cell.component != null) { int x1 = cols[i].start; int y1 = rows[r].start; int x2 = i + cell.colspan < cols.length ? cols[i + cell.colspan].start - spacingX : container.getWidth() - insets.right; int y2 = r + cell.rowspan < rows.length ? rows[r + cell.rowspan].start - spacingY : container.getHeight() - insets.bottom; if (debug) System.out.println("Layouting (" + i + ", " + r + ", " + cell.component.getClass().getName() + "): " + x1 + " " + y1 + " " + x2 + " " + y2); cell.component.setBounds(x1, y1, x2 - x1, y2 - y1); } i += cells[i][r].colspan; } } } } final public void prepareLayout(Container container) { applyTemplate(container); int numRows = lines.length, numCols = lines[0].length(); for (int i = 1; i < numRows; i++) if (lines[i].length() != numCols) throw new IllegalArgumentException("Lines have varying length"); cells = new Cell[numCols][numRows]; rows = new RC[numRows]; cols = new RC[numCols]; for (int r = 0; r < numRows; r++) rows[r] = new RC(); for (int i = 0; i < numCols; i++) cols[i] = new RC(); for (int r = 0; r < numRows; r++) for (int i = 0; i < numCols; i++) cells[i][r] = new Cell(); for (int r = 0; r < numRows; r++) { String line = lines[r]; for (int i = 0; i < numCols; ) { Cell cell = cells[i][r]; if (cell.aux) { ++i; continue; } char ch = line.charAt(i); int iNext = i; do ++iNext; while (iNext < numCols && ch == line.charAt(iNext)); int rNext = r; do ++rNext; while (rNext < numRows && ch == lines[rNext].charAt(i)); cell.weightX = numCols == 1 || iNext > i + 1 ? 1.0 : 0.0; cell.weightY = numRows == 1 || rNext > r + 1 ? 1.0 : 0.0; Component c = map.get(String.valueOf(ch)); cell.component = c; if (c != null) { cell.minWidth = c.getMinimumSize().width + spacingX; cell.minHeight = getMinimumHeight(c) + spacingY; } cell.colspan = iNext - i; cell.rowspan = rNext - r; if (cell.colspan == 1) cols[i].min = Math.max(cols[i].min, cell.minWidth); if (cell.rowspan == 1) rows[r].min = Math.max(rows[r].min, cell.minHeight); for (int r2 = r; r2 < rNext; r2++) for (int i2 = i; i2 < iNext; i2++) if (r2 != r || i2 != i) cells[i2][r2].aux = true; i = iNext; } } while (true) { for (int i = 0; i < numCols; i++) { int minStart = i == 0 ? 0 : cols[i - 1].minEnd; double weightStart = i == 0 ? 0.0 : cols[i - 1].weightSum; for (int r = 0; r < numRows; r++) { Cell cell = cells[i][r]; if (!cell.aux) { RC rc = cols[i + cell.colspan - 1]; rc.minEnd = Math.max(rc.minEnd, minStart + cell.minWidth); rc.weightSum = Math.max(rc.weightSum, weightStart + cell.weightX); } } } for (int r = 0; r < numRows; r++) { int minStart = r == 0 ? 0 : rows[r - 1].minEnd; double weightStart = r == 0 ? 0.0 : rows[r - 1].weightSum; for (int i = 0; i < numCols; i++) { Cell cell = cells[i][r]; if (!cell.aux) { RC rc = rows[r + cell.rowspan - 1]; rc.minEnd = Math.max(rc.minEnd, minStart + cell.minHeight); rc.weightSum = Math.max(rc.weightSum, weightStart + cell.weightY); } } } if (allWeightsZero(cols)) { for (int r = 0; r < numRows; r++) for (int i = 0; i < numCols; i++) cells[i][r].weightX = 1.0; continue; } if (allWeightsZero(rows)) { for (int r = 0; r < numRows; r++) for (int i = 0; i < numCols; i++) cells[i][r].weightY = 1.0; continue; } break; } Insets insets = getInsets(container); determineStarts(cols, insets.left, container.getWidth() - insets.left - insets.right + spacingX, spacingX); determineStarts(rows, insets.top, container.getHeight() - insets.top - insets.bottom + spacingY, spacingY); } final public boolean allWeightsZero(RC[] rcs) { for (int i = 0; i < rcs.length; i++) if (rcs[i].weightSum != 0.0) return false; return true; } static public int getMinimumHeight(Component c) { return c.getMinimumSize().height; } final public void applyTemplate(Container container) { if (template == STALACTITE) { Component[] components = container.getComponents(); lines = new String[components.length + 2]; map.clear(); for (int i = 0; i < components.length; i++) { String s = String.valueOf(makeIndexChar(i)); map.put(s, components[i]); lines[i] = s; } lines[components.length] = lines[components.length + 1] = " "; } else if (template == FORM) { Component[] components = container.getComponents(); int numRows = components.length / 2; lines = new String[numRows + 2]; map.clear(); for (int row = 0; row < numRows; row++) { String lower = String.valueOf(makeIndexChar(row)); String upper = String.valueOf(makeAlternateIndexChar(row)); Component rightComponent = components[row * 2 + 1]; if (rightComponent instanceof DummyComponent) upper = lower; lines[row] = (formWideLeftSide ? lower + lower : lower) + (formWideRightSide ? upper + upper : upper); map.put(lower, components[row * 2]); if (!(rightComponent instanceof DummyComponent)) map.put(upper, rightComponent); } lines[numRows] = lines[numRows + 1] = (formWideLeftSide ? " " : " ") + (formWideRightSide ? " " : " "); } else if (template == LEFT_ALIGNED_ROW) { lines = new String[] { makeSingleRow(container) + RIGHT_CHAR + RIGHT_CHAR }; } else if (template == CENTERED_ROW) { lines = new String[] { "" + LEFT_CHAR + LEFT_CHAR + makeSingleRow(container) + RIGHT_CHAR + RIGHT_CHAR }; } else if (template == RIGHT_ALIGNED_ROW) { lines = new String[] { "" + LEFT_CHAR + LEFT_CHAR + makeSingleRow(container) }; } } final public String makeSingleRow(Container container) { Component[] components = container.getComponents(); StringBuffer buf = new StringBuffer(); map.clear(); for (int i = 0; i < components.length; i++) { String s = String.valueOf(makeAlternateIndexChar(i)); map.put(s, components[i]); buf.append(s); } return buf.toString(); } static public void determineStarts(RC[] rcs, int start, int totalSize, int spacing) { int minTotal = rcs[rcs.length - 1].minEnd; double weightSum = rcs[rcs.length - 1].weightSum; int spare = (int) ((totalSize - minTotal) / (weightSum == 0.0 ? 1.0 : weightSum)); int x = start, minSum = 0; double prevWeightSum = 0.0; for (int i = 0; i < rcs.length; i++) { int width = rcs[i].minEnd - minSum + (int) ((rcs[i].weightSum - prevWeightSum) * spare) - spacing; rcs[i].start = x; x += width + spacing; prevWeightSum = rcs[i].weightSum; minSum = rcs[i].minEnd; } } public void addLayoutComponent(String s, Component component) { map.put(s, component); } public Dimension minimumLayoutSize(Container container) { prepareLayout(container); Insets insets = getInsets(container); Dimension result = new Dimension(insets.left + cols[cols.length - 1].minEnd + insets.right - spacingX, insets.top + rows[rows.length - 1].minEnd + insets.bottom - spacingY); return result; } final public Insets getInsets(Container container) { Insets insets = container.getInsets(); return new Insets(insets.top + insetTop, insets.left + insetLeft, insets.bottom + insetBottom, insets.right + insetRight); } public Dimension preferredLayoutSize(Container container) { return minimumLayoutSize(container); } public LetterLayout setSpacing(int x, int y) { spacingX = x; spacingY = y; return this; } public LetterLayout setSpacing(int spacing) { return setSpacing(spacing, spacing); } public LetterLayout setBorder(int top, int left, int bottom, int right) { insetTop = top; insetLeft = left; insetBottom = bottom; insetRight = right; return this; } public LetterLayout setBorder(int inset) { return setBorder(inset, inset, inset, inset); } public LetterLayout setTopBorder(int inset) { insetTop = inset; return this; } public static LetterLayout stalactite() { return new LetterLayout(STALACTITE); } public static LetterLayout leftAlignedRow() { return new LetterLayout(LEFT_ALIGNED_ROW); } public static LetterLayout leftAlignedRow(int spacing) { return leftAlignedRow().setSpacing(spacing); } public static LetterLayout centeredRow() { return new LetterLayout(CENTERED_ROW); } public static LetterLayout rightAlignedRow() { return new LetterLayout(RIGHT_ALIGNED_ROW); } public static JPanel rightAlignedRowPanel(JComponent... components) { return makePanel(new LetterLayout(RIGHT_ALIGNED_ROW), components); } static public JPanel makePanel(LetterLayout letterLayout, JComponent[] components) { JPanel panel = new JPanel(letterLayout); for (JComponent component : components) { panel.add(component); } return panel; } public static LetterLayout form() { LetterLayout letterLayout = new LetterLayout(FORM); letterLayout.formWideLeftSide = true; letterLayout.formWideRightSide = true; return letterLayout; } public static LetterLayout formWideRightSide() { LetterLayout letterLayout = new LetterLayout(FORM); letterLayout.formWideRightSide = true; return letterLayout; } public static Component getDummyComponent() { return new DummyComponent(); } public static JPanel newPanel(String... lines) { return new JPanel(new LetterLayout(lines)); } public boolean isDebug() { return debug; } public void setDebug(boolean debug) { this.debug = debug; } public static char makeIndexChar(int idx) { return (char) ('a' + idx * 2); } public static char makeAlternateIndexChar(int idx) { return (char) ('b' + idx * 2); } public static char LEFT_CHAR = ',', RIGHT_CHAR = '.'; public static void main(String[] args) { System.out.println((int) makeIndexChar(0)); System.out.println((int) makeAlternateIndexChar(0)); System.out.println((int) makeIndexChar(32000)); System.out.println((int) makeAlternateIndexChar(32000)); System.out.println((int) LEFT_CHAR); System.out.println((int) RIGHT_CHAR); } } static public Q dm_q() { return dm_current_mandatory().q(); } static public void dm_q(Runnable r) { dm_inQ(r); } static public void dm_q(DynModule module, Runnable r) { module.q().add(r); } static public A dm_q(IF0 f) { return dm_evalInQ(if0ToF0(f)); } static public void dm_inQ(Runnable r) { dm_q().add(r); } static public A dm_evalInQ(F0 f) { return dm_evalInQ(dm_current_mandatory(), f); } static public A dm_evalInQ(IF0 f) { return dm_evalInQ(dm_current_mandatory(), if0ToF0(f)); } static public A dm_evalInQ(DynModule module, F0 f) { return evalInQ(module.q(), f); } static public A evalInQ(Q q, final F0 f) { if (isInQ(q)) return callF(f); final Var> var = new Var(); q.add(new Runnable() { public void run() { try { try { var.set(eitherA(callF(f))); } catch (Throwable e) { var.set(eitherB(e)); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "try {\r\n var.set(eitherA(callF(f)));\r\n } catch (Throwable e) {\r\n ..."; } }); return returnOrThrow_either(waitForVarToBeNotNull(var)); } static public boolean isInQ(Q q) { return q != null && isCurrentThread(q.rst.thread); } static public A returnOrThrow_either(Either e) { if (isEitherB(e)) throw rethrow(e.b()); return eitherAOpt(e); } static public A waitForVarToBeNotNull(Var v) { try { synchronized (v) { while (!v.has()) v.wait(); return v.get(); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean isCurrentThread(Thread t) { return t != null && t == currentThread(); } static public boolean isEitherB(Either e) { return eitherIsB(e); } }