Warning : session_start(): open(/var/lib/php/sessions/sess_mv02bd6l5mdian60hn7plhbcrk, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning : session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
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 java.util.function.*;
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 java.awt.geom.*;
import javax.imageio.*;
import java.math.*;
import java.text.SimpleDateFormat;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.awt.geom.*;
import java.text.*;
import java.util.TimeZone;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import static x30_pkg.x30_util.DynamicObject;
import java.nio.file.Path;
import java.nio.file.Files;
class main {
static class AIList extends Concept {
static final String _fieldOrder = "name text botFlag mighty modified status textMD5 lines";
String name;
String text;
boolean botFlag, mighty;
long modified;
String status;
transient String textMD5;
transient int lines = -1;
boolean isPublicRead() { return cic(status, "PUBLIC READ"); }
}
static ConceptFieldIndexCI nameIndex;
static volatile long totalChars = -1;
static class Session extends Concept {
String cookie;
String mech_filter;
}
public static void main(final String[] args) throws Exception {
dbSaveEvery(60);
dbIndexing(AIList.class, "name");
nameIndex = indexConceptFieldCI(AIList.class, "name");
{ startThread(new Runnable() { public void run() { try { mech_guessLanguage("");
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mech_guessLanguage(\"\");"; }}); } // preload
calcOnConceptChanges(10000, new Runnable() { public void run() { try { calcTotalSize();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "calcTotalSize();"; }}, true);
addConceptIndex(new IConceptIndex() {
public void update(Concept c) {
try { if (c instanceof AIList) sendToUpdatesBot("mechListChange", ((AIList) c).name); } catch (Throwable __e) { printStackTrace(__e); }
}
public void remove(Concept c) {
try { if (c instanceof AIList) sendToUpdatesBot("removeMechList", ((AIList) c).name); } catch (Throwable __e) { printStackTrace(__e); }
}
});
updateListNamesList();
}
static Object html(String uri, final Map params) { try {
AutoCloseable __13 = countDispatch("html"); try {
Object response;
Matches m = new Matches();
String cookie = cookieFromUser();
String filter = params.get("mech_filter");
print("cookie=" + cookie + ", filter=" + filter + ", dialogID=" + getDialogID());
Session session = empty(cookie) ? null : uniq(Session.class, "cookie", cookie);
if (session != null && filter != null) {
cset(session, "mech_filter" , filter);
return hrefresh(rawSelfLink());
}
boolean authed = webAuthed(params);
if (eq(uri, "/list-count")) return serveText(countConcepts(AIList.class));
if ((response = serveListText(uri, params, authed)) != null) return response;
// Append API
if (swic(uri, "/bot-list-append/", m)) {
params.put("name" , urldecode(m.rest()));
uri = "/bot-list-append";
}
if (eq(uri, "/bot-list-append")) {
String mode = params.get("mode");
Lock __2 = dbLock(); lock(__2); try {
String name = params.get("name"), text = params.get("text");
if (!authed)
name = "Unauthorized Appends | " + name;
AIList l = getList(name);
//if (!authed) cset(l, status := "PUBLIC READ");
if (eq(mode, "uniqCI")) {
text = lines(listMinusSet(tlft(text), asCISet(tlft(l.text))));
if (empty(text)) return "No change";
}
if (eq(mode, "uniq")) {
text = lines(listMinusSet(tlft(text), tlft(l.text)));
if (empty(text)) return "No change";
}
listAppendWithLog(l, text);
return "Changed";
} finally { unlock(__2); } }
if (!authed && eq(uri, "/list-names"))
return serveText(jsonEncode(sortedIC(collect(publicReadLists(), "name"))));
if (!authed && eq(uri, "/list-md5s"))
return serveText(jsonEncode(map(publicReadLists(), new F1>() { public List get(AIList l) { try { return ll(l.name, md5OfList(l)); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ll(l.name, md5OfList(l))"; }})));
if (!authed && eq(uri, "/list-md5s-and-statuses"))
return serveText(jsonEncode(map(publicReadLists(), new F1>() { public List get(AIList l) { try { return ll(l.name, md5OfList(l), l.status, str(lineCountOfList(l))); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ll(l.name, md5OfList(l), l.status, str(lineCountOfList(l)))"; }})));
if (eq(uri, "/authed")) return yesno(authed);
// Show list (unauthed)
if (!authed && startsWith(uri, "/list/", m)) {
AIList l = getList_noCreate(urldecode(m.get(0)));
if (l == null || !l.isPublicRead()) return serve404("List not found");
return htitle_h2(htmlencode(l.name)) + hpre_htmlencode(l.text);
}
boolean alphabetical = eq(uri, "/alphabetical");
if (!authed && (eq(uri, "/") || alphabetical)) {
List list = alphabetical
? sortedByFieldIC("name", publicReadLists())
: sortedByFieldDesc("modified", publicReadLists());
return h3_title("Bot Data")
+ hBoolSelector(alphabetical, "/", "By date", "/alphabetical", "Alphabetical")
+ listLists(list);
}
// Search results
String q = params.get("q");
if (nempty(q)) {
List found = scoredSearch_AIList(q, listsForAuth(authed));
if (eq(uri, "/json-search"))
return serveText(jsonEncode(collect("name", found)));
return hmobilefix()
+ htitle_h3("mech.botcompany.de: Search results for " + htmlencode(singleQuote(q)))
+ listLists(found);
}
if (!authed) return redirectToWebAuth();
// AUTHED FROM HERE ON
{ var __12= html_serveDispatches(uri); if (__12 != null) return __12; }
if (swic(uri, "/list-id/", m)) {
AIList l = getList_noCreate(urldecode(m.rest()));
return l == null ? "List not found" : str(l.id);
}
if (eq(uri, "/fix-unauth")) {
for (AIList l : list(AIList.class)) if (swic(l.name, "Unauthorized Appends |"))
cset(l, "status" , "");
return "OK";
}
// API
if (eq(uri, "/download"))
return subBot_serveFileWithName("mechlists-" + ymd_minus_hms() + ".gz", conceptsFile()); // TODO: concurrent writes?
if (eq(uri, "/list-names"))
return serveText(jsonEncode(sortedIC(collect(list(AIList.class), "name"))));
if (eq(uri, "/list-md5s"))
return serveText(jsonEncode(map(list(AIList.class), new F1>() { public List get(AIList l) { try { return ll(l.name, md5OfList(l)); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ll(l.name, md5OfList(l))"; }})));
if (eq(uri, "/list-md5s-and-statuses"))
return serveText(jsonEncode(map(list(AIList.class), new F1>() { public List get(AIList l) { try { return ll(l.name, md5OfList(l), l.status, str(lineCountOfList(l))); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "ll(l.name, md5OfList(l), l.status, str(lineCountOfList(l)))"; }})));
if (eq(uri, "/bot-edited-lists"))
return serveText(jsonEncode(sortedIC(collect(conceptsWhere(AIList.class, "botFlag" , true), "name"))));
// Create API
if (eq(uri, "/bot-list-create")) {
Lock __3 = dbLock(); lock(__3); try {
String name = params.get("name");
getList(name);
return "OK";
} finally { unlock(__3); } }
// Edit API
if (eq(uri, "/bot-list-edit")) {
Lock __4 = dbLock(); lock(__4); try {
String name = params.get("name"), text = params.get("text");
AIList l = getList(name);
if (eq(l.text, text)) return "No change";
listReplaceWithLog(l, text);
return "Changed";
} finally { unlock(__4); } }
// Show list (authed)
if (startsWith(uri, "/list/", m)) {
String name = urldecode(m.get(0));
AIList l = eq("1", params.get("create")) ? getList(name) : getList_noCreate(name);
if (l == null)
return "List not found"
+ (!authed ? "" : hpostform(hhidden("create" , 1) + hsubmit("Create")));
boolean delete = eq(params.get("delete"), "1");
// Rename list
String renameTo = params.get("renameTo");
if (nempty(renameTo) && !delete) {
if (neqic(l.name, renameTo) && getList_noCreate(renameTo) != null)
return "Can't rename - list " + quote(renameTo) + " already exists";
String oldName = l.name;
cset(l, "name" , renameTo);
updateListNamesList();
return nav() + "List " + quote(oldName) + " renamed to " + quote(renameTo);
}
if (delete) {
logStructure("versions.log", litmap("id" , l.id, "status" , "delete me", "date" , now()));
deleteConcept(l);
updateListNamesList();
return nav() + "List deleted";
}
// Update text
String text = params.get("human");
String status = params.get("status");
if (text != null) {
Lock __5 = dbLock(); lock(__5); try {
//printStruct(ll(+text, +status));
if (neqAny(text, l.text, status, unnull(l.status))) {
logStructure("versions.log", litmap("id" , l.id, "text", text, "status", status, "date" , now()));
if (status != null) cset(l, "status", status);
cset(l, "text", text, "textMD5" , md5(text), "lines" , -1, "botFlag" , false, "modified" , now());
listTextChanged(l);
//printStruct("l.text=" + sfu(text));
}
return hrefresh(0, rawLink(uri) + "?random=" + randomID());
} finally { unlock(__5); } }
String textArea = htextarea(l.text, "name" , "human", "cols" , 80, "rows" , 30);
List tok = javaTok(l.status);
jreplace(tok, "bb", "iframe 1018300");
int idx = jfind(tok, "iframe ");
if (idx > 0) {
String analyzer = tok.get(idx+2);
String subUri = joinSubList(tok, idx+4, smartIndexOf(tok, idx, ",")-1);
textArea = htableRaw2_singleRow(ll(textArea, iframe(relativeRawBotLink(analyzer, subUri + "?list=" + urlencode(l.name)), "width" , "500", "height" , "500")),
null, null, ll("valign" , "top"));
}
// Serve list text (editable)
return nav() + htitle(l.name)
+ h2(ahref(neatMechListURL(l.name), htmlencode2(l.name)) + " [" + nLines(countLines(l.text)) + "]")
+ hpostform(
"Status: " + htextinput("status", "value" , l.status)
+ h3("Contents (" + (l.botFlag ? "bot" : "human") + "-edited)")
+ p(hsubmit("Save"))
+ textArea
+ p(hsubmit("Save"))
)
+ hpostform(
"New name: " + htextinput("renameTo", "value" , l.name)
+ " "
+ hsubmit("Rename list") + " or " + hbutton("Delete list", "name" , "delete", "type" , "submit", "value" , 1, "onClick" , "return confirm('Really delete?')")
);
}
// New list
String newList = trim(params.get("newList"));
if (nempty(newList)) {
AIList l = getList(newList);
return hrefresh(rawLink("/list/" + urlencode(l.name)));
}
// Overview
List list = alphabetical
? sortedByFieldIC("name", list(AIList.class))
: sortedByFieldDesc("modified", list(AIList.class));
final String prefix = session == null ? null : session.mech_filter;
if (nempty(prefix))
list = filter(list , new F1() { public Boolean get(AIList l) { try { return swic(l.name, prefix); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "swic(l.name, prefix)"; }});
return hmobilefix()
+ hcomment("cookie=" + cookie)
+ htitle_h3("mech.botcompany.de [" + n2(l(list), "list")
+ (totalChars >= 0 ? ", " + toK(totalChars) + "K chars" : "")
+ "]")
+ htableRaw_singleRow(ll(
hform("Search: " + htextinput("q", "style" , "width: 200px") + " " + hsubmit("Search")),
hpostform("| New list: " + htextinput("newList", "style" , "background-color: yellow") + " " + hsubmit("Create list"))))
+ hBoolSelector(alphabetical, "/", "By date", "/alphabetical", "Alphabetical")
+ listLists(list)
+ hpostform("Only show lists starting with: "
+ htextinput("mech_filter", "value" , prefix)
+ " " + hsubmit("OK"));
} finally { _close(__13); }} catch (Exception __e) { throw rethrow(__e); } }
static String nav() {
return hmobilefix() + p(ahref(rawLink(), "<< back"));
}
static AIList getList_noCreate(String name) {
return getList(name, false);
}
static AIList getList(String name) {
return getList(name, true);
}
static AIList getList(String name, boolean create) {
Lock __6 = dbLock(); lock(__6); try {
AIList l = findConcept(AIList.class, "name", name);
if (l == null) l = nameIndex.get(name);
if (l == null) if (!create) return null; else {
l = cnew(AIList.class, "name", name);
logStructure("versions.log", litmap("id" , l.id, "name", name, "date" , now(), "mode" , "List created"));
updateListNamesList();
}
if (l.modified == 0) cset(l, "modified" , now());
return l;
} finally { unlock(__6); } }
static String listLists(List list) {
return ul(map(list, new F1() { public String get(AIList l) { try {
int n = lineCountOfList(l);
List status = new ArrayList();
boolean german = eq("german", mech_guessLanguage_quick(l.name));
//if (l.mighty) status.add(german ? "GENUTZT" : "USED");
addIfNempty(status, htmlencode(l.status));
if (n != 0) status.add(n2(n, german ? "Zeile" : "line", german ? "Zeilen": "lines"));
return ahref(rawLink("/list/" + urlencode(l.name)),
htmlencode(or2(l.name, "[no name]")) + appendBracketed(joinWithComma(status)));
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "int n = lineCountOfList(l);\r\n new L status;\r\n bool german = eq('germ..."; }}));
}
static List scoredSearch_AIList(String query, Iterable data) {
Map scores = new HashMap();
List prepared = scoredSearch_prepare(query);
for (AIList l : data)
putUnlessZero(scores, l,
3*scoredSearch_score(l.name, prepared)
+ 2*scoredSearch_score(l.status, prepared)
+ scoredSearch_score(l.text, prepared));
return keysSortedByValuesDesc(scores);
}
static void calcTotalSize() {
long total = 0;
for (AIList l : list(AIList.class))
total += l(l.text);
totalChars = total;
}
static String export_getListText(String listName) {
AIList l = getList_noCreate(listName);
return l == null ? "" : l.text;
}
static String export_setListText(String listName, String text) {
AIList l = getList(listName);
if (eq(l.text, text)) return "No change";
logStructure("versions.log", litmap("id" , l.id, "text", text, "date" , now(), "mode" , "bot edit"));
cset(l, "text", text, "textMD5" , md5(text), "lines" , -1, "botFlag" , true, "modified" , now());
listTextChanged(l);
return "Changed";
}
static Object serveListText(String uri, Map params, boolean authed) {
Matches m = new Matches();
if (startsWith(uri, "/list-text/", m)) {
boolean opt = eq("1", params.get("opt"));
boolean withStatus = eq("1", params.get("withStatus"));
boolean create = authed && eq("1", params.get("create"));
String md5 = params.get("md5");
int md5Len = parseIntOpt(params.get("l"));
String name = urldecode(m.get(0));
Lock __7 = dbLock(); lock(__7); try {
AIList l = create ? getList(name) : getList_noCreate(name);
if (!authed && l != null && !l.isPublicRead())
l = null;
//ret subBot_serve404("Not logged in");
cset(l, "mighty" , true);
if (l == null)
if (opt)
return serveText(jsonEncode(litmap("Text" , "")));
else
return serveText(jsonEncode(litmap("Error", ll("List not found", name))));
else {
Map map = litmap("Name" , l.name, "Status" , withStatus ? l.status : null);
if (md5 != null) {
String actualMD5 = md5OfList(l);
print("md5: " + md5 + " / " + actualMD5);
if (eq(actualMD5, md5))
return serveText(jsonEncode(mapPlus(map, "Same" , true)));
else if (md5Len != 0 && eq(md5(takeFirst(l.text, md5Len)), md5))
return serveText(jsonEncode(mapPlus(map, "Appended" , true, "Text" , substring(l.text, md5Len))));
}
return serveText(jsonEncode(mapPlus(map, "Text" , l.text)));
}
} finally { unlock(__7); } }
return null;
}
static String md5OfList(AIList l) {
Lock __8 = dbLock(); lock(__8); try {
if (l.textMD5 == null) l.textMD5 = md5(l.text);
return l.textMD5;
} finally { unlock(__8); } }
static int lineCountOfList(AIList l) {
Lock __9 = dbLock(); lock(__9); try {
if (l.lines < 0) l.lines = countLines(l.text);
return l.lines;
} finally { unlock(__9); } }
static List publicReadLists() {
return filter(list(AIList.class) , new F1() { public Boolean get(AIList l) { try { return l.isPublicRead(); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "l.isPublicRead()"; }});
}
static void updateListNamesList() {
Lock __10 = dbLock(); lock(__10); try {
AIList l = getList("All public-read mech lists");
TreeSet actual = new TreeSet(collect(publicReadLists(), "name"));
Set listed = asHashSet(lines(l.text));
if (nempty(setMinusSet(listed, actual)))
listReplaceWithLog(l, lines(actual));
else
listAppendWithLog(l, lines(setMinusSet(actual, listed)));
} finally { unlock(__10); } }
static void listAppendWithLog(AIList l, String text) {
if (emptyAfterTrim(text)) return;
logStructure("versions.log", litmap("id" , l.id, "text", text, "date" , now(), "mode" , "bot append"));
cset(l, "text" , appendNewLineIfNempty(rtrim(l.text)) + text, "botFlag" , true, "modified" , now(), "textMD5" , null, "lines" , -1);
listTextChanged(l);
}
static void listReplaceWithLog(AIList l, String text) {
if (eq(text, l.text)) return;
logStructure("versions.log", litmap("id" , l.id, "text", text, "date" , now(), "mode" , "bot edit"));
cset(l, "text", text, "textMD5" , md5(text), "lines" , -1, "botFlag" , true, "modified" , now());
listTextChanged(l);
}
static ThreadLocal listTextChanged_noRecurse = new ThreadLocal();
static void listTextChanged(AIList l) {
if (!isTrue(listTextChanged_noRecurse.get()) && cic(l.status, "auto global ids")) { try {
List entries = splitAtEmptyLines(l.text);
String text = joinWithEmptyLines(map(__43 -> nlLogic_addGlobalID(__43), entries));
AutoCloseable __14 = tempSetThreadLocal(listTextChanged_noRecurse, true); try {
listReplaceWithLog(l, text);
} finally { _close(__14); }} catch (Throwable __e) { printStackTrace(__e); }}
if (!isTrue(listTextChanged_noRecurse.get()) && cic(l.status, "gazelle ids")) { try {
List entries = splitAtEmptyLines(l.text);
String text = joinWithEmptyLines(map(__44 -> gazelle_addGlobalID(__44), entries));
AutoCloseable __15 = tempSetThreadLocal(listTextChanged_noRecurse, true); try {
listReplaceWithLog(l, text);
} finally { _close(__15); }} catch (Throwable __e) { printStackTrace(__e); }}
}
static String mechList_opt_raw_fresh(String name) {
return export_getListText(name);
}
static List listsForAuth(boolean authed) {
return authed ? list(AIList.class) : publicReadLists();
}
static boolean cic(Collection l, String s) {
return containsIgnoreCase(l, s);
}
static boolean cic(Collection l, Symbol s) {
return contains(l, s);
}
static boolean cic(String[] l, String s) {
return containsIgnoreCase(l, s);
}
static boolean cic(String s, char c) {
return containsIgnoreCase(s, c);
}
static boolean cic(String a, String b) {
return containsIgnoreCase(a, b);
}
static void dbSaveEvery(double seconds) {
db_mainConcepts().autoSaveInterval = toMS_int(seconds);
}
static void dbIndexing(Object... params) {
db();
indexConceptFields(params);
}
static ConceptFieldIndexCI indexConceptFieldCI(Class c, String field) {
return indexConceptFieldCI(db_mainConcepts(), c, field);
}
static ConceptFieldIndexCI indexConceptFieldCI(Concepts concepts, Class c, String field) {
ConceptFieldIndexCI idx = getConceptFieldCIIndex(concepts, c, field);
return idx != null ? idx : new ConceptFieldIndexCI(concepts, c, field);
}
static Thread startThread(Object runnable) {
return startThread(defaultThreadName(), runnable);
}
static Thread startThread(String name, Runnable runnable) {
runnable = wrapAsActivity(runnable);
return startThread(newThread(runnable, name));
}
static Thread startThread(String name, Object runnable) {
runnable = wrapAsActivity(runnable);
return startThread(newThread(toRunnable(runnable), name));
}
static Thread startThread(Thread t) {
_registerThread(t);
t.start();
return t;
}
static String mech_guessLanguage(String s) {
try {
String func = first(mechList_opt("List => Language | Best guessing function"));
return (String) callAndMake_extended(func, s);
} catch (Throwable e) {
return null;
}
}
static RuntimeException rethrow(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static RuntimeException rethrow(String msg, Throwable t) {
throw new RuntimeException(msg, t);
}
static java.util.Timer calcOnConceptChanges(int delay, final Object runnable, final boolean runOnFirstTime) {
return doEvery_daemon(delay, 0, new Runnable() {
long c = runOnFirstTime ? -1 : changeCount();
SingleThread thread = new SingleThread();
public void run() {
long _c = changeCount();
if (_c != c && !thread.running()) {
c = _c;
thread.go(runnable);
}
}
});
}
static void addConceptIndex(IConceptIndex index) {
db_mainConcepts().addConceptIndex(index);
}
static void sendToUpdatesBot(String uri, Object... params) {
sendToSnippetUpdatesBot(uri, params);
}
static A printStackTrace(A e) {
// we go to system.out now - system.err is nonsense
if (e != null) print(getStackTrace(e));
return e;
}
static void printStackTrace() {
printStackTrace(new Throwable());
}
static void printStackTrace(String msg) {
printStackTrace(new Throwable(msg));
}
static void printStackTrace(String msg, Throwable e) {
printStackTrace(new Throwable(msg, e));
}
static class countDispatch_Data {
int running;
long invocations, totalTime;
}
static Map countDispatch_map = synchroMap();
static Closeable countDispatch(final String methodName) {
countDispatch_Data data;
synchronized(countDispatch_map) {
data = countDispatch_map.get(methodName);
if (data == null) countDispatch_map.put(methodName, data = new countDispatch_Data());
}
data.running++;
final countDispatch_Data _data = data;
final long time = sysNow();
return new Closeable() { public void close() {
_data.totalTime += sysNow()-time;
_data.running--;
_data.invocations++;
}};
}
static String cookieFromUser() {
return (String) callOpt(getBot("#1002157"), "cookieFromUser");
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static boolean printAlsoToSystemOut = true;
static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
static boolean print_silent = false; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal print_byThread; // special handling by thread - prefers F1
static volatile Object print_allThreads;
static volatile Object print_preprocess;
static void print() {
print("");
}
static A print(String s, A o) {
print(combinePrintParameters(s, o));
return o;
}
// slightly overblown signature to return original object...
static A print(A o) {
ping_okInCleanUp();
if (print_silent) return o;
String s = o + "\n";
print_noNewLine(s);
return o;
}
static void print_noNewLine(String s) {
try {
Object f = getThreadLocal(print_byThread_dontCreate());
if (f == null) f = print_allThreads;
if (f != null)
// We do need the general callF machinery here as print_byThread is sometimes shared between modules
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 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);
if (printAlsoToSystemOut)
System.out.print(s);
vmBus_send("printed", mc(), s);
}
static void print_autoRotate() {
}
static String getDialogID() {
return (String) callOpt(getMainBot(), "getDialogID");
}
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); }
static boolean empty(CharSequence s) { return s == null || s.length() == 0; }
static boolean empty(Map map) { return map == null || map.isEmpty(); }
static boolean empty(Object[] o) { return o == null || o.length == 0; }
static boolean empty(BitSet bs) { return bs == null || bs.isEmpty(); }
static 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 boolean empty(Iterator i) { return i == null || !i.hasNext(); }
static boolean empty(double[] a) { return a == null || a.length == 0; }
static boolean empty(float[] a) { return a == null || a.length == 0; }
static boolean empty(int[] a) { return a == null || a.length == 0; }
static boolean empty(long[] a) { return a == null || a.length == 0; }
static boolean empty(byte[] a) { return a == null || a.length == 0; }
static boolean empty(short[] a) { return a == null || a.length == 0; }
static boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); }
static boolean empty(IMultiMap mm) { return mm == null || mm.size() == 0; }
static boolean empty(File f) { return getFileSize(f) == 0; }
static boolean empty(Rect r) { return !(r != null && r.w != 0 && r.h != 0); }
static boolean empty(Chain c) { return c == null; }
static boolean empty(AppendableChain c) { return c == null; }
static A uniq(Class c, Object... params) {
return uniqueConcept(c, params);
}
static A uniq(Concepts cc, Class c, Object... params) {
return uniqueConcept(cc, c, params);
}
// returns number of changes
static int cset(Concept c, Object... values) { try {
if (c == null) return 0;
warnIfOddCount(values = expandParams(c.getClass(), values));
int changes = 0;
for (int i = 0; i+1 < l(values); i += 2)
if (_csetField(c, (String) values[i], values[i+1])) ++changes;
return changes;
} catch (Exception __e) { throw rethrow(__e); } }
static int cset(Iterable extends Concept> l, Object... values) {
int changes = 0;
for (Concept c : unnullForIteration(l))
changes += cset(c, values);
return changes;
}
static int cset(Concept.Ref c, Object... values) {
return cset(getVar(c), values);
}
static String hrefresh(String target) {
return hrefresh(0, target);
}
static String hrefresh(double seconds) {
return hrefresh(seconds, "");
}
static String hrefresh(double seconds, String target) {
return tag("meta", "", "http-equiv", "refresh", "content", iceil(seconds) + (nempty(target) ? "; url=" + target : ""));
}
static String rawSelfLink(String uri) {
return relativeRawBotLink(programID(), uri);
}
static String rawSelfLink() {
return rawSelfLink("");
}
static boolean webAuthed() {
return eq(Boolean.TRUE, callOpt(getBot("#1002590"), "currentHttpRequestAuthorized"));
}
static boolean webAuthed(Map params) {
return empty(params.get("unauthed")) && (eq(masterPW(), params.get("_pass")) || webAuthed());
}
static boolean eq(Object a, Object b) {
return a == b || a != null && b != null && a.equals(b);
}
// a little kludge for stuff like eq(symbol, "$X")
static boolean eq(Symbol a, String b) {
return eq(str(a), b);
}
// TODO: at least convert to UTF-8 on the fly
static Object serveText(Object s) {
return call(getMainBot(), "serveByteArray", toUtf8(str(s)), "text/plain; charset=utf8");
}
static int countConcepts(Concepts concepts, Class c, Object... params) {
return concepts.countConcepts(c, params);
}
static int countConcepts(Class c, Object... params) {
return db_mainConcepts().countConcepts(c, params);
}
static int countConcepts() {
return db_mainConcepts().countConcepts();
}
static int countConcepts(String className) {
return db_mainConcepts().countConcepts(className);
}
static int countConcepts(Concepts concepts, String className) {
return concepts.countConcepts(className);
}
static int countConcepts(Concepts concepts) {
return concepts.countConcepts();
}
static boolean swic(String a, String b) {
return startsWithIgnoreCase(a, b);
}
static 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 String urldecode(String x) {
try {
return URLDecoder.decode(unnull(x), "UTF-8");
} catch (UnsupportedEncodingException e) { throw new RuntimeException(e); }
}
static Lock dbLock() {
return db_mainConcepts().lock;
}
static Lock dbLock(Concepts cc) {
return cc == null ? null : cc.lock;
}
static Lock dbLock(Concept c) {
return dbLock(c == null ? null : c._concepts);
}
static void lock(Lock lock) { try {
ping();
if (lock == null) return;
try {
vmBus_send("locking", lock, "thread" , currentThread());
lock.lockInterruptibly();
vmBus_send("locked", lock, "thread" , currentThread());
} catch (InterruptedException e) {
Object reason = vm_threadInterruptionReasonsMap().get(currentThread());
print("Locking interrupted! Reason: " + strOr(reason, "Unknown"));
printStackTrace(e);
rethrow(e);
}
// NO call to ping here! Make sure lock is always released.
} catch (Exception __e) { throw rethrow(__e); } }
static void lock(Lock lock, String msg) {
print("Locking: " + msg);
lock(lock);
}
static void lock(Lock lock, String msg, long timeout) {
print("Locking: " + msg);
lockOrFail(lock, timeout);
}
static ReentrantLock lock() {
return fairLock();
}
static String lines(Iterable lines) { return fromLines(lines); }
static String lines(Object[] lines) { return fromLines(asList(lines)); }
static List lines(String s) { return toLines(s); }
// convenience map call
static String lines(Iterable l, IF1 f) {
return mapToLines(l, f);
}
static List listMinusSet(Iterable l, Collection extends A> stuff) {
if (l == null) return null;
if (empty(stuff)) return asList(l);
Set extends A> set = asSet(stuff);
List l2 = new ArrayList();
for (A a : l) if (!set.contains(a)) l2.add(a);
return l2;
}
static List listMinusSet(Iterable l, Collection stuff, Collection extends A> stuff2) {
return listMinusSet(listMinusSet(l, stuff), stuff2);
}
static List tlft(String s) { return toLinesFullTrim(s); }
static List tlft(File f) { return toLinesFullTrim(f); }
static TreeSet asCISet(Iterable c) {
return toCaseInsensitiveSet(c);
}
static TreeSet asCISet(String... x) {
return toCaseInsensitiveSet(x);
}
static void unlock(Lock lock, String msg) {
if (lock == null) return;
lock.unlock();
vmBus_send("unlocked", lock, "thread" , currentThread());
print("Unlocked: " + msg); // print afterwards to make sure the lock is always unlocked
}
static void unlock(Lock lock) {
if (lock == null) return;
lock.unlock();
vmBus_send("unlocked", lock, "thread" , currentThread());
}
static String jsonEncode(Object o) {
StringBuilder buf = new StringBuilder();
jsonEncode(o, buf);
return str(buf);
}
static 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 List sortedIC(Collection l) {
return sortedIgnoreCase(l);
}
static List collect(Iterable c, String field) {
return collectField(c, field);
}
static List collect(String field, Iterable c) {
return collectField(c, field);
}
/*ifclass Concept
static L collect(Class c, S field) {
ret collect(list(c), field);
}
endif
TODO: make translator ignore stuff in ifclass until resolved
*/
static List map(Iterable l, Object f) { return map(f, l); }
static List map(Object f, Iterable l) {
List x = emptyList(l);
if (l != null) for (Object o : l)
{ ping(); x.add(callF(f, o)); }
return x;
}
// map: func(key, value) -> list element
static List map(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 List map(Object f, Object[] l) { return map(f, asList(l)); }
static List map(Object[] l, Object f) { return map(f, l); }
static List map(Object f, Map map) {
return map(map, f);
}
static List map(Iterable l, F1 f) { return map(f, l); }
static List map(F1 f, Iterable l) {
List x = emptyList(l);
if (l != null) for (A o : l)
{ ping(); x.add(callF(f, o)); }
return x;
}
static List map(IF1 f, Iterable l) { return map(l, f); }
static List map(Iterable l, IF1 f) {
List x = emptyList(l);
if (l != null) for (A o : l)
{ ping(); x.add(f.get(o)); }
return x;
}
static List map(IF1 f, A[] l) { return map(l, f); }
static List map(A[] l, IF1 f) {
List x = emptyList(l);
if (l != null) for (A o : l)
{ ping(); x.add(f.get(o)); }
return x;
}
static List map(Map map, IF2 f) {
List x = new ArrayList();
if (map != null) for (Map.Entry e : map.entrySet()) { ping();
x.add(f.get(e.getKey(), e.getValue()));
}
return x;
}
// new magic alias for mapLL - does it conflict?
static List map(IF1 f, A data1, A... moreData) {
List x = emptyList(l(moreData)+1);
x.add(f.get(data1));
if (moreData != null) for (A o : moreData)
{ ping(); x.add(f.get(o)); }
return x;
}
// get purpose 1: access a list/array/map (safer version of x.get(y))
static A get(List l, int idx) {
return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null;
}
// seems to conflict with other signatures
/*static B get(Map map, A key) {
ret map != null ? map.get(key) : null;
}*/
static A get(A[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : null;
}
// default to false
static boolean get(boolean[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : false;
}
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
try {
if (o == null) return null;
if (o instanceof Class) return get((Class) o, field);
if (o instanceof Map)
return ((Map) o).get(field);
Field f = getOpt_findField(o.getClass(), field);
if (f != null) {
makeAccessible(f);
return f.get(o);
}
if (o instanceof DynamicObject)
return getOptDynOnly(((DynamicObject) o), field);
} catch (Exception e) {
throw asRuntimeException(e);
}
throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName());
}
static Object get_raw(String field, Object o) {
return get_raw(o, field);
}
static Object get_raw(Object o, String field) { try {
if (o == null) return null;
Field f = get_findField(o.getClass(), field);
makeAccessible(f);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
static Object get(Class c, String field) {
try {
Field f = get_findStaticField(c, field);
makeAccessible(f);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field get_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 Field get_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 Object get(String field, Object o) {
return get(o, field);
}
static boolean get(BitSet bs, int idx) {
return bs != null && bs.get(idx);
}
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
static String str(Object o) {
return o == null ? "null" : o.toString();
}
static String str(char[] c) {
return new String(c);
}
static String str(char[] c, int offset, int count) {
return new String(c, offset, count);
}
static String yesno(boolean b) {
return yesno((Boolean) b);
}
static String yesno(Boolean b) {
return eq(b, true) ? "Yes. " : eq(b, false) ? "No. " : "Unknown. ";
}
static boolean startsWith(String a, String b) {
return a != null && a.startsWith(unnull(b));
}
static boolean startsWith(String a, char c) {
return nemptyString(a) && a.charAt(0) == c;
}
static boolean startsWith(String a, String b, Matches m) {
if (!startsWith(a, b)) return false;
if (m != null) m.m = new String[] {substring(a, strL(b))};
return true;
}
static 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 Object serve404() {
return subBot_serve404();
}
static Object serve404(String msg) {
return subBot_serve404(msg);
}
static String htitle_h2(String s) {
return htitle_noEncode(dropTags(s)) + h2(s);
}
static String htmlencode(Object o) {
return htmlencode(str(o));
}
static 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("");
out.append(intToHex_flexLength(cp));
out.append(';');
i += Character.charCount(cp)-1;
} else
out.append(c);
}
return out.toString();
}
static String hpre_htmlencode(Object contents, Object... params) {
return pre_htmlencode(contents, params);
}
static 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 List sortedByFieldIC(String field, Collection c) {
return sortedByFieldIC(c, field);
}
static List sortedByFieldDesc(Collection c, String field) {
List l = new ArrayList(c);
sort(l, descFieldComparator(field));
return l;
}
static List sortedByFieldDesc(String field, Collection c) {
return sortedByFieldDesc(c, field);
}
static String h3_title(String s) {
return h3_htitle(s);
}
// params = relative link, HTML, relative link, HTML, ...
static String hBoolSelector(boolean value, String... params) {
List l = new ArrayList();
for (int i = 0; i < l(params); i += 2) {
boolean selected = value != (i == 0);
String link = params[i], html = params[i+1];
if (selected)
l.add(b("[" + html + "]"));
else
l.add(ahref(rawSelfLink(link), html));
}
return join(" | ", l);
}
static boolean nempty(Collection c) {
return !empty(c);
}
static boolean nempty(CharSequence s) {
return !empty(s);
}
static boolean nempty(Object[] o) { return !empty(o); }
static boolean nempty(byte[] o) { return !empty(o); }
static boolean nempty(int[] o) { return !empty(o); }
static boolean nempty(BitSet bs) { return !empty(bs); }
static boolean nempty(Map m) {
return !empty(m);
}
static boolean nempty(Iterator i) {
return i != null && i.hasNext();
}
static boolean nempty(IMultiMap mm) { return mm != null && mm.size() != 0; }
static boolean nempty(Object o) { return !empty(o); }
static boolean nempty(Rect r) { return r != null && r.w != 0 && r.h != 0; }
static boolean nempty(MultiSet ms) { return ms != null && !ms.isEmpty(); }
static String hmobilefix() {
return " ";
}
static String hmobilefix(String html) {
return hAddToHead(html, hmobilefix());
}
static String htitle_h3(String s) {
return h3_htitle(s);
}
static String singleQuote(Object o) {
if (o == null) return "null";
return singleQuote(str(o));
}
static String singleQuote(String s) {
if (s == null) return "null";
StringBuilder out = new StringBuilder((int) (l(s)*1.5+2));
singleQuote_impl(s, out);
return out.toString();
}
static void singleQuote_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
out.append(c);
}
out.append('\'');
}
static String redirectToWebAuth() {
return "Not authed. " + ahref(relativeBotLink("#1002590"), "Authenticate");
}
static Object html_serveDispatches(String uri) {
if (eq(uri, "/dispatches"))
return htmlencode(sfu(mapValues(new F1() { public Map get(countDispatch_Data d) { try {
return mapPlus(objectToMap(d), "averageTime" , ratio(d.totalTime, d.invocations));
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "mapPlus(objectToMap(d), averageTime := ratio(d.totalTime, d.invocations))"; }}, cloneMap(countDispatch_map))));
return null;
}
static List list(Class type) { return list(type, db_mainConcepts()); }
static List list(Class type, Concepts cc) {
return cc.list(type);
}
static List list(Concepts concepts, Class type) {
return concepts.list(type);
}
static List list(String type) {
return db_mainConcepts().list(type);
}
static List list(Concepts concepts, String type) {
return concepts.list(type);
}
static List list(Concepts concepts) {
return asList(concepts.allConcepts());
}
static Object subBot_serveFileWithName(File file) {
return subBot_serveFileWithName(file, file.getName());
}
static Object subBot_serveFileWithName(File file, String name) {
return call(getMainBot(), "serveFileWithName", file, name);
}
static Object subBot_serveFileWithName(String name, File file) {
return subBot_serveFileWithName(file, name);
}
static Object subBot_serveFileWithName(File file, String name, String mimeType) {
return call(getMainBot(), "serveFileWithName", file, name, mimeType);
}
static String ymd_minus_hms() {
return ymd() + "-" + hms();
}
static File conceptsFile(String progID) {
return getProgramFile(progID, conceptsFileName());
}
static File conceptsFile() {
return conceptsFile(dbProgramID());
}
static File conceptsFile(Concepts concepts) {
return concepts.conceptsFile();
}
static Collection conceptsWhere(Class c, Object... params) {
return findConceptsWhere(c, params);
}
static Collection conceptsWhere(String c, Object... params) {
return findConceptsWhere(c, params);
}
static Collection conceptsWhere(Concepts concepts, Class c, Object... params) {
return findConceptsWhere(concepts, c, params);
}
static String hpostform(Object contents, Object... params) {
return tag("form", contents, concatArrays(new Object[] {"method", "POST"}, params));
}
static String hhidden(String name, Object value, Object... params) {
return tag("input", "", concatArrays(new Object[] {"type", "hidden", "name", name, "value", value}, params));
}
static String hhidden(Map map, String... keys) {
return hiddenFields(map, keys);
}
static String hsubmit(String text, Object... params) {
return tag("input", "", concatArrays(new Object[] {"type", "submit", "value", text}, params));
}
static String hsubmit() {
return hsubmit("Submit");
}
static boolean neqic(String a, String b) {
return !eqic(a, b);
}
static boolean neqic(char a, char b) {
return !eqic(a, b);
}
static String quote(Object o) {
if (o == null) return "null";
return quote(str(o));
}
static 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 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 void logStructure(File logFile, Object o) {
logQuoted(logFile, structure(o));
}
// quick version - log to file in program directory
static void logStructure(String fileName, Object o) {
logStructure(getProgramFile(fileName), o);
}
static void logStructure(String progID, String fileName, Object o) {
logStructure(getProgramFile(progID, fileName), o);
}
static HashMap litmap(Object... x) {
HashMap map = new HashMap();
litmap_impl(map, x);
return map;
}
static 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 long now_virtualTime;
static long now() {
return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis();
}
static void deleteConcept(long id) {
db_mainConcepts().deleteConcept(id);
}
static void deleteConcept(Concepts concepts, long id) {
concepts.deleteConcept(id);
}
static void deleteConcept(Concept c) {
if (c != null) c.delete();
}
static void deleteConcept(Concept.Ref ref) {
if (ref != null) deleteConcept(ref.get());
}
static boolean neqAny(Object... l) {
for (int i = 0; i < l(l); i += 2)
if (neq(l[i], l[i+1])) return true;
return false;
}
static String unnull(String s) {
return s == null ? "" : s;
}
static Collection unnull(Collection l) {
return l == null ? emptyList() : l;
}
static List unnull(List l) { return l == null ? emptyList() : l; }
static int[] unnull(int[] l) { return l == null ? emptyIntArray() : l; }
static char[] unnull(char[] l) { return l == null ? emptyCharArray() : l; }
static double[] unnull(double[] l) { return l == null ? emptyDoubleArray() : l; }
static Map unnull(Map l) {
return l == null ? emptyMap() : l;
}
static Iterable unnull(Iterable i) {
return i == null ? emptyList() : i;
}
static A[] unnull(A[] a) {
return a == null ? (A[]) emptyObjectArray() : a;
}
static BitSet unnull(BitSet b) {
return b == null ? new BitSet() : b;
}
static Pt unnull(Pt p) {
return p == null ? new Pt() : p;
}
//ifclass Symbol
static Symbol unnull(Symbol s) {
return s == null ? emptySymbol() : s;
}
//endif
static Pair unnull(Pair p) {
return p != null ? p : new Pair(null, null);
}
static int unnull(Integer i) { return i == null ? 0 : i; }
static long unnull(Long l) { return l == null ? 0L : l; }
static double unnull(Double l) { return l == null ? 0.0 : l; }
static String md5(String text) { try {
if (text == null) return "-";
return bytesToHex(md5_impl(toUtf8(text))); // maybe different than the way PHP does it...
} catch (Exception __e) { throw rethrow(__e); } }
static String md5(byte[] data) {
if (data == null) return "-";
return bytesToHex(md5_impl(data));
}
static byte[] md5_impl(byte[] data) { try {
return MessageDigest.getInstance("MD5").digest(data);
} catch (Exception __e) { throw rethrow(__e); } }
static String md5(File file) {
return md5OfFile(file);
}
static String rawLink(String pageName) {
return "/" + parseSnippetID(getProgramID()) + "/raw" + addPrefix("/", pageName);
}
static String rawLink() {
return "/" + parseSnippetID(getProgramID()) + "/raw";
}
static String rawLink(String pageName, String contents) {
return ahref(rawLink(pageName), contents);
}
static int randomID_defaultLength = 12;
static String randomID(int length) {
return makeRandomID(length);
}
static String randomID(Random r, int length) {
return makeRandomID(r, length);
}
static String randomID() {
return randomID(randomID_defaultLength);
}
static String randomID(Random r) {
return randomID(r, randomID_defaultLength);
}
static String htextarea(String text, Object... params) {
params = html_massageAutofocusParam(params);
return hopeningTag("textarea", params) + htmlencode2(text) + "";
}
// TODO: extended multi-line strings
static int javaTok_n, javaTok_elements;
static boolean javaTok_opt = false;
static 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;
// scan for whitespace
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);
// scan for non-whitespace
// Special JavaX syntax: 'identifier
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 == '\'') { // allow multi-line strings, but not for '
++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) == '\'')); // for stuff like "don't"
else if (Character.isDigit(c)) {
do ++j; while (j < l && Character.isDigit(s.charAt(j)));
if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L
} 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 List javaTok(List tok) {
return javaTokWithExisting(join(tok), tok);
}
static String jreplace(String s, String in, String out) {
return jreplace(s, in, out, null);
}
static String jreplace(String s, String in, String out, Object condition) {
List tok = javaTok(s);
return jreplace(tok, in, out, condition) ? join(tok) : s;
}
// leaves tok properly tokenized
// returns true iff anything was replaced
static boolean jreplace(List tok, String in, String out) {
return jreplace(tok, in, out, false, true, null);
}
static boolean jreplace(List tok, String in, String out, Object condition) {
return jreplace(tok, in, out, false, true, condition);
}
static boolean jreplace(List tok, String in, String out, IF2, Integer, Boolean> condition) {
return jreplace(tok, in, out, (Object) condition);
}
static 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++) { // TODO: don't need this check anymore
i = findCodeTokens(tok, i+1, ignoreCase, toks, condition);
if (i < 0)
return anyChange;
List subList = tok.subList(i-1, i+lTokin-1); // N to N
String expansion = jreplaceExpandRefs(out, subList);
int end = i+lTokin-2;
clearAllTokens(tok, i, end); // C to C
tok.set(i, expansion);
if (reTok) // would this ever be false??
reTok(tok, i, end);
i = end;
anyChange = true;
}
throw fail("woot? 10000! " + quote(in) + " => " + quote(out));
}
static boolean jreplace_debug = false;
static int jfind(String s, String in) {
return jfind(javaTok(s), in);
}
static int jfind(List tok, String in) {
return jfind(tok, 1, in);
}
static int jfind(List tok, int startIdx, String in) {
return jfind(tok, startIdx, in, (ITokCondition) null);
}
static int jfind(List tok, String in, Object condition) {
return jfind(tok, 1, in, condition);
}
static int jfind(List tok, String in, IIntPred condition) { return jfind(tok, 1, in, condition); }
static int jfind(List tok, int startIndex, String in, IIntPred condition) {
return jfind(tok, startIndex, in, tokCondition(condition));
}
static int jfind(List tok, String in, ITokCondition condition) { return jfind(tok, 1, in, condition); }
static int jfind(List tok, int startIndex, String in, ITokCondition condition) {
return jfind(tok, startIndex, in, (Object) condition);
}
static int jfind(List tok, int startIdx, String in, Object condition) {
//LS tokin = jfind_preprocess(javaTok(in));
return jfind(tok, startIdx, javaTokForJFind_array(in), condition);
}
// assumes you preprocessed tokin
static int jfind(List tok, List tokin) {
return jfind(tok, 1, tokin);
}
static int jfind(List tok, int startIdx, List tokin) {
return jfind(tok, startIdx, tokin, null);
}
static int jfind(List tok, int startIdx, String[] tokinC, Object condition) {
return findCodeTokens(tok, startIdx, false, tokinC, condition);
}
static int jfind(List tok, int startIdx, List tokin, Object condition) {
return jfind(tok, startIdx, codeTokensAsStringArray(tokin), condition);
}
static 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 String joinSubList(List l, int i, int j) {
return join(subList(l, i, j));
}
static String joinSubList(List l, int i) {
return join(subList(l, i));
}
// returns l(s) if not found
static 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 int smartIndexOf(String s, int i, char c) {
return smartIndexOf(s, c, i);
}
static 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 int smartIndexOf(String s, String sub) {
return smartIndexOf(s, sub, 0);
}
static int smartIndexOf(String s, char c) {
return smartIndexOf(s, c, 0);
}
static int smartIndexOf(List l, A sub) {
return smartIndexOf(l, sub, 0);
}
static int smartIndexOf(List l, int start, A sub) {
return smartIndexOf(l, sub, start);
}
static int smartIndexOf(List l, A sub, int start) {
int i = indexOf(l, sub, start);
return i < 0 ? l(l) : i;
}
static String htableRaw2_singleRow(List rows, List paramsTable, List paramsTR, List paramsTD) {
return htableRaw2(ll(rows), paramsTable, paramsTR, paramsTD);
}
static String iframe(String url, Object... params) {
return hfulltag("iframe", "", arrayPlus(params, "src" , url));
}
static String relativeRawBotLink() {
return relativeRawBotLink(programID());
}
static String relativeRawBotLink(long botID) {
return "/" + botID + "/raw";
}
static String relativeRawBotLink(String botID) {
return relativeRawBotLink(parseSnippetID(botID));
}
static String relativeRawBotLink(long botID, String uri) {
return "/" + botID + "/raw" + addPrefix("/", uri);
}
static String relativeRawBotLink(String botID, String uri) {
return relativeRawBotLink(parseSnippetID(botID), uri);
}
static String urlencode(String x) {
try {
return URLEncoder.encode(unnull(x), "UTF-8");
} catch (UnsupportedEncodingException e) { throw new RuntimeException(e); }
}
static String htitle(String title) {
return hfulltag("title", htmlencode_noQuotes(title));
}
static String h2(String s, Object... params) {
return tag("h2", s, params);
}
static String ahref(String link, Object contents, Object... params) {
return link == null ? str(contents) : href(link, contents, params);
}
static String neatMechListURL(String listName) {
return "http://botcompany.de/mech/raw/list/" + urlencode(listName);
}
static String htmlencode2(String s) {
return htmlencode_noQuotes(s);
}
static String nLines(long n) { return n2(n, "line"); }
static String nLines(Collection l) { return nLines(l(l)); }
static String nLines(String s) { return nLines(countLines(s)); }
static int countLines(String s) {
return l(toLines(s)); // yeah could be optimized :-)
}
// first element of params can be the value
static 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 String htextinput(String name) {
return htextinput(name, "");
}
static String h3(String s, Object... params) {
return tag("h3", s, params) + "\n";
}
static String p(Object contents, Object... params) {
return hfulltag("p", contents, params) + "\n";
}
static String p() { return p(""); }
static String hbutton(String text, Object... params) {
return hfulltag("button", text, params);
}
static String trim(String s) { return s == null ? null : s.trim(); }
static String trim(StringBuilder buf) { return buf.toString().trim(); }
static String trim(StringBuffer buf) { return buf.toString().trim(); }
static 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 List filter(Object pred, Iterable c) {
return filter(c, pred);
}
static 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 List filter(F1 pred, Iterable c) {
return filter(c, pred);
}
//ifclass IF1
static 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 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 List filter(IF1 pred, Iterable c) {
return filter(c, pred);
}
//endif
static String hcomment(String text) {
return hcommentSafe(text);
}
static String n2(long l) { return formatWithThousands(l); }
static String n2(AtomicLong l) { return n2(l.get()); }
static String n2(Collection l) { return n2(l(l)); }
static String n2(Map map) { return n2(l(map)); }
static String n2(double l, String singular) {
return empty(singular) ? str(l) : n2(l, singular, singular + "s");
}
static String n2(double l, String singular, String plural) {
if (fraction(l) == 0)
return n2((long) l, singular, plural);
else
return l + " " + plural;
}
static String n2(long l, String singular, String plural) {
return n_fancy2(l, singular, plural);
}
static String n2(long l, String singular) {
return empty(singular) ? n2(l) : n_fancy2(l, singular, singular + "s");
}
static String n2(Collection l, String singular) {
return n2(l(l), singular);
}
static String n2(Collection l, String singular, String plural) {
return n_fancy2(l, singular, plural);
}
static String n2(Map m, String singular, String plural) {
return n_fancy2(m, singular, plural);
}
static String n2(Map m, String singular) {
return n2(l(m), singular);
}
static String n2(long[] a, String singular) { return n2(l(a), singular); }
static String n2(Object[] a, String singular) { return n2(l(a), singular); }
static String n2(Object[] a, String singular, String plural) { return n_fancy2(a, singular, plural); }
static String n2(MultiSet ms, String singular) { return n2(ms, singular, singular + "s"); }
static String n2(MultiSet ms, String singular, String plural) {
return n_fancy2(ms, singular, plural);
}
static String n2(IMultiMap mm, String singular) { return n2(mm, singular, singular + "s"); }
static String n2(IMultiMap mm, String singular, String plural) {
return n_fancy2(l(mm), singular, plural);
}
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(short[] a) { return a == null ? 0 : a.length; }
static int l(long[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(double[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static long l(File f) { return f == null ? 0 : f.length(); }
static int l(MultiSet ms) { return ms == null ? 0 : ms.size(); }
static int l(IMultiMap mm) { return mm == null ? 0 : mm.size(); }
static int l(AppendableChain a) { return a == null ? 0 : a.size; }
static long toK(long l) {
return (l+1023)/1024;
}
static String htableRaw_singleRow(List row, Object... params) {
return htableRaw(ll(row), params);
}
static String hform(Object contents, Object... params) {
return htag("form", contents, params);
}
static void _close(AutoCloseable c) {
if (c != null) try {
c.close();
} catch (Throwable e) {
// Some classes stupidly throw an exception on double-closing
if (c instanceof javax.imageio.stream.ImageOutputStream)
return;
else throw rethrow(e);
}
}
static A findConcept(Class c, Object... params) {
return findConceptWhere(c, params);
}
static A findConcept(Concepts concepts, Class c, Object... params) {
return findConceptWhere(concepts, c, params);
}
static Concept cnew(String name, Object... values) {
return cnew(db_mainConcepts(), name, values);
}
static Concept cnew(Concepts concepts, String name, Object... values) {
Class extends Concept> cc = findClass(name);
concepts_unlisted.set(true);
Concept c;
try {
c = cc != null ? nuObject(cc) : new Concept(name);
} finally {
concepts_unlisted.set(null);
}
csetAll(c, values);
concepts.register(c);
return c;
}
static A cnew(Class cc, Object... values) {
return cnew(db_mainConcepts(), cc, values);
}
static A cnew(Concepts concepts, Class cc, Object... values) {
concepts_unlisted.set(true);
A c;
try {
c = nuObject(cc);
} finally {
concepts_unlisted.set(null);
}
csetAll(c, values);
concepts.register(c);
return c;
}
static String ul(String... list) {
return ul(asList(list));
}
static String ul(Collection list, Object... params) {
StringBuilder buf = new StringBuilder();
int i = indexOf(params, null); // null separates params for ul from params for li
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 String mech_guessLanguage_quick(String s) {
return guessGermanOrEnglish(s);
}
static void addIfNempty(Collection l, String s) {
if (nempty(s)) l.add(s);
}
static void addIfNempty(Collection l, Map m) {
if (nempty(m)) l.add(m);
}
static void addIfNempty(Collection l, Collection c) {
if (nempty(c)) l.add(c);
}
static String or2(String a, String b) {
return nempty(a) ? a : b;
}
static String or2(String a, String b, String c) {
return or2(or2(a, b), c);
}
static String appendBracketed(Object o) {
String b = strOrNull(o);
return empty(b) ? "" : "" + " (" + b + ")";
}
static String appendBracketed(String a, String b) {
return a + appendBracketed(b);
}
static String joinWithComma(Collection c) {
return join(", ", c);
}
static String joinWithComma(Object... c) {
return join(", ", c);
}
static String joinWithComma(String... c) {
return join(", ", c);
}
static String joinWithComma(Pair p) {
return p == null ? "" : joinWithComma(str(p.a), str(p.b));
}
static List scoredSearch_prepare(String query) {
return map(__45 -> replacePlusWithSpace(__45), splitAtSpace(query));
}
static void putUnlessZero(Map map, A key, int value) {
if (map != null && key != null && value != 0) map.put(key, value);
}
static void putUnlessZero(Map map, A key, double value) {
if (map != null && key != null && value != 0) map.put(key, value);
}
// Search for some words in some texts and return a total score
static 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 int scoredSearch_score(String s, List words) {
int score = 0;
if (nempty(s))
for (String word : unnullForIteration(words))
score += scoredSearch_score_single(s, word);
return score;
}
static int scoredSearch_score(String s, String query) {
return scoredSearch_score(s, scoredSearch_prepare(query));
}
static List keysSortedByValuesDesc(final Map map) {
List l = new ArrayList(map.keySet());
sort(l, mapComparatorDesc(map));
return l;
}
static int parseIntOpt(String s) { return parseIntOpt(s, 0); }
static int parseIntOpt(String s, int defValue) {
return isInteger(s) ? parseInt(s) : defValue;
}
static Map mapPlus(Map m, Object... data) {
m = cloneMap(m);
litmap_impl(m, data);
return m;
}
static List takeFirst(List l, int n) {
return l(l) <= n ? l : newSubListOrSame(l, 0, n);
}
static List takeFirst(int n, List l) {
return takeFirst(l, n);
}
static String takeFirst(int n, String s) { return substring(s, 0, n); }
static String takeFirst(String s, int n) { return substring(s, 0, n); }
static CharSequence takeFirst(int n, CharSequence s) { return subCharSequence(s, 0, n); }
static List takeFirst(int n, Iterator it) {
if (it == null) return null;
List l = new ArrayList();
for (int _repeat_0 = 0; _repeat_0 < n; _repeat_0++) { if (it.hasNext()) l.add(it.next()); else break; }
return l;
}
static List takeFirst(int n, Iterable i) {
if (i == null) return null;
return i == null ? null : takeFirst(n, i.iterator());
}
static List takeFirst(int n, IterableIterator i) {
return takeFirst(n, (Iterator ) i);
}
static int[] takeFirst(int n, int[] a) { return takeFirstOfIntArray(n, a); }
static short[] takeFirst(int n, short[] a) { return takeFirstOfShortArray(n, a); }
static byte[] takeFirst(int n, byte[] a) { return takeFirstOfByteArray(n, a); }
static byte[] takeFirst(byte[] a, int n) { return takeFirstOfByteArray(n, a); }
static double[] takeFirst(int n, double[] a) { return takeFirstOfDoubleArray(n, a); }
static double[] takeFirst(double[] a, int n) { return takeFirstOfDoubleArray(n, a); }
static String substring(String s, int x) {
return substring(s, x, strL(s));
}
static 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);
}
// convenience method for quickly dropping a prefix
static String substring(String s, CharSequence l) {
return substring(s, lCharSequence(l));
}
static HashSet asHashSet(Collection c) {
synchronized(collectionMutex(c)) {
return new HashSet(c);
}
}
static HashSet asHashSet(A[] a) {
return a == null ? null : new HashSet(Arrays.asList(a));
}
static Set setMinusSet(Set l, Collection stuff) {
if (empty(stuff)) return l;
Set set = asSet(stuff);
Set l2 = similarEmptySet(l);
for (A a : l) if (!set.contains(a)) l2.add(a);
return l2;
}
static Set setMinusSet(Collection l, Collection stuff) {
return setMinusSet(asSet(l), stuff);
}
static boolean emptyAfterTrim(String s) {
return empty(trim(s));
}
static String appendNewLineIfNempty(String s) {
return empty(s) ? "" : s + "\n";
}
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 boolean isTrue(Object o) {
if (o instanceof Boolean)
return ((Boolean) o).booleanValue();
if (o == null) return false;
if (o instanceof ThreadLocal) // TODO: remove this
return isTrue(((ThreadLocal) o).get());
throw fail(getClassName(o));
}
static boolean isTrue(Boolean b) {
return b != null && b.booleanValue();
}
static List splitAtEmptyLines(String text) {
List lines = toLines(text);
int n = l(lines), i = 0;
List parts = new ArrayList();
while (true) { ping();
while (i < n && emptyAfterTrim(lines.get(i))) ++i;
if (i >= n) break;
int j = i;
while (j < n && !emptyAfterTrim(lines.get(j))) ++j;
parts.add(fromLines(subList(lines, i, j)));
i = j;
}
return parts;
}
static String joinWithEmptyLines(Iterable l) {
return join("\n\n", map(__46 -> rtrim(__46), l));
}
static String joinWithEmptyLines(String... l) {
return joinWithEmptyLines(asList(l));
}
static String nlLogic_addGlobalID(String rule) {
rule = ltrim(rule);
if (!startsWith(rule, "[id:"))
rule = "[id: " + aGlobalID() +
(rule.startsWith("[") ? ", " + dropPrefix("[", rule) : "] " + rule);
return rule;
}
static 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 String gazelle_addGlobalID(String rule) {
if (!containsStartingWith(lines(rule), "[id:"))
rule = appendWithNewLine(rule, "[id: " + aGlobalID() + "]");
return rule;
}
static AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) {
return print_byThread().get() == null ? tempInterceptPrint(f) : null;
}
static boolean containsIgnoreCase(Collection l, String s) {
if (l != null) for (String x : l)
if (eqic(x, s))
return true;
return false;
}
static boolean containsIgnoreCase(String[] l, String s) {
if (l != null) for (String x : l)
if (eqic(x, s))
return true;
return false;
}
static boolean containsIgnoreCase(String s, char c) {
return indexOfIgnoreCase(s, String.valueOf(c)) >= 0;
}
static boolean containsIgnoreCase(String a, String b) {
return indexOfIgnoreCase(a, b) >= 0;
}
static boolean contains(Collection c, Object o) {
return c != null && c.contains(o);
}
static boolean contains(Iterable it, Object a) {
if (it != null)
for (Object o : it)
if (eq(a, o))
return true;
return false;
}
static boolean contains(Object[] x, Object o) {
if (x != null)
for (Object a : x)
if (eq(a, o))
return true;
return false;
}
static boolean contains(String s, char c) {
return s != null && s.indexOf(c) >= 0;
}
static boolean contains(String s, String b) {
return s != null && s.indexOf(b) >= 0;
}
static boolean contains(BitSet bs, int i) {
return bs != null && bs.get(i);
}
static 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 boolean contains(Rect r, Pt p) { return rectContains(r, p); }
static volatile Concepts mainConcepts; // Where we create new concepts
static Concepts db_mainConcepts() {
if (mainConcepts == null)
mainConcepts = newConceptsWithClassFinder(getDBProgramID());
return mainConcepts;
}
static void cleanMeUp_concepts() {
if (db_mainConcepts() != null) db_mainConcepts().cleanMeUp();
// mainConcepts = null; // TODO
}
static int toMS_int(double seconds) {
return toInt_checked((long) (seconds*1000));
}
static void db() {
conceptsAndBot();
}
// use -10000 for 10 seconds plus slowdown logic
static void db(Integer autoSaveInterval) {
conceptsAndBot(autoSaveInterval);
}
// first parameter can be Concepts
static 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 ConceptFieldIndexCI getConceptFieldCIIndex(Class c, String field) {
return getConceptFieldCIIndex(db_mainConcepts(), c, field);
}
static ConceptFieldIndexCI getConceptFieldCIIndex(Concepts concepts, Class c, String field) {
return (ConceptFieldIndexCI) concepts.getCIFieldIndex(c, field);
}
static String defaultThreadName_name;
static String defaultThreadName() {
if (defaultThreadName_name == null)
defaultThreadName_name = "A thread by " + programID();
return defaultThreadName_name;
}
static Runnable wrapAsActivity(Object r) {
if (r == null) return null;
Runnable r2 = toRunnable(r);
Object mod = dm_current_generic();
if (mod == null) return r2;
return new Runnable() { public void run() { try {
AutoCloseable c = (AutoCloseable) (rcall("enter", mod));
AutoCloseable __1 = c; try {
r2.run();
} finally { _close(__1); }} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "AutoCloseable c = (AutoCloseable) (rcall enter(mod));\r\n temp c;\r\n r2.r..."; }};
}
// runnable = Runnable or String (method name)
static Thread newThread(Object runnable) {
return new BetterThread(_topLevelErrorHandling(toRunnable(runnable)));
}
static Thread newThread(Object runnable, String name) {
if (name == null) name = defaultThreadName();
return new BetterThread(_topLevelErrorHandling(toRunnable(runnable)), name);
}
static Thread newThread(String name, Object runnable) {
return newThread(runnable, name);
}
static Runnable toRunnable(final Object o) {
if (o == null) return null;
if (o instanceof Runnable) return (Runnable) o;
if (o instanceof String) throw fail("callF_legacy");
return new Runnable() { public void run() { try { callF(o) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(o)"; }};
}
static Map _registerThread_threads;
static Object _onRegisterThread; // voidfunc(Thread)
static 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 void _registerThread() {
_registerThread(Thread.currentThread());
}
static Object first(Object list) {
return first((Iterable) list);
}
static A first(List list) {
return empty(list) ? null : list.get(0);
}
static A first(A[] bla) {
return bla == null || bla.length == 0 ? null : bla[0];
}
static Pair first(Map map) {
return mapEntryToPair(first(entrySet(map)));
}
static Pair first(MultiMap mm) {
if (mm == null) return null;
var e = first(mm.data.entrySet());
if (e == null) return null;
return pair(e.getKey(), first(e.getValue()));
}
static A first(IterableIterator i) {
return first((Iterator ) i);
}
static A first(Iterator i) {
return i == null || !i.hasNext() ? null : i.next();
}
static A first(Iterable i) {
if (i == null) return null;
Iterator it = i.iterator();
return it.hasNext() ? it.next() : null;
}
static Character first(String s) { return empty(s) ? null : s.charAt(0); }
static Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); }
static A first(Pair p) {
return p == null ? null : p.a;
}
static A first(T3 t) {
return t == null ? null : t.a;
}
static Byte first(byte[] l) {
return empty(l) ? null : l[0];
}
static A first(A[] l, IF1 pred) {
return firstThat(l, pred);
}
static A first(Iterable l, IF1 pred) {
return firstThat(l, pred);
}
static A first(IF1 pred, Iterable l) {
return firstThat(pred, l);
}
static A first(AppendableChain a) {
return a == null ? null : a.element;
}
static List mechList_opt(String name) {
return mechList_opt_tlft(name);
}
static Object callAndMake_extended(String code, final Object... args) {
if (code == null) return null;
code = trim(code);
if (isQuoted(code)) return unquote(code);
if (isInteger(code)) return parseInt(code);
if (isIdentifier(code))
return eq(code, "x") ? first(args) : callAndMake(code, args);
List tok = javaTok(code);
if (lCodeTokens(tok) == 4 && eq(second(tok), "f") && isIdentifier(get(tok, 3)) && eq("/", get(tok, 5)))
if (eq("1", get(tok, 7)))
return standardFunctionReference_1(get(tok, 3));
else if (eq("2", get(tok, 7)))
return standardFunctionReference_2(get(tok, 3));
Pair> p = tok_parseFunctionCall(tok);
if (p == null) throw fail("Can't parse: " + code);
return callAndMake(p.a, map_toArray(new F1() { public Object get(String arg) { try { return callAndMake_extended(arg, args); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "callAndMake_extended(arg, args)"; }}, p.b));
}
static void _handleError(Error e) {
//call(javax(), '_handleError, e);
}
// firstDelay = delay
static FixedRateTimer doEvery_daemon(long delay, final Object r) { return doEvery_daemon(defaultTimerName(), delay, r); }
static FixedRateTimer doEvery_daemon(String timerName, long delay, final Object r) {
return doEvery_daemon(timerName, delay, delay, r);
}
static FixedRateTimer doEvery_daemon(long delay, long firstDelay, final Object r) { return doEvery_daemon(defaultTimerName(), delay, firstDelay, r); }
static FixedRateTimer doEvery_daemon(String timerName, long delay, long firstDelay, final Object r) {
FixedRateTimer timer = new FixedRateTimer(true);
timer.scheduleAtFixedRate(smartTimerTask(r, timer, delay), firstDelay, delay);
return timer;
}
static FixedRateTimer doEvery_daemon(double delaySeconds, final Object r) {
return doEvery_daemon(toMS(delaySeconds), r);
}
static long changeCount() {
return db_mainConcepts().changes;
}
static void sendToSnippetUpdatesBot(String uri, Object... params) {
try { loadPageWithParams(butterBotURL("#1019175") + addSlashPrefix(uri), params); } catch (Throwable __e) { print(exceptionToStringShort(__e)); }
}
static String getStackTrace(Throwable throwable) {
lastException(throwable);
return getStackTrace_noRecord(throwable);
}
static String getStackTrace_noRecord(Throwable throwable) {
StringWriter writer = new StringWriter();
throwable.printStackTrace(new PrintWriter(writer));
return hideCredentials(writer.toString());
}
static String getStackTrace() {
return getStackTrace_noRecord(new Throwable());
}
static String getStackTrace(String msg) {
return getStackTrace_noRecord(new Throwable(msg));
}
static Map synchroMap() {
return synchroHashMap();
}
static Map synchroMap(Map map) {
return new SynchronizedMap(map);
}
static long sysNow() {
ping();
return System.nanoTime()/1000000;
}
static Object callOpt(Object o) {
return callF(o);
}
static Object callOpt(Object o, String method, Object... args) {
return callOpt_withVarargs(o, method, args);
}
static Object getBot(String botID) {
return callOpt(getMainBot(), "getBot", botID);
}
static String combinePrintParameters(String s, Object o) {
return (endsWithLetterOrDigit(s) ? s + ": " : s) + o;
}
static void ping_okInCleanUp() {
if (ping_pauseAll || ping_anyActions)
ping_impl(true);
}
// this syntax should be removed...
static Object getThreadLocal(Object o, String name) {
ThreadLocal t = (ThreadLocal) (getOpt(o, name));
return t != null ? t.get() : null;
}
static A getThreadLocal(ThreadLocal tl) {
return tl == null ? null : tl.get();
}
static A getThreadLocal(ThreadLocal tl, A defaultValue) {
return or(getThreadLocal(tl), defaultValue);
}
static ThreadLocal print_byThread_dontCreate() {
return print_byThread;
}
static boolean isFalse(Object o) {
return eq(false, o);
}
static Map> callF_cache = newDangerousWeakHashMap();
static A callF(F0 f) {
return f == null ? null : f.get();
}
static B callF(F1 f, A a) {
return f == null ? null : f.get(a);
}
static A callF(IF0 f) {
return f == null ? null : f.get();
}
static B callF(IF1 f, A a) {
return f == null ? null : f.get(a);
}
static B callF(A a, IF1 f) {
return f == null ? null : f.get(a);
}
static C callF(F2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static C callF(IF2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static void callF(VF1 f, A a) {
if (f != null) f.get(a);
}
static void callF(A a, IVF1 f) {
if (f != null) f.get(a);
}
static void callF(IVF1 f, A a) {
if (f != null) f.get(a);
}
static Object callF(Runnable r) { { if (r != null) r.run(); } return null; }
static Object callF(Object f, Object... args) {
return safeCallF(f, args);
}
static Object safeCallF(Object f, Object... args) {
if (f instanceof Runnable) {
((Runnable) f).run();
return null;
}
if (f == null) return null;
Class c = f.getClass();
ArrayList methods;
synchronized(callF_cache) {
methods = callF_cache.get(c);
if (methods == null)
methods = callF_makeCache(c);
}
int n = l(methods);
if (n == 0) {
if (f instanceof String)
throw fail("Legacy call: " + f);
throw fail("No get method in " + getClassName(c));
}
if (n == 1) return invokeMethod(methods.get(0), f, args);
for (int i = 0; i < n; i++) {
Method m = methods.get(i);
if (call_checkArgs(m, args, false))
return invokeMethod(m, f, args);
}
throw fail("No matching get method in " + getClassName(c));
}
// used internally
static ArrayList callF_makeCache(Class c) {
ArrayList l = new ArrayList();
Class _c = c;
do {
for (Method m : _c.getDeclaredMethods())
if (m.getName().equals("get")) {
makeAccessible(m);
l.add(m);
}
if (!l.isEmpty()) break;
_c = _c.getSuperclass();
} while (_c != null);
callF_cache.put(c, l);
return l;
}
static 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 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 void vmBus_send(String msg, Object... args) {
Object arg = vmBus_wrapArgs(args);
pcallFAll_minimalExceptionHandling(vm_busListeners_live(), msg, arg);
pcallFAll_minimalExceptionHandling(vm_busListenersByMessage_live().get(msg), msg, arg);
}
static void vmBus_send(String msg) {
vmBus_send(msg, (Object) null);
}
static Class mc() {
return main.class;
}
static Object mainBot;
static Object getMainBot() {
return mainBot;
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(Object... objects) { throw new Fail(objects); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static String getType(Object o) {
return getClassName(o);
}
static long getFileSize(String path) {
return path == null ? 0 : new File(path).length();
}
static long getFileSize(File f) {
return f == null ? 0 : f.length();
}
static A uniqueConcept(Class c, Object... params) {
return uniqueConcept(db_mainConcepts(), c, params);
}
static 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);
} else {
}
return x;
} finally { _close(__1); }}
static void warnIfOddCount(Object... list) {
if (odd(l(list)))
printStackTrace("Odd list size: " + list);
}
static Object[] expandParams(Class c, Object[] params) {
if (l(params) == 1)
params = new Object[] { singleFieldName(c), params[0] };
else
warnIfOddCount(params);
return params;
}
// returns true if change
static boolean _csetField(Concept c, String field, Object value) { try {
Field f = setOpt_findField(c.getClass(), field);
//print("cset: " + c.id + " " + field + " " + struct(value) + " " + f);
if (value instanceof RC) value = c._concepts.getConcept((RC) value);
value = deref(value);
if (value instanceof String && l((String) value) >= concepts_internStringsLongerThan) value = intern((String) value);
if (f == null) {
// dynamic field (undeclared)
assertIdentifier(field);
Object oldVal = mapGet(c.fieldValues, field);
if (value instanceof Concept) {
if (oldVal instanceof Concept.Ref)
// change existing reference
return ((Concept.Ref) oldVal).set((Concept) value);
else {
// overwrite non-reference value if any,
// create new reference
dynamicObject_setRawFieldValue(c, field, c.new Ref((Concept) value));
c.change(); return true;
}
} else {
// value is not a concept
// if it was a reference, cleanly delete it
if (oldVal instanceof Concept.Ref) ((Concept.Ref) oldVal).unindexAndDrop();
if (eq(oldVal, value)) return false;
if (isConceptList(value) && nempty(((List) value))) {
// TODO: clean-up etc
dynamicObject_setRawFieldValue(c, field, c.new RefL(((List) value)));
c.change(); return true;
}
if (value == null) {
// delete field
dynamicObject_dropRawField(c, field);
} else {
// update or create field
if (!isPersistable(value))
throw fail("Can't persist: " + c + "." + field + " = "+ value);
dynamicObject_setRawFieldValue(c, field, value);
}
c.change(); return true;
}
} else if (isSubtypeOf(f.getType(), Concept.Ref.class)) {
// Concept.Ref magic
((Concept.Ref) f.get(c)).set((Concept) derefRef(value));
c.change(); return true;
} else if (isSubtypeOf(f.getType(), Concept.RefL.class)) {
// Concept.RefL magic
((Concept.RefL) f.get(c)).replaceWithList(lmap(__47 -> derefRef(__47), (List) value));
c.change(); return true;
} else {
Object old = f.get(c);
if (neq(value, old)) {
boolean isTransient = isTransient(f);
if (!isTransient && !isPersistable(value))
throw fail("Can't persist: " + c + "." + field + " = "+ value);
f.set(c, value);
if (!isTransient) c.change();
return true;
}
}
return false;
} catch (Exception __e) { throw rethrow(__e); } }
static String unnullForIteration(String s) {
return s == null ? "" : s;
}
static Collection unnullForIteration(Collection l) {
return l == null ? immutableEmptyList() : l;
}
static List unnullForIteration(List l) { return l == null ? immutableEmptyList() : l; }
static int[] unnullForIteration(int[] l) { return l == null ? emptyIntArray() : l; }
static char[] unnullForIteration(char[] l) { return l == null ? emptyCharArray() : l; }
static double[] unnullForIteration(double[] l) { return l == null ? emptyDoubleArray() : l; }
static short[] unnullForIteration(short[] l) { return l == null ? emptyShortArray() : l; }
static Map unnullForIteration(Map l) {
return l == null ? immutableEmptyMap() : l;
}
static Iterable unnullForIteration(Iterable i) {
return i == null ? immutableEmptyList() : i;
}
static A[] unnullForIteration(A[] a) {
return a == null ? (A[]) emptyObjectArray() : a;
}
static BitSet unnullForIteration(BitSet b) {
return b == null ? new BitSet() : b;
}
static Pt unnullForIteration(Pt p) {
return p == null ? new Pt() : p;
}
//ifclass Symbol
static Symbol unnullForIteration(Symbol s) {
return s == null ? emptySymbol() : s;
}
//endif
static Pair unnullForIteration(Pair p) {
return p != null ? p : new Pair(null, null);
}
static long unnullForIteration(Long l) { return l == null ? 0L : l; }
static A getVar(IF0 v) {
return v == null ? null : v.get();
}
static A getVar(Optional v) {
return v == null ? null : v.orElse(null);
}
static String tag(String tag) {
return htag(tag);
}
static String tag(String tag, Object contents, Object... params) {
return htag(tag, str(contents), params);
}
static String tag(String tag, StringBuilder contents, Object... params) {
return htag(tag, contents, params);
}
static String tag(String tag, StringBuffer contents, Object... params) {
return htag(tag, contents, params);
}
static int iceil(double d) {
return (int) Math.ceil(d);
}
static String programID() {
return getProgramID();
}
static String programID(Object o) {
return getProgramID(o);
}
static String masterPW() {
return trim(loadTextFile(secretProgramFile("#1002590", "master-pw")));
}
static Object call(Object o) {
return callF(o);
}
// varargs assignment fixer for a single string array argument
static Object call(Object o, String method, String[] arg) {
return call(o, method, new Object[] {arg});
}
static Object call(Object o, String method, Object... args) {
//ret call_cached(o, method, args);
return call_withVarargs(o, method, args);
}
static byte[] toUtf8(String s) { try {
return s.getBytes(utf8charset());
} catch (Exception __e) { throw rethrow(__e); } }
static boolean startsWithIgnoreCase(String a, String b) {
return regionMatchesIC(a, 0, b, 0, b.length());
}
// legacy mode
//sbool ping_actions_shareable = true;
static volatile boolean ping_pauseAll = false;
static int ping_sleep = 100; // poll pauseAll flag every 100
static volatile boolean ping_anyActions = false;
static Map ping_actions = newWeakHashMap();
static ThreadLocal ping_isCleanUpThread = new ThreadLocal();
// ignore pingSource if not PingV3
static boolean ping(PingSource pingSource) { return ping(); }
// always returns true
static boolean ping() {
//ifdef useNewPing
newPing();
//endifdef
if (ping_pauseAll || ping_anyActions) ping_impl(true /* XXX */);
//ifndef LeanMode ping_impl(); endifndef
return true;
}
// returns true when it slept
static boolean ping_impl(boolean okInCleanUp) { try {
if (ping_pauseAll && !isAWTThread()) {
do
Thread.sleep(ping_sleep);
while (ping_pauseAll);
return true;
}
if (ping_anyActions) { // don't allow sharing ping_actions
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 Thread currentThread() {
return Thread.currentThread();
}
static Map vm_threadInterruptionReasonsMap() {
return vm_generalWeakSubMap("Thread interruption reasons");
}
static String strOr(Object o, String ifNull) {
return o == null ? ifNull : str(o);
}
static void lockOrFail(Lock lock, long timeout) { try {
ping();
vmBus_send("locking", lock, "thread" , currentThread());
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);
}
vmBus_send("locked", lock, "thread" , currentThread());
ping();
} catch (Exception __e) { throw rethrow(__e); } }
static ReentrantLock fairLock() {
return new ReentrantLock(true);
}
// usually L
static 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 String fromLines(String... lines) {
return fromLines(asList(lines));
}
// unclear semantics as to whether return null on null
static ArrayList asList(A[] a) {
return a == null ? new ArrayList () : new ArrayList (Arrays.asList(a));
}
static ArrayList asList(int[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (int i : a) l.add(i);
return l;
}
static ArrayList asList(long[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (long i : a) l.add(i);
return l;
}
static ArrayList asList(float[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (float i : a) l.add(i);
return l;
}
static ArrayList asList(double[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (double i : a) l.add(i);
return l;
}
static ArrayList asList(short[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (short i : a) l.add(i);
return l;
}
static ArrayList asList(Iterator it) {
ArrayList l = new ArrayList();
if (it != null)
while (it.hasNext())
l.add(it.next());
return l;
}
// disambiguation
static ArrayList asList(IterableIterator s) {
return asList((Iterator) s);
}
static 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 ArrayList asList(Producer p) {
ArrayList l = new ArrayList();
A a;
if (p != null) while ((a = p.next()) != null)
l.add(a);
return l;
}
static ArrayList asList(Enumeration e) {
ArrayList l = new ArrayList();
if (e != null)
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
static ArrayList asList(ReverseChain c) {
return c == null ? emptyList() : c.toList();
}
static List asList(Pair p) {
return p == null ? null : ll(p.a, p.b);
}
static IterableIterator toLines(File f) {
return linesFromFile(f);
}
static 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 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 List mapToLines(Map map) {
List l = new ArrayList();
for (Object key : keys(map))
l.add(str(key) + " = " + str(map.get(key)));
return l;
}
static String mapToLines(Map map, Object f) {
return lines(map(map, f));
}
static String mapToLines(Object f, Map map) {
return lines(map(map, f));
}
static String mapToLines(Object f, Iterable l) {
return lines(map(f, l));
}
static String mapToLines(Iterable l, IF1 f) {
return mapToLines((Object) f, l);
}
static String mapToLines(IF1 f, Iterable l) {
return mapToLines((Object) f, l);
}
static String mapToLines(Map map, IF2 f) {
return lines(map(map, f));
}
static String mapToLines(IF1 f, A data1, A... moreData) {
return lines(map(f, data1, moreData));
}
static Set asSet(Object[] array) {
HashSet set = new HashSet();
for (Object o : array)
if (o != null)
set.add(o);
return set;
}
static Set asSet(String[] array) {
TreeSet set = new TreeSet();
for (String o : array)
if (o != null)
set.add(o);
return set;
}
static 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;
}
// Note: does not clone the set (keeps multiset alive)
static Set asSet(MultiSet ms) {
return ms == null ? null : ms.asSet();
}
static List toLinesFullTrim(String s) {
List l = new ArrayList();
for (String line : toLines(s)) if (nempty(line = trim(line))) l.add(line);
return l;
}
static List toLinesFullTrim(File f) {
List l = new ArrayList();
for (String line : linesFromFile(f)) if (nempty(line = trim(line))) l.add(line);
return l;
}
static TreeSet toCaseInsensitiveSet(Iterable c) {
if (isCISet(c)) return (TreeSet) c;
TreeSet set = caseInsensitiveSet();
addAll(set, c);
return set;
}
static TreeSet toCaseInsensitiveSet(String... x) {
TreeSet set = caseInsensitiveSet();
addAll(set, x);
return set;
}
static Set keys(Map map) {
return map == null ? new HashSet() : map.keySet();
}
// convenience shortcut for keys_gen
static Set keys(Object map) {
return keys((Map) map);
}
static Set keys(MultiSet ms) {
return ms.keySet();
}
static Set keys(IMultiMap mm) {
return mm.keySet();
}
static String className(Object o) {
return getClassName(o);
}
static List sortedIgnoreCase(Collection c) {
List l = cloneList(c);
Collections.sort(l, caseInsensitiveComparator());
return l;
}
static 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 List collectField(String field, Iterable c) {
return collectField(c, field);
}
static ArrayList emptyList() {
return new ArrayList();
//ret Collections.emptyList();
}
static ArrayList emptyList(int capacity) {
return new ArrayList(max(0, capacity));
}
// Try to match capacity
static ArrayList emptyList(Iterable l) {
return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
}
static ArrayList emptyList(Object[] l) {
return emptyList(l(l));
}
// get correct type at once
static ArrayList emptyList(Class c) {
return new ArrayList();
}
static Field getOpt_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);
return null;
}
static Field makeAccessible(Field f) {
try {
f.setAccessible(true);
} catch (Throwable e) {
// Note: The error reporting only works with Java VM option --illegal-access=deny
vmBus_send("makeAccessible_error", e, f);
}
return f;
}
static Method makeAccessible(Method m) {
try {
m.setAccessible(true);
} catch (Throwable e) {
vmBus_send("makeAccessible_error", e, m);
}
return m;
}
static Constructor makeAccessible(Constructor c) {
try {
c.setAccessible(true);
} catch (Throwable e) {
vmBus_send("makeAccessible_error", e, c);
}
return c;
}
static Object getOptDynOnly(DynamicObject o, String field) {
if (o == null || o.fieldValues == null) return null;
return o.fieldValues.get(field);
}
static RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static boolean nemptyString(String s) {
return s != null && s.length() > 0;
}
static int strL(String s) {
return s == null ? 0 : s.length();
}
static int listL(Collection l) {
return l == null ? 0 : l.size();
}
static boolean neq(Object a, Object b) {
return !eq(a, b);
}
static Object subBot_serve404() {
return call(getMainBot(), "serve404");
}
static Object subBot_serve404(String msg) {
return call(getMainBot(), "serve404", msg);
}
static String htitle_noEncode(String title) {
return tag("title", title);
}
static String dropTags(String html) {
return dropAllTags(html);
}
static List dropTags(List tok) {
return dropAllTags(tok);
}
static String intToHex_flexLength(int i) {
return Integer.toHexString(i);
}
static String pre_htmlencode(Object contents, Object... params) {
return pre(htmlencode_noQuotes(str(contents)), params);
}
static void sort(T[] a, Comparator super T> c) {
if (a != null) Arrays.sort(a, c);
}
static void sort(T[] a) {
if (a != null) Arrays.sort(a);
}
static void sort(int[] a) { if (a != null) Arrays.sort(a); }
static void sort(List a, Comparator super T> c) {
if (a != null) Collections.sort(a, c);
}
static void sort(List a) {
if (a != null) Collections.sort(a);
}
static int compareIC(String s1, String s2) {
return compareIgnoreCase_jdk(s1, s2);
}
static Object getOpt(Object o, String field) {
return getOpt_cached(o, field);
}
static Object getOpt(String field, Object o) {
return getOpt_cached(o, field);
}
static Object getOpt_raw(Object o, String field) { try {
Field f = getOpt_findField(o.getClass(), field);
if (f == null) return null;
makeAccessible(f);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
// access of static fields is not yet optimized
static Object getOpt(Class c, String field) { try {
if (c == null) return null;
Field f = getOpt_findStaticField(c, field);
if (f == null) return null;
makeAccessible(f);
return f.get(null);
} catch (Exception __e) { throw rethrow(__e); } }
static Field getOpt_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);
return null;
}
static Comparator descFieldComparator(final String field) {
return new Comparator () {
public int compare(A a, A b) {
return cmp(getOpt(b, field), getOpt(a, field));
}
};
}
static String h3_htitle(String s) {
return htitle(s) + h3(s);
}
static String b(Object contents, Object... params) {
return tag("b", contents, params);
}
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));
}
public static String join(String glue, Object... strings) {
return join(glue, Arrays.asList(strings));
}
static String join(Iterable strings) {
return join("", strings);
}
static String join(Iterable strings, String glue) {
return join(glue, strings);
}
public static String join(String[] strings) {
return join("", strings);
}
static String join(String glue, Pair p) {
return p == null ? "" : str(p.a) + glue + str(p.b);
}
// if block exists: put tag after
// if not: add tag in front of the whole HTML
static 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 String relativeBotLink() {
return relativeBotLink(programID());
}
static String relativeBotLink(String botID) {
return "/" + parseSnippetID(botID);
}
static String relativeBotLink(String botID, String uri) {
return "/" + parseSnippetID(botID) + addPrefix("/", uri);
}
static String sfu(Object o) { return structureForUser(o); }
static 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 Map mapValues(Map map, IF1 f) {
return mapValues(f, map);
}
static Map mapValues(IF1 f, Map map) {
Map m = similarEmptyMap(map);
for (Map.Entry extends A, ? extends B> __0 : _entrySet( map))
{ A key = __0.getKey(); B val = __0.getValue(); m.put(key, f.get(val)); }
return m;
}
static Map mapValues(Map map, Object func) {
return mapValues(func, map);
}
static MultiMap mapValues(IF1 func, MultiMap mm) {
return mapMultiMapValues(func, mm);
}
static MultiMap mapValues(MultiMap mm, IF1 func) {
return mapValues(func, mm);
}
// o is either a map already (string->object) or an arbitrary object,
// in which case its fields are converted into a map.
static 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();
}
// XXX NEW - hopefully this doesn't break anything
if (o instanceof DynamicObject)
putAll(map, ((DynamicObject) o).fieldValues);
return map;
} catch (Exception __e) { throw rethrow(__e); } }
// same for a collection (convert each element)
static List> objectToMap(Iterable l) {
if (l == null) return null;
List x = new ArrayList();
for (Object o : l)
x.add(objectToMap(o));
return x;
}
static long ratio(long x, long y) {
return y == 0 ? 0 : x/y;
}
static double ratio(double x, double y) {
return y == 0 ? 0 : x/y;
}
static Map cloneMap(Map map) {
if (map == null) return new HashMap();
// assume mutex is equal to map
synchronized(map) {
return map instanceof TreeMap ? new TreeMap((TreeMap) map) // copies comparator
: map instanceof LinkedHashMap ? new LinkedHashMap(map)
: new HashMap(map);
}
}
static 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 String ymd() {
return ymd(now());
}
static String ymd(long now) {
return year(now) + formatInt(month(now), 2) + formatInt(dayOfMonth(now), 2);
}
static String ymd(long now, TimeZone tz) {
return year(now, tz) + formatInt(month(now, tz), 2) + formatInt(dayOfMonth(now, tz), 2);
}
static String hms() {
return hms(now());
}
static String hms(long time) {
return new SimpleDateFormat("HHmmss").format(time);
}
static File getProgramFile(String progID, String fileName) {
if (new File(fileName).isAbsolute())
return new File(fileName);
return new File(getProgramDir(progID), fileName);
}
static File getProgramFile(String fileName) {
return getProgramFile(getProgramID(), fileName);
}
static String conceptsFileName() {
return "concepts.structure.gz";
}
static String dbProgramID() {
return getDBProgramID();
}
static Collection findConceptsWhere(Class c, Object... params) {
return findConceptsWhere(db_mainConcepts(), c, params);
}
static Collection findConceptsWhere(String c, Object... params) {
return findConceptsWhere(db_mainConcepts(), c, params);
}
static Collection findConceptsWhere(Concepts concepts, Class c, Object... params) {
ping();
params = expandParams(c, params);
// indexed
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;
}
}
// table scan
return filterConcepts(concepts.list(c), params);
}
static Collection findConceptsWhere(Concepts concepts, String c, Object... params) {
return filterConcepts(concepts.list(c), params);
}
static 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;
}
// grabs only the specified keys from the map.
static String hiddenFields(Map map, Collection keys) {
StringBuilder buf = new StringBuilder();
for (String key : keys) {
String value = map.get(key);
if (!empty(value))
buf.append(htag("input", "", "type", "hidden", "name", key, "value", value) + "\n");
}
return str(buf);
}
static String hiddenFields(Map map, String... keys) {
return hiddenFields(map, asList(keys));
}
static boolean eqic(String a, String b) {
if ((a == null) != (b == null)) return false;
if (a == null) return true;
return a.equalsIgnoreCase(b);
}
static boolean eqic(Symbol a, Symbol b) {
return eq(a, b);
}
static boolean eqic(Symbol a, String b) {
return eqic(asString(a), b);
}
static 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 void logQuoted(String logFile, String line) {
logQuoted(getProgramFile(logFile), line);
}
static void logQuoted(File logFile, String line) {
appendToFile(logFile, quote(line) + "\n");
}
static boolean structure_showTiming, structure_checkTokenCount;
static String structure(Object o) {
return structure(o, new structure_Data());
}
static String structure(Object o, structure_Data d) {
StringWriter sw = new StringWriter();
d.out = new PrintWriter(sw);
structure_go(o, d);
String s = str(sw);
if (structure_checkTokenCount) {
print("token count=" + d.n);
assertEquals("token count", l(javaTokC(s)), d.n);
}
return s;
}
static void structure_go(Object o, structure_Data d) {
structure_1(o, d);
while (nempty(d.stack))
popLast(d.stack).run();
}
static void structureToPrintWriter(Object o, PrintWriter out) { structureToPrintWriter(o, out, new structure_Data()); }
static void structureToPrintWriter(Object o, PrintWriter out, structure_Data d) {
d.out = out;
structure_go(o, d);
}
// leave to false, unless unstructure() breaks
static boolean structure_allowShortening = false;
// info on how to serialize objects of a certain class
static class structure_ClassInfo {
Class c;
String shortName;
List fields;
Method customSerializer;
IVF1 serializeObject; // can be set by caller of structure function
boolean special = false; // various special classes
boolean nullInstances = false; // serialize all instances as null (e.g. lambdas/anonymous classes)
}
static class structure_Data {
PrintWriter out;
int stringSizeLimit;
int shareStringsLongerThan = 20;
boolean noStringSharing = false;
boolean storeBaseClasses = false;
boolean honorFieldOrder = true;
String mcDollar = actualMCDollar();
IdentityHashMap seen = new IdentityHashMap();
//new BitSet refd;
HashMap strings = new HashMap();
HashSet concepts = new HashSet();
HashMap infoByClass = new HashMap();
// wrapper for _persistenceInfo field or _persistenceInfo method
// by class (taking the object instance)
HashMap> persistenceInfo = new HashMap();
int n; // token count
List stack = new ArrayList();
// append single token
structure_Data append(String token) { out.print(token); ++n; return this; }
structure_Data append(int i) { out.print(i); ++n; return this; }
// append multiple tokens
structure_Data append(String token, int tokCount) { out.print(token); n += tokCount; return this; }
// extend last token
structure_Data app(String token) { out.print(token); return this; }
structure_Data app(int i) { out.print(i); return this; }
structure_ClassInfo infoForClass(Class c) {
structure_ClassInfo info = infoByClass.get(c);
if (info == null) info = newClass(c);
return info;
}
// called when a new class is detected
// can be overridden by clients
structure_ClassInfo newClass(Class c) {
structure_ClassInfo info = new structure_ClassInfo();
info.c = c;
infoByClass.put(c, info);
String name = c.getName();
String shortName = dropPrefix("loadableUtils.utils$", dropPrefix(mcDollar, name));
if (startsWithDigit(shortName)) shortName = name; // for anonymous classes
info.shortName = shortName;
try {
if (isSyntheticOrAnonymous(c)) {
info.special = info.nullInstances = true;
return info;
}
if (c.isEnum()) {
info.special = true;
return info;
}
if ((info.customSerializer = findMethodNamed(c, "_serialize"))
!= null) info.special = true;
if (storeBaseClasses) {
Class sup = c.getSuperclass();
if (sup != Object.class) {
append("bc ");
append(shortDynClassNameForStructure(c));
out.print(" ");
append(shortDynClassNameForStructure(sup));
out.print(" ");
infoForClass(sup); // transitively write out superclass relations
}
}
if (!isPersistableClass(c))
warn("Class not persistable: " + c + " (anonymous or no default constructor)");
} catch (Throwable e) { printStackTrace(e);
info.nullInstances = true;
}
return info;
}
void setFields(structure_ClassInfo info, List fields) {
info.fields = fields;
}
void writeObject(Object o, String shortName, Map fv) {
String singleField = fv.size() == 1 ? first(fv.keySet()) : null;
append(shortName);
n += countDots(shortName)*2; // correct token count
int l = n;
Iterator it = fv.entrySet().iterator();
stack.add(new Runnable() { public void run() { try {
if (!it.hasNext()) {
if (n != l)
append(")");
} else {
Map.Entry e = (Map.Entry) it.next();
append(n == l ? "(" : ", ");
append((String) e.getKey()).append("=");
stack.add(this);
structure_1(e.getValue(), structure_Data.this);
}
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!it.hasNext()) {\r\n if (n != l)\r\n append(\")\");\r\n } el..."; }});
}
}
static void structure_1(final Object o, final structure_Data d) { try {
if (o == null) { d.append("null"); return; }
Class c = o.getClass();
boolean concept = false;
concept = o instanceof Concept;
structure_ClassInfo info = d.infoForClass(c);
List lFields = info.fields;
if (lFields == null) {
// these are never back-referenced (for readability)
if (o instanceof Number) {
PrintWriter out = d.out;
if (o instanceof Integer) { int i = ((Integer) o).intValue(); out.print(i); d.n += i < 0 ? 2 : 1; return; }
if (o instanceof Long) { long l = ((Long) o).longValue(); out.print(l); out.print("L"); d.n += l < 0 ? 2 : 1; return; }
if (o instanceof Short) { short s = ((Short) o).shortValue(); d.append("sh "); out.print(s); d.n += s < 0 ? 2 : 1; return; }
if (o instanceof Float) { d.append("fl ", 2); quoteToPrintWriter(str(o), out); return; }
if (o instanceof Double) { d.append("d(", 3); quoteToPrintWriter(str(o), out); d.append(")"); return; }
if (o instanceof BigInteger) { out.print("bigint("); out.print(o); out.print(")"); d.n += ((BigInteger) o).signum() < 0 ? 5 : 4; return; }
}
if (o instanceof Boolean) {
d.append(((Boolean) o).booleanValue() ? "t" : "f"); return;
}
if (o instanceof Character) {
d.append(quoteCharacter((Character) o)); return;
}
if (o instanceof File) {
d.append("File ").append(quote(((File) o).getPath())); return;
}
// referencable objects follow
Integer ref = d.seen.get(o);
if (o instanceof String && ref == null) ref = d.strings.get((String) o);
if (ref != null) { /*d.refd.set(ref);*/ d.append("t").app(ref); return; }
if (!(o instanceof String))
d.seen.put(o, d.n); // record token number
else {
String s = d.stringSizeLimit != 0 ? shorten((String) o, d.stringSizeLimit) : (String) o;
if (!d.noStringSharing) {
if (d.shareStringsLongerThan == Integer.MAX_VALUE)
d.seen.put(o, d.n);
if (l(s) >= d.shareStringsLongerThan)
d.strings.put(s, d.n);
}
quoteToPrintWriter(s, d.out); d.n++; return;
}
if (o instanceof Set) {
/*O set2 = unwrapSynchronizedSet(o);
if (set2 != o) {
d.append("sync");
o = set2;
} TODO */
if (((Set) o) instanceof TreeSet) {
d.append(isCISet_gen((Set) o) ? "ciset" : "treeset");
structure_1(new ArrayList((Set) o), d);
return;
}
// assume it's a HashSet or LinkedHashSet
d.append(((Set) o) instanceof LinkedHashSet ? "lhs" : "hashset");
structure_1(new ArrayList((Set) o), d);
return;
}
String name = c.getName();
if (o instanceof Collection
&& !isJavaXClassName(name)
/* && neq(name, "main$Concept$RefL") */) {
// it's a list
if (name.equals("java.util.Collections$SynchronizedList")
|| name.equals("java.util.Collections$SynchronizedRandomAccessList")) {
d.append("sync ");
{ structure_1(unwrapSynchronizedList(((List) o)), d); return; }
}
else if (name.equals("java.util.LinkedList")) d.append("ll");
d.append("[");
final int l = d.n;
final Iterator it = cloneList((Collection) o).iterator();
d.stack.add(new Runnable() { public void run() { try {
if (!it.hasNext())
d.append("]");
else {
d.stack.add(this);
if (d.n != l) d.append(", ");
structure_1(it.next(), d);
}
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!it.hasNext())\r\n d.append(\"]\");\r\n else {\r\n d.sta..."; }});
return;
}
if (o instanceof SynchronizedMap) {
d.append("sync ");
{ structure_1(((SynchronizedMap) o).m, d); return; }
}
if (o instanceof Map && !startsWith(name, d.mcDollar)) {
if (o instanceof LinkedHashMap) d.append("lhm");
else if (o instanceof HashMap) d.append("hm");
else if (o instanceof TreeMap)
d.append(isCIMap_gen((TreeMap) o) ? "cimap" : "tm");
else if (name.equals("java.util.Collections$SynchronizedMap")
|| name.equals("java.util.Collections$SynchronizedSortedMap")
|| name.equals("java.util.Collections$SynchronizedNavigableMap")) {
d.append("sync ");
{ structure_1(unwrapSynchronizedMap(((Map) o)), d); return; }
}
d.append("{");
final int l = d.n;
final Iterator it = cloneMap((Map) o).entrySet().iterator();
d.stack.add(new Runnable() {
boolean v = false;
Map.Entry e;
public void run() {
if (v) {
d.append("=");
v = false;
d.stack.add(this);
structure_1(e.getValue(), d);
} else {
if (!it.hasNext())
d.append("}");
else {
e = (Map.Entry) it.next();
v = true;
d.stack.add(this);
if (d.n != l) d.append(", ");
structure_1(e.getKey(), d);
}
}
}
});
return;
}
if (c.isArray()) {
if (o instanceof byte[]) {
d.append("ba ").append(quote(bytesToHex((byte[]) o))); return;
}
final int n = Array.getLength(o);
if (o instanceof boolean[]) {
String hex = boolArrayToHex((boolean[]) o);
int i = l(hex);
while (i > 0 && hex.charAt(i-1) == '0' && hex.charAt(i-2) == '0') i -= 2;
d.append("boolarray ").append(n).app(" ").append(quote(substring(hex, 0, i))); return;
}
String atype = "array"/*, sep = ", "*/; // sep is not used yet
if (o instanceof int[]) {
//ret "intarray " + quote(intArrayToHex((int[]) o));
atype = "intarray";
//sep = " ";
} else if (o instanceof double[]) {
atype = "dblarray";
//sep = " ";
} else {
Pair p = arrayTypeAndDimensions(c);
if (p.a == int.class) atype = "intarray";
else if (p.a == byte.class) atype = "bytearray";
else if (p.a == boolean.class) atype = "boolarray";
else if (p.a == double.class) atype = "dblarray";
else if (p.a == String.class) { atype = "array S"; d.n++; }
else atype = "array"; // fail("Unsupported array type: " + p.a);
if (p.b > 1) {
atype += "/" + p.b; // add number of dimensions
d.n += 2; // 2 additional tokens will be written
}
}
d.append(atype).append("{");
d.stack.add(new Runnable() {
int i;
public void run() {
if (i >= n)
d.append("}");
else {
d.stack.add(this);
if (i > 0) d.append(", ");
structure_1(Array.get(o, i++), d);
}
}
});
return;
}
if (o instanceof Class) {
d.append("class(", 2).append(quote(((Class) o).getName())).append(")"); return;
}
if (o instanceof Throwable) {
d.append("exception(", 2).append(quote(((Throwable) o).getMessage())).append(")"); return;
}
if (o instanceof BitSet) {
BitSet bs = (BitSet) o;
d.append("bitset{", 2);
int l = d.n;
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
if (d.n != l) d.append(", ");
d.append(i);
}
d.append("}"); return;
}
// Need more cases? This should cover all library classes...
if (name.startsWith("java") || name.startsWith("sun")) {
d.append("j ").append(quote(str(o))); return; // Hm. this is not unstructure-able except for java.awt.Color
}
/*if (name.equals("main$Lisp")) {
fail("lisp not supported right now");
}*/
if (info.special) {
if (c.isEnum()) {
d.append("enum ");
d.append(info.shortName);
d.out.append(' ');
d.append(((Enum) o).ordinal());
return;
}
if (info.customSerializer != null) {
// custom serialization (_serialize method)
Object o2 = invokeMethod(info.customSerializer, o);
d.append("cu ");
String shortName = dropPrefix(d.mcDollar, name);
d.append(shortName);
d.out.append(' ');
structure_1(o2, d);
return;
} else if (info.nullInstances) { d.append("null"); return; }
else if (info.serializeObject != null)
{ info.serializeObject.get(o); return; }
else throw fail("unknown special type");
}
String dynName = shortDynClassNameForStructure(o);
if (concept && !d.concepts.contains(dynName)) {
d.concepts.add(dynName);
d.append("c ");
}
// serialize an object with fields.
// first, collect all fields and values in fv.
TreeSet fields = new TreeSet(new Comparator() {
public int compare(Field a, Field b) {
return stdcompare(a.getName(), b.getName());
}
});
Class cc = c;
while (cc != Object.class) {
for (Field field : getDeclaredFields_cached(cc)) {
String fieldName = field.getName();
if (fieldName.equals("_persistenceInfo"))
d.persistenceInfo.put(c, obj -> (Map) fieldGet(field, obj));
if ((field.getModifiers() & (java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.TRANSIENT)) != 0)
continue;
fields.add(field);
// put special cases here...?
}
cc = cc.getSuperclass();
}
Method persistenceInfoMethod = findInstanceMethod(c, "_persistenceInfo");
if (persistenceInfoMethod != null)
d.persistenceInfo.put(c, obj -> (Map) invokeMethod(persistenceInfoMethod, obj));
lFields = asList(d.honorFieldOrder ? fieldObjectsInFieldOrder(c, fields) : fields);
// Render this$0/this$1 first because unstructure needs it for constructor call.
int n = l(lFields);
for (int i = 0; i < n; i++) {
Field f = lFields.get(i);
if (f.getName().startsWith("this$")) {
lFields.remove(i);
lFields.add(0, f);
break;
}
}
d.setFields(info, lFields);
} // << if (lFields == null)
else { // ref handling for lFields != null
Integer ref = d.seen.get(o);
if (ref != null) { /*d.refd.set(ref);*/ d.append("t").app(ref); return; }
d.seen.put(o, d.n); // record token number
}
// get _persistenceInfo from field and/or dynamic field
IF1 piGetter = d.persistenceInfo.get(c);
Map persistenceInfo = piGetter == null ? null : piGetter.get(o);
if (piGetter == null && o instanceof DynamicObject)
persistenceInfo = (Map) getOptDynOnly(((DynamicObject) o), "_persistenceInfo");
LinkedHashMap fv = new LinkedHashMap();
for (Field f : lFields) {
Object value;
try {
value = f.get(o);
} catch (Exception e) {
value = "?";
}
if (value != null && (persistenceInfo == null
|| !Boolean.FALSE.equals(persistenceInfo.get(f.getName()))))
fv.put(f.getName(), value);
}
String shortName = info.shortName;
// Now we have fields & values. Process fieldValues if it's a DynamicObject.
// omit field "className" if equal to class's name
if (concept && eq(fv.get("className"), shortName))
fv.remove("className");
if (o instanceof DynamicObject) {
putAll(fv, (Map) fv.get("fieldValues"));
fv.remove("fieldValues");
if (((DynamicObject) o).className != null) {
// TODO: this probably doesn't work with inner classes
shortName = shortDynClassNameForStructure((DynamicObject) o);
fv.remove("className");
}
}
d.writeObject(o, shortName, fv);
} catch (Exception __e) { throw rethrow(__e); } }
static int[] emptyIntArray_a = new int[0];
static int[] emptyIntArray() { return emptyIntArray_a; }
static char[] emptyCharArray = new char[0];
static char[] emptyCharArray() { return emptyCharArray; }
static double[] emptyDoubleArray = new double[0];
static double[] emptyDoubleArray() { return emptyDoubleArray; }
static Map emptyMap() {
return new HashMap();
}
static Object[] emptyObjectArray_a = new Object[0];
static Object[] emptyObjectArray() { return emptyObjectArray_a; }
static Symbol emptySymbol_value;
static Symbol emptySymbol() {
if (emptySymbol_value == null) emptySymbol_value = symbol("");
return emptySymbol_value;
}
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 boolean md5OfFile_verbose = false;
static String md5OfFile(String path) {
return md5OfFile(newFile(path));
}
static 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); } }
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 String programID;
static String getProgramID() {
return nempty(programID) ? formatSnippetIDOpt(programID) : "?";
}
// TODO: ask JavaX instead
static String getProgramID(Class c) {
String id = (String) getOpt(c, "programID");
if (nempty(id))
return formatSnippetID(id);
return "?";
}
static String getProgramID(Object o) {
return getProgramID(getMainClass(o));
}
static String addPrefix(String prefix, String s) {
return s.startsWith(prefix) ? s : prefix + s;
}
static String makeRandomID(int length) {
return makeRandomID(length, defaultRandomGenerator());
}
static 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 String makeRandomID(Random r, int length) {
return makeRandomID(length, r);
}
static Object[] html_massageAutofocusParam(Object[] params) {
Object autofocus = optPar("autofocus", params);
return changeParam(params, "autofocus" , eqOneOf(autofocus, html_valueLessParam(), true, 1, "1", "autofocus") ? html_valueLessParam() : null);
}
static String hopeningTag(String tag, Map params) {
return hopeningTag(tag, mapToParams(params));
}
static 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 (eqOneOf(val, html_valueLessParam(), true))
buf.append(" " + name);
else {
String s = str(val);
if (!empty(s))
buf.append(" " + name + "=" + htmlQuote(s));
}
}
}
buf.append(">");
return str(buf);
}
static boolean regionMatches(String a, int offsetA, String b, int offsetB, int len) {
return a != null && b != null && a.regionMatches(offsetA, b, offsetB, len);
}
static boolean regionMatches(String a, int offsetA, String b) {
return regionMatches(a, offsetA, b, 0, l(b));
}
static 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 String javaTok_substringC(String s, int i, int j) {
return s.substring(i, j);
}
static 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;
// scan for whitespace
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);
// scan for non-whitespace
// Special JavaX syntax: 'identifier
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 /*|| s.charAt(j) == '\n'*/) { // allow multi-line strings
++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)); // for stuff like "don't"
else if (Character.isDigit(c)) {
do ++j; while (j < l && Character.isDigit(s.charAt(j)));
if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L
} 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 boolean javaTokWithExisting_isCopyable(String t, String s, int i, int j) {
return t.length() == j-i
&& s.regionMatches(i, t, 0, j-i); // << could be left out, but that's brave
}
static Map javaTokForJFind_array_cache = synchronizedMRUCache(1000);
static 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;
}
// Note: In the transpiler, this version is used: #1025802
static int findCodeTokens(List tok, String... tokens) {
return findCodeTokens(tok, 1, false, tokens);
}
static int findCodeTokens(List tok, boolean ignoreCase, String... tokens) {
return findCodeTokens(tok, 1, ignoreCase, tokens);
}
static int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String... tokens) {
return findCodeTokens(tok, startIdx, ignoreCase, tokens, null);
}
static HashSet findCodeTokens_specials = lithashset("*", "", "", "