import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.table.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.imageio.*; import java.math.*; import x30_pkg.x30_util; import static x30_pkg.x30_util.VF1; import static x30_pkg.x30_util.l; import static x30_pkg.x30_util.indexOf; import static x30_pkg.x30_util.getOpt; import static x30_pkg.x30_util.setOpt; import static x30_pkg.x30_util.callOpt; import static x30_pkg.x30_util.newWeakHashMap; import static x30_pkg.x30_util.newDangerousWeakHashMap; import static x30_pkg.x30_util.get; import static x30_pkg.x30_util.get_raw; import static x30_pkg.x30_util.assertTrue; import static x30_pkg.x30_util.isHeadless; import static x30_pkg.x30_util.isAndroid; import static x30_pkg.x30_util.isTrue; import x30_pkg.x30_util.DynamicObject; import loadableUtils.utils; import static loadableUtils.utils._threadInfo; import static loadableUtils.utils._threadInheritInfo; import static loadableUtils.utils.dm_currentModule; import static loadableUtils.utils.dm_current_mandatory; import static loadableUtils.utils.match; import static loadableUtils.utils.fieldType; import static loadableUtils.utils.format3; import static loadableUtils.utils.vm_generalIdentityHashSet; import static loadableUtils.utils.vm_generalHashMap; import static loadableUtils.utils.vm_generalWeakSubMap; import static loadableUtils.utils.bindToComponent; import static loadableUtils.utils.struct; import static loadableUtils.utils.structure; import static loadableUtils.utils.loadPage; import static loadableUtils.utils.loadPage_utf8; import static loadableUtils.utils.loadPageSilently; import static loadableUtils.utils.loadSnippet; import static loadableUtils.utils.loadSnippetQuietly; import static loadableUtils.utils.sendToLocalBotOpt; import static loadableUtils.utils.componentPopupMenu; import static loadableUtils.utils.dm_current_generic; import static loadableUtils.utils.dm_current_mandatory_generic; import static loadableUtils.utils.cset; import static loadableUtils.utils.DynamicObject_loading; import static loadableUtils.utils.concepts_unlisted; import static loadableUtils.utils.rethrow; import static loadableUtils.utils.hasBot; import static loadableUtils.utils.concepts_setUnlistedByDefault; import static loadableUtils.utils.realMC_tl; import loadableUtils.utils.F0; import loadableUtils.utils.F1; import loadableUtils.utils.IF0; import loadableUtils.utils.IF1; import loadableUtils.utils.IVF1; import loadableUtils.utils.IVF2; import loadableUtils.utils.Matches; import loadableUtils.utils.BetterLabel; import loadableUtils.utils.SingleComponentPanel; import loadableUtils.utils.Snippet; import loadableUtils.utils.Q; import loadableUtils.utils.structure_Data; import loadableUtils.utils.RGBImage; import loadableUtils.utils.RGB; import loadableUtils.utils.MakesBufferedImage; import loadableUtils.utils.MultiSet; import loadableUtils.utils.Concept; import loadableUtils.utils.Concepts; import loadableUtils.utils.RC; import loadableUtils.utils.IConceptIndex; import loadableUtils.utils.IConceptCounter; import loadableUtils.utils.IterableIterator; import loadableUtils.utils.IFieldIndex; import loadableUtils.utils.PersistableThrowable; import loadableUtils.utils.DynModule; import loadableUtils.utils.DynPrintLog; import loadableUtils.utils.Rect; import loadableUtils.utils.Pt; import loadableUtils.utils.SecretValue; import loadableUtils.utils.HCRUD; import loadableUtils.utils.HCRUD_Data; import loadableUtils.utils.HCRUD_Concepts; import loadableUtils.utils.DefaultValueConverterForField; import loadableUtils.utils.OrError; import loadableUtils.utils.HTML; import java.text.*; import java.text.SimpleDateFormat; import java.nio.charset.Charset; import java.text.NumberFormat; import javax.swing.undo.UndoManager; import java.awt.datatransfer.StringSelection; import java.util.TimeZone; import java.awt.geom.*; import javax.imageio.metadata.*; import javax.imageio.stream.*; import javax.swing.border.*; class main { static public class MemberCompany extends Concept { static final public String _fieldOrder = "productName description funding raised payZonesSubscribed ends"; public String productName; public String description; public String funding; public String raised; public int payZonesSubscribed; public String ends; } static public class Pays5 extends GazelleExamples { public void init() { super.init(); botName = heading = adminName = "PAYS5"; templateID = "#1030430"; cssID = "396"; enableVars = true; enableAvatars = true; showTalkToBotLink = true; enableRadioButtons = true; quickRadioButtons = true; newDialogAfterWindowClosed = true; showJoiningConversation = true; timeZone = nyTimeZone_string(); phoneNumberSpecialInputField = false; } public List crudClasses(Req req) { return listPlus(super.crudClasses(req), MemberCompany.class); } public Set hiddenCrudClasses() { return litset(); } public List botCmdClasses() { return dynNewBot2_botCmdClasses(); } public String authFormHeading() { return h3("pays5.com"); } public void makeFramer(Req req) { super.makeFramer(req); req.framer.renderTitle = () -> h1(ahref(baseLink + "/", "Pays5.com") + " " + htmlEncode2(req.framer.title)); } public String calcVar(Conversation conv, String var) { if (eqic(var, "hasUserName")) return str(nempty(calcVar(conv, "userName"))); return super.calcVar(conv, var); } public String cssURL() { return "https://pays5.com/text/" + cssID; } public Object serveOtherPage(Req req) { if (eqOptSlash(req.uri, "/companies")) { req.markNoSpam(); String template = getText(eq(req.params.get("dev"), "1") ? 2961 : 2559); SmoothHTMLTemplater templater = new SmoothHTMLTemplater(template); templater.entriesByType.put("company", map(list(MemberCompany.class), x -> templater.mapToEntry(litcimap("Wash pebbles", x.productName, "spherical hydrogel sanitiser", x.description, "$ 435,000", x.funding, "% 1.245", x.raised, "6,432", x.payZonesSubscribed, "34 days", x.ends)))); return templater.render(); } return super.serveOtherPage(req); } public boolean allowedTemplateID(String id) { return sameSnippetID(id, "#1030498"); } } static public boolean _moduleClass_Pays5 = true; static public class GazelleExamples extends DynGazelleRocks { public void init() { super.init(); useBotNameAsModuleName = false; } public List navLinks(Object... __) { return itemPlusList(ahref("https://bea.gazelle.rocks", "Switch to BEA", "title", "Latest iteration of Gazelle"), super.navLinks(__)); } } static public boolean _moduleClass_GazelleExamples = true; static public String programID; static public void _onLoad_initUtils() { utils.__javax = javax(); } static public void _onLoad_defaultClassFinder() { setDefaultClassFinder(new F1() { public Class get(String name) { Class c = findClass_fullName(name); if (c != null) return c; if (name.startsWith("main$")) return loadableUtils.utils.findClass_fullName("loadableUtils.utils" + name.substring(4)); return null; } }); } static public ThreadLocal dynamicObjectIsLoading_threadLocal() { return DynamicObject_loading; } static volatile public Concepts mainConcepts; static public Concepts db_mainConcepts() { if (mainConcepts == null) mainConcepts = newConceptsWithClassFinder(getDBProgramID()); return mainConcepts; } static public void cleanMeUp_concepts() { if (db_mainConcepts() != null) db_mainConcepts().cleanMeUp(); } static public String nyTimeZone_string() { return "US/Eastern"; } static public List listPlus(Collection l, A... more) { return concatLists(l, asList(more)); } static public HashSet litset(A... items) { return lithashset(items); } static public String h3(String s, Object... params) { return tag("h3", s, params) + "\n"; } static public String h1(String s, Object... params) { return hfulltag("h1", s, params); } static public String ahref(String link, Object contents, Object... params) { return link == null ? str(contents) : href(link, contents, params); } static public String htmlEncode2(String s) { return htmlencode_noQuotes(s); } static public String htmlEncode2(Object o) { return htmlEncode2(strOrEmpty(o)); } static public boolean eqic(String a, String b) { if ((a == null) != (b == null)) return false; if (a == null) return true; return a.equalsIgnoreCase(b); } static public boolean eqic(Symbol a, Symbol b) { return eq(a, b); } static public boolean eqic(Symbol a, String b) { return eqic(asString(a), b); } static public boolean eqic(char a, char b) { if (a == b) return true; char u1 = Character.toUpperCase(a); char u2 = Character.toUpperCase(b); if (u1 == u2) return true; return Character.toLowerCase(u1) == Character.toLowerCase(u2); } static public String str(Object o) { return o == null ? "null" : o.toString(); } static public String str(char[] c) { return new String(c); } static public boolean nempty(Collection c) { return !empty(c); } static public boolean nempty(CharSequence s) { return !empty(s); } static public boolean nempty(Object[] o) { return !empty(o); } static public boolean nempty(byte[] o) { return !empty(o); } static public boolean nempty(int[] o) { return !empty(o); } static public boolean nempty(Map m) { return !empty(m); } static public boolean nempty(Iterator i) { return i != null && i.hasNext(); } static public boolean nempty(Object o) { return !empty(o); } static public boolean nempty(IntRange r) { return !empty(r); } static public boolean nempty(Rect r) { return r != null && r.w != 0 && r.h != 0; } static public boolean eqOptSlash(String a, String b) { int n = lCommonPrefix(a, b); int la = l(a), lb = l(b); if (n == la && n == lb) return true; if (n == lb && n == la - 1 && lastChar(a) == '/') return true; if (n == la && n == lb - 1 && lastChar(b) == '/') return true; return false; } static public String getText(final AbstractButton c) { return c == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return c.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getText();"; } }); } static public String getText(final JTextComponent c) { return c == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return c.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getText();"; } }); } static public String getText(final JLabel l) { return l == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return l.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret l.getText();"; } }); } static public String getText(final JComboBox cb) { if (cb == null) return null; if (isEditableComboBox(cb)) return unnull((String) cb.getEditor().getItem()); else return str(cb.getSelectedItem()); } static public boolean eq(Object a, Object b) { return a == b || a != null && b != null && a.equals(b); } static public boolean eq(Symbol a, String b) { return eq(str(a), b); } static public List map(Iterable l, Object f) { return map(f, l); } static public List map(Object f, Iterable l) { List x = emptyList(l); if (l != null) for (Object o : l) { ping(); x.add(callF(f, o)); } return x; } static public List map(Iterable l, F1 f) { return map(f, l); } static public List map(F1 f, Iterable l) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(callF(f, o)); } return x; } static public List map(IF1 f, Iterable l) { return map(l, f); } static public List map(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static public List map(IF1 f, A[] l) { return map(l, f); } static public List map(A[] l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static public List map(Object f, Object[] l) { return map(f, asList(l)); } static public List map(Object[] l, Object f) { return map(f, l); } static public List map(Object f, Map map) { return map(map, f); } static public List map(Map map, Object f) { List x = new ArrayList(); if (map != null) for (Object _e : map.entrySet()) { ping(); Map.Entry e = (Map.Entry) _e; x.add(callF(f, e.getKey(), e.getValue())); } return x; } static public List map(Map map, IF2 f) { return map(map, (Object) f); } static public 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; } static public List list(Class type) { return db_mainConcepts().list(type); } static public List list(Concepts concepts, Class type) { return concepts.list(type); } static public List list(String type) { return db_mainConcepts().list(type); } static public List list(Concepts concepts, String type) { return concepts.list(type); } static public TreeMap litcimap(Object... x) { return litCIMap(x); } static public boolean sameSnippetID(String a, String b) { if (!isSnippetID(a) || !isSnippetID(b)) return false; return parseSnippetID(a) == parseSnippetID(b); } static public List itemPlusList(A a, Collection l) { return concatLists(ll(a), l); } static public Class javax() { return getJavaX(); } static public void setDefaultClassFinder(Object cf) { _defaultClassFinder_value = cf; } static public HashMap findClass_fullName_cache = new HashMap(); static public Class findClass_fullName(String name) { synchronized (findClass_fullName_cache) { if (findClass_fullName_cache.containsKey(name)) return findClass_fullName_cache.get(name); Class c; try { c = Class.forName(name); } catch (ClassNotFoundException e) { c = null; } findClass_fullName_cache.put(name, c); return c; } } static public Object _defaultClassFinder_value = defaultDefaultClassFinder(); static public Object _defaultClassFinder() { return _defaultClassFinder_value; } static public Concepts newConceptsWithClassFinder(String progID) { Concepts cc = new Concepts(progID); cc.classFinder = _defaultClassFinder(); return cc; } static public String getDBProgramID_id; static public String getDBProgramID() { return nempty(getDBProgramID_id) ? getDBProgramID_id : programIDWithCase(); } static public List concatLists(Iterable... lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) addAll(l, list); return l; } static public List concatLists(Collection> lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) addAll(l, list); return l; } static public ArrayList asList(A[] a) { return a == null ? new ArrayList() : new ArrayList(Arrays.asList(a)); } static public ArrayList asList(int[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (int i : a) l.add(i); return l; } static public ArrayList asList(long[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (long i : a) l.add(i); return l; } static public ArrayList asList(float[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (float i : a) l.add(i); return l; } static public ArrayList asList(double[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (double i : a) l.add(i); return l; } static public ArrayList asList(Iterator it) { ArrayList l = new ArrayList(); if (it != null) while (it.hasNext()) l.add(it.next()); return l; } static public ArrayList asList(IterableIterator s) { return asList((Iterator) s); } static public ArrayList asList(Iterable s) { if (s instanceof ArrayList) return (ArrayList) s; ArrayList l = new ArrayList(); if (s != null) for (A a : s) l.add(a); return l; } static public ArrayList asList(Producer p) { ArrayList l = new ArrayList(); A a; if (p != null) while ((a = p.next()) != null) l.add(a); return l; } static public ArrayList asList(Enumeration e) { ArrayList l = new ArrayList(); if (e != null) while (e.hasMoreElements()) l.add(e.nextElement()); return l; } static public List asList(Pair p) { return p == null ? null : ll(p.a, p.b); } static public HashSet lithashset(A... items) { HashSet set = new HashSet(); for (A a : items) set.add(a); return set; } static public String tag(String tag) { return htag(tag); } static public String tag(String tag, Object contents, Object... params) { return htag(tag, str(contents), params); } static public String tag(String tag, StringBuilder contents, Object... params) { return htag(tag, contents, params); } static public String tag(String tag, StringBuffer contents, Object... params) { return htag(tag, contents, params); } static public String hfulltag(String tag) { return hfulltag(tag, ""); } static public String hfulltag(String tag, Object contents, Object... params) { return hopeningTag(tag, params) + str(contents) + ""; } static public String href(String link, Object contents, Object... params) { if (link == null) return str(contents); return hfulltag("a", contents, arrayPlus(params, "href", link)); } static public String htmlencode_noQuotes(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '<') out.append("<"); else if (c == '>') out.append(">"); else if (c > 127 || c == '&') { int cp = s.codePointAt(i); out.append("&#x"); out.append(intToHex_flexLength(cp)); out.append(';'); i += Character.charCount(cp) - 1; } else out.append(c); } return out.toString(); } static public String strOrEmpty(Object o) { return o == null ? "" : str(o); } static public String asString(Object o) { return o == null ? null : o.toString(); } static public boolean empty(Collection c) { return c == null || c.isEmpty(); } static public boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); } static public boolean empty(CharSequence s) { return s == null || s.length() == 0; } static public boolean empty(Map map) { return map == null || map.isEmpty(); } static public boolean empty(Object[] o) { return o == null || o.length == 0; } static public boolean empty(Object o) { if (o instanceof Collection) return empty((Collection) o); if (o instanceof String) return empty((String) o); if (o instanceof Map) return empty((Map) o); if (o instanceof Object[]) return empty((Object[]) o); if (o instanceof byte[]) return empty((byte[]) o); if (o == null) return true; throw fail("unknown type for 'empty': " + getType(o)); } static public boolean empty(Iterator i) { return i == null || !i.hasNext(); } static public boolean empty(double[] a) { return a == null || a.length == 0; } static public boolean empty(float[] a) { return a == null || a.length == 0; } static public boolean empty(int[] a) { return a == null || a.length == 0; } static public boolean empty(long[] a) { return a == null || a.length == 0; } static public boolean empty(byte[] a) { return a == null || a.length == 0; } static public boolean empty(short[] a) { return a == null || a.length == 0; } static public boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); } static public boolean empty(MultiMap mm) { return mm == null || mm.isEmpty(); } static public boolean empty(File f) { return getFileSize(f) == 0; } static public boolean empty(IntRange r) { return r == null || r.empty(); } static public boolean empty(Rect r) { return !(r != null && r.w != 0 && r.h != 0); } static public int lCommonPrefix(String a, String b) { int i = 0, n = Math.min(l(a), l(b)); while (i < n && a.charAt(i) == b.charAt(i)) ++i; return i; } static public char lastChar(String s) { return empty(s) ? '\0' : s.charAt(l(s) - 1); } static public void swingAndWait(Runnable r) { try { if (isAWTThread()) r.run(); else EventQueue.invokeAndWait(addThreadInfoToRunnable(r)); } catch (Exception __e) { throw rethrow(__e); } } static public Object swingAndWait(final Object f) { if (isAWTThread()) return callF(f); else { final Var result = new Var(); swingAndWait(new Runnable() { public void run() { try { result.set(callF(f)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "result.set(callF(f));"; } }); return result.get(); } } static public boolean isEditableComboBox(final JComboBox cb) { return cb != null && swing(new F0() { public Boolean get() { try { return cb.isEditable(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret cb.isEditable();"; } }); } static public String unnull(String s) { return s == null ? "" : s; } static public Collection unnull(Collection l) { return l == null ? emptyList() : l; } static public List unnull(List l) { return l == null ? emptyList() : l; } static public int[] unnull(int[] l) { return l == null ? emptyIntArray() : l; } static public char[] unnull(char[] l) { return l == null ? emptyCharArray() : l; } static public double[] unnull(double[] l) { return l == null ? emptyDoubleArray() : l; } static public Map unnull(Map l) { return l == null ? emptyMap() : l; } static public Iterable unnull(Iterable i) { return i == null ? emptyList() : i; } static public A[] unnull(A[] a) { return a == null ? (A[]) emptyObjectArray() : a; } static public BitSet unnull(BitSet b) { return b == null ? new BitSet() : b; } static public Pt unnull(Pt p) { return p == null ? new Pt() : p; } static public Symbol unnull(Symbol s) { return s == null ? emptySymbol() : s; } static public Pair unnull(Pair p) { return p != null ? p : new Pair(null, null); } static public int unnull(Integer i) { return i == null ? 0 : i; } static public long unnull(Long l) { return l == null ? 0L : l; } static public double unnull(Double l) { return l == null ? 0.0 : l; } static public ArrayList emptyList() { return new ArrayList(); } static public ArrayList emptyList(int capacity) { return new ArrayList(max(0, capacity)); } static public ArrayList emptyList(Iterable l) { return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList(); } static public ArrayList emptyList(Object[] l) { return emptyList(l(l)); } static public ArrayList emptyList(Class c) { return new ArrayList(); } static volatile public boolean ping_pauseAll = false; static public int ping_sleep = 100; static volatile public boolean ping_anyActions = false; static public Map ping_actions = newWeakHashMap(); static public ThreadLocal ping_isCleanUpThread = new ThreadLocal(); static public boolean ping() { newPing(); if (ping_pauseAll || ping_anyActions) ping_impl(true); return true; } static public boolean ping_impl(boolean okInCleanUp) { try { if (ping_pauseAll && !isAWTThread()) { do Thread.sleep(ping_sleep); while (ping_pauseAll); return true; } if (ping_anyActions) { if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get())) failIfUnlicensed(); Object action = null; synchronized (ping_actions) { if (!ping_actions.isEmpty()) { action = ping_actions.get(currentThread()); if (action instanceof Runnable) ping_actions.remove(currentThread()); if (ping_actions.isEmpty()) ping_anyActions = false; } } if (action instanceof Runnable) ((Runnable) action).run(); else if (eq(action, "cancelled")) throw fail("Thread cancelled."); } return false; } catch (Exception __e) { throw rethrow(__e); } } static public Object callF(Object f, Object... args) { try { if (f instanceof String) return callMC((String) f, args); return x30_util.callF(f, args); } catch (Exception __e) { throw rethrow(__e); } } static public A callF(F0 f) { return f == null ? null : f.get(); } static public A callF(IF0 f) { return f == null ? null : f.get(); } static public B callF(F1 f, A a) { return f == null ? null : f.get(a); } static public B callF(IF1 f, A a) { return f == null ? null : f.get(a); } static public C callF(F2 f, A a, B b) { return f == null ? null : f.get(a, b); } static public void callF(VF1 f, A a) { if (f != null) f.get(a); } static public Object callMC(String method, Object... args) { return call(mc(), method, args); } static public Object call(Object o) { return callF(o); } static public Object call(Object o, String method, Object... args) { return call_withVarargs(o, method, args); } static public TreeMap litCIMap(Object... x) { TreeMap map = caseInsensitiveMap(); litmap_impl(map, x); return map; } public static boolean isSnippetID(String s) { try { parseSnippetID(s); return true; } catch (RuntimeException e) { return false; } } public static long parseSnippetID(String snippetID) { long id = Long.parseLong(shortenSnippetID(snippetID)); if (id == 0) throw fail("0 is not a snippet ID"); return id; } static public List ll(A... a) { ArrayList l = new ArrayList(a.length); if (a != null) for (A x : a) l.add(x); return l; } static public Class __javax; static public Class getJavaX() { try { return __javax; } catch (Exception __e) { throw rethrow(__e); } } static public Object defaultDefaultClassFinder() { return new F1() { public Class get(String name) { Class c = get2(name); return c; } public Class get2(String name) { if (eq(name, "
")) return mc(); { Class c = findClass_fullName(name); if (c != null) return c; } if (startsWithAny(name, "loadableUtils.utils$", "main$", mcDollar())) for (String pkg : ll("loadableUtils.utils$", mcDollar())) { String newName = pkg + afterDollar(name); { Class c = findClass_fullName(newName); if (c != null) return c; } } return null; } }; } static public String programIDWithCase() { return nempty(caseID()) ? programID() + "/" + quoteUnlessIdentifierOrInteger(caseID()) : programID(); } static public void addAll(Collection c, Iterable b) { if (c != null && b != null) for (A a : b) c.add(a); } static public boolean addAll(Collection c, Collection b) { return c != null && b != null && c.addAll(b); } static public boolean addAll(Collection c, B... b) { return c != null && b != null && c.addAll(Arrays.asList(b)); } static public Map addAll(Map a, Map b) { if (a != null && b != null) a.putAll(b); return a; } static public String htag(String tag) { return htag(tag, ""); } static public String htag(String tag, Object contents, Object... params) { String openingTag = hopeningTag(tag, params); String s = str(contents); if (empty(s) && neqic(tag, "script")) return dropLast(openingTag) + "/>"; return openingTag + s + ""; } static public String hopeningTag(String tag, Map params) { return hopeningTag(tag, mapToParams(params)); } static public String hopeningTag(String tag, Object... params) { StringBuilder buf = new StringBuilder(); buf.append("<" + tag); params = unrollParams(params); for (int i = 0; i < l(params); i += 2) { String name = (String) get(params, i); Object val = get(params, i + 1); if (nempty(name) && val != null) { if (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 public String a(String noun) { if (eq(noun, "")) return "?"; return ("aeiou".indexOf(noun.charAt(0)) >= 0 ? "an " : "a ") + noun; } static public String a(String contents, Object... params) { return hfulltag("a", contents, params); } static public Object[] arrayPlus(Object[] a1, Object... a2) { return concatArrays(a1, a2); } static public String intToHex_flexLength(int i) { return Integer.toHexString(i); } static public RuntimeException fail() { throw new RuntimeException("fail"); } static public RuntimeException fail(Throwable e) { throw asRuntimeException(e); } static public RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); } static public RuntimeException fail(Object... objects) { throw new Fail(objects); } static public RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); } static public RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); } static public String getType(Object o) { return getClassName(o); } static public long getFileSize(String path) { return path == null ? 0 : new File(path).length(); } static public long getFileSize(File f) { return f == null ? 0 : f.length(); } static public boolean isAWTThread() { if (isAndroid()) return false; if (isHeadless()) return false; return isAWTThread_awt(); } static public boolean isAWTThread_awt() { return SwingUtilities.isEventDispatchThread(); } static public Runnable addThreadInfoToRunnable(final Object r) { final Object info = _threadInfo(); return info == null ? asRunnable(r) : new Runnable() { public void run() { try { _inheritThreadInfo(info); callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_inheritThreadInfo(info); callF(r);"; } }; } static public Object swing(Object f) { return swingAndWait(f); } static public A swing(F0 f) { return (A) swingAndWait(f); } static public A swing(IF0 f) { return (A) swingAndWait(f); } static public int[] emptyIntArray_a = new int[0]; static public int[] emptyIntArray() { return emptyIntArray_a; } static public char[] emptyCharArray = new char[0]; static public char[] emptyCharArray() { return emptyCharArray; } static public double[] emptyDoubleArray = new double[0]; static public double[] emptyDoubleArray() { return emptyDoubleArray; } static public Map emptyMap() { return new HashMap(); } static public Object[] emptyObjectArray_a = new Object[0]; static public Object[] emptyObjectArray() { return emptyObjectArray_a; } static public Symbol emptySymbol_value; static public Symbol emptySymbol() { if (emptySymbol_value == null) emptySymbol_value = symbol(""); return emptySymbol_value; } static public int max(int a, int b) { return Math.max(a, b); } static public int max(int a, int b, int c) { return max(max(a, b), c); } static public long max(int a, long b) { return Math.max((long) a, b); } static public long max(long a, long b) { return Math.max(a, b); } static public double max(int a, double b) { return Math.max((double) a, b); } static public float max(float a, float b) { return Math.max(a, b); } static public double max(double a, double b) { return Math.max(a, b); } static public int max(Collection c) { int x = Integer.MIN_VALUE; for (int i : c) x = max(x, i); return x; } static public double max(double[] c) { if (c.length == 0) return Double.MIN_VALUE; double x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static public float max(float[] c) { if (c.length == 0) return Float.MAX_VALUE; float x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static public byte max(byte[] c) { byte x = -128; for (byte d : c) if (d > x) x = d; return x; } static public short max(short[] c) { short x = -0x8000; for (short d : c) if (d > x) x = d; return x; } static public int max(int[] c) { int x = Integer.MIN_VALUE; for (int d : c) if (d > x) x = d; return x; } static public void newPing() { var tl = newPing_actionTL(); Runnable action = tl == null ? null : tl.get(); { if (action != null) action.run(); } } static public void failIfUnlicensed() { assertTrue("license off", licensed()); } static public Thread currentThread() { return Thread.currentThread(); } static public Class mc() { return main.class; } static public Object call_withVarargs(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findStaticMethod(method, args); if (me != null) return invokeMethod(me, null, args); List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } { if (!(isStaticMethod(m))) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, null, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me != null) return invokeMethod(me, o, args); List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, o, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } } catch (Exception __e) { throw rethrow(__e); } } static public TreeMap caseInsensitiveMap() { return new TreeMap(caseInsensitiveComparator()); } static public HashMap litmap(Object... x) { HashMap map = new HashMap(); litmap_impl(map, x); return map; } static public void litmap_impl(Map map, Object... x) { if (x != null) for (int i = 0; i < x.length - 1; i += 2) if (x[i + 1] != null) map.put(x[i], x[i + 1]); } static public String shortenSnippetID(String snippetID) { if (snippetID.startsWith("#")) snippetID = snippetID.substring(1); String httpBlaBla = "http://tinybrain.de/"; if (snippetID.startsWith(httpBlaBla)) snippetID = snippetID.substring(httpBlaBla.length()); return "" + parseLong(snippetID); } static public Object get2(Object o, String field1, String field2) { return get(get(o, field1), field2); } static public boolean startsWithAny(String a, Collection b) { for (String prefix : unnullForIteration(b)) if (startsWith(a, prefix)) return true; return false; } static public boolean startsWithAny(String a, String... b) { if (b != null) for (String prefix : unnullForIteration(b)) if (startsWith(a, prefix)) return true; return false; } static public boolean startsWithAny(String a, Collection b, Matches m) { for (String prefix : unnullForIteration(b)) if (startsWith(a, prefix, m)) return true; return false; } static public String mcDollar() { return mcName() + "$"; } static public String afterDollar(String s) { return substring(s, smartIndexOf(s, '$') + 1); } static volatile public String caseID_caseID; static public String caseID() { return caseID_caseID; } static public void caseID(String id) { caseID_caseID = id; } static public String programID() { return getProgramID(); } static public String programID(Object o) { return getProgramID(o); } static public String quoteUnlessIdentifierOrInteger(String s) { return quoteIfNotIdentifierOrInteger(s); } static public boolean neqic(String a, String b) { return !eqic(a, b); } static public boolean neqic(char a, char b) { return !eqic(a, b); } static public A[] dropLast(A[] a) { return dropLast(a, 1); } static public A[] dropLast(A[] a, int n) { if (a == null) return null; n = Math.min(n, a.length); A[] b = arrayOfSameType(a, a.length - n); System.arraycopy(a, 0, b, 0, b.length); return b; } static public List dropLast(List l) { return subList(l, 0, l(l) - 1); } static public List dropLast(int n, List l) { return subList(l, 0, l(l) - n); } static public List dropLast(Iterable l) { return dropLast(asList(l)); } static public String dropLast(String s) { return substring(s, 0, l(s) - 1); } static public String dropLast(String s, int n) { return substring(s, 0, l(s) - n); } static public String dropLast(int n, String s) { return dropLast(s, n); } static public Object[] mapToParams(Map map) { return mapToObjectArray(map); } static public Object[] unrollParams(Object[] params) { if (l(params) == 1 && params[0] instanceof Map) return mapToParams((Map) params[0]); return params; } static public boolean eqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return true; return false; } static public Object html_valueLessParam_cache; static public Object html_valueLessParam() { if (html_valueLessParam_cache == null) html_valueLessParam_cache = html_valueLessParam_load(); return html_valueLessParam_cache; } static public Object html_valueLessParam_load() { return new Object(); } static public String htmlQuote(String s) { return "\"" + htmlencode_forParams(s) + "\""; } static public Object[] concatArrays(Object[]... arrays) { int l = 0; for (Object[] a : arrays) l += l(a); Object[] x = new Object[l]; int i = 0; for (Object[] a : arrays) if (a != null) { System.arraycopy(a, 0, x, i, l(a)); i += l(a); } return x; } static public RuntimeException asRuntimeException(Throwable t) { if (t instanceof Error) _handleError((Error) t); return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static public String getClassName(Object o) { return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName(); } static public Runnable asRunnable(Object o) { return toRunnable(o); } static public void _inheritThreadInfo(Object info) { _threadInheritInfo(info); } static public WeakHasherMap symbol_map = new WeakHasherMap(new Hasher() { public int hashCode(Symbol symbol) { return symbol.text.hashCode(); } public boolean equals(Symbol a, Symbol b) { if (a == null) return b == null; return b != null && eq(a.text, b.text); } }); static public Symbol symbol(String s) { if (s == null) return null; synchronized (symbol_map) { Symbol symbol = new Symbol(s, true); Symbol existingSymbol = symbol_map.findKey(symbol); if (existingSymbol == null) symbol_map.put(existingSymbol = symbol, true); return existingSymbol; } } static public Symbol symbol(CharSequence s) { if (s == null) return null; if (s instanceof Symbol) return (Symbol) s; if (s instanceof String) return symbol((String) s); return symbol(str(s)); } static public Symbol symbol(Object o) { return symbol((CharSequence) o); } static public x30_pkg.x30_util.BetterThreadLocal newPing_actionTL; static public x30_pkg.x30_util.BetterThreadLocal newPing_actionTL() { if (newPing_actionTL == null) newPing_actionTL = vm_generalMap_getOrCreate("newPing_actionTL", () -> new x30_pkg.x30_util.BetterThreadLocal()); return newPing_actionTL; } static volatile public boolean licensed_yes = true; static public boolean licensed() { if (!licensed_yes) return false; ping_okInCleanUp(); return true; } static public void licensed_off() { licensed_yes = false; } static final public Map callOpt_cache = newDangerousWeakHashMap(); static public Object callOpt_cached(Object o, String methodName, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(methodName, args); if (me == null || (me.getModifiers() & Modifier.STATIC) == 0) return null; return invokeMethod(me, null, args); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(methodName, args); if (me == null) return null; return invokeMethod(me, o, args); } } catch (Exception __e) { throw rethrow(__e); } } static public _MethodCache callOpt_getCache(Class c) { _MethodCache cache = callOpt_cache.get(c); if (cache == null) callOpt_cache.put(c, cache = new _MethodCache(c)); return cache; } static public Object invokeMethod(Method m, Object o, Object... args) { try { try { return m.invoke(o, args); } catch (InvocationTargetException e) { throw rethrow(getExceptionCause(e)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(e.getMessage() + " - was calling: " + m + ", args: " + joinWithSpace(classNames(args))); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean isStaticMethod(Method m) { return methodIsStatic(m); } static public Object[] massageArgsForVarArgsCall(Method m, Object[] args) { Class[] types = m.getParameterTypes(); int n = types.length - 1, nArgs = args.length; if (nArgs < n) return null; for (int i = 0; i < n; i++) if (!argumentCompatibleWithType(args[i], types[i])) return null; Class varArgType = types[n].getComponentType(); for (int i = n; i < nArgs; i++) if (!argumentCompatibleWithType(args[i], varArgType)) return null; Object[] newArgs = new Object[n + 1]; arraycopy(args, 0, newArgs, 0, n); Object[] varArgs = arrayOfType(varArgType, nArgs - n); arraycopy(args, n, varArgs, 0, nArgs - n); newArgs[n] = varArgs; return newArgs; } static public String joinWithComma(Collection c) { return join(", ", c); } static public String joinWithComma(String... c) { return join(", ", c); } static public String joinWithComma(Pair p) { return p == null ? "" : joinWithComma(str(p.a), str(p.b)); } static public List classNames(Collection l) { return getClassNames(l); } static public List classNames(Object[] l) { return getClassNames(Arrays.asList(l)); } static public Comparator caseInsensitiveComparator() { return betterCIComparator(); } static public long parseLong(String s) { if (empty(s)) return 0; return Long.parseLong(dropSuffix("L", s)); } static public long parseLong(Object s) { return Long.parseLong((String) s); } static public String unnullForIteration(String s) { return s == null ? "" : s; } static public Collection unnullForIteration(Collection l) { return l == null ? immutableEmptyList() : l; } static public List unnullForIteration(List l) { return l == null ? immutableEmptyList() : l; } static public int[] unnullForIteration(int[] l) { return l == null ? emptyIntArray() : l; } static public char[] unnullForIteration(char[] l) { return l == null ? emptyCharArray() : l; } static public double[] unnullForIteration(double[] l) { return l == null ? emptyDoubleArray() : l; } static public short[] unnullForIteration(short[] l) { return l == null ? emptyShortArray() : l; } static public Map unnullForIteration(Map l) { return l == null ? immutableEmptyMap() : l; } static public Iterable unnullForIteration(Iterable i) { return i == null ? immutableEmptyList() : i; } static public A[] unnullForIteration(A[] a) { return a == null ? (A[]) emptyObjectArray() : a; } static public BitSet unnullForIteration(BitSet b) { return b == null ? new BitSet() : b; } static public Pt unnullForIteration(Pt p) { return p == null ? new Pt() : p; } static public Symbol unnullForIteration(Symbol s) { return s == null ? emptySymbol() : s; } static public Pair unnullForIteration(Pair p) { return p != null ? p : new Pair(null, null); } static public long unnullForIteration(Long l) { return l == null ? 0L : l; } static public boolean startsWith(String a, String b) { return a != null && a.startsWith(unnull(b)); } static public boolean startsWith(String a, char c) { return nemptyString(a) && a.charAt(0) == c; } static public boolean startsWith(String a, String b, Matches m) { if (!startsWith(a, b)) return false; if (m != null) m.m = new String[] { substring(a, strL(b)) }; return true; } static public boolean startsWith(List a, List b) { if (a == null || listL(b) > listL(a)) return false; for (int i = 0; i < listL(b); i++) if (neq(a.get(i), b.get(i))) return false; return true; } static public String mcName() { return mc().getName(); } static public String substring(String s, int x) { return substring(s, x, strL(s)); } static public String substring(String s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; int n = s.length(); if (y < x) y = x; if (y > n) y = n; if (x >= y) return ""; return s.substring(x, y); } static public String substring(String s, IntRange r) { return r == null ? null : substring(s, r.start, r.end); } static public String substring(String s, CharSequence l) { return substring(s, lCharSequence(l)); } static public int smartIndexOf(String s, String sub, int i) { if (s == null) return 0; i = s.indexOf(sub, min(i, l(s))); return i >= 0 ? i : l(s); } static public int smartIndexOf(String s, int i, char c) { return smartIndexOf(s, c, i); } static public int smartIndexOf(String s, char c, int i) { if (s == null) return 0; i = s.indexOf(c, min(i, l(s))); return i >= 0 ? i : l(s); } static public int smartIndexOf(String s, String sub) { return smartIndexOf(s, sub, 0); } static public int smartIndexOf(String s, char c) { return smartIndexOf(s, c, 0); } static public int smartIndexOf(List l, A sub) { return smartIndexOf(l, sub, 0); } static public int smartIndexOf(List l, int start, A sub) { return smartIndexOf(l, sub, start); } static public int smartIndexOf(List l, A sub, int start) { int i = indexOf(l, sub, start); return i < 0 ? l(l) : i; } static public String getProgramID() { return nempty(programID) ? formatSnippetIDOpt(programID) : "?"; } static public String getProgramID(Class c) { String id = (String) getOpt(c, "programID"); if (nempty(id)) return formatSnippetID(id); return "?"; } static public String getProgramID(Object o) { return getProgramID(getMainClass(o)); } static public String quoteIfNotIdentifierOrInteger(String s) { if (s == null) return null; return isJavaIdentifier(s) || isInteger(s) ? s : quote(s); } static public A[] arrayOfSameType(A[] a, int n) { return newObjectArrayOfSameType(a, n); } static public List subList(List l, int startIndex) { return subList(l, startIndex, l(l)); } static public List subList(int startIndex, List l) { return subList(l, startIndex); } static public List subList(int startIndex, int endIndex, List l) { return subList(l, startIndex, endIndex); } static public List subList(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = Math.max(0, startIndex); endIndex = Math.min(n, endIndex); if (startIndex > endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return l.subList(startIndex, endIndex); } static public List subList(List l, IntRange r) { return subList(l, r.start, r.end); } static public Object[] mapToObjectArray(Map map) { List l = new ArrayList(); for (Object o : keys(map)) { l.add(o); l.add(map.get(o)); } return toObjectArray(l); } static public Object[] mapToObjectArray(Object f, Collection l) { int n = l(l); Object[] array = new Object[n]; if (n != 0) { Iterator it = iterator(l); for (int i = 0; i < n; i++) array[i] = callF(f, it.next()); } return array; } static public Object[] mapToObjectArray(Object f, Object[] l) { int n = l(l); Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = callF(f, l[i]); return array; } static public Object[] mapToObjectArray(Collection l, IF1 f) { return mapToObjectArray(f, l); } static public Object[] mapToObjectArray(A[] l, IF1 f) { return mapToObjectArray(f, l); } static public Object[] mapToObjectArray(IF1 f, A[] l) { int n = l(l); Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = f.get(l[i]); return array; } static public ThreadLocal htmlencode_forParams_useV2 = new ThreadLocal(); static public String htmlencode_forParams(String s) { if (s == null) return ""; if (isTrue(htmlencode_forParams_useV2.get())) return htmlencode_forParams_v2(s); StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>') { out.append("&#"); out.append((int) c); out.append(';'); } else out.append(c); } return out.toString(); } static public void _handleError(Error e) { call(javax(), "_handleError", e); } static public Runnable toRunnable(final Object o) { if (o instanceof Runnable) return (Runnable) o; return new Runnable() { public void run() { try { callF(o); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(o)"; } }; } static public A vm_generalMap_getOrCreate(Object key, F0 create) { return vm_generalMap_getOrCreate(key, f0ToIF0(create)); } static public A vm_generalMap_getOrCreate(Object key, IF0 create) { Map generalMap = vm_generalMap(); if (generalMap == null) return null; synchronized (generalMap) { A a = (A) (vm_generalMap_get(key)); if (a == null) vm_generalMap_put(key, a = create == null ? null : create.get()); return a; } } static public void ping_okInCleanUp() { if (ping_pauseAll || ping_anyActions) ping_impl(true); } static public Throwable getExceptionCause(Throwable e) { Throwable c = e.getCause(); return c != null ? c : e; } static public String joinWithSpace(Iterable c) { return join(" ", c); } static public String joinWithSpace(String... c) { return join(" ", c); } static public boolean methodIsStatic(Method m) { return (m.getModifiers() & Modifier.STATIC) != 0; } static public boolean argumentCompatibleWithType(Object arg, Class type) { return arg == null ? !type.isPrimitive() : isInstanceX(type, arg); } static public void arraycopy(Object[] a, Object[] b) { if (a != null && b != null) arraycopy(a, 0, b, 0, Math.min(a.length, b.length)); } static public void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) { if (n != 0) System.arraycopy(src, srcPos, dest, destPos, n); } static public A[] arrayOfType(Class type, int n) { return makeArray(type, n); } static public A[] arrayOfType(int n, Class type) { return arrayOfType(type, n); } public static String join(String glue, Iterable strings) { if (strings == null) return ""; if (strings instanceof Collection) { if (((Collection) strings).size() == 1) return str(first((Collection) strings)); } StringBuilder buf = new StringBuilder(); Iterator i = strings.iterator(); if (i.hasNext()) { buf.append(i.next()); while (i.hasNext()) buf.append(glue).append(i.next()); } return buf.toString(); } public static String join(String glue, String... strings) { return join(glue, Arrays.asList(strings)); } static public String join(Iterable strings) { return join("", strings); } static public String join(Iterable strings, String glue) { return join(glue, strings); } public static String join(String[] strings) { return join("", strings); } static public String join(String glue, Pair p) { return p == null ? "" : str(p.a) + glue + str(p.b); } static public List getClassNames(Collection l) { List out = new ArrayList(); if (l != null) for (Object o : l) out.add(o == null ? null : getClassName(o)); return out; } static public betterCIComparator_C betterCIComparator_instance; static public betterCIComparator_C betterCIComparator() { if (betterCIComparator_instance == null) betterCIComparator_instance = new betterCIComparator_C(); return betterCIComparator_instance; } final static public class betterCIComparator_C implements Comparator { public int compare(String s1, String s2) { if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return 1; int n1 = s1.length(); int n2 = s2.length(); int min = Math.min(n1, n2); for (int i = 0; i < min; i++) { char c1 = s1.charAt(i); char c2 = s2.charAt(i); if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); if (c1 != c2) { return c1 - c2; } } } } return n1 - n2; } } static public String dropSuffix(String suffix, String s) { return nempty(suffix) && endsWith(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static public List immutableEmptyList() { return Collections.emptyList(); } static public short[] emptyShortArray = new short[0]; static public short[] emptyShortArray() { return emptyShortArray; } static public Map immutableEmptyMap() { return Collections.emptyMap(); } static public boolean nemptyString(String s) { return s != null && s.length() > 0; } static public int strL(String s) { return s == null ? 0 : s.length(); } static public int listL(Collection l) { return l == null ? 0 : l.size(); } static public boolean neq(Object a, Object b) { return !eq(a, b); } static public int lCharSequence(CharSequence s) { return s == null ? 0 : s.length(); } static public int min(int a, int b) { return Math.min(a, b); } static public long min(long a, long b) { return Math.min(a, b); } static public float min(float a, float b) { return Math.min(a, b); } static public float min(float a, float b, float c) { return min(min(a, b), c); } static public double min(double a, double b) { return Math.min(a, b); } static public double min(double[] c) { double x = Double.MAX_VALUE; for (double d : c) x = Math.min(x, d); return x; } static public float min(float[] c) { float x = Float.MAX_VALUE; for (float d : c) x = Math.min(x, d); return x; } static public byte min(byte[] c) { byte x = 127; for (byte d : c) if (d < x) x = d; return x; } static public short min(short[] c) { short x = 0x7FFF; for (short d : c) if (d < x) x = d; return x; } static public int min(int[] c) { int x = Integer.MAX_VALUE; for (int d : c) if (d < x) x = d; return x; } static public String formatSnippetIDOpt(String s) { return isSnippetID(s) ? formatSnippetID(s) : s; } static public String formatSnippetID(String id) { return "#" + parseSnippetID(id); } static public String formatSnippetID(long id) { return "#" + id; } static public Class getMainClass() { return mc(); } static public Class getMainClass(Object o) { try { if (o == null) return null; if (o instanceof Class && eq(((Class) o).getName(), "x30")) return (Class) o; ClassLoader cl = (o instanceof Class ? (Class) o : o.getClass()).getClassLoader(); if (cl == null) return null; String name = mainClassNameForClassLoader(cl); return loadClassFromClassLoader_orNull(cl, name); } catch (Exception __e) { throw rethrow(__e); } } static public boolean isJavaIdentifier(String s) { if (empty(s) || !Character.isJavaIdentifierStart(s.charAt(0))) return false; for (int i = 1; i < s.length(); i++) if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; return true; } static public boolean isInteger(String s) { int n = l(s); if (n == 0) return false; int i = 0; if (s.charAt(0) == '-') if (++i >= n) return false; while (i < n) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static public String quote(Object o) { if (o == null) return "null"; return quote(str(o)); } static public String quote(String s) { if (s == null) return "null"; StringBuilder out = new StringBuilder((int) (l(s) * 1.5 + 2)); quote_impl(s, out); return out.toString(); } static public void quote_impl(String s, StringBuilder out) { out.append('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') out.append('\\').append(c); else if (c == '\r') out.append("\\r"); else if (c == '\n') out.append("\\n"); else if (c == '\t') out.append("\\t"); else if (c == '\0') out.append("\\0"); else out.append(c); } out.append('"'); } static public A[] newObjectArrayOfSameType(A[] a) { return newObjectArrayOfSameType(a, a.length); } static public A[] newObjectArrayOfSameType(A[] a, int n) { return (A[]) Array.newInstance(a.getClass().getComponentType(), n); } static public Set keys(Map map) { return map == null ? new HashSet() : map.keySet(); } static public Set keys(Object map) { return keys((Map) map); } static public Set keys(MultiSet ms) { return ms.keySet(); } static public Set keys(MultiMap mm) { return mm.keySet(); } static public Set keys(MultiSetMap mm) { return mm.keySet(); } static public Object[] toObjectArray(Collection c) { return toObjectArray((Iterable) c); } static public Object[] toObjectArray(Iterable c) { List l = asList(c); return l.toArray(new Object[l.size()]); } static public Iterator iterator(Iterable c) { return c == null ? emptyIterator() : c.iterator(); } static public String htmlencode_forParams_v2(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { out.append("&#"); out.append((int) c); out.append(';'); } else out.append(c); } return out.toString(); } static public IF0 f0ToIF0(F0 f) { return f == null ? null : () -> f.get(); } static public Map vm_generalMap_map; static public Map vm_generalMap() { if (vm_generalMap_map == null) vm_generalMap_map = (Map) get(javax(), "generalMap"); return vm_generalMap_map; } static public Object vm_generalMap_get(Object key) { return vm_generalMap().get(key); } static public Object vm_generalMap_put(Object key, Object value) { return mapPutOrRemove(vm_generalMap(), key, value); } static public boolean isInstanceX(Class type, Object arg) { if (type == boolean.class) return arg instanceof Boolean; if (type == int.class) return arg instanceof Integer; if (type == long.class) return arg instanceof Long; if (type == float.class) return arg instanceof Float; if (type == short.class) return arg instanceof Short; if (type == char.class) return arg instanceof Character; if (type == byte.class) return arg instanceof Byte; if (type == double.class) return arg instanceof Double; return type.isInstance(arg); } static public A[] makeArray(Class type, int n) { return (A[]) Array.newInstance(type, n); } static public Object first(Object list) { return first((Iterable) list); } static public A first(List list) { return empty(list) ? null : list.get(0); } static public A first(A[] bla) { return bla == null || bla.length == 0 ? null : bla[0]; } static public A first(IterableIterator i) { return first((Iterator) i); } static public A first(Iterator i) { return i == null || !i.hasNext() ? null : i.next(); } static public A first(Iterable i) { if (i == null) return null; Iterator it = i.iterator(); return it.hasNext() ? it.next() : null; } static public Character first(String s) { return empty(s) ? null : s.charAt(0); } static public Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); } static public A first(Pair p) { return p == null ? null : p.a; } static public Byte first(byte[] l) { return empty(l) ? null : l[0]; } static public A first(A[] l, IF1 pred) { return firstThat(l, pred); } static public A first(Iterable l, IF1 pred) { return firstThat(l, pred); } static public A first(IF1 pred, Iterable l) { return firstThat(pred, l); } static public boolean endsWith(String a, String b) { return a != null && a.endsWith(b); } static public boolean endsWith(String a, char c) { return nempty(a) && lastChar(a) == c; } static public boolean endsWith(String a, String b, Matches m) { if (!endsWith(a, b)) return false; m.m = new String[] { dropLast(l(b), a) }; return true; } static public String mainClassNameForClassLoader(ClassLoader cl) { return or((String) callOpt(cl, "mainClassName"), "main"); } static public Class loadClassFromClassLoader_orNull(ClassLoader cl, String name) { try { return cl == null ? null : cl.loadClass(name); } catch (ClassNotFoundException e) { return null; } } static public Iterator emptyIterator() { return Collections.emptyIterator(); } static public B mapPutOrRemove(Map map, A key, B value) { if (map != null && key != null) if (value != null) return map.put(key, value); else return map.remove(key); return null; } static public A firstThat(Iterable l, Object pred) { if (l != null) for (A a : l) if (checkCondition(pred, a)) return a; return null; } static public A firstThat(A[] l, IF1 pred) { if (l != null) for (A a : l) if (pred.get(a)) return a; return null; } static public A firstThat(Iterable l, IF1 pred) { return firstThat(l, (Object) pred); } static public A firstThat(IF1 pred, Iterable l) { return firstThat(l, pred); } static public A or(A a, A b) { return a != null ? a : b; } static public boolean checkCondition(Object condition, Object... args) { return isTrue(callF(condition, args)); } static public boolean checkCondition(IF1 condition, A arg) { return isTrue(callF(condition, arg)); } final static public class _MethodCache { final public Class c; final public HashMap> cache = new HashMap(); public _MethodCache(Class c) { this.c = c; _init(); } public void _init() { Class _c = c; while (_c != null) { for (Method m : _c.getDeclaredMethods()) if (!isAbstract(m) && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); _c = _c.getSuperclass(); } for (Class intf : allInterfacesImplementedBy(c)) for (Method m : intf.getDeclaredMethods()) if (m.isDefault() && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); } public Method findMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } public Method findStaticMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (isStaticMethod(me) && call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } } static public String passwordSalt() { File f = programSecretFile("password-salt"); if (fileExists(f)) return loadTextFile(f); File global = javaxSecretDir("password-salt"); if (fileExists(global)) return loadTextFile(global); return loadTextFileOrCreateWithRandomID(f); } static public class PostReferenceable extends Concept { } static public class User extends PostReferenceable { static final public String _fieldOrder = "name passwordMD5 contact isMaster botToken lastSeen"; public String name; public SecretValue passwordMD5; public String contact; public boolean isMaster = false; public SecretValue botToken = aSecretGlobalID(); public long lastSeen; public String name() { return name; } public String toString() { return nempty(name) ? "User " + name : super.toString(); } } static public class UserCreatedObject extends PostReferenceable { static final public String _fieldOrder = "creator botInfo"; public Ref creator = new Ref(); public String botInfo; } static public class UserPost extends UserCreatedObject { public String type, title, text; public boolean isPublic = true, hidden; public boolean creating = false; public long xmodified; public long bumped; static public List fieldsToSaveOnDelete = ll("id", "text", "title", "type", "creatorID", "postRefs", "postRefTags", "hidden", "isPublic", "created", "_modified", "xmodified", "botInfo", "creating"); public String text() { return text; } public RefL postRefs = new RefL(); public List postRefTags = new ArrayList(); static public String _fieldOrder = "title text type postRefs isPublic"; public String toString() { String content = nempty(title) ? shorten(title) : escapeNewLines(shorten(text)); return content + " [by " + author() + "]"; } public boolean isReply() { return nempty(postRefs); } public boolean isBotPost() { return nempty(botInfo); } public boolean isMasterMade() { return creator.has() && creator.get().isMaster; } public String author() { String author = userName(creator.get()); if (isBotPost()) author += "'s bot " + quote(botInfo); return author; } public void change() { super.change(); ((DynGazelleRocks) botMod()).distributePostChanges(this); } public List> postRefsWithTags() { return zipTwoListsToPairs_lengthOfFirst(postRefs, postRefTags); } public List postRefsWithTag(String tag) { return pairsAWhereB(postRefsWithTags(), t -> eqic_unnull(t, tag)); } public UserPost primaryRefPost() { return optCast(UserPost.class, first(postRefsWithTag(""))); } public void _setModified(long modified) { super._setModified(modified); setXModified(modified); } public void bump() { bumped = now(); _change_withoutUpdatingModifiedField(); for (UserPost p : syncInstancesOf(UserPost.class, postRefs)) p.setXModified(); } public long modifiedOrBumped() { return max(_modified, bumped); } public void setXModified() { setXModified(now()); } public void setXModified(long modified) { boolean changed = modified > xmodified; xmodified = modified; _change_withoutUpdatingModifiedField(); if (changed) ((DynGazelleRocks) botMod()).distributePostChanges(this); } public void _backRefsModified() { super._backRefsModified(); setXModified(now()); } public int distanceToUserPost() { int n = 0; UserPost post = this; while (post != null && n < 100) { if (!post.isBotPost()) return n; post = post.primaryRefPost(); } return -1; } public boolean isJavaXCode() { return eqicOrSwicPlusSpace(type, "JavaX Code"); } } abstract static public class DynGazelleRocks extends DynNewBot2 { transient public boolean inlineSearch = false; static public boolean _switchableField_webPushEnabled = true; public boolean webPushEnabled = true; static public boolean _switchableField_showPostStats = true; public boolean showPostStats = false; static public boolean _switchableField_showSuggestorBot = true; public boolean showSuggestorBot = true; static public boolean _switchableField_showMetaBotOnEveryPage = true; public boolean showMetaBotOnEveryPage = true; static public boolean _switchableField_delayAfterSuggestion = true; public int delayAfterSuggestion = 1000; static public boolean _switchableField_defaultBotPost = true; public int defaultBotPost = 238410; static public boolean _switchableField_teamPostID = true; public long teamPostID; static public boolean _switchableField_favIconID = true; public long favIconID; static public boolean _switchableField_defaultFavIconSnippet = true; public String defaultFavIconSnippet = gazelleFavIconSnippet(); static public boolean _switchableField_gazelleBotURL = true; public String gazelleBotURL = null; static public boolean _switchableField_salterService = true; public String salterService; transient public double systemLoad; transient public long processSize; public void init() { dm_require("#1017856/SystemLoad"); dm_vmBus_onMessage("systemLoad", new VF1() { public void get(Double load) { try { if (setField("systemLoad", load)) distributeDivChanges("serverLoadRightHemi"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (setField(systemLoad := load))\r\n distributeDivChanges(\"serverLoadRi..."; } }); dm_vmBus_onMessage("processSize", new VF1() { public void get(Long processSize) { try { if (setField("processSize", processSize)) distributeDivChanges("memRightHemi"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (setField(+processSize))\r\n distributeDivChanges(\"memRightHemi\");"; } }); botName = heading = adminName = "gazelle.rocks"; templateID = "#1030086"; cssID = "237267"; enableUsers = true; useWebSockets = true; showRegisterLink = true; showTalkToBotLink = false; alwaysRedirectToHttps = true; redirectOnLogout = true; showFullErrors = true; inlineSearch = true; lockWhileDoingBotActions = false; showMailSenderInfo = false; if (empty(salterService)) passwordSalt(); } public void makeIndices() { super.makeIndices(); indexConceptFieldCI(User.class, "name"); indexConceptFieldDesc(UserPost.class, "xmodified"); indexConceptFieldDesc(UserPost.class, "_modified"); indexConceptFieldCI(UserPost.class, "botInfo"); } public void start() { init(); super.start(); db_mainConcepts().modifyOnCreate = true; printConceptIndices(); onConceptsChange(new Runnable() { public int postCount = countConcepts(UserPost.class); public void run() { AutoCloseable __7 = enter(); try { int count = countConcepts(UserPost.class); if (count != postCount) { postCount = count; distributeDivChanges("postCount"); } } finally { _close(__7); } } }); internalUser(); } public void requestServed() { distributeDivChanges("webRequestsRightHemi"); } public class WebSocketInfo extends Meta implements AutoCloseable { public boolean _isTransient() { return true; } public String uri; public Map params; public Req req; public WeakReference webSocket; public Set> messageHandlers = syncLinkedHashSet(); public Set closeHandlers = syncLinkedHashSet(); public Map misc = syncMap(); public WebSocketInfo(Object webSocket) { this.webSocket = weakRef(webSocket); setFieldToIVF1Proxy(webSocket, "onMessage", msg -> { AutoCloseable __8 = enter(); try { try { String data = rcall_string("getTextPayload", msg); pcallFAll(messageHandlers, data); } catch (Throwable __e) { _handleException(__e); } } finally { _close(__8); } }); } public String uri() { return uri; } public Map params() { return params; } public String get(String param) { return mapGet(params, param); } public void setParams(Map params) { this.params = params; req.params = params; } public Object dbRepresentation; public Set> liveDivs = new HashSet(); public void eval(String jsCode) { eval(jsCode, null); } public void eval(String jsCode, Object... __) { jsCode = jsDollarVars(jsCode, __); if (empty(jsCode)) return; dm_call(webSocket.get(), "send", jsonEncode(litmap("eval", jsCode))); } public void send(String jsonData) { if (empty(jsonData)) return; dm_call(webSocket.get(), "send", jsonData); } public AutoCloseable onStringMessage(IVF1 onMsg) { return tempAdd(messageHandlers, onMsg); } public AutoCloseable onClose(Runnable r) { return tempAdd(closeHandlers, r); } public void callCloseHandlers() { pcallFAll(closeHandlers); } public void close() { cleanUp(webSocket.get()); } } transient public Map webSockets = syncWeakHashMap(); public void cleanMeUp_webSockets() { closeAllKeysAndClear((Map) webSockets); } public void handleWebSocket(Object ws) { set(ws, "onClose", new Runnable() { public void run() { try { var info = webSockets.get(ws); if (info != null) { try { onWebSocketClose(info); } catch (Throwable __e) { _handleException(__e); } } webSockets.remove(ws); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "var info = webSockets.get(ws);\r\n if (info != null) pcall { onWebSocketCl..."; } }); set(ws, "onOpen", new Runnable() { public void run() { try { AutoCloseable __9 = enter(); try { String uri = (String) (rcall("getUri", ws)); Map params = (Map) (rcall("getParms", ws)); print("WebSocket opened! uri: " + uri + ", params: " + params); WebSocketInfo info = new WebSocketInfo(ws); IWebRequest webRequest = proxy(IWebRequest.class, call(ws, "webRequest")); info.req = webRequestToReq(webRequest); String cookie = cookieFromWebRequest(webRequest); AuthedDialogID auth = authObject(cookie); fillReqAuthFromCookie(info.req, cookie, auth); AutoCloseable __10 = tempSetTL(currentReq, info.req); try { info.uri = uri; info.params = params; webSockets.put(ws, info); try { onNewWebSocket(info); } catch (Throwable __e) { _handleException(__e); } long objectID = toLong(params.get("objectID")); long modified = toLong(params.get("modified")); if (objectID != 0) { UserPost c = getConceptOpt(UserPost.class, objectID); print("Modification: " + c.xmodified + " / " + c._modified + " / " + modified); if (c != null && c.xmodified > modified) reloadBody(ws); } } finally { _close(__10); } } finally { _close(__9); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); \r\n String uri = (String) (rcall getUri(ws));\r\n Map..."; } }); setFieldToIVF1Proxy(ws, "onMessage", msg -> { AutoCloseable __11 = enter(); try { try { WebSocketInfo info = webSockets.get(ws); if (info == null) return; String data = rcall_string("getTextPayload", msg); Map map = jsonDecodeMap(data); Object div = map.get("liveDiv"); if (div instanceof String) { String contentDesc = (String) div; syncAdd(info.liveDivs, pair(((String) div), (Object) contentDesc)); reloadDiv(ws, ((String) div), calcDivContent(contentDesc)); } } catch (Throwable __e) { _handleException(__e); } } finally { _close(__11); } }); } public String serveRegisterForm(Map params) { String user = trim(params.get("user")); String pw = trim(params.get("f_pw")); String pw2 = trim(params.get("pw2")); String redirect = params.get("redirect"); String contact = trim(params.get("contact")); redirect = dropParamFromURL(redirect, "logout"); if (empty(redirect)) redirect = baseLink + "/"; List msgs = new ArrayList(); if (nempty(user) || nempty(pw)) { Lock __1 = dbLock(); lock(__1); try { if (empty(user)) msgs.add("Please enter a user name"); else if (l(user) < 4) msgs.add("Minimum user name length: 4 characters"); else if (l(user) > 30) msgs.add("Maximum user name length: 30 characters"); else if (hasConceptIC(User.class, "name", user)) msgs.add("This user exists, please choose a different name"); if (regexpContainsIC("[^a-z0-9\\-\\.]", user)) msgs.add("Bad characters in user name (please use only a-z, 0-9, - and .)"); if (empty(pw)) msgs.add("Please enter a password. Don't use one of your regular (important) passwords! Just make one up and let the browser save it."); else if (l(pw) < 6) msgs.add("Minimum password length: 6 characters"); if (neq(pw, pw2)) msgs.add("Passwords don't match"); if (empty(msgs)) { User userObj = cnew(User.class, "name", user, "passwordMD5", new SecretValue(hashPW(pw)), "contact", contact); vmBus_send("userCreated", userObj); return hrefresh(5.0, redirect) + "User " + user + " created! Redirecting..."; } } finally { unlock(__1); } } return hhtml(hhead(htitle("Register new user") + hsansserif() + hmobilefix() + hresponstable()) + hbody(hfullcenter(h3_htmlEncode(adminName + " | Register new user") + hpostform(hhidden("redirect", redirect) + tag("table", (empty(msgs) ? "" : tr(td() + td() + td(htmlEncode2_nlToBr(lines_rtrim(msgs))))) + tr(td_valignTop("Choose a user name:") + td_valignTop(hinputfield("user", user) + "
" + "(Minimum length 4. Characters allowed: a-z, 0-9, - and .)")) + tr(td_valignTop("Choose a password:") + td_valignTop(hpassword("f_pw", pw) + "
" + "(Minimum length 6 characters)")) + tr(td_valignTop("Repeat the password please:") + td(hpassword("pw2", pw2))) + tr(td_valignTop("Way to contact you (e.g. e-mail) - optional:") + td(hinputfield("contact", contact))) + tr(td() + td(hsubmit("Register"))), "class", "responstable"), "action", baseLink + "/register")))); } public boolean calcMasterAuthed(Req req) { return super.calcMasterAuthed(req) || req.auth != null && req.auth.user.has() && req.auth.user.get().isMaster; } public Object serveOtherPage(Req req) { String uri = req.uri; Matches m = new Matches(); if (eq(uri, "/register")) return serveRegisterForm(req.params); if (eq(uri, "/becomeMaster") && req.auth != null && req.auth.user != null) { String pw = trim(req.params.get("masterPW")); if (eq(pw, realPW())) { cset(req.auth.user, "isMaster", true); return "You are master, " + req.auth.user + "!"; } if (nempty(pw)) return "Bad master PW"; return hhtml(hhead(htitle("Become master") + hsansserif() + hmobilefix() + hresponstable()) + hbody(hfullcenter(h3_htmlEncode(adminName + " | Become master") + hpostform(tag("table", tr(td_valignTop("You are:") + td_valignTop(htmlEncode2(req.auth.user.get().name))) + tr(td_valignTop("Enter the master password:") + td_valignTop(hpassword("masterPW", pw))) + tr(td() + td(hsubmit("Become master user"))), "class", "responstable"), "action", baseLink + "/becomeMaster")))); } if (swic(uri, "/text/", m)) { long id = parseLong(m.rest()); UserPost post = getConceptOpt(UserPost.class, id); if (post == null) return serve404("Post with ID " + id + " not found"); if (!post.isPublic) return serve404("Post is not public"); String ct = req.params.get("ct"); Object response = nempty(ct) ? serveWithContentType(post.text(), ct) : serveText(post.text()); if (eq(ct, "text/javascript")) addHeader("Service-Worker-Allowed", "/", response); return response; } if (swic(uri, "/postRefs/", m)) { long id = parseLong(m.rest()); UserPost post = getConceptOpt(UserPost.class, id); if (post == null) return serve404("Post with ID " + id + " not found"); if (!post.isPublic) return serve404("Post is not public"); return serveJSON(lmap(__60 -> conceptID(__60), post.postRefs)); } if (swic(uri, "/postRefsWithTags/", m)) { long id = parseLong(m.rest()); UserPost post = getConceptOpt(UserPost.class, id); if (post == null) return serve404("Post with ID " + id + " not found"); if (!post.isPublic) return serve404("Post is not public"); return serveJSON(map(post.postRefsWithTags(), p -> litorderedmap("id", conceptID(p.a), "as", p.b))); } String uri2 = dropSlashPrefix(uri); if (isInteger(uri2)) { long id = parseLong(uri2); { Object __5 = serveIntegerLink(req, id); if (__5 != null) return __5; } } { Object __6 = serveOtherPage2(req); if (__6 != null) return __6; } return super.serveOtherPage(req); } static public boolean _switchableField_bot_maxPollSeconds = true; public double bot_maxPollSeconds = 600; static public boolean _switchableField_bot_pollInterval = true; public int bot_pollInterval = 500; public Class defaultCRUDClass() { return Sequence.class; } public Object serveOtherPage2(Req req) { Matches m = new Matches(); String uri = dropTrailingSlashIfNemptyAfterwards(req.uri); if (eq(uri, "/admin")) return hrefresh(baseLink + "/crud/" + shortClassName(defaultCRUDClass())); if (eq(uri, "/latestPost")) { UserPost post = highestConceptByField(UserPost.class, "created"); if (post == null) return serve404("No posts in database"); return servePost(post, req); } if (eq(uri, "/latestModifiedPost")) { UserPost post = highestConceptByField(UserPost.class, "_modified"); if (post == null) return serve404("No posts in database"); return servePost(post, req); } if (eq(uri, "/rootPosts")) { Collection posts = sortedByConceptIDDesc(filter(list(UserPost.class), post -> empty(post.postRefs))); framer().navBeforeTitle = true; framer().title = "Root Posts"; framer().add(ul(lmap(__61 -> postToHTMLWithDate(__61), posts))); return framer().render(); } if (eq(uri, "/allPosts")) { Collection posts = sortedByConceptIDDesc(list(UserPost.class)); framer().navBeforeTitle = true; framer().title = "All Posts"; framer().add(ul(lmap(__62 -> postToHTMLWithDate(__62), posts))); return framer().render(); } if (eq(uri, "/latestPosts")) { Collection posts = takeFirst(50, sortedByConceptIDDesc(list(UserPost.class))); framer().navBeforeTitle = true; framer().title = "Latest Posts & Replies"; framer().add(ul(lmap(__63 -> postToHTMLWithDate(__63), posts))); return framer().render(); } if (eq(uri, "/latestModifiedPosts")) { Collection posts = takeFirst(50, sortedByFieldDesc("_modified", list(UserPost.class))); framer().navBeforeTitle = true; framer().title = "Latest Modified Posts & Replies"; framer().add(ul(lmap(__64 -> postToHTMLWithDate(__64), posts))); return framer().render(); } if (eq(uri, "/mainPosts")) { Collection posts = takeFirst(50, sortedByConceptID(conceptsWhereCI(UserPost.class, "type", "Main"))); framer().navBeforeTitle = true; framer().title = "Main Posts"; framer().add(ul(lmap(__65 -> postToHTMLWithDate(__65), posts))); return framer().render(); } if (swic(uri, "/html/", m) && isInteger(m.rest())) { long id = parseLong(m.rest()); return serveHTMLPost(id); } if (swic(uri, "/htmlEmbedded/", m) && isInteger(m.rest())) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); HTMLFramer1 framer = framer(); framer.title = "[" + post.id + "] " + or2(post.title, shorten(post.text)); framer.add(hcomment("Post begins here") + "\n" + post.text + "\n" + hcomment("Post ends here")); return framer.render(); } if (swic(uri, "/css/", m) && isInteger(m.rest())) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); return serveWithContentType(post.text, "text/css"); } if (eq(uri, "/search")) { framer().navBeforeTitle = true; String q = trim(req.params.get("q")); framer().title = joinNemptiesWithColon("Search", q); framer().add(hcomment("cookie: " + req.webRequest.cookie())); framer().add(hform(hinputfield("q", q, "autofocus", true) + " " + hsubmit("Search"))); framer().add(p(small("Search help: If you search for multiple words, they can appear in any order in the text. An underscore matches any character. Plus means space. Post titles, texts and types are searched."))); if (nempty(q)) { ScoredSearcher searcher = new ScoredSearcher<>(q); long id = parseLongOpt_pcall(q); for (UserPost post : list(UserPost.class)) searcher.add(post, (post.id == id ? 4 : 0) + searcher.score(post.title) * 3 + searcher.score(post.text) * 2 + searcher.score(post.type) + searcher.score(joinWithSpace(post.postRefTags)) * 0.5); List posts = searcher.get(); framer().add(p(b(addPlusToCount(searcher.maxResults, l(posts), nPosts(posts)) + " found for " + htmlEncode2(q)))); framer().add(ul(lmap(__66 -> postToHTMLWithDate(__66), posts))); } return framer().render(); } if (eq(uri, "/jstree/replies")) { UserPost post = getConcept(UserPost.class, parseLong(req.params.get("post"))); if (post == null) return serveJSON(ll()); Collection refs = referencingPosts(post); return serveJSON(map(refs, p -> litorderedmap("id", p.id, "text", postToHTMLWithDate(post), "children", nempty(referencingPosts(p)) ? true : null, "type", "root"))); } if (startsWith(uri, "/touchPost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); if (!canEditPost(post)) return "You are not authorized to do this"; touchConcept(post); return hscript("setTimeout('history.go(-1)', 1000);") + "Post " + post.id + " touched"; } if (startsWith(uri, "/hidePost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); if (!canEditPost(post)) return "You are not authorized to do this"; cset(post, "hidden", true); return hrefresh(postLink(post)); } if (startsWith(uri, "/unhidePost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); if (!canEditPost(post)) return "You are not authorized to do this"; cset(post, "hidden", false); return hrefresh(postLink(post)); } if (startsWith(uri, "/markSafe/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); UserPost codePost = optCast(UserPost.class, first(post.postRefs)); if (codePost == null) return "Code post not found"; if (!canEditPost(codePost)) return "You are not authorized to do this"; uniqCI(UserPost.class, "creator", currentUser(), "text", "Mark safe", "postRefs", ll(post)); sleepSeconds(6); touchConcept(codePost); return hrefresh(postLink(codePost)); } if (eq(uri, "/mirrorAllConversations")) { if (!req.masterAuthed) return serveAuthForm(rawLink(uri)); for (Conversation c : list(Conversation.class)) rstUpdateMirrorPosts.add(c); return "OK"; } if (startsWith(uri, "/mirrorConversation/", m)) { if (!req.masterAuthed) return serveAuthForm(rawLink(uri)); long id = parseLong(m.rest()); Conversation conv = getConcept(Conversation.class, id); if (conv == null) return "Conversation not found"; conv.updateMirrorPost(); return "Mirror post updated (" + htmlEncode2(str(conv.mirrorPost.get())) + ")"; } if (eqic(uri, "/favicon.ico")) return serveFavIcon(); if (startsWith(uri, "/bot/", m)) { req.subURI = m.rest(); String json = req.params.get("json"); Map data = new HashMap(); if (nempty(json)) data = jsonDecodeMap(json); data.putAll(withoutKey("json", req.params)); User user; String userName = (String) (data.get("_user")); if (nempty(userName)) { String botToken = (String) (data.get("_botToken")); if (botToken == null) return serveJSON("error", "Need _botToken"); user = conceptWhereIC(User.class, "name", userName); if (user == null) return serveJSON("error", "User not found"); if (!eq(botToken, getVar(user.botToken))) return serveJSON("error", "Wrong bot token"); } else user = user(req); String function = beforeSlashOrAll(req.subURI); req.subURI = substring(req.subURI, l(function) + 1); req.webRequest.noSpam(); { Object __41 = servePossiblyUserlessBotFunction(req, function, data, user); if (__41 != null) return __41; } if (user == null) return serveJSON("error", "Need _user"); if (eq(function, "authTest")) return serveJSON("status", "You are authorized as " + user.name); if (eq(function, "postCount")) return serveJSON("result", countConcepts(UserPost.class)); if (eq(function, "listPosts")) { List fields = unnull(stringToStringListOpt(__105 -> tok_identifiersInOrder(__105), data.get("fields"))); if (!fields.contains("id")) fields.add(0, "id"); long changedAfter = toLong(data.get("changedAfter")); long repliesTo = toLong(data.get("repliesTo")); double pollFor = min(bot_maxPollSeconds, toLong(data.get("pollFor"))); long startTime = sysNow(); if (changedAfter > 0 && changedAfter == now()) sleep(1); Collection posts; while (true) { if (repliesTo != 0) { posts = referencingPosts(getConcept(UserPost.class, repliesTo)); if (changedAfter != 0) posts = objectsWhereFieldGreaterThan(posts, "_modified", changedAfter); } else { posts = changedAfter == 0 ? list(UserPost.class) : conceptsWithFieldGreaterThan_sorted(UserPost.class, "_modified", changedAfter); } if (nempty(posts) || pollFor == 0 || elapsedSeconds_sysNow(startTime) >= pollFor) return serveJSON_breakAtLevels(2, "result", map(posts, post -> mapToValues(fields, field -> getPostFieldForBot(post, field)))); sleep(bot_pollInterval); } } if (eq(function, "createPost")) { Either e = createPostArgs(user, data); if (e.isB()) return serveJSON("error", e.b()); Pair post = uniq2(UserPost.class, e.a()); if (!post.b) post.a.bump(); return serveJSON("status", post.b ? "Post created" : "Post existed already, bumped", "postID", post.a.id); } if (eq(function, "editPost")) { long postID = toLong(data.get("postID")); UserPost post = getConcept(UserPost.class, postID); if (post == null) return serveJSON("error", "Post " + postID + " not found"); Either e = createPostArgs(user, data); if (e.isB()) return serveJSON("error", e.b()); int changes = cset(post, e.a()); return serveJSON(changes > 0 ? "Post updated" : "Post updated, no changes", "postID", postID); } if (eq(function, "deletePosts")) { List ids = allToLong(tok_integersInOrder((String) data.get("ids"))); List results = new ArrayList(); List errors = new ArrayList(); for (long id : unnullForIteration(ids)) { UserPost post = getConceptOpt(UserPost.class, id); if (post == null) errors.add("Post " + id + " not found"); else { if (!user.isMaster && neq(post.creator.get(), user)) errors.add("Can't delete post " + id + " from other user"); else { deletePost(post); results.add("Post " + id + " deleted"); } } } return serveJSON(litorderedmap("results", results, "errors", errors)); } return serveBotFunction(req, function, data, user); } if (teamPostID != 0 && eq(uri, "/team")) return serveHTMLPost(teamPostID); if (startsWith(uri, "/history/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); return servePostHistory(post); } if (startsWith(uri, "/htmlBot/", m)) { long id = parseLong(beforeSlashOrAll(m.rest())); UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post not found"); return doPost(htmlBotURLOnBotServer(id), req.params()); } if (eq(uri, "/deletedPosts")) { CloseableIterableIterator lines = linesFromFile(deletedPostsFile()); try { List posts = new ArrayList(); while (lines.hasNext()) { String line = lines.next(); if (isProperlyQuoted(line)) { Map map = safeUnstructureMap(unquote(line)); posts.add(onlyKeys(map, "id", "title", "type")); } } return serveText("Deleted posts:\n" + lines(lmap(__67 -> struct(__67), posts))); } finally { _close(lines); } } if (eq(uri, "/formToPost")) { User user = currentUser(); if (user == null) serve500("Please log in first"); Map params = cloneMap(req.params); String type = or2(getAndRemove(params, "_type"), "Form Input"); String title = getAndRemove(params, "_title"); List postRefs = map(id -> getConceptOpt(UserPost.class, parseLong(id)), tok_integersInOrder(getAndRemove(params, "_postRefs"))); List postRefTags = lines(getAndRemove(params, "_postRefTags")); String text = sortLinesAlphaNumIC(mapToLines(params, (k, v) -> urlencode(k) + "=" + urlencode(v))); Pair p = uniq2(UserPost.class, "creator", user, "text", text, "type", type, "title", title, "postRefs", postRefs, "postRefTags", postRefTags); return (p.b ? "Post " + p.a.id + " created" : "Post " + p.a.id + " exists") + hrefresh(2.0, "/" + p.a.id); } if (eq(uri, "/webPushSubscribe")) { Map data = jsonDecodeMap(mapGet(req.webRequest.files(), "postData")); printVars_str("webPushSubscribe", "data", data); cnew(WebPushSubscription.class, "data", data, "clientIP", req.webRequest.clientIP()); return serveJSON(litmap("message", "success")); } if (eq(uri, "/changePassword")) { if (!req.masterAuthed) return serveAuthForm(rawLink(uri)); String name = assertNempty(req.get("user")); String newPW = assertNempty(req.get("newPW")); User user = conceptWhereCI(User.class, "name", name); if (user == null) return "User not found"; cset(user, "passwordMD5", new SecretValue(hashPW(newPW))); return "PW updated"; } if (eq(uri, "/webPushNotify")) { if (!req.masterAuthed) return serveAuthForm(rawLink(uri)); String msg = or2(req.params.get("msg"), "Hello user. It is " + localTimeWithSeconds() + " on the server"); WebPushSubscription sub = getConcept(WebPushSubscription.class, toLong(req.params.get("webPushSubID"))); if (sub == null) return serve404("webPushSubID not found"); String mod = dm_require("#1030463/WebPushKeyManager"); dm_call(mod, "sendNotification", sub.data, msg); return "Push message sent"; } if (eq(uri, "/hashPW") && req.masterAuthed) return hashPW(req.params.get("pw")); return null; } public Object servePostHistory(UserPost post) { return serveText(unquoteAllLines(loadTextFile(postHistoryFile(post)))); } public Either createPostArgs(User user, Map data) { String text = (String) (data.get("text")); String type = (String) (data.get("type")); String title = (String) (data.get("title")); String botInfo = or2((String) data.get("botInfo"), "Made by bot"); List postRefTags = unnull(lines((String) data.get("refTags"))); List postRefs = new ArrayList(); Object _refs = data.get("refs"); if (_refs instanceof String) for (String s : tok_integersInOrder((String) _refs)) { UserPost ref = getConcept(UserPost.class, parseLong(s)); if (ref == null) return eitherB("Post " + s + " not found"); postRefs.add(ref); } if (empty(text) && empty(title)) return eitherB("Need either a text or a title"); boolean isPublic = eqOneOf(data.get("isPublic"), null, true, "1", "t", "true"); return eitherA(litparams("creator", user, "text", text, "type", type, "title", title, "isPublic", isPublic, "botInfo", botInfo, "postRefs", postRefs, "postRefTags", postRefTags)); } public Object serveBotFunction(Req req, String function, Map data, User user) { return serveJSON("error", "You are logged in correctly but function is unknown: " + function); } public Object servePossiblyUserlessBotFunction(Req req, String function, Map data, User user) { return null; } public Object servePost(UserPost post, Req req) { if (!post.isPublic) return serve404("Post is not public"); HTMLFramer1 framer = framer(); framer.add(hjs("webSocketQuery = " + jsQuote("?objectID=" + post.id + "&modified=" + post.xmodified) + ";\n" + "if (ws != null) ws.url = ws.url.split(\"?\")[0] + webSocketQuery;")); framer.title = "[" + post.id + "] " + or2(post.title, shorten(post.text)); framer.add(p("By " + htmlEncode2(post.author()) + ". " + renderConceptDate(post))); if (nempty(post.type)) framer.add(p("Post type: " + htmlEncode2(post.type))); List actions = new ArrayList(); if (eqic(post.type, "HTML")) actions.add(targetBlank("/html/" + post.id, "Show as HTML page")); if (eqic(post.type, "HTML (embedded)")) actions.add(targetBlank("/htmlEmbedded/" + post.id, "Show as HTML page")); if (eqicOneOf(post.type, "JavaX Code (HTML Bot)", "JavaX Code (Live Home Page)")) actions.add(targetBlank(htmlBotURL(post.id), "Show as HTML page")); if (eqic(post.type, "Conversation HTML")) actions.add(targetBlank("/demo?cookie=htmlDemo&_autoOpenBot=1&chatContentsPost=" + post.id, "Show in chat box")); if (canEditPost(post)) { actions.add(ahref(conceptEditLink(post), "Edit post")); actions.add(ahref(touchLink(post), "Touch post")); actions.add(post.hidden ? ahref(unhideLink(post), "Unhide post") : ahref(hideLink(post), "Hide post")); } actions.add(ahref(replyLink(post), "Reply")); actions.add(ahref(conceptDuplicateLink(post), "Duplicate")); actions.add(ahref(conceptEditLink(post, "onlyFields", "title"), "Rename")); if (postHasHistory(post)) actions.add(ahref("/history/" + post.id, "History")); actions.add(ahref(baseLink + "/text/" + post.id, "Raw Text")); if (post.isJavaXCode()) { actions.add(targetBlank(simulateBotLink(post), "Talk to this bot")); actions.add(ahref(gazelleBotURL + "/transpilation/" + post.id, "Show Java transpilation")); } framer.add(p_vbar(actions)); List postRefs = cloneList(post.postRefs); if (nempty(postRefs)) { framer.add(p("In reference to:")); List> l = post.postRefsWithTags(); framer.add(ul(mapPairsToList(l, (ref, as) -> htmlEncode2(as) + " " + objectToHTML(ref)))); } String text = post.text; String html = null; if (post.isJavaXCode()) { try { JavaXHyperlinker hl = new JavaXHyperlinker(); hl.targetBlank = true; html = hl.codeToHTML(text); } catch (Throwable __e) { _handleException(__e); } } if (html == null) html = htmlEncodeWithLinking(post.text); if (eq(req.params.get("showLineFeeds"), "1")) html = html_showLineFeedsForPRE(html); framer.add(div(sourceCodeToHTML_noEncode(html), "style", hstyle_sourceCodeLikeInRepo())); Collection refs = referencingPosts(post); refs = reversed(refs); Pair, List> p = filterAntiFilter(refs, post2 -> !post2.hidden); if (nempty(p.a)) { framer.add(p("Referenced by posts (latest first):")); UserPost latestCodeSafetyPost = highestBy(p2 -> p2.modifiedOrBumped(), filter(p.a, p2 -> eqic(p2.botInfo, "Code Safety Checker"))); framer.add(ul(map(p.a, p2 -> { String html2 = htmlEncode2(squareBracketIfNempty(getPostRefTag(p2, post))) + " " + objectToHTML(p2); if (p2 == latestCodeSafetyPost && cic(p2.text, "Unknown identifiers:")) html2 += " " + hbuttonLink("/markSafe/" + p2.id, htmlEncode2("Mark safe")); return html2; }))); } if (nempty(p.b)) { framer.add(p("Referenced by hidden posts:")); framer.add(ul(map(p.b, p2 -> htmlEncode2(squareBracketIfNempty(getPostRefTag(p2, post))) + " " + objectToHTML(p2)))); } if (showPostStats) { String stats = nLines(countLines(post.text)) + ", distance to user post: " + post.distanceToUserPost(); framer.add(p_alignRight(small(span_title(stats, "Post stats")))); } return framer.render(); } public String getPostRefTag(UserPost a, UserPost b) { return get(a.postRefTags, indexOf(a.postRefs, b)); } public String htmlEncodeWithLinking(String text) { String html = htmlEncode2(text); return regexpReplace(html, gazelle_postMentionRegexp(), matcher -> { UserPost post = getConceptOpt(UserPost.class, parseLong(matcher.group(1))); return post == null ? matcher.group() : ahref(postLink(post), matcher.group()); }); } public List referencingPosts(UserPost post) { return sortedByCalculatedField(p -> p.modifiedOrBumped(), instancesOf(UserPost.class, allBackRefs(post))); } public List referencingPostsWithTag(UserPost post, String tag) { return filter(referencingPosts(post), p -> eqic_unnull(getPostRefTag(p, post), tag)); } public String serveAuthForm(String redirect) { return hAddToHead(super.serveAuthForm(redirect), hInitWebSocket()); } public String authFormMoreContent() { return navDiv(); } public String navDiv() { return div_vbar(navLinks(), "style", "margin-bottom: 0.5em"); } public Object handleAuth(Req req, String cookie) { String name = trim(req.params.get("user")), pw = trim(req.params.get("pw")); if (nempty(name) && nempty(pw) && nempty(cookie)) { Domain authDomain; User user = findOrCreateUserForLogin(name, pw); if (user == null) return errorMsg("User " + htmlEncode2(name) + " not found"); if (!eq(getVar(user.passwordMD5), hashPW(pw))) return errorMsg("Bad password, please try again"); cset(uniq(AuthedDialogID.class, "cookie", cookie), "restrictedToDomain", null, "master", user.isMaster, "user", user); String redirect = req.params.get("redirect"); if (nempty(redirect)) return hrefresh(redirect); } return null; } public User findOrCreateUserForLogin(String name, String pw) { return conceptWhereCI(User.class, "name", name); } public Object serve2(Req req) { if (req.auth != null) { cset(req.auth, "userMode", false); if (req.auth.user.get() != null) cset(req.auth.user.get(), "lastSeen", now()); } return super.serve2(req); } public String hashPW(String pw) { if (nempty(salterService)) return assertMD5(postPage(salterService, "pw", pw)); else return md5(pw + passwordSalt()); } public Req currentReq() { return currentReq.get(); } final public boolean isMasterAuthed() { return inMasterMode(); } final public boolean masterAuthed() { return inMasterMode(); } public boolean inMasterMode() { return inMasterMode(currentReq()); } final public boolean isMasterAuthed(Req req) { return inMasterMode(req); } final public boolean masterAuthed(Req req) { return inMasterMode(req); } public boolean inMasterMode(Req req) { return req.masterAuthed && !(req.auth != null && req.auth.userMode); } public Map filtersForClass(Class c, Req req) { if (c == UserPost.class) { if (req.auth != null && !inMasterMode(req)) return litmap("creator", req.auth.user.get()); } return super.filtersForClass(c, req); } public String loggedInUserDesc_html(Req req) { if (req.auth == null) return ahref(loginLink(), "not logged in"); if (req.auth.user.get() == null) return req.masterAuthed ? "master user" : "anonymous user " + req.auth.id; return "user " + req.auth.user.get().name; } public String loginLink() { return baseLink + "/"; } public HCRUD_Concepts crudData(Class c, Req req) { HCRUD_Concepts cc = super.crudData(c, req); if (c == UserPost.class) { cc.useDynamicComboBoxes = true; cc.lsMagic = true; cc.itemName = () -> "Post"; cc.dropEmptyListValues = false; if (eq(req.params.get("noace"), "1")) cc.addRenderer("text", new HCRUD_Data.TextArea(80, 20)); else cc.addRenderer("text", new HCRUD_Data.AceEditor(80, 20)); cc.addRenderer("postRefTags", new HCRUD_Data.FlexibleLengthList(new HCRUD_Data.TextField(20))); cc.addRenderer("type", new HCRUD_Data.ComboBox(true, itemPlus("", userPostTypesByPopularity()))); cc.fieldHelp("type", "Type of post (any format, optional)", "title", "Title for this post (any format, optional)", "text", "Text contents of this post (any format)", "nameInRepo", "Name in repository (not really used yet)", "botInfo", "Info on which bot made this post (if any)"); cc.massageItemMapForList = (item, map) -> { applyFunctionToValue(__68 -> shorten(__68), map, "text", "title", "type", "nameInRepo"); List refs = ((UserPost) item).postRefs; map.put("postRefs", new HTML(joinWithBR(lmap(__69 -> objectToHTML(__69), refs)))); }; cc.getObject = id -> { Map map = cc.getObject_base(id); List refs = (List) (map.get("postRefs")); List tags = (List) (map.get("postRefTags")); print("counts:" + l(refs) + "/" + l(tags)); map.put("postRefTags", padList(tags, l(refs), "")); return map; }; cc.emptyObject = () -> { Map item = cc.emptyObject_base(); item.put("creator", req.auth.user.get()); return item; }; cc.getObjectForDuplication = id -> { Map item = cc.getObjectForDuplication_base(id); item.put("creator", req.auth.user.get()); UserPost post = getConcept(UserPost.class, toLong(id)); List postRefs = cloneList((List) item.get("postRefs")); List tags = cloneList((List) item.get("postRefTags")); for (int i = 0; i < l(tags); i++) if (eqic(tags.get(i), "created from")) { remove(postRefs, i); tags.remove(i--); } int idx = l(postRefs); postRefs.add(post); listSet(tags, idx, "created from"); item.put("postRefs", postRefs); item.put("postRefTags", tags); print("tags", tags); return item; }; cc.fieldsToHideInCreationForm = litset("hidden", "creating"); cc.lockDB = true; cc.afterUpdate = (post, oldValues) -> { Map newValues = cgetAll_cloneLists(post, keys(oldValues)); for (Map.Entry __0 : _entrySet(newValues)) { String field = __0.getKey(); Object newVal = __0.getValue(); Object oldVal = oldValues.get(field); if (eq(oldVal, newVal)) { printVars_str("field", field, "oldVal", oldVal); continue; } IF1 f = o -> o instanceof Concept ? ((Concept) o).id : null; Object oldValForLog = defaultMetaTransformer().transform(f, oldVal); Object newValForLog = defaultMetaTransformer().transform(f, newVal); Map logEntry = litorderedmap("date", now(), "field", field, "oldVal", oldValForLog, "newVal", newValForLog); printStruct("logEntry", logEntry); logStructure(postHistoryFile(((UserPost) post)), logEntry); } }; cc.actuallyDeleteConcept = post -> deletePost(((UserPost) post)); } return cc; } public HCRUD makeCRUD(Class c, Req req) { HCRUD crud = super.makeCRUD(c, req); if (c == UserPost.class) { crud.refreshAfterCommand = (params, msgs) -> { UserPost post = getConcept(UserPost.class, toLong(crud.objectIDToHighlight)); return post != null ? hrefresh(postLink(post)) : crud.refreshAfterCommand_base(params, msgs); }; crud.renderCmds = map -> { UserPost post = getConcept(UserPost.class, toLong(crud.itemID(map))); return joinNemptiesWithVBar(crud.renderCmds_base(map), ahref(postLink(post), "Show post"), ahref(touchLink(post), "Touch", "title", "Mark post as modified so it is looked at by bots again")); }; crud.uneditableFields = litset("xmodified", "creating", "bumped"); if (showSuggestorBot) crud.moreSelectizeOptions = name -> ", onChange: function() { console.log(\"selectize onChange\"); sugTrigger(); }"; crud.showQuickSaveButton = true; crud.massageFormMatrix = (map, matrix) -> { if (showSuggestorBot) { List entries = ((HCRUD_Concepts) crud.data).comboBoxItems(conceptsWhereIC(UserPost.class, "type", "JavaX Code (Post Edit Suggestor)")); String js = hscript(replaceVars("\r\n const suggestorSelector = $(\"[name=suggestorID]\");\r\n var sugLoading = false, sugTriggerAgain = false;\r\n\r\n function sugTrigger() {\r\n //console.log(\"sugTrigger\");\r\n if (sugLoading) { sugTriggerAgain = true; return; }\r\n\r\n const sugText = suggestorSelector.text();\r\n //console.log(\"sugText=\" + sugText);\r\n const sugMatch = sugText.match(/\\d+/);\r\n if (!sugMatch) {\r\n //$(\"#suggestorResult\").html(\"\");\r\n $(\"#suggestorResult\").hide();\r\n return;\r\n }\r\n const suggestorID = sugMatch[0];\r\n\r\n // get form data as JSON\r\n \r\n var data = {};\r\n $(suggestorSelector).closest(\"form\").serializeArray().map(function(x){data[x.name] = x.value;});\r\n const json = JSON.stringify(data);\r\n console.log(\"JSON: \" + json);\r\n \r\n const url = \"" + gazelleBotURL + "/chatBotReply/\" + suggestorID;\r\n console.log(\"Loading \" + url);\r\n sugLoading = true;\r\n $.post(url, {q : json},\r\n function(result) {\r\n console.log(\"Suggestor result: \" + result);\r\n const answer = !result ? \"\" : JSON.parse(result).answer;\r\n if (answer) {\r\n $(\"#suggestorResult .sectionContents\").html(answer);\r\n $(\"#suggestorResult\").show();\r\n } else\r\n $(\"#suggestorResult\").hide();\r\n //$(\"#suggestorResult\").html(answer ? \"Suggestor says: \" + answer : \"\");\r\n }\r\n ).always(function() {\r\n console.log(\"sug loading done\");\r\n setTimeout(function() {\r\n sugLoading = false;\r\n if (sugTriggerAgain) { sugTriggerAgain = false; sugTrigger(); }\r\n }, delayAfterSuggestion);\r\n });\r\n }\r\n\r\n $(document).ready(function() {\r\n $(\"input[type=text], input[type=hidden], textarea, select\").on('input propertychange change', sugTrigger);\r\n sugTrigger();\r\n });\r\n suggestorSelector.change(sugTrigger);\r\n ", "delayAfterSuggestion", delayAfterSuggestion)); long defaultSuggestor = parseFirstLong(userDefaults(req.auth.user.get()).get("Default Suggestor Bot")); String selectedSuggestor = firstWhereFirstLongIs(entries, defaultSuggestor); matrix.add(0, ll("Suggestor Bot", crud.addHelpText("Choose a bot to assist you in editing this post [feature in development]", p_alignRight(crud.renderComboBox("suggestorID", selectedSuggestor, entries, false))) + htitledSectionWithDiv("Suggestion", "", "id", "suggestorResult", "style", "display: none", "innerDivStyle", "max-height: 150px; overflow: auto") + js)); } }; crud.flexibleLengthListLeeway = 3; } if (c == User.class) { crud.allowCreate = false; } return crud; } public String authFormHeading() { return h3_htmlEncode("Welcome to the Gazelle AI System") + p(hsnippetimg_scaleToWidth(200, "#1101482", 425, 257, "title", "Gazelle")); } public void makeFramer(Req req) { super.makeFramer(req); req.framer.renderTitle = () -> h1(ahref(baseLink + "/", himgsnippet("#1102967", "style", "height: 1em; vertical-align: bottom", "title", "Gazelle.rocks Logo")) + " " + req.framer.encodedTitle()); req.framer.add(() -> navDiv()); if (showMetaBotOnEveryPage && !eq(req.params.get("_reloading"), "1")) req.framer.willRender.add(new Runnable() { public void run() { try { req.framer.add(hscript("var botConfig = \"codePost=" + defaultBotPost + "\"; ") + hjssrc(baseLink + "/script")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "req.framer.add(hscript(\"var botConfig = \\\"codePost=\" + defaultBotPost + \"\\\"; ..."; } }); } public HTMLFramer1 framer() { return framer(currentReq.get()); } public HTMLFramer1 framer(Req req) { if (req.framer == null) makeFramer(req); return req.framer; } public String postLink(UserPost post) { return objectLink(post); } public String postLink(long postID) { return objectLink(getConcept(UserPost.class, postID)); } public String touchLink(UserPost post) { return baseLink + "/touchPost/" + post.id; } public String hideLink(UserPost post) { return baseLink + "/hidePost/" + post.id; } public String unhideLink(UserPost post) { return baseLink + "/unhidePost/" + post.id; } public String objectLink(Concept c) { return baseLink + "/" + c.id; } public String objectToHTML(Concept c) { return c == null ? "-" : ahref(objectLink(c), htmlEncode2(str(c))); } public String postToHTMLWithDate(UserPost post) { return post == null ? "" : objectToHTML(post) + " " + span(htmlEncode2(renderHowLongAgoPlusModified(post.created, post._modified)), "style", "color: #888"); } public boolean canEditPost(UserPost post) { User user = currentUser(); return user != null && (user.isMaster || user == post.creator.get()); } public User currentUser() { Req req = currentReq.get(); return req != null && req.auth != null ? req.auth.user.get() : null; } public String replyLink(UserPost post) { return appendQueryToURL(crudLink(UserPost.class), "cmd", "new", "fList_postRefs_0", post == null ? null : post.id); } public String newPostLink() { return replyLink(null); } public List navLinks(Object... __) { return gazelle_navLinks(baseLink, inlineSearch && !eq(currentReq.get().uri, "/search") ? "" : null, paramsPlus(__, "withTeam", teamPostID != 0)); } public List botCmdClasses() { return ll(); } public List crudClasses(Req req) { List l = super.crudClasses(req); l = listMinusSet(l, hiddenCrudClasses()); l.add(UserPost.class); l.add(UploadedImage.class); if (req.masterAuthed) { l.add(User.class); } return l; } @Override public Collection cruddableClasses(Req req) { return addAllAndReturnCollection(super.cruddableClasses(req), WebPushSubscription.class); } public Set hiddenCrudClasses() { return litset(Lead.class, ConversationFeedback.class, Domain.class, UserKeyword.class, UploadedSound.class, Settings.class); } public Object getPostFieldForBot(UserPost post, String field) { if (eq(field, "creatorID")) return post.creator.get().id; if (eq(field, "creatorName")) return post.creator.get().name; if (eq(field, "creatorIsMaster")) return post.creator.get().isMaster; if (eq(field, "postRefs")) return lmap(__70 -> conceptID(__70), post.postRefs); return cget(post, field); } public void deletePost(UserPost post) { if (post == null) return; print("Deleting post " + post); Lock __2 = dbLock(); lock(__2); try { long filePos = l(deletedPostsFile()); logStructure(deletedPostsFile(), mapToValues(UserPost.fieldsToSaveOnDelete, field -> getPostFieldForBot(post, field))); for (Pair p : post.postRefsWithTags()) if (p.a instanceof UserPost) logStructure(deletedRepliesFile((UserPost) p.a), litorderedmap("tag", p.b, "id", post.id, "filePos", filePos, "type", post.type)); cdelete(post); } finally { unlock(__2); } } public File deletedPostsFile() { return programFile("deleted-posts.log"); } public Object serveHTMLPost(long id) { UserPost post = getConcept(UserPost.class, id); if (post == null) return serve404("Post " + id + " not found"); return post.text; } transient public ReliableSingleThread_Multi rstDistributePostChanges = new ReliableSingleThread_Multi<>(1000, __14 -> distributePostChanges_impl(__14)); public void distributePostChanges(UserPost post) { rstDistributePostChanges.add(post); } public void distributePostChanges_impl(UserPost post) { AutoCloseable __12 = enter(); try { String uri = "/" + post.id; for (Pair p : syncMapToPairs(webSockets)) { if (eq(p.b.uri, uri)) reloadBody(p.a); } if (eqic(post.type, "Line Labels")) { UserPost parent = post.primaryRefPost(); print("Line labels post " + post.id + ", parent=" + parent); updateLineLabels(parent); } } finally { _close(__12); } } public void updateLineLabels(UserPost post) { try { if (post == null || !eqic(post.type, "Detailed Conversation Mirror")) return; print("Looking at conversation mirror " + post.id + " - " + post.title); long convID = toLong(regexpFirstGroupIC("Conversation (\\d+) with details", post.title)); Conversation conv = getConcept(Conversation.class, convID); if (conv == null) return; print("updateLineLabels " + convID + " / " + post.id); MultiMap, String> labels = new MultiMap(); for (UserPost p : referencingPostsWithTag(post, "")) if (eqic(p.type, "Line Labels")) { try { Map map = safeUnstructMapAllowingClasses(p.text(), Pair.class); print("Got labels map: " + map); putAll(labels, map); } catch (Throwable __e) { _handleException(__e); } } boolean change = false; for (Msg msg : cloneList(conv.msgs)) { List lbls = uniquifyAndSortAlphaNum(allToUpper(labels.get(pair(msg.time, msg.text)))); if (nempty(lbls)) print("Got labels: " + lbls); if (!eq(msg.labels, lbls)) { msg.labels = lbls; change = true; } } if (change) conv.incReloadCounter(); } catch (Throwable __e) { _handleException(__e); } } public void reloadBody(Object ws) { print("Reloading body through WebSocket"); String jsCode = " {\r\n const loc = new URL(document.location);\r\n const params = new URLSearchParams(loc.search);\r\n params.set('_reloading', '1');\r\n loc.search = params;\r\n console.log(\"Getting: \" + loc);\r\n $.get(loc, function(html) {\r\n var bodyHtml = /([\\s\\S]*)<\\/body>/.exec(html)[1];\r\n if (bodyHtml) {\r\n //$(\"body\").html(bodyHtml);\r\n $('body > *:not(.chatbot)').remove();\r\n $(\"body\").prepend(bodyHtml);\r\n }\r\n });\r\n } "; dm_call(ws, "send", jsonEncode(litmap("eval", jsCode))); } transient public ReliableSingleThread_Multi rstDistributeDivChanges = new ReliableSingleThread_Multi<>(1000, __15 -> distributeDivChanges_impl(__15), new F0() { public AutoCloseable get() { try { return enter(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret enter();"; } }); public void distributeDivChanges(String contentDesc) { rstDistributeDivChanges.add(contentDesc); } public void distributeDivChanges_impl(String contentDesc) { AutoCloseable __13 = enter(); try { String content = null; for (Pair p : syncMapToPairs(webSockets)) { for (String div : asForPairsWithB(p.b.liveDivs, contentDesc)) { if (content == null) content = calcDivContent(contentDesc); if (content == null) { print("No content for " + contentDesc); return; } reloadDiv(p.a, div, content); } } } finally { _close(__13); } } public void reloadDiv(Object ws, String div, String content) { String jsCode = replaceDollarVars(" $(\"#\" + $div).html($content);", "div", jsQuote(div), "content", jsQuote(content)); dm_call(ws, "send", jsonEncode(litmap("eval", jsCode))); } public String calcDivContent(String contentDesc) { if (eq(contentDesc, "postCount")) return nPosts(countConcepts(UserPost.class)); if (eq(contentDesc, "webRequestsRightHemi")) return n2(requestsServed); if (eq(contentDesc, "serverLoadRightHemi")) return formatDoubleX(systemLoad, 1); if (eq(contentDesc, "memRightHemi")) return str_toM(processSize); return null; } public int countUserPosts() { return countConcepts(UserPost.class, "botInfo", null) + countConcepts(UserPost.class, "botInfo", ""); } public int countBotPosts() { return countConcepts(UserPost.class) - countUserPosts(); } public Collection allUserPosts() { return filter(list(UserPost.class), p -> !p.isBotPost()); } public List userPostTypesByPopularity() { return listToTopTenCI(map(allUserPosts(), p -> p.type)); } public void startMainScript(Conversation conv) { UserPost post = getConceptOpt(UserPost.class, parseLong(mapGet(conv.botConfig, "codePost"))); if (post != null) { CustomBotStep step = uniq(CustomBotStep.class, "codePostID", post.id); if (executeStep(step, conv)) nextStep(conv); } else super.startMainScript(conv); } public String simulateBotLink(UserPost post) { return appendQueryToURL(baseLink + "/demo", "_botConfig", makePostData("codePost", post.id), "_newConvCookie", 1, "_autoOpenBot", 1); } @Override public boolean isRequestFromBot(Req req) { return startsWith(req.uri, "/bot/"); } public User internalUser() { return uniqCI(User.class, "name", "internal"); } transient public ReliableSingleThread_Multi rstUpdateMirrorPosts = new ReliableSingleThread_Multi<>(100, c -> c.updateMirrorPost()); public File postHistoryFile(UserPost post) { return programFile("Post Histories/" + post.id + ".log"); } public boolean postHasHistory(UserPost post) { return fileNempty(postHistoryFile(post)); } public File deletedRepliesFile(UserPost post) { return programFile("Deleted Replies/" + post.id + ".log"); } public String makeClassNavItem(Class c, Req req) { String html = super.makeClassNavItem(c, req); if (c == UserPost.class) { int count1 = countUserPosts(), count2 = countBotPosts(); if (count1 != 0 || count2 != 0) html += " " + roundBracket(n2(count1) + " from users, " + n2(count2) + " from bots"); } return html; } @Override public String modifyTemplateBeforeDelivery(String html, Req req) { String contentsPostID = req.params.get("chatContentsPost"); if (nempty(contentsPostID)) { html = html.replace("#N#", "99999"); html = html.replace("chatBot_interval = 1000", "chatBot_interval = 3600*1000"); html = html.replace("#INCREMENTALURL#", baseLink + "/text/" + contentsPostID + "?"); } return html; } public String headingForReq(Req req) { String codePost = decodeHQuery(req.params.get("_botConfig")).get("codePost"); if (nempty(codePost)) { UserPost post = getConcept(UserPost.class, parseLong(codePost)); return post == null ? null : post.title; } return null; } public UserPost homePagePost() { return firstThat(p -> p.isMasterMade(), conceptsWhereIC(UserPost.class, "type", "JavaX Code (Live Home Page)")); } public Object serveHomePage() { try { UserPost post = homePagePost(); if (post != null) return loadPage(htmlBotURLOnBotServer(post.id)); } catch (Throwable __e) { _handleException(__e); } return null; } public String callHtmlBot(long id, Map params) { return id == 0 ? "" : doPost(htmlBotURLOnBotServer(id), params); } public String callHtmlBot_dropMadeByComment(long id, Map params) { return regexpReplace_direct(callHtmlBot(id, params), "^\n", ""); } public String htmlBotURL(long postID) { return baseLink + "/htmlBot/" + postID; } public String htmlBotURLOnBotServer(long postID) { return gazelleBotURL + "/htmlBot/" + postID; } public UserPost userDefaultsPost(User user) { return conceptWhereIC(UserPost.class, "creator", user, "type", "My Defaults"); } public Map userDefaults(User user) { UserPost post = userDefaultsPost(user); return post == null ? emptyMap() : parseColonPropertyCIMap(post.text); } public double favIconCacheHours() { return 24; } public Object favIconHeaders(Object response) { call(response, "addHeader", "Cache-Control", "public, max-age=" + iround(hoursToSeconds(favIconCacheHours()))); return response; } public Object serveFavIcon() { if (favIconID != 0) { UploadedFile f = getConcept(UploadedFile.class, favIconID); if (f != null) return favIconHeaders(subBot_serveFile(f.theFile(), faviconMimeType())); } return favIconHeaders(subBot_serveFile(loadLibrary(defaultFavIconSnippet), faviconMimeType())); } public String cssURL() { return gazelle_textURL(parseLong(cssID)); } public String getText(long postID) { UserPost post = getConcept(UserPost.class, postID); return post == null ? null : post.text(); } @Override public void addThingsAboveCRUDTable(Req req, Class c, List aboveTable) { if (c == User.class) aboveTable.add(p(ahref(baseLink + "/register", "Register new user"))); } public User user(Req req) { if (req == null) return null; AuthedDialogID auth = req.auth; return auth == null ? null : auth.user(); } public Object serveIntegerLink(Req req, long id) { UserPost post = getConceptOpt(UserPost.class, id); if (post == null) return null; return servePost(post, req); } public void onNewWebSocket(WebSocketInfo ws) { } public void onWebSocketClose(WebSocketInfo ws) { ws.callCloseHandlers(); } public String cookieFromWebRequest(IWebRequest req) { if (req == null) return null; { String __4 = req.cookie(); if (!empty(__4)) return __4; } return afterLastEquals(req.headers().get("cookie")); } public void makeMaster() { var users = listMinus(list(User.class), internalUser()); if (empty(users)) { infoMessage("Please first register a user in the web interface!"); return; } ShowComboBoxForm cb = new ShowComboBoxForm(); cb.desc = "Select user to upgrade"; cb.itemDesc = "User to make master"; cb.items = map(users, user -> user.id + " " + user.name); cb.action = user -> { startThread(new Runnable() { public void run() { try { enter(); long userID = parseFirstLong(user); User userObj = getConcept(User.class, userID); printVars("user", user, "userID", userID, "userObj", userObj); makeMaster(userObj); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "enter();\r\n long userID = parseFirstLong(user);\r\n User userObj = get..."; } }); }; cb.show(); } public void makeMaster(User user) { if (user == null) return; if (!swingConfirm("Turn " + user + " into a master user?")) return; cset(user, "isMaster", true); infoMessage(user + " is now my master!!"); } public Object[] popDownButtonEntries() { return objectArrayPlus(super.popDownButtonEntries(), "Make master user...", runnableThread(new Runnable() { public void run() { try { AutoCloseable __17 = enter(); try { makeMaster(); } finally { _close(__17); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); makeMaster();"; } })); } } static public class CustomBotStep extends BotStep implements IInputHandler { public long codePostID; public String toString() { return "CustomBotStep " + codePostID; } public boolean run(Conversation conv) { String answer; try { Map result = (Map) (postJSONPage(replyURL(), "initial", 1, "cookie", conv.cookie)); answer = (String) result.get("answer"); } catch (Throwable e) { _handleException(e); answer = "Error: " + e.getMessage(); } conv.add(new Msg(false, answer)); cset(conv, "inputHandler", this); return false; } public String replyURL() { return ((DynGazelleRocks) botMod()).gazelleBotURL + "/chatBotReply/" + codePostID; } public boolean handleInput(String s, Conversation conv) { String answer; try { Map result = (Map) (postJSONPage(replyURL(), "q", s, "cookie", conv.cookie)); answer = (String) result.get("answer"); } catch (Throwable e) { _handleException(e); answer = "Error: " + e.getMessage(); } conv.add(new Msg(false, answer)); return true; } } static public String userName(User user) { return user != null ? user.name : "?"; } static public class WebPushSubscription extends Concept { public String clientIP; public Map data; } static public interface Hasher { public int hashCode(A a); public boolean equals(A a, A b); } static public interface IF2 { public C get(A a, B b); } static public class Symbol implements CharSequence { public String text; public Symbol() { } public Symbol(String text, boolean dummy) { this.text = text; } public int hashCode() { return _hashCode(text); } public String toString() { return text; } public boolean equals(Object o) { return this == o; } public int length() { return text.length(); } public char charAt(int index) { return text.charAt(index); } public CharSequence subSequence(int start, int end) { return text.substring(start, end); } } static public class Var implements IVar, ISetter { public Var() { } public Var(A v) { this.v = v; } public A v; public synchronized void set(A a) { if (v != a) { v = a; notifyAll(); } } public synchronized A get() { return v; } public synchronized boolean has() { return v != null; } public synchronized void clear() { v = null; } public String toString() { return str(this.get()); } } static final public class WeakHasherMap extends AbstractMap implements Map { public Hasher hasher = null; final public boolean keyEquals(Object k1, Object k2) { return (hasher == null ? k1.equals(k2) : hasher.equals(k1, k2)); } final public int keyHashCode(Object k1) { return (hasher == null ? k1.hashCode() : hasher.hashCode(k1)); } final public WeakKey WeakKeyCreate(K k) { if (k == null) return null; else return new WeakKey(k); } final public WeakKey WeakKeyCreate(K k, ReferenceQueue q) { if (k == null) return null; else return new WeakKey(k, q); } final public class WeakKey extends WeakReference { public int hash; public WeakKey(K k) { super(k); hash = keyHashCode(k); } final public WeakKey create(K k) { if (k == null) return null; else return new WeakKey(k); } public WeakKey(K k, ReferenceQueue q) { super(k, q); hash = keyHashCode(k); } final public WeakKey create(K k, ReferenceQueue q) { if (k == null) return null; else return new WeakKey(k, q); } @Override public boolean equals(Object o) { if (o == null) return false; if (this == o) return true; if (!(o.getClass().equals(WeakKey.class))) return false; Object t = this.get(); @SuppressWarnings("unchecked") Object u = ((WeakKey) o).get(); if ((t == null) || (u == null)) return false; if (t == u) return true; return keyEquals(t, u); } @Override public int hashCode() { return hash; } } public HashMap hash; public ReferenceQueue queue = new ReferenceQueue(); @SuppressWarnings("unchecked") final public void processQueue() { WeakKey wk; while ((wk = (WeakKey) queue.poll()) != null) { hash.remove(wk); } } public WeakHasherMap(int initialCapacity, float loadFactor) { hash = new HashMap(initialCapacity, loadFactor); } public WeakHasherMap(int initialCapacity) { hash = new HashMap(initialCapacity); } public WeakHasherMap() { hash = new HashMap(); } public WeakHasherMap(Hasher h) { hash = new HashMap(); hasher = h; } @Override public int size() { return entrySet().size(); } @Override public boolean isEmpty() { return entrySet().isEmpty(); } @Override public boolean containsKey(Object key) { @SuppressWarnings("unchecked") K kkey = (K) key; return hash.containsKey(WeakKeyCreate(kkey)); } @Override public V get(Object key) { @SuppressWarnings("unchecked") K kkey = (K) key; return hash.get(WeakKeyCreate(kkey)); } @Override public V put(K key, V value) { processQueue(); return hash.put(WeakKeyCreate(key, queue), value); } @Override public V remove(Object key) { processQueue(); @SuppressWarnings("unchecked") K kkey = (K) key; return hash.remove(WeakKeyCreate(kkey)); } @Override public void clear() { processQueue(); hash.clear(); } @SuppressWarnings("TypeParameterShadowing") final public class Entry implements Map.Entry { public Map.Entry ent; public K key; public Entry(Map.Entry ent, K key) { this.ent = ent; this.key = key; } @Override public K getKey() { return key; } @Override public V getValue() { return ent.getValue(); } @Override public V setValue(V value) { return ent.setValue(value); } final public boolean keyvalEquals(K o1, K o2) { return (o1 == null) ? (o2 == null) : keyEquals(o1, o2); } final public boolean valEquals(V o1, V o2) { return (o1 == null) ? (o2 == null) : o1.equals(o2); } @SuppressWarnings("NonOverridingEquals") public boolean equals(Map.Entry e) { return (keyvalEquals(key, e.getKey()) && valEquals(getValue(), e.getValue())); } @Override public int hashCode() { V v; return (((key == null) ? 0 : keyHashCode(key)) ^ (((v = getValue()) == null) ? 0 : v.hashCode())); } } final public class EntrySet extends AbstractSet> { public Set> hashEntrySet = hash.entrySet(); @Override public Iterator> iterator() { return new Iterator>() { public Iterator> hashIterator = hashEntrySet.iterator(); public Map.Entry next = null; @Override public boolean hasNext() { while (hashIterator.hasNext()) { Map.Entry ent = hashIterator.next(); WeakKey wk = ent.getKey(); K k = null; if ((wk != null) && ((k = wk.get()) == null)) { continue; } next = new Entry(ent, k); return true; } return false; } @Override public Map.Entry next() { if ((next == null) && !hasNext()) throw new NoSuchElementException(); Map.Entry e = next; next = null; return e; } @Override public void remove() { hashIterator.remove(); } }; } @Override public boolean isEmpty() { return !(iterator().hasNext()); } @Override public int size() { int j = 0; for (Iterator> i = iterator(); i.hasNext(); i.next()) j++; return j; } @Override public boolean remove(Object o) { processQueue(); if (!(o instanceof Map.Entry)) return false; @SuppressWarnings("unchecked") Map.Entry e = (Map.Entry) o; Object ev = e.getValue(); WeakKey wk = WeakKeyCreate(e.getKey()); Object hv = hash.get(wk); if ((hv == null) ? ((ev == null) && hash.containsKey(wk)) : hv.equals(ev)) { hash.remove(wk); return true; } return false; } @Override public int hashCode() { int h = 0; for (Iterator> i = hashEntrySet.iterator(); i.hasNext(); ) { Map.Entry ent = i.next(); WeakKey wk = ent.getKey(); Object v; if (wk == null) continue; h += (wk.hashCode() ^ (((v = ent.getValue()) == null) ? 0 : v.hashCode())); } return h; } } public Set> entrySet = null; @Override public Set> entrySet() { if (entrySet == null) entrySet = new EntrySet(); return entrySet; } public K findKey(Object key) { processQueue(); K kkey = (K) key; WeakKey wkey = WeakKeyCreate(kkey); WeakKey found = hashMap_findKey(hash, wkey); return found == null ? null : found.get(); } } static public class SmoothHTMLTemplater { public String template; public boolean verbose = false; public Map>> entriesByType = ciMap(); public List tok; public List commentRanges; public List comments; public SmoothHTMLTemplater() { } public SmoothHTMLTemplater(String template) { this.template = template; } static public class Replacement implements IFieldsToList { static final public String _fieldOrder = "exampleValue actualValue"; public String exampleValue; public String actualValue; public Replacement() { } public Replacement(String exampleValue, String actualValue) { this.actualValue = actualValue; this.exampleValue = exampleValue; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + exampleValue + ", " + actualValue + ")"; } public boolean equals(Object o) { if (!(o instanceof Replacement)) return false; Replacement __1 = (Replacement) o; return eq(exampleValue, __1.exampleValue) && eq(actualValue, __1.actualValue); } public int hashCode() { int h = 2098787826; h = boostHashCombine(h, _hashCode(exampleValue)); h = boostHashCombine(h, _hashCode(actualValue)); return h; } public Object[] _fieldsToList() { return new Object[] { exampleValue, actualValue }; } public String replaceIn(String text) { return replaceIC(text, exampleValue, actualValue); } } public List mapToEntry(Map map) { return map(map, (key, value) -> new Replacement(key, str(value))); } public String render() { tok = htmlTok(template); commentRanges = charRangesOfHTMLComments(template); comments = map(commentRanges, r -> htmlCommentContents(substring(template, r))); Matches m = new Matches(); List> replacements = new ArrayList(); for (int i = 0; i < l(comments); i++) { String comment = comments.get(i); if (match("start * block", comment, m)) { String type = m.unq(0); String endPat = format3("end * block", type); if (verbose) print("Start of block found: " + i + " / " + comment); int j = indexOfMatches(endPat, comments, i + 1); int jEndOfList = indexOfMatches(format3("end * list", type), comments, i + 1); if (j < 0) { warn("End of block comment not found: " + endPat); continue; } if (verbose) print("End of block found: " + j + " / " + comments.get(j)); if (!isEntity(type)) { print("Not an entity: " + type); continue; } List> entries = getEntries(type); if (verbose) print(nEntries(entries)); IntRange r1 = commentRanges.get(i), r2 = commentRanges.get(j); IntRange rEndOfList = commentRanges.get(jEndOfList >= 0 ? jEndOfList : j); String contents = substring(template, r1.end, r2.start); addPair(replacements, intRange(r1.end, rEndOfList.start), lines(map(entries, entry -> rewriteEntry(contents, entry)))); i = j; } } if (verbose) pnlStruct("Replacement", replacements); return replaceCharRanges(template, replacements); } public boolean isEntity(String type) { return true; } public String rewriteEntry(String text, List entry) { for (Replacement r : unnullForIteration(entry)) text = r.replaceIn(text); return text; } public List> getEntries(String type) { return entriesByType.get(type); } } static public class Fail extends RuntimeException implements IFieldsToList { public Object[] objects; public Fail() { } public Fail(Object... objects) { this.objects = objects; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + objects + ")"; } public Object[] _fieldsToList() { return new Object[] { objects }; } } static public class Meta implements IMeta { volatile public Object meta; public void _setMeta(Object meta) { this.meta = meta; } public Object _getMeta() { return meta; } } static public class HTMLFramer1 { public String title; public boolean titleIsHTML = false; public List navItems = new ArrayList(); public List contents = new ArrayList(); public LinkedHashSet headElements = new LinkedHashSet(); public boolean navBeforeTitle = false; public List willRender = new ArrayList(); static public class NavItem implements IFieldsToList { static final public String _fieldOrder = "link html targetBlank"; public String link; public String html; public NavItem() { } public NavItem(String link, String html) { this.html = html; this.link = link; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + link + ", " + html + ")"; } public boolean equals(Object o) { if (!(o instanceof NavItem)) return false; NavItem __1 = (NavItem) o; return eq(link, __1.link) && eq(html, __1.html); } public int hashCode() { int h = -900864330; h = boostHashCombine(h, _hashCode(link)); h = boostHashCombine(h, _hashCode(html)); return h; } public Object[] _fieldsToList() { return new Object[] { link, html }; } public boolean targetBlank = false; } public String get() { return render(); } transient public IF0 render; public String render() { return render != null ? render.get() : render_base(); } final public String render_fallback(IF0 _f) { return _f != null ? _f.get() : render_base(); } public String render_base() { callFAll(willRender); return hhtml(hhead(htitle(titleIsHTML ? hTitleClean(title) : title) + lines(headElements)) + hbody((navBeforeTitle ? renderNav() + renderTitle() : renderTitle() + renderNav()) + nemptyLines(contents))); } transient public IF0 renderTitle; public String renderTitle() { return renderTitle != null ? renderTitle.get() : renderTitle_base(); } final public String renderTitle_fallback(IF0 _f) { return _f != null ? _f.get() : renderTitle_base(); } public String renderTitle_base() { return h1(encodedTitle()); } public String encodedTitle() { return titleIsHTML ? title : htmlEncode2(title); } transient public IF0 renderNav; public String renderNav() { return renderNav != null ? renderNav.get() : renderNav_base(); } final public String renderNav_fallback(IF0 _f) { return _f != null ? _f.get() : renderNav_base(); } public String renderNav_base() { if (empty(navItems)) return ""; return div_vbar(map(__25 -> renderNavItem(__25), navItems), "style", "margin-bottom: 0.5em"); } public String renderNavItem(NavItem ni) { return ahref_possiblyTargetBlank(ni.link, ni.html, ni.targetBlank); } public void addNavItem(String html) { navItems.add(new NavItem(null, html)); } public void addNavItems(Iterable htmls) { forEach(__71 -> addNavItem(__71), htmls); } public void addNavItem(String link, String html, Object... __) { navItems.add(setAll(new NavItem(link, html), filterParams(__, "targetBlank"))); } final public void addInHEAD(Object html) { addInHead(html); } public void addInHead(Object html) { headElements.add(str(html)); } public void add(String html) { add((Object) html); } public void add(IF0 html) { add(lambdaToToString(html)); } public void add(Object html) { if (notNullOrEmptyString(html)) contents.add(html); } public void addAll(Collection l) { forEach(__72 -> add(__72), l); } public void clearNavItems() { navItems.clear(); } public HTMLFramer1 setTitle(String title) { this.title = title; return this; } public String htmlTitle(String title) { this.title = title; titleIsHTML = true; return title; } public Collection headElements() { return headElements; } } static public interface IWebRequest { public String uri(); public Map params(); public Map headers(); public Map files(); default public String clientIP() { return unnull(getClientIPFromHeaders(headers())); } default public String getHeader(String name) { return mapGet(headers(), name); } default public String domain() { return getHeader("host"); } public String cookie(); public boolean isHttps(); public boolean isPost(); default public String protocol() { return isHttps() ? "https://" : "http://"; } default public void noSpam() { } default public String get(String param) { return mapGet(params(), param); } default public String userAgent() { return getHeader("user-agent"); } default public Object proxy(String url, boolean rewriteHost, boolean rewritePort) { throw unimplemented(); } } static public interface ISetter { public void set(A a); } static public class JavaXHyperlinker { public boolean targetBlank = false; public Map shortFor = litmap("BigInt", "BigInteger", "$1", "m.unq(0)", "$2", "m.unq(1)", "$3", "m.unq(2)", "LS", "List", "sclass", "static class", "asclass", "abstract static class", "svoid", "static void", "SS", "Map", "S", "String", "ret", "return", "L", "List", "Cl", "Collection", "O", "Object", "sO", "static Object", "sS", "static String", "fO", "final Object", "fS", "final String", "sS", "static String", "sbool", "static boolean", "fbool", "final boolean", "bool", "boolean", "Int", "Integer", "cast", "casting to the type required on the left-hand side", "°", "()", "ItIt", "IterableIterator", "ES", "Ext (string plus extended information)", "CloseableItIt", "CloseableIterableIterator", "LPairS", "List>", "ISegmenter", "IF1>"); public String explFunc = "anonymous function declaration (similar to Java 8 lambdas)"; public String explPNoconsole = "Main program including Substance L&F, started in non-AWT thread, hiding the console"; public Map tokenExplanations = litmap("cm", "cm summons the last version of a module in Stefan's OS (cm originally stood for 'compact module')", "~.", "short for accessing a field or calling a method by reflection", "beaConcept", "a BEA concept is just a concept (database-enabled Java class) derived from BEAObject (the AGI base class)", "== null ?:", "short for: == null ? null :", "p-exp {", "main program with automatic upgrade", "mapLike", "a function that takes a global function name as first argument and can be called like this: (...)", "mapMethodLike", "a function that takes a method or field name as first argument and can be called like this: (...)", "func(", explFunc, "func{", explFunc, "voidfunc", "anonymous function declaration without return value (similar to Java 8 lambdas)", "ctex", "ctex rethrows exceptions as RuntimeExceptions so you don't have to declare them", "p {", "short for: public static void main(String[] args)", "p-experiment {", "Main program with a nice big console & auto-restart", "p-substance {", "Main program including Substance L&F, started in AWT thread", "p-subst {", "Main program including Substance L&F, started in non-AWT thread", "p-noconsole {", explPNoconsole, "pn {", explPNoconsole, "answer {", "Answer function - static S answer(S s) { new Matches m; ...; null; }", "time {", "Run the code block and print how long it took", "cprint {", "A module with default class name derived from DynPrintLog", "semiauto {", "In a semiauto block, JavaX automatically adds a ; to (almost) every line", "autosemi {", "In an autosemi block, JavaX automatically adds a ; to (almost) every line", "Clusters", "Clusters is short for Map>", "temp", "temp is like try (...) extending to the end of the current block", "pcall {", "protected call - try { ... } catch { print exception }", "r {", "r { ... } is short for: new Runnable() { public void run() { ... } }", "runnable {", "runnable { ... } is short for: new Runnable() { public void run() { ... } }", "pcall-short {", "protected call, shorter output - try { ... } catch { printShortException }", "LPair<", "LPair<...> is short for: L>", "visualize {", "Visualisation method for an OS module; returns a Swing component", "visualize as", "define a visualization for the module", "enhanceFrame {", "Method that changes properties of an OS module's frame", "run {", "short for: public void run()", "start {", "Method that is run when an OS module is loaded", "enter {", "Methods in a module should be marked 'enter' for bookkeeping", "vf<", "reference to function as voidfunc", "compact module", "try to save memory by reusing code between modules", "cmodule", "cmodule = compact module for Stefan's OS. compact = try to save memory by reusing code between modules", "cmodule2", "cmodule2 = compact module for Stefan's OS (newer version). compact = try to save memory by reusing code between modules", "rThread {", "Runnable in a new thread", "shit(", "short for: return with print", "shit:", "short for: return with print", ":=", "the := operator translates to a simple comma, but converts an identifier on its left-hand side into a string", "noeq", "don't auto-generate equals+hashCode methods", "for single (", "for single is for ping + singletonUnlessNull", "selfType", "selfType is replaced with the enclosing class's name", "runnable class", "short for: class X implementing Runnable { run { ... }}", "aka", "In JavaX, methods can have multiple names"); public Map sc, sf; public StringTree2 tokenExplanationsTree; public JavaXHyperlinker() { clearCaches(); tokenExplanationsTree = stringTree2_javaTok(tokenExplanations); } public String codeToHTML(String code) { return codeToHTML(code, true); } public String codeToHTML(String code, boolean real) { List tok = javaTok(code); Map links = new HashMap(); Map explanations = new HashMap(); putMultipleKeys(explanations, allPlus(4, jfindAll(tok, "void q {")), "Function will execute in module's queue"); Map styles = new HashMap(); tokensToColors(tok, styles); Matches m = new Matches(); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); String prev = get(tok, i - 2), prevPrev = get(tok, i - 4); String next = get(tok, i + 2); String sfID = sf.get(t); if (startsWith(t, "lambda", m) && isInteger(m.rest()) && isIdentifier(next)) explanations.put(i, ("lambda reference to a " + (m.rest()) + "-argument function")); if (eq(t, "is") && isIdentifier(next)) explanations.put(i, "synonym of 'implements'"); if (eq(t, "methodLambda0") && isIdentifier(next)) explanations.put(i, ("short for: x -> x." + next + "() (with a fresh variable instead of x)")); if (eq(t, "swappable") && isIdentifier(next)) explanations.put(i, "swappable functions can be exchanged per object instance"); if (eq(t, "main") && isIdentifier(next)) explanations.put(i, "reference to the current 'main' class (where all the standard functions are held, not always called 'main')"); if (eq(t, "autoDispose") && isIdentifier(next)) explanations.put(i, "autoDispose adds a cleanMeUp method that properly disposes of this variable"); if (eq(t, "macro") && isIdentifier(next)) explanations.put(i, "define a macro called '" + next + "', visible until the end of the enclosing block (or until redefined)"); if (eq(t, "virtual") && isIdentifier(next)) explanations.put(i, "\"virtual\" represents a type that is not visible in this realm, so it is transpiled to just Object"); if (eq(t, "concept") && isIdentifier(next)) explanations.put(i, "A concept is like a Java class, but persistable"); if (eq(t, "flexeq") && isIdentifier(next)) explanations.put(i, "flexeq is a fix for records inside parameterized classes"); if (eq(t, "switchable") && isIdentifier(next)) explanations.put(i, "A field that can be changed through the module's popup menu"); if (eq(t, "embedded") && isIdentifier(next)) explanations.put(i, "\"embedded\" allows you to put a function where they would not normally be allowed"); if (eq(t, "visual") && isIdentifier(next)) explanations.put(i, "short definition of the visualize() function"); if (eq(t, "dm_q") && isIdentifier(next)) explanations.put(i, "Function reference delegating to module queue"); if (eq(t, "!") && isIdentifier(prev) && neq(next, "=")) explanations.put(i, "! is short for .get()"); if (eq(t, "#") && isIdentifier(next)) explanations.put(i, "# makes an identifier local to the scope"); if (eq(t, "f") && isIdentifier(next)) explanations.put(i, "f references a static function in the main class"); if (eq(t, "r") && isIdentifier(next)) explanations.put(i, "short for: r { " + next + "() }"); if (eqOneOf(t, "rThread", "rThreadEnter") && isIdentifier(next)) explanations.put(i, "short for: " + t + " { " + next + "() }"); if (eq(t, "dispose") && isIdentifier(next)) explanations.put(i, "short for: cleanUp(" + next + "); " + next + " = null;"); if (eq(t, "*") && eq(next, "(")) explanations.put(i, "Short syntax for a constructor declaration"); if (eq(t, "thread") && eq(next, "{")) explanations.put(i, "Start a new thread with the following code"); if (eq(t, "module") && isIdentifier(next)) explanations.put(i, "A module is a class that can be loaded in Stefan's OS"); if (eq(t, "record") && isIdentifier(next)) explanations.put(i, "A record is a value-based class"); if (eq(t, "srecord") && isIdentifier(next)) explanations.put(i, "An srecord is a static value-based class"); if (eqOneOf(t, "cached", "simplyCached") && isIdentifier(next)) explanations.put(i, "A function that caches its return value"); if (eq(t, "thread") && isQuoted(next)) explanations.put(i, "Start a new thread with the following name & code"); if (eq(t, "if") && isQuoted(next)) { try { List tok2 = tok_subListWithoutBorderNTokens(tok, i, i + 3); tok_expandIfQuoted(tok2); explanations.put(i, "short for: " + join(tok2)); } catch (Throwable __e) { _handleException(__e); } } if (eq(t, "html") && eq(next, "{")) explanations.put(i, "short for: static Object html(String uri, final Map params) ctex {"); if (eq(t, "try") && eq(next, "answer")) doublePut(explanations, i, i + 2, "\"try answer\" returns the expression if it isn't null or empty"); if (isSingleQuoteIdentifier(t)) explanations.put(i, "string constant, " + quote(fromSingleQuoteIdentifier(t))); if (eq(t, "event") && isIdentifier(next)) explanations.put(i, "declare a function called " + next + "() plus helpers for adding listeners"); if (eqOneOf(t, "null", "false", "true", "this") && eq(next, ";") && tok_tokenBeforeLonelyReturnValue(tok, i - 2)) doublePut(explanations, i, i + 2, "short for: return " + t + ";"); String e = shortFor.get(t); if (e != null) mapPut(explanations, i, "short for: " + e); if (!explanations.containsKey(i) && sfID != null) { if (eqOneOf(prev, "f", "r", "rThread") || startsWith(prev, "lambda") || isIdentifier(next) && eqGet(tok, i + 4, "(") || eqOneOf(next, "(", "°") && (neq(prev, ".") || eq(prevPrev, "main") && neq(get(tok, i - 6), ".")) || eq(prev, "{") && eq(next, "}") && eq(prevPrev, "postProcess") || eq(prev, ":") && eq(prevPrev, ":")) links.put(i, sfID); } List fewTokens = codeTokens(subList(tok, i - 1, i + 2 * 5)); Pair p = stringTreeLeafValue2(tokenExplanationsTree, fewTokens); if (p != null) { int lastCodeToken = i + p.b * 2 - 2; if (eq(get(tok, lastCodeToken), "{")) lastCodeToken -= 2; mapPutInRange(explanations, i, lastCodeToken + 1, p.a); } if (isQuoted(t) && eq(prev, "(") && isIdentifier(prevPrev) && isMechFunction(prevPrev)) mapPut(links, i, neatMechListURL(unquote(t))); String id = sc.get(t); if (id != null) links.put(i, id); } StringBuilder out = new StringBuilder(); Map titles = getSnippetTitles(filter(__73 -> isSnippetID(__73), values(links))); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (empty(t)) continue; String id = links.get(i), ex = explanations.get(i); String style = styles.get(i); if (t.startsWith("[[") && t.endsWith("]]")) { String explanation = "[[...]] denotes a multi-line string constant (as in Lua)"; out.append(dottedSpan("[[", explanation)); String inner = htmlencode(dropPrefix("[[", dropSuffix("]]", t))); out.append(span(inner, "style", "background-color: #77FF77")); out.append(dottedSpan("]]", explanation)); continue; } if (t.startsWith("[=[") && t.endsWith("]=]")) { String explanation = "[=[...]=] denotes a multi-line string constant (as in Lua)"; out.append(dottedSpan("[=[", explanation)); String inner = htmlencode(dropPrefix("[=[", dropSuffix("]=]", t))); out.append(span(inner, "style", "background-color: #77FF77")); out.append(dottedSpan("]=]", explanation)); continue; } String enc = htmlencode(t); out.append(id != null ? ahref(makeLink(real, id), enc, "title", isSnippetID(id) ? titles.get(fsI(id)) : ex, "style", "text-decoration: none; color: black; border-bottom: dotted 1px", "target", targetBlank ? "_blank" : null) : ex != null ? dottedSpan(enc, ex) : style != null ? span(enc, "style", style) : enc); } String html = str(out); html = dynamize_noEncode(html); return html; } public String makeLink(boolean real, String id) { if (isURL(id)) return id; if (real) return longSnippetLink(id); return "/" + psI(id); } public void clearCaches() { stdFunctions_clearCache(); sc = standardClassesMap(); sf = stdFunctions_cached(); } public boolean isMechFunction(String s) { return startsWithOneOf(s, "mech", "mL"); } public void tokensToColors(List tok, Map styles) { for (int i = 0; i < l(tok); i += 2) if (tok_whitespaceContainsJavaComments(tok.get(i))) styles.put(i, "color: #666666"); } } static public class IntRange { public int start, end; public IntRange() { } public IntRange(int start, int end) { this.end = end; this.start = start; } public IntRange(IntRange r) { start = r.start; end = r.end; } public boolean equals(Object o) { return stdEq2(this, o); } public int hashCode() { return stdHash2(this); } final public int length() { return end - start; } final public boolean empty() { return start >= end; } final public boolean isEmpty() { return start >= end; } static public String _fieldOrder = "start end"; public String toString() { return "[" + start + ";" + end + "]"; } } static public class MultiMap { public Map> data = new HashMap>(); public int fullSize; public MultiMap() { } public MultiMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); } public MultiMap(MultiMap map) { putAll(map); } public MultiMap(Map> data) { this.data = data; } public void put(A key, B value) { synchronized (data) { List list = data.get(key); if (list == null) data.put(key, list = _makeEmptyList()); list.add(value); ++fullSize; } } public void add(A key, B value) { put(key, value); } public void addAll(A key, Collection values) { putAll(key, values); } public void addAllIfNotThere(A key, Collection values) { synchronized (data) { for (B value : values) setPut(key, value); } } public void setPut(A key, B value) { synchronized (data) { if (!containsPair(key, value)) put(key, value); } } public boolean containsPair(A key, B value) { synchronized (data) { return get(key).contains(value); } } public void putAll(Collection keys, B value) { synchronized (data) { for (A key : unnullForIteration(keys)) put(key, value); } } public void putAll(A key, Collection values) { synchronized (data) { if (nempty(values)) getActual(key).addAll(values); } } public void putAll(Iterable> pairs) { synchronized (data) { for (Pair p : unnullForIteration(pairs)) put(p.a, p.b); } } public void removeAll(A key, Collection values) { synchronized (data) { for (B value : values) remove(key, value); } } public List get(A key) { synchronized (data) { List list = data.get(key); return list == null ? Collections.emptyList() : list; } } public List getOpt(A key) { synchronized (data) { return data.get(key); } } public List getActual(A key) { synchronized (data) { List list = data.get(key); if (list == null) data.put(key, list = _makeEmptyList()); return list; } } public void clean(A key) { synchronized (data) { List list = data.get(key); if (list != null && list.isEmpty()) { fullSize -= l(list); data.remove(key); } } } public Set keySet() { synchronized (data) { return data.keySet(); } } public Set keys() { synchronized (data) { return data.keySet(); } } public void remove(A key) { synchronized (data) { fullSize -= l(getOpt(key)); data.remove(key); } } public void remove(A key, B value) { synchronized (data) { List list = data.get(key); if (list != null) { if (list.remove(value)) fullSize--; if (list.isEmpty()) data.remove(key); } } } public void clear() { synchronized (data) { data.clear(); } } public boolean containsKey(A key) { synchronized (data) { return data.containsKey(key); } } public B getFirst(A key) { synchronized (data) { List list = get(key); return list.isEmpty() ? null : list.get(0); } } public void addAll(MultiMap map) { putAll(map); } public void putAll(MultiMap map) { synchronized (data) { for (A key : map.keySet()) putAll(key, map.get(key)); } } public void putAll(Map map) { synchronized (data) { if (map != null) for (Map.Entry e : map.entrySet()) put(e.getKey(), e.getValue()); } } final public int keyCount() { return keysSize(); } public int keysSize() { synchronized (data) { return l(data); } } final public int fullSize() { return size(); } public int size() { synchronized (data) { return fullSize; } } public List reverseGet(B b) { synchronized (data) { List l = new ArrayList(); for (A key : data.keySet()) if (data.get(key).contains(b)) l.add(key); return l; } } public Map> asMap() { synchronized (data) { return cloneMap(data); } } public boolean isEmpty() { synchronized (data) { return data.isEmpty(); } } public List _makeEmptyList() { return new ArrayList(); } public Collection> allLists() { synchronized (data) { return new ArrayList(data.values()); } } public Collection> values() { return allLists(); } public List allValues() { return concatLists(data.values()); } public Object mutex() { return data; } public String toString() { return "mm" + str(data); } } static public interface IFieldsToList { public Object[] _fieldsToList(); } static public class Worker extends Concept { public String loginName, displayName; public boolean available = false; public long lastOnline; public Ref image = new Ref(); static public String _fieldOrder = "loginName displayName"; public String renderAsHTML() { return htmlEncode2(loginName + " (display name: " + displayName + ")"); } } abstract static public class DynNewBot2 extends DynPrintLogAndEnabled { public void setEleu(Object eleu) { mainBot = eleu; } public int maxRefsToShow = 5; volatile public long requestsServed; transient public String templateID = "#1029809"; static public String cssID = "#1029808"; transient public String botName = "DynNewBot2"; transient public String heading = "DynNewBot2"; transient public String adminName = "DynNewBot2 Admin"; transient public String botImageID = "#1102935"; transient public String userImageID = "#1102803"; transient public String chatHeaderImageID = "#1102802"; transient public String timeZone = ukTimeZone_string(); transient public String baseLink = ""; transient public boolean newDesign = true; transient public boolean ariaLiveTrick = false; transient public boolean ariaLiveTrick2 = true; public class WorkerChat { public int workerLongPollTick = 200; public int workerLongPollMaxWait = 1000 * 30; public long lastWorkerRequested; public String mainAdminLink = "/"; public Object html(DynNewBot2.Req req) { Map params = req.params; String uri = req.uri, uri2 = appendSlash(uri); boolean requestAuthed = req.auth != null; Conversation conv = req.conv; if (startsWith(uri2, "/worker/")) { if (!req.webRequest.isHttps()) return subBot_serveRedirect("https://" + req.webRequest.domain() + req.uri + htmlQuery(req.params)); if (!requestAuthed) return serveAuthForm(params.get("uri")); if (nempty(params.get("turnBotOn"))) conv.turnBotOn(); return serveWorkerPage(req); } return null; } public String serveWorkerPage(DynNewBot2.Req req) { AuthedDialogID auth = req.auth; Conversation conv = req.conv; String uri = req.uri; Map params = req.params; String cookie = conv.cookie; String uri2 = afterLastSlash(uri); if (eq(uri2, "availableWorkers")) return "Available workers: " + or2(joinWithComma(map(workersAvailable(), w -> w.renderAsHTML())), "-"); if (nempty(params.get("workerLogOut"))) cset(auth, "loggedIn", null); if (auth.loggedIn != null && nempty(params.get("workerAvailableBox"))) if (cset_trueIfChanged(auth.loggedIn, "available", nempty(params.get("workerAvailable")))) noteConversationChange(); if (nempty(params.get("acceptConversation"))) { if (conv.worker == null) { cset(conv, "worker", auth.loggedIn); conv.turnBotOff(); } } String loginID = params.get("workerLogIn"); if (nempty(loginID)) cset(auth, "loggedIn", getConcept(Worker.class, parseLong(loginID))); Map map = prependEmptyOptionForHSelect(mapToOrderedMap(conceptsSortedByFieldCI(Worker.class, "loginName"), w -> pair(w.id, w.loginName))); if (auth.loggedIn == null) return hsansserif() + p("You are not logged in as a worker") + hpostform("Log in as: " + hselect("workerLogIn", map, conceptID(auth.loggedIn)) + " " + hsubmit("OK"), "action", botMod().baseLink + "/worker"); if (eq(uri2, "conversation")) { if (conv == null) return "Conversation not found"; String onOffURL = botMod().baseLink + "/worker/botOnOff" + hquery("cookie", cookie) + "&on="; return hsansserif() + loadJQuery() + hhidden("cookie", cookie) + hpostform(hhidden("cookie", cookie) + p(renderBotStatus(conv)) + p(conv.botOn ? hsubmit("Accept conversation", "name", "acceptConversation") : hsubmit("Turn bot back on", "name", "turnBotOn")), "action", botMod().baseLink + "/worker/innerFrameSet", "target", "innerFrameSet") + hscriptsrc(botMod().baseLink + "/script" + hquery("workerMode", 1, "cookie", conv.cookie)); } if (eq(uri2, "conversations")) { cset(auth.loggedIn, "lastOnline", now()); boolean poll = eq("1", params.get("poll")); String content = ""; if (poll) { long seenChange = parseLong(params.get("lastChange")); vmBus_send("chatBot_startingWorkerPoll", mc(), conv); long start = sysNow(); List msgs; boolean first = true; while (licensed() && sysNow() < start + workerLongPollMaxWait && lastConversationChange == seenChange) sleep(workerLongPollTick); printVars_str("lastWorkerRequested", lastWorkerRequested, "seenChange", seenChange); if (lastWorkerRequested > seenChange) content = hscript("\r\n window.parent.parent.frames[0].sendDesktopNotification(\"A worker is requested!\", { action: function() { window.focus(); } });\r\n window.parent.parent.frames[0].playWorkerRequestedSound();\r\n "); } long pingThreshold = now() - activeConversationTimeout(); List convos = sortByCalculatedFieldDesc(c -> c.lastMsgTime(), conceptsWithFieldGreaterThan(Conversation.class, "lastPing", pingThreshold)); content += hhiddenWithID("lastConversationChange", lastConversationChange) + tag("table", hsimpletableheader("IP", "Country", "Bot/worker status", "Last change", "Last messages") + mapToLines(convos, c -> { List lastMsgs = lastTwo(c.msgs); String style = c == conv ? "background: #90EE90" : null; String convLink = botMod().baseLink + "/worker/innerFrameSet" + hquery("cookie", c.cookie); return tag("tr", td(ahref(convLink, c.ip, "target", "innerFrameSet")) + td(getCountry(c)) + td(renderBotStatus(c)) + td(renderHowLongAgo(c.lastMsgTime())) + td(ahref(convLink, hparagraphs(lambdaMap(__74 -> renderMsgForWorkerChat(__74), lastMsgs)), "target", "innerFrameSet", "style", "text-decoration: none")), "style", style); }), "class", "responstable"); if (poll) return content; String incrementalURL = botMod().baseLink + "/worker/conversations?poll=1&lastChange="; return hhtml(hhead(hsansserif() + loadJQuery() + hscript_clickableRows()) + hbody(h3(botName) + hpostform("Logged in as " + htmlEncode2(auth.loggedIn.loginName) + " (display name: " + htmlEncode2(auth.loggedIn.displayName) + ")" + hhidden("workerAvailableBox", 1) + "   " + hcheckboxWithText("workerAvailable", "I am available", auth.loggedIn.available, "onclick", "form.submit()") + "   " + hsubmit("Log out", "name", "workerLogOut"), "target", "innerFrameSet", "action", botMod().baseLink + "/worker/innerFrameSet") + p("Available workers: " + b(or2(joinWithComma(map(workersAvailable(), w -> w.displayName)), "none"))) + h3("Active conversations") + hcss_responstable() + hdivWithID("contentArea", content) + hscript("\r\n function poll_start() {\r\n var lastChange = $(\"#lastConversationChange\").val();\r\n if (!lastChange)\r\n setTimeout(poll_start, 1000);\r\n else {\r\n var url = \"#INCREMENTALURL#\" + lastChange;\r\n console.log(\"Loading \" + url);\r\n $.get(url, function(src) {\r\n if (src.match(/^ERROR/)) console.log(src);\r\n else {\r\n console.log(\"Loaded \" + src.length + \" chars\");\r\n $(\"#contentArea\").html(src);\r\n }\r\n setTimeout(poll_start, 1000);\r\n }, 'text')\r\n .fail(function() {\r\n console.log(\"Rescheduling after fail\");\r\n setTimeout(poll_start, 1000);\r\n });\r\n }\r\n }\r\n poll_start();\r\n ".replace("#INCREMENTALURL#", incrementalURL)))); } if (eq(uri2, "notificationArea")) return hhtml(hhead(hsansserif() + loadJQuery()) + hbody(hdesktopNotifications() + div(small(span(hbutton("CLICK HERE to enable notification sounds!"), "id", "enableSoundsBtn") + " | " + span("", "id", "notiStatus")), "style", "float: right") + hscript("\r\n function enableSounds() {\r\n document.removeEventListener('click', enableSounds);\r\n $(\"#enableSoundsBtn\").html(\"Notification sounds enabled\");\r\n }\r\n document.addEventListener('click', enableSounds);\r\n \r\n if (window.workerRequestedSound == null) {\r\n console.log(\"Loading worker requested sound\");\r\n window.workerRequestedSound = new Audio(\"https://botcompany.de/files/1400404/worker-requested.mp3\");\r\n }\r\n \r\n function playWorkerRequestedSound() {\r\n console.log(\"Playing worker requested sound\");\r\n window.workerRequestedSound.play();\r\n }\r\n window.playWorkerRequestedSound = playWorkerRequestedSound;\r\n\r\n "))); if (eq(uri2, "innerFrameSet")) return hhtml(hhead_title("Worker Chat [" + auth.loggedIn.loginName + "]") + hframeset_cols("*,*", tag("frame", "", "name", "conversations", "src", botMod().baseLink + "/worker/conversations" + hquery("cookie", cookie)) + tag("frame", "", "name", "conversation", "src", conv == null ? null : botMod().baseLink + "/worker/conversation" + hquery("cookie", cookie)))); return hhtml(hhead_title("Worker Chat [" + auth.loggedIn.loginName + "]") + hframeset_rows("50,*", tag("frame", "", "name", "notificationArea", "src", botMod().baseLink + "/worker/notificationArea") + tag("frame", "", "name", "innerFrameSet", "src", conv == null ? null : botMod().baseLink + "/worker/innerFrameSet" + hquery("cookie", cookie)))); } public String renderMsgForWorkerChat(Msg msg) { return (msg.fromWorker != null ? htmlEncode2(msg.fromWorker.displayName) : msg.fromUser ? "User" : "Bot") + ": " + b(htmlEncode2If(shouldHtmlEncodeMsg(msg), msg.text)); } public Collection workersAvailable() { long timestamp = now() - workerLongPollMaxWait - 10000; return filter(list(Worker.class), w -> w.available && w.lastOnline >= timestamp); } public boolean anyWorkersAvailable() { return nempty(workersAvailable()); } public String renderBotStatus(Conversation conv) { return "Bot is " + b(conv.botOn ? "on" : "off") + "
" + "Assigned worker: " + b(conv.worker == null ? "none" : conv.worker.displayName); } } transient public WorkerChat workerChat = new WorkerChat(); transient public ReliableSingleThread rstBotActions = dm_rst(this, new Runnable() { public void run() { try { botActions(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "botActions();"; } }); transient public String defaultHeaderColorLeft = "#2a27da"; transient public String defaultHeaderColorRight = "#00ccff"; transient public boolean enableUsers = false; transient public boolean useWebSockets = false; transient public boolean showRegisterLink = false; transient public boolean showTalkToBotLink = false; transient public boolean alwaysRedirectToHttps = false; transient public boolean redirectOnLogout = false; transient public boolean showFullErrors = false; transient public boolean lockWhileDoingBotActions = false; transient public boolean standardButtonsAsSymbols = false; transient public boolean enableVars = false; transient public boolean enableAvatars = false; transient public boolean enableRandomActions = false; transient public boolean recordExecutionsAndInputs = true; transient public boolean phoneNumberSpecialInputField = true; transient public boolean enableRadioButtons = false; transient public boolean newDialogAfterWindowClosed = false; transient public boolean showJoiningConversation = false; transient public boolean quickRadioButtons = false; transient public boolean useDynamicComboBoxes = false; transient public boolean prefixPrintsWithConvID = true; transient public boolean enableUndoStates = false; transient public boolean showCRUDToEveryone = false; transient public boolean showCRUDToNonMasterUsers = true; transient public boolean showOnlySelectedObject = false; transient public boolean storeBaseClassesInStructure = false; transient public boolean botDisabled = false; transient public boolean useBotNameAsModuleName = true; transient public boolean showMailSenderInfo = true; transient public boolean authedDialogIDForEveryCookie = false; transient public boolean showDeliveredDomains = true; public String mailSenderInfo; transient public int typingTimeshift = 2000; transient public ThreadLocal currentReq = new ThreadLocal(); transient volatile public Scorer consistencyCheckResults; transient public Lock statsLock = lock(); transient public Map specialPurposes = litcimap("bad email address", "Please enter a valid e-mail address", "bad phone number", "Please enter a valid phone number"); transient public String nameOfReferencesColumn = "Referenced by"; transient public Set requestsInFlight = syncWeakSet(); public void start() { super.start(); if (useBotNameAsModuleName) dm_setModuleName(botName); dm_assertFirstSibling(); concepts_setUnlistedByDefault(true); standardTimeZone(); standardTimeZone_name = timeZone; print("DB program ID: " + dbProgramID()); realPW(); pWebChatBot(); dm_doEvery(60.0, new Runnable() { public void run() { try { cleanConversations(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cleanConversations();"; } }); rstBotActions.trigger(); } public void indexAllLinkableClasses() { ensureConceptClassesAreIndexed(allLinkableClasses()); } public JComponent visualize() { JComponent _c = super.visualize(); addToControlArea(jPopDownButton_noText(popDownButtonEntries())); return _c; } public Object[] popDownButtonEntries() { return litobjectarray("Show/edit master password...", runnableThread(new Runnable() { public void run() { try { AutoCloseable __24 = enter(); try { editMasterPassword(); } finally { _close(__24); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); editMasterPassword();"; } }), !showMailSenderInfo ? null : "Show/edit mail sender info...", runnableThread(new Runnable() { public void run() { try { AutoCloseable __25 = enter(); try { editMailSenderInfo(); } finally { _close(__25); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp enter(); editMailSenderInfo();"; } })); } static public class Req implements IWebRequest { public IWebRequest webRequest; public String uri; public Map params; public AuthedDialogID auth; public Domain authDomainObj; public String authDomain; public HTMLFramer1 framer; public boolean masterAuthed = false; public Conversation conv; public String subURI; public WeakReference handlingThread; public String uri() { return uri; } final public String subUri() { return subURI(); } public String subURI() { return subURI; } public Map params() { return params; } public Map headers() { return webRequest.headers(); } public Map files() { return webRequest.files(); } public boolean isHttps() { return webRequest.isHttps(); } public String cookie() { return webRequest.cookie(); } public boolean requestAuthed() { return auth != null; } public String get(String param) { return mapGet(params, param); } public boolean isPost() { return webRequest.isPost(); } public void markNoSpam() { webRequest.noSpam(); } public void noSpam() { markNoSpam(); } public String uriWithParams() { return appendParamsToURL(uri, params); } public HTMLFramer1 framer() { return framer; } } public boolean calcMasterAuthed(Req req) { return req != null && req.auth != null && req.auth.master; } public Object html(IWebRequest request) { AutoCloseable __19 = enter(); try { vmBus_logMethodCall("html", "this", this, "request", request); try { return html2(request); } catch (Throwable e) { printStackTrace(e); return subBot_serve500(showFullErrors || calcMasterAuthed(currentReq()) ? getStackTrace(e) : "Error."); } finally { currentReq.set(null); } } finally { _close(__19); } } public Req currentReq() { return currentReq.get(); } public void requestServed() { } public Object html2(IWebRequest request) { htmlencode_forParams_useV2(); { Lock __2 = statsLock; lock(__2); try { requestsServed++; change(); requestServed(); vmBus_logMethodCall("html", "this", this, "requestsServed", requestsServed); } finally { unlock(__2); } } Req req = webRequestToReq(request); AutoCloseable __20 = tempAdd(requestsInFlight, req); try { if (alwaysRedirectToHttps) { Object __10 = redirectToHttps(req); if (__10 != null) return __10; } vmBus_logMethodCall("html", "Calling html3"); return html3(req); } finally { _close(__20); } } public Req newReq() { return new Req(); } public Req webRequestToReq(IWebRequest request) { Req req = newReq(); req.webRequest = request; req.uri = request.uri(); req.params = request.params(); req.handlingThread = weakRef(currentThread()); return req; } public Object html3(Req req) { IWebRequest request = req.webRequest; String uri = req.uri; Map params = req.params; if (eq(params.get("_newConvCookie"), "1")) return hrefresh(appendQueryToURL(req.uri, mapPlus(mapMinus(req.params, "_newConvCookie"), "cookie", "test_" + aGlobalID()))); String cookie = request.cookie(); boolean workerMode = nempty(params.get("workerMode")) || startsWith(uri, "/worker"); String domain = request.domain(), _domain = domain; saveDeliveredDomain(domain); Domain domainObj = findDomainObj(domain); String convCookie = params.get("cookie"); Conversation conv = botDisabled ? null : isRequestFromBot(req) ? null : nempty(convCookie) ? getConv(convCookie) : nempty(cookie) ? getConv(cookie) : null; req.conv = conv; AutoCloseable tempThing = conv == null || !prefixPrintsWithConvID ? null : temp_printPrefix("Conv " + conv.cookie + ": "); AutoCloseable __21 = tempThing; try { currentReq.set(req); String botConfig = params.get("_botConfig"); Map botConfigParams = decodeURIParams(botConfig); String simulatedDomain = botConfigParams.get("domain"); Domain domainObj2 = nempty(simulatedDomain) ? findDomainObj(simulatedDomain) : domainObj; if (nempty(botConfigParams)) cset(conv, "botConfig", botConfigParams); if (conv != null && !workerMode) if (cset_trueIfChanged(conv, "ip", request.clientIP(), "domain", domain, "domainObj", domainObj2)) { calcCountry(conv); initAvatar(conv); } { Object __11 = handleAuth(req, cookie); if (__11 != null) return __11; } Matches m = new Matches(); if (startsWith(uri, "/worker-image/", m)) { long id = parseLong(m.rest()); return subBot_serveFile_maxCache(workerImageFile(id), "image/jpeg"); } if (startsWith(uri, "/uploaded-image/", m)) { long id = parseLong(m.rest()); UploadedImage img = getConcept(UploadedImage.class, id); return img == null ? serve404() : subBot_serveFile_maxCache(img.imageFile(), "image/jpeg"); } if (startsWith(uri, "/uploaded-sound/", m)) { long id = parseLong(m.rest()); UploadedSound sound = getConcept(UploadedSound.class, id); return sound == null ? serve404() : subBot_serveFile_maxCache(sound.soundFile(), sound.mimeType); } if (startsWith(uri, "/uploaded-file/", m)) { long id = parseLong(dropAfterSlash(m.rest())); UploadedFile f = getConcept(UploadedFile.class, id); return f == null ? serve404() : subBot_serveFile_maxCache(f.theFile(), or2(params.get("ct"), or2(trim(f.mimeType), binaryMimeType()))); } AuthedDialogID auth = authObject(cookie); fillReqAuthFromCookie(req, cookie, auth); if (eq(params.get("logout"), "1")) { { Object __12 = handleLogout(req); if (__12 != null) return __12; } auth = authObject(cookie); } boolean requestAuthed = req.auth != null; boolean masterAuthed = req.masterAuthed; Domain authDomainObj = req.authDomainObj; String authDomain = req.authDomain; if (requestAuthed) req.markNoSpam(); { Object __13 = serve2(req); if (__13 != null) return __13; } makeFramer(req); HTMLFramer1 framer = req.framer; if (showCRUDToEveryone || showCRUDToNonMasterUsers && requestAuthed || req.masterAuthed) { Object __14 = serveCRUD(req); if (__14 != null) return __14; } if (!requestAuthed && settings().talkToBotOnlyWithAuth) return serveAuthForm(params.get("uri")); if (eq(uri, "/emoji-picker/index.js")) return withHeader(subBot_maxCacheHeaders(serveInputStream(bufferedFileInputStream(loadLibrary("#1400436")), "text/javascript"))); if (eq(uri, "/emoji-picker-test")) return loadSnippet("#1029870"); if (eq(uri, "/logs")) { if (!masterAuthed) return serveAuthForm(rawLink(uri)); return webChatBotLogsHTML2(rawLink(uri), params); } if (eq(uri, "/refchecker")) { if (!masterAuthed) return serveAuthForm(rawLink(uri)); ConceptsRefChecker refChecker = new ConceptsRefChecker(db_mainConcepts()); List errors = refChecker.run(); if (eq(params.get("fix"), "1")) return serveText(refChecker.fixAll()); else return serveText(jsonEncode_breakAtLevels(2, litorderedmap("errors", allToString(errors)))); } if (eq(uri, "/backupDBNow")) { if (!masterAuthed) return serveAuthForm(rawLink(uri)); return serveText("Backed up DB as " + fileInfo(backupConceptsNow())); } if (eq(uri, "/auth-only")) { if (!requestAuthed) return serveAuthForm(params.get("uri")); return ""; } if (eq(uri, "/leads-api")) return serveLeadsAPI(request); if (workerChat != null) { Object __15 = workerChat.html(req); if (__15 != null) return __15; } String message = trim(params.get("btn")); if (empty(message)) message = trim(params.get("message")); if (match("new dialog", message)) { Lock __3 = dbLock(); lock(__3); try { conv.newDialog(); message = null; } finally { unlock(__3); } } if (eqic(message, "!toggle notifications")) { cset(conv, "notificationsOn", !conv.notificationsOn); message = null; } if (eqic(message, "!undo states")) { conv.add(new Msg(false, n2(conv.undoStates, "undo state"))); message = null; } this.conv.set(conv); if (nempty(message) && !lastUserMessageWas(conv, message)) { Lock __4 = dbLock(); lock(__4); try { print("Adding message: " + message); possiblyTriggerNewDialog(conv); if (workerMode) { Msg msg = new Msg(false, message); msg.fromWorker = auth.loggedIn; conv.add(msg); } else { conv.add(new Msg(true, message)); addScheduledAction(new OnUserMessage(conv)); } } finally { unlock(__4); } } String testMode = params.get("testMode"); if (nempty(testMode)) { print("Setting testMode", testMode); cset(conv, "testMode", eq("1", testMode)); } if (eq(uri, "/msg")) return withHeader("OK"); if (eq(uri, "/typing")) { if (workerMode) { conv.botTyping = now(); print(conv.botTyping + " Bot typing in: " + conv.cookie); } else { conv.userTyping = now(); print(conv.userTyping + " User typing in: " + conv.cookie); } return withHeader("OK"); } if (eq(uri, "/renderMessages")) { long msgTime = parseLong(params.get("msgTime")); List msgs = conv.allMsgs(); if (msgTime != 0) msgs = filter(msgs, msg -> msg.time == msgTime); StringBuilder buf = new StringBuilder(); renderMessages(conv, buf, msgs, msg -> false); return hhtml_title_body(nMessages(msgs), hstylesheetsrc(cssURL()) + p(nMessages(msgs) + " found") + buf); } if (eq(uri, "/incremental")) { if (newDialogAfterWindowClosed && !conv.isActive()) { print("Clearing conversation, timed out"); Lock __5 = dbLock(); lock(__5); try { conv.newDialog(); } finally { unlock(__5); } } long start = sysNow(), start2 = now(); print("start2", start2); cset(conv, "lastPing", now()); possiblyTriggerNewDialog(conv); int a = parseInt(params.get("a")); int reloadCounter = conv.reloadCounter; List msgs; boolean first = true; int timeout = toInt(req.params.get("timeout")); long endTime = start + (timeout <= 0 || timeout > longPollMaxWait / 1000 ? longPollMaxWait : timeout * 1000L); while (licensed() && sysNow() < endTime) { int as = conv.archiveSize(); msgs = cloneSubList(conv.msgs, a - as); boolean reloadTriggered = conv.reloadCounter > reloadCounter; boolean actuallyNewDialog = a < as; boolean newDialog = actuallyNewDialog || reloadTriggered; if (newDialog) msgs = cloneList(conv.msgs); long typing = workerMode ? conv.userTyping : conv.botTyping; boolean otherPartyTyping = typing >= start2 - typingTimeshift; boolean anyEvent = nempty(msgs) || newDialog || otherPartyTyping; if (!anyEvent) { if (first) { first = false; } sleep(longPollTick); } else { if (eq(req.params.get("json"), "1")) return serveJSON_breakAtLevels(2, litorderedmap("n", conv.allCount(), "newDialog", trueOrNull(newDialog), "otherPartyTyping", trueOrNull(otherPartyTyping), "msgs", map(msgs, msg -> litorderedmap("time", msg.time, "fromUser", msg.fromUser, "fromWorker", msg.fromWorker == null ? null : msg.fromWorker.displayName, "text", msg.text, "labels", msg.labels)))); StringBuilder buf = new StringBuilder(); if (newDialog) { String l = or2_trim(domainObj2.headerColorLeft, defaultDomain().headerColorLeft, defaultHeaderColorLeft), r = or2_trim(domainObj2.headerColorRight, defaultDomain().headerColorRight, defaultHeaderColorRight); buf.append(hcss(".chat_header { background: linear-gradient(135deg, " + hexColorToCSSRGB(l) + " 0%, " + hexColorToCSSRGB(r) + " 100%); }")); buf.append(hscript("$('#chatBot_notiToggleText').text(" + jsQuote("Turn " + (conv.notificationsOn ? "off" : "on") + " notifications") + ");")); if (showJoiningConversation) { buf.append(hscript("$('#otherSideTyping .joining').html(" + jsQuote(nameOfBotSide(conv) + " now joining conversation...") + ");" + "setTimeout(function() { $('#otherSideTyping .joining').html(''); }, 5000);")); } } if (otherPartyTyping) { buf.append(hscript("showTyping(" + jsQuote(conv.botImg()) + ");")); } renderMessages(conv, buf, msgs); if (ariaLiveTrick2 && !workerMode) { Msg msg = lastBotMsg(msgs); if (msg != null) { String author = msg.fromWorker != null ? htmlEncode2(msg.fromWorker.displayName) : botName; buf.append(hscript("$(\"#screenreadertrick\").html(" + jsQuote(author + " says: " + msg.text) + ");")); } } if (a != 0 && anyInterestingMessages(msgs, workerMode)) buf.append(hscript(stringIf(conv.notificationsOn, "window.playChatNotification();\n") + "window.setTitleStatus(" + jsQuote((workerMode ? "User" : botName) + " says…") + ");")); String html = str(buf); return withHeader("\n" + html); } } return withHeader(""); } if (eqOneOf(uri, "/script", "/demo")) { Lock __6 = dbLock(); lock(__6); try { String myTemplateID = templateID; String templateIDParam = req.params.get("templateID"); if (nempty(templateIDParam) && allowedTemplateID(templateIDParam)) myTemplateID = templateIDParam; String html = loadSnippet_cached(myTemplateID); String botLayout = req.params.get("botLayout"); String layout = or2(botLayout, defaultBotLayout()); html = modifyTemplateBeforeDelivery(html, req); String heading = or2(headingForReq(req), or2(trim(domainObj2.botName), this.heading)); String botImg = botImageForDomain(domainObj); UploadedSound sound = settings().notificationSound.get(); String notificationSound = sound != null ? sound.soundURL() : defaultNotificationSound(); String miscParam = workerMode ? "workerMode=1&" : ""; if (nempty(botLayout)) miscParam += "botLayout=" + urlencode(botLayout) + "&"; String incrementalURL = baseLink + "/incremental?" + miscParam + "a="; String typingURL = baseLink + "/typing?" + miscParam; String msgURL = baseLink + "/msg?" + miscParam + "message="; if (eqic(layout, "sahil")) { html = replaceDollarVars(html, "incrementalURL", incrementalURL, "typingURL", typingURL, "msgURL", msgURL, "n", 0, "notificationSound", notificationSound, "workerMode", workerMode, "heading", heading, "botImg", botImg); } else { String langlinks = ""; if (html.contains(langlinks)) html = html.replace(langlinks, ahref(rawLink("eng"), "English") + " | " + ahref(rawLink("deu"), "German")); html = html.replace("#COUNTRY#", lower(conv.country)); html = html.replace("#BOTIMG#", botImg); html = html.replace("#N#", "0"); html = html.replace("#INCREMENTALURL#", incrementalURL); html = html.replace("#MSGURL#", msgURL); html = html.replace("#TYPINGURL#", typingURL); html = html.replace("#CSS_ID#", psI_str(cssID)); if (ariaLiveTrick || ariaLiveTrick2) html = html.replace("aria-live=\"polite\">", ">"); html = html.replace("#OTHERSIDE#", workerMode ? "User" : "Representative"); if (nempty(params.get("debug"))) html = html.replace("var showActions = false;", "var showActions = true;"); html = html.replace("#AUTOOPEN#", jsBool(workerMode || eq(params.get("_autoOpenBot"), "1") || botAutoOpen(domainObj2))); html = html.replace("#BOT_ON#", jsBool(botOn() || eq(uri, "/demo"))); html = html.replace("$HEADING", heading); html = html.replace("#WORKERMODE", jsBool(workerMode)); html = html.replace("#NOTIFICATIONSOUND#", notificationSound); html = html.replace("", ""); html = hreplaceTitle(html, heading); } if (eq(uri, "/demo")) return serveBotDemo(req, html); else return withHeader(subBot_serveJavaScript(html)); } finally { unlock(__6); } } { Object __16 = serveOtherPage(req); if (__16 != null) return __16; } if (eq(uri, "/")) { Object __17 = serveHomePage(); if (__17 != null) return __17; } if (eq(uri, "/login")) return serveAuthForm(); String uri2 = dropSlashPrefix(uri); if (!startsWith(uri, "/crud/") && nempty(uri2)) { UploadedFile fileToServe = conceptWhere(UploadedFile.class, "liveURI", urldecode(uri2)); if (fileToServe != null) return subBot_serveFile(fileToServe.theFile(), nempty(fileToServe.mimeType) ? fileToServe.mimeType : guessMimeTypeFromFileName(afterLastSlash(fileToServe.liveURI))); } if (requestAuthed) { if (masterAuthed && eq(uri, "/dialogTree")) { BotStep step = getConcept(BotStep.class, toLong(params.get("stepID"))); if (step == null) return serve404("Step not found"); return hhtml_head_title_body("Dialog Tree for " + step, hmobilefix() + hsansserif() + h2("Dialog Tree") + hcss_linkColorInherit() + hcss("\r\n .dialogTree li { margin-top: 0.8em; }\r\n ") + renderDialogTree(step)); } if (eq(uri, "/thoughts")) return serveThoughts(req); if (masterAuthed && eq(uri, "/search")) return serveSearch(req); if (eq(uri, "/leads-csv")) { String text = leadsToCSV(conceptsWhere(Lead.class, mapToParams(filtersForClass(Lead.class, req)))); String name = "bot-leads" + (authDomainObj == null ? "" : "-" + replace(str(authDomainObj), "/", "-")) + "-" + ymd_minus_hm() + ".csv"; return serveCSVWithFileName(name, text); } if (eq(uri, "/cleanConversations") && masterAuthed) { cleanConversations(); return hrefresh(baseLink + "/crud/Conversation"); } if (eq(uri, "/deleteDeliveredDomains") && masterAuthed) { deleteDeliveredDomains(); return hrefresh(baseLink + "/crud/DeliveredDomain"); } if (eq(uri, "/emojis")) { framer.title = "Emoji List"; framer.contents.add(htmlTable2(map(emojiShortNameMap(), (code, emoji) -> litorderedmap("Shortcode", code, "Emoji", emoji)))); } if (eq(uri, "/embedCode")) { String goDaddyEmbedCode = ""; framer.title = "Embed Code"; framer.contents.add(h2("Chat bot embed code") + (empty(goDaddyEmbedCode) ? "" : h3("GoDaddy Site Builder") + p("Add an HTML box with this code:") + pre(htmlEncode2(goDaddyEmbedCode)) + h3("Other")) + p("Add this code in front of your " + tt(htmlEncode2("")) + " tag:") + pre(htmlEncode2(hjavascript_src_withType("https://" + request.domain() + baseLink + "/script")))); } if (eq(uri, "/stats")) { framer.add(htableRaw2(nonNulls(renderStats()), ll("class", "responstable"), null, null)); return completeFrame(req); } if (eq(uri, "/unpackToWeb") & req.masterAuthed) { UploadedFile file = getConcept(UploadedFile.class, parseLong(req.params.get("fileID"))); if (file == null) return serve404("File not found"); String path = unnull(req.params.get("path")); File zipFile = file.theFile(); int changes = 0; for (String filePath : listZIP(zipFile)) { String liveURI = appendSlash(path) + filePath; UploadedFile entry = uniq(UploadedFile.class, "liveURI", liveURI); byte[] data = loadBinaryFromZip(zipFile, filePath); if (!fileContentsIs(entry.theFile(), data)) { ++changes; saveBinaryFile(entry.theFile(), data); touchConcept(entry); } } return "Unpacked, " + nChanges(changes); } } { Object __18 = serveDefaultPage(req); if (__18 != null) return __18; } return completeFrame(req); } finally { _close(__21); } } public Object serveDefaultPage(Req req) { return null; } public Object completeFrame() { return completeFrame(currentReq()); } transient public IF1 completeFrame; public Object completeFrame(Req req) { return completeFrame != null ? completeFrame.get(req) : completeFrame_base(req); } final public Object completeFrame_fallback(IF1 _f, Req req) { return _f != null ? _f.get(req) : completeFrame_base(req); } public Object completeFrame_base(Req req) { HTMLFramer1 framer = req.framer; boolean authed = req.requestAuthed(); if (authed) { if (settings().enableWorkerChat) framer.addNavItem(baseLink + "/worker", "Worker chat"); framer.addNavItem(baseLink + "?logout=1", "Log out"); } if (!authed || alwaysShowLogInLink()) framer.addNavItem(logInLink(), "Log in"); return framer.render(); } public boolean alwaysShowLogInLink() { return false; } public String logInLink() { return baseLink + "/"; } public Object serve2(Req req) { vmBus_send("html_serve2", this, req); return null; } public Object serveOtherPage(Req req) { return null; } public
A getDomainValue(Domain domainObj, IF1 getter, A defaultValue) { if (domainObj != null) { A val = getter.get(domainObj); if (val != null) return val; } { A val = getter.get(defaultDomain()); if (val != null) return val; } return defaultValue; } public String makeBaseTitle(Req req) { return ahref(baseLink + "/", adminName) + " " + squareBracket(loggedInUserDesc_html(req)); } public HTMLFramer1 newFramerInstance() { return new HTMLFramer1(); } public void makeFramer(Req req) { HTMLFramer1 framer = newFramerInstance(); req.framer = framer; framer.titleIsHTML = true; framer.title = makeBaseTitle(req); framer.addInHead(hsansserif() + hmobilefix() + hresponstable() + hcss_responstableForForms()); framer.addInHead(loadJQuery2()); framer.addInHead(hjs_selectize()); framer.addInHead(hjs_copyToClipboard()); framer.addInHead(hNotificationPopups()); framer.addInHead(hcss_linkColorInherit()); if (useWebSockets) framer.addInHead(webSocketHeadStuff(req)); makeNavItems(req, framer); List cmdClasses = botCmdClasses(req); if (nempty(cmdClasses)) framer.contents.add(p("Bot actions: " + joinWithVBar(map(cmdClasses, c -> makeClassNavItem(c, req))))); } public void makeNavItems(Req req, HTMLFramer1 framer) { if (showTalkToBotLink) framer.addNavItem(simulateDomainLink(req.authDomain), "Talk to bot", "targetBlank", true); for (Class c : navItemClasses(req)) framer.addNavItem(makeClassNavItem(c, req)); } public List navItemClasses(Req req) { return crudClasses(req); } public HCRUD makeCRUD(Class c, Req req) { return makeCRUD(c, req, req.framer); } public HCRUD makeCRUD(Class c, Req req, HTMLFramer1 framer) { HCRUD_Concepts data = crudData(c, req); data.referencesBlockDeletion = true; String searchQuery = trim(req.get("search")); data.customFilter = crudSearchFilter(req, data, searchQuery); HCRUD crud = new HCRUD(crudLink(c), data); crud.searchQuery = searchQuery; crud.params = req.params; crud.buttonsOnTop = neqOneOf(c, UploadedFile.class, UploadedSound.class, UploadedImage.class); crud.haveJQuery = crud.haveSelectizeJS = true; crud.sortable = true; crud.paginate = true; crud.paginator.step = 25; crud.cmdsLeft = true; crud.showCheckBoxes = true; crud.tableClass = "responstable"; crud.formTableClass = "responstableForForms"; if (!req.requestAuthed()) crud.disableAllMutationRights(); crud.renderValue_inner = value -> { if (isConceptList(value)) { List l = (List) value; return joinMap(l, ref -> p(ahref(conceptLink(ref), htmlEncode_nlToBr_withIndents(str(ref))))); } String html = crud.renderValue_inner_base(value); if (value instanceof Concept) return ahref(conceptLink((Concept) value), html); return html; }; if (c == Conversation.class) { crud.nav = () -> joinNemptiesWithVBar(crud.nav_base(), ahref(baseLink + "/cleanConversations", "Clean list")); crud.unshownFields = litset("oldDialogs", "worker", "botOn", "lastPing", "cookie", "form", "testMode", "userMessageProcessed", "newDialogTriggered"); } if (c == DeliveredDomain.class || c == Conversation.class || c == Lead.class || c == ConversationFeedback.class) crud.allowCreate = crud.allowEdit = false; if (c == Settings.class) { crud.singleton = countConcepts(Settings.class) == 1; if (!settings().multiLanguageMode) crud.unshownFields = litset("defaultLanguage"); { if (framer != null) framer.add(p(joinNemptiesWithVBar(ahref(baseLink + "/emojis", "Emojis"), ahref(baseLink + "/stats", "Stats"), ahref(baseLink + "/embedCode", "Embed Code")))); } } if (c == Lead.class) { if (framer != null) framer.add(p(ahref(baseLink + "/leads-csv", "Export as CSV"))); } if (c == BotOutgoingQuestion.class) { crud.unlistedFields = litset("multipleChoiceSeparator", "placeholder"); if (!enableRadioButtons) crud.unlistedFields.add("radioButtons"); crud.massageFormMatrix = (map, matrix) -> { int idx = indexOfPred(matrix, row -> cic(first(row), "Actions")); BotOutgoingQuestion item = getConcept(BotOutgoingQuestion.class, toLong(map.get(crud.idField()))); if (item == null) return; if (idx < 0) return; List row = matrix.get(idx); row.set(1, hcrud_mergeTables(row.get(1), tag("table", map(s -> tr(td() + td(htmlEncode2(s))), item.buttons)), "for:")); }; } data.addFilters(filtersForClass(c, req)); if (c == Domain.class) { crud.renderCmds = map -> { Domain dom = getConcept(Domain.class, toLong(crud.itemID(map))); return joinNemptiesWithVBar(crud.renderCmds_base(map), targetBlank(simulateDomainLink(dom.domainAndPath), "Talk to bot")); }; if (showDeliveredDomains) { if (framer != null) framer.add(p("See also the " + ahref(crudLink(DeliveredDomain.class), "list of domains the bot was delivered on"))); } } if (c == DeliveredDomain.class) { crud.nav = () -> joinNemptiesWithVBar(crud.nav_base(), ahref("/deleteDeliveredDomains", "Delete all")); crud.renderCmds = map -> { DeliveredDomain dom = getConcept(DeliveredDomain.class, toLong(crud.itemID(map))); return joinNemptiesWithVBar(crud.renderCmds_base(map), targetBlank(simulateDomainLink(dom.domain), "Talk to bot")); }; } if (c == UploadedImage.class) { crud.massageFormMatrix = (map, matrix) -> { UploadedImage item = getConcept(UploadedImage.class, toLong(crud.itemID(map))); addInFront(matrix, ll("Upload image", hjs_imgUploadBase64Encoder() + himageupload("id", "imgUploader") + hhiddenWithIDAndName("f_img_base64"))); }; crud.formParameters = () -> paramsPlus(crud.formParameters_base(), "onsubmit", "return submitWithImageConversion(this)"); } if (c == UploadedSound.class) { crud.massageFormMatrix = (map, matrix) -> { UploadedSound item = getConcept(UploadedSound.class, toLong(crud.itemID(map))); matrix.add(ll("Upload MP3/OGG/WAV/M4A", hjs_fileUploadBase64Encoder() + haudioUpload("id", "fileUploader") + hhiddenWithIDAndName("f_file_base64"))); }; crud.formParameters = () -> litparams("onsubmit", "return submitWithFileConversion(this)"); } if (c == UploadedFile.class) { crud.massageFormMatrix = (map, matrix) -> { UploadedFile item = getConcept(UploadedFile.class, toLong(crud.itemID(map))); matrix.add(ll("Upload File", hjs_fileUploadBase64Encoder() + hfileupload("id", "fileUploader") + hhiddenWithIDAndName("f_file_base64") + hjs("\r\n $(\"input[name=thefile]\").change(function(e) {\r\n var name = e.target.files[0].name;\r\n if (name)\r\n $(\"input[name=f_name]\").val(name); \r\n });\r\n "))); }; crud.formParameters = () -> litparams("onsubmit", "return submitWithFileConversion(this)"); } if (isSubclassOf(c, BotStep.class)) { crud.renderCmds = map -> { BotStep step = getConcept(BotStep.class, toLong(crud.itemID(map))); return joinNemptiesWithVBar(crud.renderCmds_base(map), targetBlank(simulateScriptLink(step), "Test in bot"), hPopDownButton(targetBlank(baseLink + "/dialogTree?stepID=" + step.id, "Show Dialog Tree"))); }; if (showDeliveredDomains) { if (framer != null) framer.add(p("See also the " + ahref(crudLink(DeliveredDomain.class), "list of domains the bot was delivered on"))); } } if (c == Worker.class) { crud.unshownFields = litset("lastOnline"); crud.uneditableFields = litset("available", "lastOnline"); } crud.postProcessTableRow = (item, rendered) -> { long id = crud.itemIDAsLong(item); Concept concept = getConcept(id); if (concept == null) return rendered; Collection refs = allBackRefs(concept); if (empty(refs)) return rendered; refs = sortedByConceptID(refs); String rts = req.get("refsToShow"); int refsToShow = empty(rts) ? maxRefsToShow : parseInt(rts); int more = l(refs) - refsToShow; return mapPlus(rendered, span_title("Where is this object used", nameOfReferencesColumn), joinMap(takeFirst(refsToShow, refs), ref -> p(ahref(conceptLink(ref), htmlEncode_nlToBr_withIndents(str(ref))))) + (more <= 0 ? "" : "
" + ahref(addParamsToURL(crudLink(concept), "refsToShow", 10000), "+" + n2(more) + " more"))); }; return crud; } public Class isLinkableConcept(Concept c, Req req) { if (req == null || c == null) return null; Class theClass = _getClass(c); return firstThat(allLinkableClasses(req), base -> isSubclassOf(theClass, base)); } public String crudLink(Concept c) { return conceptLink(c, currentReq()); } public String conceptLink(Concept c) { return conceptLink(c, currentReq()); } public String conceptLink(Concept c, Req req) { Class theClass = c.getClass(); if (req != null) { theClass = isLinkableConcept(c, req); if (theClass == null) return null; } return c == null ? null : appendQueryToURL(crudLink(theClass), "selectObj", c.id, "showOnlySelected", showOnlySelectedObject ? "1" : null) + "#obj" + c.id; } public String conceptEditLink(Concept c, Object... __) { return c == null ? null : appendQueryToURL(crudLink(c.getClass()), paramsPlus(__, "edit", c.id)); } public String conceptDuplicateLink(Concept c) { return c == null ? null : appendQueryToURL(crudLink(c.getClass()), "duplicate", c.id); } public
String makeClassNavItem(Class c, Req req) { HCRUD_Concepts data = crudData(c, req); HCRUD crud = makeCRUD(c, req, null); Map filters = filtersForClass(c, req); int count = countConcepts(c, mapToParams(filters)); return (crud.singleton ? "" : span(n2(count), "data-isCountOf", shortClassName(c)) + " ") + ahref(crudLink(c), count == 1 ? data.itemName() : data.itemNamePlural()) + (!crud.actuallyAllowCreate() ? "" : " " + targetBlankIf(newLinkTargetBlank(c), newLinkForCRUD(crud, c), "+", "title", "Create New " + data.itemName())); } transient public IF1 newLinkTargetBlank; public boolean newLinkTargetBlank(Class c) { return newLinkTargetBlank != null ? newLinkTargetBlank.get(c) : newLinkTargetBlank_base(c); } final public boolean newLinkTargetBlank_fallback(IF1 _f, Class c) { return _f != null ? _f.get(c) : newLinkTargetBlank_base(c); } public boolean newLinkTargetBlank_base(Class c) { return false; } public String newLinkForCRUD(HCRUD crud, Class c) { return crud.newLink(); } public Collection allLinkableClasses() { Req req = newReq(); req.masterAuthed = true; return allLinkableClasses(req); } public Collection allLinkableClasses(Req req) { return joinSets(crudClasses(req), botCmdClasses()); } public List botCmdClasses() { return dynNewBot2_botCmdClasses(); } public List dynNewBot2_botCmdClasses() { List l = ll(BotMessage.class, UploadedImage.class, BotImage.class, BotOutgoingQuestion.class, BotPause.class, Sequence.class); if (enableRandomActions) l.add(BotRandomAction.class); if (settings().multiLanguageMode) l.add(BotSwitchLanguage.class); return l; } public List crudClasses(Req req) { return dynNewBot2_crudClasses(req); } public List dynNewBot2_crudClasses(Req req) { if (req == null ? null : req.masterAuthed) { List l = ll(Conversation.class, Lead.class, ConversationFeedback.class, Domain.class, UserKeyword.class, UploadedSound.class, UploadedFile.class); if (enableAvatars) l.add(Avatar.class); l.add(Settings.class); if (settings().multiLanguageMode) l.add(Language.class); if (settings().enableWorkerChat) l.add(Worker.class); if (recordExecutionsAndInputs) addAll(l, ExecutedStep.class, InputHandled.class); return l; } else return ll(Conversation.class, Lead.class, ConversationFeedback.class); } public Map filtersForClass(Class c, Req req) { if (c == Conversation.class && req.authDomainObj != null) return litmap("domainObj", req.authDomainObj); if (eqOneOf(c, Lead.class, ConversationFeedback.class) && req.authDomainObj != null) return litmap("domain", req.authDomainObj); return null; } public String crudBase() { return baseLink + "/crud"; } public String crudLink(Class c) { return crudBase() + "/" + shortName(c); } public HCRUD_Concepts crudData(Class c, Req req) { HCRUD_Concepts cc = new HCRUD_Concepts<>(c); if (useDynamicComboBoxes) cc.useDynamicComboBoxes = true; if (eq(req.get("dynamicComboBoxes"), "1")) cc.useDynamicComboBoxes = true; cc.trimAllSingleLineValues = true; cc.fieldHelp("comment", "Put any comment about this object here"); cc.itemName = () -> replaceIfEquals(dropPrefix("Bot ", cc.itemName_base()), "Jump Button", "Button"); cc.valueConverter = new DefaultValueConverterForField() { public OrError convertValue(Object object, Field field, Object value) { print("convertValue " + field + " " + className(value)); if (value instanceof String && eq(field.getGenericType(), type_LS())) { print("tlft"); return new OrError(tlft((String) value)); } return super.convertValue(object, field, value); } }; if (c == InputHandled.class) { cc.itemNamePlural = () -> "Inputs Handled"; } if (c == Domain.class) { cc.fieldHelp("domainAndPath", "without http:// or https://", "botName", "Bot name for this domain (optional)", "headerColorLeft", "Hex color for left end of header gradient (optional)", "headerColorRight", "Hex color for right end of header gradient (optional)", "autoOpenBot", "Open the bot when page is loaded", "password", "A separate password for people who can see only this domain", "pageRegexp", "A Java-style regular expression that filters which page the bot is shown on"); cc.massageItemMapForList = (item, map) -> { map.put("domainAndPath", new HTML(b(htmlEncode2(((Domain) item).domainAndPath)))); map.put("password", new SecretValue(map.get("password"))); }; } if (c == BotOutgoingQuestion.class) { cc.dropEmptyListValues = false; cc.addRenderer("displayText", new HCRUD_Data.TextArea(80, 10)); cc.addRenderer("buttons", new HCRUD_Data.TextArea(80, 10, o -> lines_rtrim((List) o))); cc.fieldHelp("displayText", displayTextHelp(), "key", "Internal key for question (any format, can be empty, put \"-\" to disable storing answer)", "defaultValue", "What the input field is prefilled with", "placeholder", "A text the empty input field shows as a hint", "buttons", "Buttons to offer as standard answers (one per line, use | to add a shortened version submitted as user input)", "allowFreeText", "Can user enter free text in addition to clicking a button?", "multipleChoice", "Can user select multiple buttons?", "optional", "Can user skip the question by entering nothing?", "multipleChoiceSeparator", "Internal field, just leave as it is", "answerCheck", "Select this to validate user's answer against a pattern", "buttonActions", "Optional actions (one for each button in the list above)", "radioButtons", "Show buttons as radio buttons"); cc.addRenderer("answerCheck", new HCRUD_Data.ComboBox("", "email address", "phone number")); cc.massageItemMapForList = (item, map) -> { map.put("buttons", new HTML(ol_htmlEncode(((BotOutgoingQuestion) item).buttons))); map.put("buttonActions", new HTML(ul(map(((BotOutgoingQuestion) item).buttonActions, action -> ahref(conceptLink(action), htmlEncode2_nlToBr(str(action))))))); }; } if (c == UserKeyword.class) { cc.fieldHelp("language", "Language that this keyword matches in (optional)", "pattern", targetBlank("http://code.botcompany.de:8081/getraw.php?id=1030319", "'PhraseCache'") + " matching pattern (most important field)", "examples", "Example inputs that should be matched (one per line, optional)", "counterexamples", "Example inputs that should be NOT matched (one per line, optional)", "action", "What bot does when input is matched", "enabled", "Uncheck to disable this keyword", "priority", "If set, this keyword overrides other input handlers (e.g. from outgoing questions)", "precedence", "Precedence over other keywords (higher value = match first)"); for (String field : ll("examples", "counterexamples")) cc.addRenderer(field, new HCRUD_Data.TextArea(80, 5, o -> lines_rtrim((List) o))); cc.massageItemMapForList = (item, map) -> { map.put("examples", lines_rtrim(((UserKeyword) item).examples)); map.put("counterexamples", lines_rtrim(((UserKeyword) item).counterexamples)); }; } if (c == Settings.class) { cc.fieldHelp("mainDomainName", "Domain where bot is hosted (to correctly send image and sound links)", "botTypingDelay", "Delay in seconds before bot sends message, base value", "botTypingDelayPerWord", "Delay in seconds before bot sends message, per word", "botTypingMaxDelay", "Delay in seconds before bot sends message, max value", "preferredCountryCodes", "Country codes to display first in list (e.g. \"+1, +91\")", "notificationSound", "Bot message notification sound (can leave empty, then we use the " + ahref(defaultNotificationSound(), "default sound"), "talkToBotOnlyWithAuth", "Show bot only to authorized persons", "mailLeadsTo", "Where to send a mail when a new lead occurs (addresses separated by comma)", "leadMailSubject", "Subject for lead notification mails"); } if (c == Conversation.class) cc.massageItemMapForList = (item, map) -> { replaceMap(map, litorderedmap("id", map.get("id"), "IP", map.get("ip"), "started", formatLocalDateWithMinutes(((Conversation) item).created), "country", map.get("country"), "msgs", lines_rtrim(((Conversation) item).msgs), "avatar", map.get("avatar"), "answers", htmlEncode2(renderColonProperties(((Conversation) item).answers)), "stack", new HTML(ol(cloneMap(((Conversation) item).stack, activeSeq -> htmlEncode2(str(activeSeq))))))); }; if (c == BotMessage.class) { cc.addRenderer("text", new HCRUD_Data.TextArea(80, 10)); cc.addRenderer("specialPurpose", new HCRUD_Data.ComboBox(itemPlus("", keys(specialPurposes)))); cc.fieldHelp("text", displayTextHelp(), "specialPurpose", "Special occasion when to display this message", "disableInput", "Check to disable user input while this message is showing"); } if (c == Form.class) cc.massageItemMapForList = (item, map) -> { map.put("steps", pnlToStringWithEmptyLines_rtrim(((Form) item).steps)); }; if (c == Sequence.class) cc.massageItemMapForList = (item, map) -> { map.put("steps", new HTML(ol(map(((Sequence) item).steps, step -> ahref(conceptLink(step), htmlEncode2_nlToBr(str(step))))))); }; if (c == BotImage.class) cc.massageItemMapForList = (item, map) -> { String url = ((BotImage) item).imageURL(); if (isURL(url)) map.put("Image Preview", new HTML(himg(url, "style", hcrud_imagePreviewStyle()))); map.put(cc.fieldNameToHTML("imageURL"), new HTML(htmlEncode2(url) + " " + himgsnippet("#1101381", "onclick", "copyToClipboard(" + jsQuote(url) + "); " + "window.createNotification({ theme: 'success', showDuration: 3000 })({ message: " + jsQuote("Image URL copied to clipboard") + "});"))); }; if (c == UploadedImage.class) { cc.massageItemMapForList = (item, map) -> { String url = ((UploadedImage) item).imageURL(); File f = ((UploadedImage) item).imageFile(); map.put("Image Size", toK_str(fileSize(f))); if (fileSize(f) > 0) map.put("Image Preview (click for full-scale)", new HTML(targetBlank(url, himg(url, "style", hcrud_imagePreviewStyle())))); }; IVF2 massageItemMapForUpdate_old = cc.massageItemMapForUpdate; cc.massageItemMapForUpdate = (item, map) -> { cc.massageItemMapForUpdate_fallback(massageItemMapForUpdate_old, item, map); String base64 = (String) map.get("img_base64"); print("Got base64 data: " + l(base64)); if (nempty(base64)) { File f = ((UploadedImage) item).imageFile(); saveFileVerbose(f, base64decode(base64)); } map.remove("img_base64"); }; } if (c == UploadedSound.class) { cc.massageItemMapForList = (item, map) -> { String url = ((UploadedSound) item).soundURL(); File f = ((UploadedSound) item).soundFile(); map.put("Sound Size", toK_str(fileSize(f))); if (fileSize(f) > 0) map.put("Test Sound", new HTML(ahref(url, "Test Sound"))); }; IVF2 massageItemMapForUpdate_old = cc.massageItemMapForUpdate; cc.massageItemMapForUpdate = (item, map) -> { cc.massageItemMapForUpdate_fallback(massageItemMapForUpdate_old, item, map); String base64 = (String) map.get("file_base64"); print("Got base64 data: " + l(base64)); if (nempty(base64)) { File f = ((UploadedSound) item).soundFile(); saveFileVerbose(f, base64decode(base64)); } map.remove("file_base64"); }; } if (c == UploadedFile.class) { cc.fieldHelp("name", "Also used as file name when downloading", "mimeType", "Content type (MIME type) for this file (optional)", "liveURI", "URI to serve file under. No leading slash."); cc.massageItemMapForList = (item, map) -> { String url = ((UploadedFile) item).downloadURL(); File f = ((UploadedFile) item).theFile(); map.put("File Size", toK_str(fileSize(f))); if (fileSize(f) > 0) map.put("Download", new HTML(ahref(url, "Download"))); }; IVF2 massageItemMapForUpdate_old = cc.massageItemMapForUpdate; cc.massageItemMapForUpdate = (item, map) -> { cc.massageItemMapForUpdate_fallback(massageItemMapForUpdate_old, item, map); String base64 = (String) map.get("file_base64"); print("Got base64 data: " + l(base64)); if (nempty(base64)) { File f = ((UploadedFile) item).theFile(); saveFileVerbose(f, base64decode(base64)); } map.remove("file_base64"); }; } if (c == Worker.class) { cc.massageItemMapForList = (item, map) -> { AbstractBotImage image = ((Worker) item).image.get(); if (image != null) map.put("Image Preview", new HTML(himg(image.imageURL(), "style", hcrud_imagePreviewStyle()))); }; } if (c == Avatar.class) { cc.fieldHelp("shift", "hours when avatar is active, e.g. 8-18 (leave empty if always on shift, put 0-0 if never on shift)"); cc.massageItemMapForList = (item, map) -> { map.put("On Shift Now", ((Avatar) item).onShift()); }; } return cc; } public Map crudHelp() { return litmap(DeliveredDomain.class, "This list is filled by the bot with the domains it was delivered on. " + "Some may be bogus, we write down whatever the browser sends."); } public void saveDeliveredDomain(String domain) { if (empty(domain)) return; uniqCI(DeliveredDomain.class, "domain", beforeColonOrAll(domain)); } public void cleanConversations() { withDBLock(new Runnable() { public void run() { try { cdelete(filter(list(Conversation.class), c -> l(c.msgs) <= 1 && elapsedSeconds_timestamp(c.created) >= 60 && c.lastPing == 0)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cdelete(filter(list(Conversation), c -> l(c.msgs) <= 1\r\n && elapsedSec..."; } }); } public void deleteDeliveredDomains() { cdelete(DeliveredDomain.class); } public Object serveThoughts(Req req) { HTMLFramer1 framer = new HTMLFramer1(); framer.addInHead(hsansserif() + hmobilefix()); framer.add(div_floatRight(hbutton("Reload", "onclick", "location.reload()"))); framer.add(h2("Bot Thoughts")); if (req.conv == null) framer.add("No conversation"); else { framer.add(p("Conversation cookie: " + req.conv.cookie)); Conversation conv = req.conv; framer.add(h3("Stack")); framer.add(empty(conv.stack) ? p("empty") : ol(lmap(__75 -> htmlEncode2_gen(__75), reversed(conv.stack)))); } return framer.render(); } public Object serveSearch(Req req) { makeFramer(req); HTMLFramer1 framer = req.framer; framer.add("Search here"); return framer.render(); } transient public boolean debug = false; public Domain findDomainObj(String domain) { Domain domainObj = conceptWhereCI(Domain.class, "domainAndPath", domain); if (domainObj == null) domainObj = defaultDomain(); return domainObj; } public Domain defaultDomain() { return uniqCI(Domain.class, "domainAndPath", ""); } transient public int longPollTick = 200; transient public int longPollMaxWait = 1000 * 30; transient public int activeConversationSafetyMargin = 30000; transient public Set specialButtons = litciset("Cancel", "Back", "Abbrechen", "Zurück"); public String dbStats() { Collection all = list(Conversation.class); int nRealConvos = countPred(all, c -> l(c.msgs) > 1); return nConversations(nRealConvos); } public String realPW() { return loadTextFileOrCreateWithRandomID(realPWFile()); } public File realPWFile() { return secretProgramFile("password.txt"); } public String defaultRedirectAfterLogin() { return baseLink + "/"; } public String serveAuthForm() { return serveAuthForm(null); } public String serveAuthForm(String redirect) { redirect = dropParamFromURL(redirect, "logout"); if (empty(redirect)) redirect = defaultRedirectAfterLogin(); return hhtml(hhead(htitle(botName + ": Log-In") + hsansserif() + hmobilefix() + (useWebSockets ? webSocketHeadStuff() : "")) + hbody(hfullcenter(authFormHeading() + hpostform(hhidden("redirect", redirect) + tag("table", (enableUsers ? tr(td("User:") + td(hinputfield("user")) + td()) : "") + tr(td("Password:") + td(hpassword("pw")) + td(hsubmit("Log in")))), "action", baseLink + "/login") + (!showTalkToBotLink ? "" : p(ahref(baseLink + "/demo", "Talk to bot"))) + pUnlessEmpty(joinNemptiesWithSpace(!showRegisterLink ? "" : hbuttonLink(baseLink + "/register", "Register as new user"), !requestAuthed() ? "" : hbuttonLink(baseLink + "?logout=1", "Log out"))) + authFormMoreContent()))); } public String authFormHeading() { return h3_htmlEncode(adminName); } public String authFormMoreContent() { return ""; } public String leadsToCSV(Collection leads) { List fields = ciContentsIndexedList(); List rows = new ArrayList(); for (Lead lead : unnullForIteration(leads)) { List row = new ArrayList(); for (Map.Entry __22 : _entrySet(unnullForIteration(mapPlus_inFront((Map) (Map) lead.answers, "Date", formatLocalDateWithMinutes(lead.date.date), "Domain", lead.domain.get(), "Conversation ID", conceptID(lead.conversation.get()))))) { String key = __22.getKey(); Object val = __22.getValue(); int idx = fields.indexOf(key); if (idx < 0) idx = addAndReturnIndex(fields, key); listSet(row, idx, val, ""); } rows.add(row); } return formatCSVFileForExcel2(itemPlusList(fields, rows)); } public String countryCodeOptions(Conversation conv) { Collection countryCodes = putSetElementsFirst(keys(countryDialCodesMultiMap()), splitAtComma_trim(settings().preferredCountryCodes)); String selected = dialCodeStringForCountryCode(conv.country); return mapToLines(c -> { List cdc = countryDialCodesMultiMap().get(c); String text = nempty(cdc) ? c + " [" + joinWithComma(collectSorted("countryCode", cdc)) + "]" : c; return tag("option", text, "value", c, "selected", eq(c, selected) ? html_valueLessParam() : null); }, itemPlus("", countryCodes)); } public List addTypingDelays(List steps) { return concatMap(steps, step -> { double delay = step.preTypingDelay(); if (delay <= 0) return ll(step); return ll(new BotSendTyping(), new BotPause(delay), step); }); } public BotMessage messageForPurpose(String specialPurpose) { return conceptWhere(BotMessage.class, "specialPurpose", specialPurpose); } public Object serveLeadsAPI(Object req) { Map headers = (Map) (rcall("headers", req)); Map params = (Map) (get("params", req)); String tenantID = params.get("tenantID"); if (empty(tenantID)) return serveJSONError("Empty tenantID"); String pw = params.get("pw"); if (empty(pw)) pw = dropPrefix_trim("Bearer ", headers.get("Authorization")); if (empty(pw)) return serveJSONError("Empty password"); Domain domain = conceptWhere(Domain.class, "tenantID", tenantID); if (domain == null) return serveJSONError("Tenant ID not found"); if (neq(domain.password, pw)) return serveJSONError("Bad passsword"); Collection leads = conceptsWhere(Lead.class, "domain", domain); return serveJSON(map(leads, lead -> { Map map = litorderedmap("tenantID", tenantID, "leadID", lead.id, "domain", str(lead.domain), "date", formatLocalDateWithSeconds(lead.created), "data", lead.answers); return map; })); } public Object serveJSONError(String error) { return serveJSON(litorderedmap("error", error)); } public String botImageForDomain(Domain domainObj) { String botImg = imageSnippetURLOrEmptyGIF(chatHeaderImageID); if (domainObj != null && domainObj.botImage.has()) botImg = domainObj.botImage.get().imageURL(); else if (defaultDomain().botImage.has()) botImg = defaultDomain().botImage.get().imageURL(); return botImg; } public String simulateDomainLink(String domain) { return appendQueryToURL(baseLink + "/demo", "_botConfig", makePostData("domain", domain), "_newConvCookie", 1, "_autoOpenBot", 1); } public String simulateScriptLink(BotStep script) { return appendQueryToURL(baseLink + "/demo", "_botConfig", makePostData("mainScript", script.id), "_newConvCookie", 1, "_autoOpenBot", 1); } public Scorer consistencyCheckResults() { if (consistencyCheckResults == null) consistencyCheckResults = doConsistencyChecks(); return consistencyCheckResults; } public Scorer doConsistencyChecks() { Scorer scorer = scorerWithSuccessesAndErrors(); for (UserKeyword uk : list(UserKeyword.class)) try { localConsistencyCheck(uk, scorer); } catch (Throwable e) { scorer.addError(htmlEncode2(str(e))); } try { globalConsistencyCheck(scorer); } catch (Throwable e) { scorer.addError(htmlEncode2(str(e))); } return scorer; } public void localConsistencyCheck(UserKeyword uk, Scorer scorer) { String patHTML = span_title(str(uk.parsedPattern()), htmlEncode2(uk.pattern)); String item = "[Entry " + ahref(conceptLink(uk), uk.id) + "] "; for (String input : unnullForIteration(uk.examples)) { boolean ok = uk.matchWithTypos(input); scorer.add(ok, ok ? item + "Example OK: " + patHTML + " => " + htmlEncode2(quote(input)) : item + "Example doesn't match pattern: " + patHTML + " => " + htmlEncode2(quote(input))); } for (String input : unnullForIteration(uk.counterexamples)) { boolean ok = !uk.matchWithTypos(input); scorer.add(ok, ok ? item + "Counterexample OK: " + patHTML + " => " + htmlEncode2(quote(input)) : item + "Counterexample matches pattern: " + patHTML + " => " + htmlEncode2(quote(input))); } } public void globalConsistencyCheck(Scorer scorer) { List list = concatLists(enabledUserKeywordsForPriority(true), enabledUserKeywordsForPriority(false)); for (UserKeyword uk : list) for (String example : unnullForIteration(uk.examples)) { String item1 = ahref(conceptLink(uk), uk.id); UserKeyword found = firstThat(list, uk2 -> uk2.matchWithTypos(example)); if (found == null) continue; if (found == uk) scorer.addOK("[Entry " + item1 + "] Global check OK for input " + htmlEncode2(quote(example))); else { String item2 = ahref(conceptLink(found), found.id); String items = "[Entries " + item1 + " and " + item2 + "] "; scorer.addError(items + "Input " + htmlEncode2(quote(example)) + " shadowed by pattern: " + htmlEncode2(quote(found.pattern)) + ". Try reducing precedence value of entry " + item2 + " or increasing precedence value of entry " + item1); } } } static public Collection enabledUserKeywordsForPriority(boolean priority) { return sortByFieldDesc("precedence", conceptsWhere(UserKeyword.class, onlyNonNullParams("priority", priority))); } public boolean handleGeneralUserInput(Conversation conv, Msg msg, Boolean priority) { for (UserKeyword qa : enabledUserKeywordsForPriority(priority)) { if (qa.enabled && qa.matchWithTypos(msg.text)) { print("Matched pattern: " + qa.pattern + " / " + msg.text); conv.noteEvent(new EvtMatchedUserKeyword(qa, msg)); conv.callSubroutine(qa.action.get()); conv.scheduleNextStep(); return true; } } return false; } public void didntUnderstandUserInput(Conversation conv, Msg msg) { } transient public Settings settings_cache; public Settings settings() { if (settings_cache == null) settings_cache = settings_load(); return settings_cache; } public Settings settings_load() { Settings settings = conceptWhere(Settings.class); print("Got settings: " + settings); return settings; } public String displayTextHelp() { return "Text to show to user (can include HTML and " + targetBlank(baseLink + "/emojis", "emojis") + ")"; } public void botActions() { Lock __7 = lockWhileDoingBotActions ? dbLock() : null; lock(__7); try { while (licensed()) { ScheduledAction action = lowestConceptByField(ScheduledAction.class, "time"); if (action == null) break; if (action.time > now()) { doAfter(100, rstBotActions); break; } cdelete(action); print("Executing action " + action); try { action.run(); } catch (Throwable __e) { _handleException(__e); } } } finally { unlock(__7); } } public void addScheduledAction(ScheduledAction action) { addScheduledAction(action, 0); } public void addScheduledAction(ScheduledAction action, long delay) { action.time = now() + delay; registerConcept(action); rstBotActions.trigger(); } transient public ThreadLocal out = new ThreadLocal(); transient public ThreadLocal conv = new ThreadLocal(); transient public long lastConversationChange = now(); public void makeIndices() { indexConceptFieldDesc(ScheduledAction.class, "time"); indexConceptFieldCI(Domain.class, "domainAndPath"); indexConceptFieldCI(DeliveredDomain.class, "domain"); indexConceptFieldCI(CannedAnswer.class, "hashTag"); indexConceptFieldCI(Language.class, "languageName"); indexConceptField(Lead.class, "domain"); indexConceptField(ConversationFeedback.class, "domain"); indexConceptField(UploadedFile.class, "liveURI"); } public void startDB() { db(); } public void pWebChatBot() { db_mainConcepts().storeBaseClassesInStructure = storeBaseClassesInStructure || storeBaseClassesInStructure; startDB(); indexConceptFields(Conversation.class, "cookie", Conversation.class, "worker", Conversation.class, "lastPing", Worker.class, "loginName", AuthedDialogID.class, "cookie"); db_mainConcepts().miscMapPut(DynNewBot2.class, this); assertNotNull("settings 1", uniq(Settings.class)); indexSingletonConcept(Settings.class); assertNotNull("settings 2", uniq(Settings.class)); makeIndices(); indexAllLinkableClasses(); assertNotNull("settings 3", uniq(Settings.class)); uniq(BotSaveLead.class); uniq(BotSaveFeedback.class); uniq(BotClearStack.class); uniq(BotEndConversation.class); uniq(BotDoNothing.class); uniq(BotIdleMode.class); uniq(BotNewDialog.class); if (enableUndoStates) uniq(BotGoBack.class); if (enableAvatars) uniq(RandomAvatar.class); } public void addReplyToConvo(Conversation conv, IF0 think) { out.set(new Out()); String reply = ""; try { reply = think.get(); } catch (Throwable __e) { _handleException(__e); } Msg msg = new Msg(false, reply); msg.out = out.get(); conv.add(msg); } public Msg msgFromThinkFunction(IF0 think) { out.set(new Out()); String reply = ""; try { reply = think.get(); } catch (Throwable __e) { _handleException(__e); } Msg msg = new Msg(false, reply); msg.out = out.get(); return msg; } public Object withHeader(String html) { return withHeader(subBot_noCacheHeaders(subBot_serveHTML(html))); } public Object withHeader(Object response) { call(response, "addHeader", "Access-Control-Allow-Origin", "*"); return response; } public String renderMessageText(String text, boolean htmlEncode) { text = trim(text); if (eqic(text, "!rate conversation")) text = "Rate this conversation"; if (htmlEncode) text = htmlEncode2(text); text = nlToBr(text); return html_emojisToUnicode(text); } public void renderMessages(Conversation conv, StringBuilder buf, List msgs) { renderMessages(conv, buf, msgs, msg -> msg == last(msgs)); } public void renderMessages(Conversation conv, StringBuilder buf, List msgs, IF1 showButtons) { if (empty(msgs)) return; ChatRenderer renderer = makeChatRenderer(currentReq()); for (Msg m : msgs) { boolean showTheButtons = showButtons.get(m); if (m.fromUser || neqOneOf(m.text, "-", "") || showTheButtons && m.out != null && nempty(m.out.buttons)) renderer.appendMsg(conv, buf, m, showTheButtons); if (showTheButtons) { buf.append(hscript(botMod().phoneNumberSpecialInputField ? "$(\"#chat_telephone, .iti\").hide(); $(\"#chat_message\").show().prop('disabled', false).focus();" : "$(\"#chat_message\").prop('disabled', false).focus();")); if (m.out != null && nempty(m.out.javaScript)) buf.append(hscript(m.out.javaScript)); } } } abstract public class ChatRenderer { abstract public void appendMsg(Conversation conv, StringBuilder buf, Msg m, boolean showButtons); public Conversation conv; public String id; public Msg m; public String html; public String name; public String time; public String text; public boolean bot = false; public Worker fromWorker; public Out out; public List labels; public boolean useTrick = false; public String author; public String imgURL; public void prepare(Conversation conv, Msg m) { this.conv = conv; this.m = m; html = renderMessageText(m.text, shouldHtmlEncodeMsg(m)); name = m.fromUser ? defaultUserName() : botName; time = formatTime(m.time); text = html; modifyTextForRendering(); bot = !m.fromUser; fromWorker = m.fromWorker; out = m.out; labels = m.labels; useTrick = ariaLiveTrick; id = randomID(); author = fromWorker != null ? htmlEncode2(fromWorker.displayName) : botName; if (bot) { if (fromWorker != null && fileExists(workerImageFile(fromWorker.id))) imgURL = fullRawLink("worker-image/" + fromWorker.id); else imgURL = conv.botImg(); } } public void modifyTextForRendering() { if (eqic(text, "!back")) text = unicode_undoArrow(); } abstract public String renderMultipleChoice(List buttons, Collection selections, String multipleChoiceSeparator); public String renderSingleChoice(List buttons) { List out = new ArrayList(); for (int i = 0; i < l(buttons); i++) { String code = buttons.get(i); String text = replaceButtonText(code); String userInput = htmldecode_dropAllTags(text); List split = splitAtVerticalBar(text); if (l(split) == 2) { userInput = second(split); text = code = first(split); } out.add(hbuttonOnClick_returnFalse(text, "submitAMsg(" + jsQuote(userInput) + ")", "class", "chatbot-choice-button automated-message", "title", eq(code, text) ? null : code)); if (!specialButtons.contains(code) && i + 1 < l(buttons) && specialButtons.contains(buttons.get(i + 1))) out.add("  "); } return lines(out); } } public class ChatRendererSahilStyle extends ChatRenderer { public void appendMsg(Conversation conv, StringBuilder buf, Msg m, boolean showButtons) { prepare(conv, m); List div = new ArrayList(); List inMessage = new ArrayList(); List afterMessage = new ArrayList(); if (!bot) imgURL = "/pays5/imgs/icons/avatar.svg"; if (nempty(imgURL)) { div.add(div("", "class", "bg-img", "role", "img", "aria-labelledby", m.fromUser ? "Avatar" : "Bot", "style", "background-image: url('" + imgURL + "')")); } if (showButtons) appendButtons(inMessage, afterMessage, m.out); div.add(span(text + lines(inMessage), "class", "message")); div.add(span(time, "class", "message-timestamp")); buf.append(div(lines(div) + lines(afterMessage), "class", "message-wrapper" + stringUnless(bot, " user"))).append("\n"); } public void appendButtons(List inMessage, List afterMessage, Out out) { String placeholder = out == null ? "" : unnull(out.placeholder); String defaultInput = out == null ? "" : unnull(out.defaultInput); inMessage.add(hscript("chatBot_setInput(" + jsQuote(defaultInput) + ", " + jsQuote(placeholder) + ");")); if (out == null) return; List buttons = out.buttons; if (empty(buttons)) return; String buttonsHtml; if (out.multipleChoice) inMessage.add(span(renderMultipleChoice(buttons, text_multipleChoiceSplit(out.defaultInput, out.multipleChoiceSeparator), out.multipleChoiceSeparator), "class", "select-options")); else if (out.radioButtons) inMessage.add(span(renderRadioButtons(buttons, out.defaultInput), "class", "select-options")); else afterMessage.add(div(renderSingleChoice(buttons), "class", "automated-messages")); } public String renderMultipleChoice(List buttons, Collection selections, String multipleChoiceSeparator) { Set selectionSet = asCISet(selections); String rand = randomID(); String className = "chat_multiplechoice_" + rand; String allCheckboxes = "$(\"." + className + "\")"; if (eq(multipleChoiceSeparator, ",")) multipleChoiceSeparator += " "; return joinWithBR(map(buttons, name -> span(span("", "class", "square-box") + " " + name, "class", className + " option" + stringIf(contains(selectionSet, name), " selected"), "data-value", name))) + "
" + hbuttonOnClick_returnFalse("OK", "submitMsg()", "class", "btn btn-ok") + hscript(replaceDollarVars("\r\n $(\".$className *, .$className\").click(function(e) {\r\n e.stopImmediatePropagation(); // prevent double firing\r\n\r\n // toggle check box\r\n console.log(\"Target: \" + e.target);\r\n $(e.target).closest(\".option\").toggleClass(\"selected\");\r\n\r\n // update message\r\n var theList = $('.$className.selected').map(function() { return this.dataset.value; }).get();\r\n console.log('theList: ' + theList);\r\n $('#chat_message').val(theList.join($sep));\r\n });\r\n //$(\".$className *\").click(function(e) { e.stopPropagation(); });\r\n ", "className", className, "sep", jsQuote(multipleChoiceSeparator))); } public String renderRadioButtons(List buttons, String selection) { String rand = randomID(); String className = "chat_radio_" + rand; String allRadioButtons = "$(\"." + className + "\")"; return joinWithBR(map(buttons, name -> span(span("", "class", "square-box round") + " " + name, "class", className + " option" + stringIf(eqic(selection, name), " selected"), "data-value", name))) + (quickRadioButtons ? "" : "
" + hbuttonOnClick_returnFalse("OK", "submitMsg()", "class", "btn btn-ok")) + hscript(replaceDollarVars("\r\n $(\".$className *, .$className\").click(function(e) {\r\n e.stopImmediatePropagation(); // prevent double firing\r\n var option = $(e.target).closest(\".option\");\r\n \r\n // clear other radio buttons\r\n $(\".$className\").removeClass(\"selected\");\r\n\r\n // activate radio button\r\n option.addClass(\"selected\");\r\n\r\n // update message\r\n $('#chat_message').val(option[0].dataset.value);\r\n\r\n if ($quickRadioButtons)\r\n submitMsg();\r\n });\r\n //$(\".$className *\").click(function(e) { e.stopPropagation(); });\r\n ", "className", className, "quickRadioButtons", quickRadioButtons)); } } public class ChatRendererHusainStyle extends ChatRenderer { public void appendMsg(Conversation conv, StringBuilder buf, Msg m, boolean showButtons) { prepare(conv, m); String tag = useTrick ? "div" : "span"; if (bot) { if (nempty(m.text)) { if (fromWorker != null) buf.append("

" + author + "

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

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

=> " + (step2 == null ? "no action defined" : renderDialogTree(step2))); } return stepToHTMLFull(step) + ulIfNempty(children, "class", "dialogTree"); } } public String stepToHTMLFull(BotStep step) { if (step == null) return "-"; String link = conceptLink(step, currentReq()); return ahref_unstyled(link, prependSquareBracketed(step.id)) + ahref(link, htmlEncode2_nlToBr(step.fullToString())); } public String renderDialogTree(BotStep step) { return new RenderDialogTree().render(step); } public ChatRenderer makeChatRenderer(Req req) { String botLayout = req.params.get("botLayout"); String layout = or2(botLayout, defaultBotLayout()); return eqic(layout, "sahil") ? new ChatRendererSahilStyle() : new ChatRendererHusainStyle(); } public String defaultBotLayout() { return "husain"; } public boolean allowedTemplateID(String id) { return false; } public double typingDelayForText(String text) { double perWord = settings().botTypingDelayPerWord; double x = settings().botTypingDelay; if (perWord != 0) x += countWords(dropHTMLTags(text)) * settings().botTypingDelayPerWord; double max = settings().botTypingMaxDelay; if (max != 0) x = min(x, max); return x; } public String nameOfBotSide(Conversation conv) { String __9 = calcVar(conv, "botName"); if (!empty(__9)) return __9; return "Representative"; } public void addThingsAboveCRUDTable(Req req, Class c, List aboveTable) { } public boolean checkPhoneNumber(String s) { return isValidInternationalPhoneNumber(s); } public void onNewLead(Lead lead) { for (String address : splitAtComma_trim(settings().mailLeadsTo)) try { String text = formatColonProperties(lead.answers); sendMailThroughScript(mailSenderInfo, "auto@botcompany.de", address, settings().leadMailSubject, text); } catch (Throwable e) { printStackTrace(e); appendToFile(programFile("mail-errors"), getStackTrace(e)); } } public void doUndo(Conversation conv) { UndoState undoState = syncNextToLast(conv.undoStates); print("Undo state: " + undoState); if (undoState != null) { syncRemoveLast(2, conv.undoStates); conv.dropScheduledActions(); syncReplaceCollection(conv.stack, undoState.stack); print("Stack after undo: " + conv.stack); conv.scheduleNextStep(); } } public Collection cruddableClasses(Req req) { List classes = crudClasses(req); List cmdClasses = botCmdClasses(req); return flattenList2(classes, DeliveredDomain.class, cmdClasses); } public List botCmdClasses(Req req) { return req.masterAuthed ? botCmdClasses() : null; } public Object serveCRUD(Req req) { String uri = req.uri(); if (!uri.startsWith(crudBase())) return null; for (Class c : (Set) asSet(cruddableClasses(req))) if (eq(uri, dropUriPrefix(baseLink, crudLink(c)))) { HCRUD crud = makeCRUD(c, req); return serveCRUD(req, c, crud); } return null; } public Object serveCRUD(Req req, Class c, HCRUD crud) { HTMLFramer1 framer = req.framer; Map params = req.params(); String help = mapGet(crudHelp(), c); if (nempty(help)) framer.add(p(help)); String json = crud.handleComboSearch(params); if (nempty(json)) return serveText(json); List aboveTable = new ArrayList(); if (c == UserKeyword.class) { Scorer scorer = consistencyCheckResults(); framer.add(p("Consistency check results: " + nTests(scorer.successes) + " OK, " + nErrors(scorer.errors))); if (nempty(scorer.errors)) framer.add(ul(map(scorer.errors, e -> "Error: " + e))); } addThingsAboveCRUDTable(req, c, aboveTable); String baseTitle = framer.title; crud.makeFrame = (title, contents) -> { framer.title = joinNemptiesWithVBar(title, baseTitle); return h2(title) + lines(aboveTable) + contents; }; crud.processSortParameter(params); framer.add(crud.renderPage(params)); framer.add(hjs_markRowMagic()); return completeFrame(req); } public IF1, Collection> crudSearchFilter(Req req, HCRUD_Concepts data, String searchQuery) { if (empty(searchQuery)) return null; boolean debug = eq(req.get("searchDebug"), "1"); HTMLFramer1 framer = req.framer; return objects -> { ScoredSearcher searcher = new ScoredSearcher<>(searchQuery); if (debug) { if (framer != null) framer.add(hcomment(renderVars_struct("searcher", searcher))); } for (A a : unnullForIteration(objects)) { Map map = allConceptFieldsAsMap(a); List fields = allToString(values(map)); fields.add(str(a.id)); if (debug) { if (framer != null) framer.add(hcomment(renderVars_str("a", a, "fields", fields))); } double score = searcher.scoreFields(fields) + searcher.scoreFields(keys(map)) * 0.2; searcher.put(a, score); } return searcher.get(); }; } public boolean requestAuthed() { return currentReq() != null && currentReq().requestAuthed(); } public String webSocketHeadStuff() { return webSocketHeadStuff(currentReq()); } transient public IF1 webSocketHeadStuff; public String webSocketHeadStuff(Req req) { return webSocketHeadStuff != null ? webSocketHeadStuff.get(req) : webSocketHeadStuff_base(req); } final public String webSocketHeadStuff_fallback(IF1 _f, Req req) { return _f != null ? _f.get(req) : webSocketHeadStuff_base(req); } public String webSocketHeadStuff_base(Req req) { return hreconnectingWebSockets() + hjs("\r\n var webSocketQuery = window.location.search;\r\n var ws;\r\n var wsVerbose = true;\r\n var wsReady = false;\r\n \r\n function wsOnOpen(onOpen) {\r\n if (wsReady) onOpen();\r\n else {\r\n var old = ws.onopen;\r\n ws.onopen = function() {\r\n if (old) old();\r\n onOpen();\r\n };\r\n };\r\n }\r\n \r\n //$(document).ready(function() {\r\n var url = ((window.location.protocol === \"https:\") ? \"wss://\" : \"ws://\") + window.location.host + " + jsQuote(baseLink + req.uri()) + " + webSocketQuery;\r\n console.log(\"Opening WebSocket: \" + url);\r\n ws = new ReconnectingWebSocket(url);\r\n ws.onopen = function(event) {\r\n wsReady = true;\r\n console.log(\"WebSocket ready!\");\r\n ws.onmessage = " + js_evalOnWebSocketMessage() + ";\r\n };\r\n //});\r\n "); } public void fillReqAuthFromCookie(Req req, String cookie, AuthedDialogID auth) { req.auth = auth; boolean requestAuthed = auth != null; if (requestAuthed) cset(auth, "lastSeen", now()); req.masterAuthed = calcMasterAuthed(req); req.authDomainObj = !requestAuthed ? null : auth.restrictedToDomain.get(); req.authDomain = !requestAuthed ? null : auth.domain(); } transient public IF0>> renderStats; public List> renderStats() { return renderStats != null ? renderStats.get() : renderStats_base(); } final public List> renderStats_fallback(IF0>> _f) { return _f != null ? _f.get() : renderStats_base(); } public List> renderStats_base() { long us = db_mainConcepts().uncompressedSize; return ll(ll("Concepts", n2(conceptCount())), ll("DB size on disk", htmlEncode2(toK_str(fileSize(conceptsFile())))), us == 0 ? null : ll("DB size uncompressed", htmlEncode2(toK_str(us))), ll("DB load time", htmlEncode2(renderDBLoadTime())), ll("DB save time", htmlEncode2(renderDBSaveTime())), ll("Last saved", htmlEncode2(renderHowLongAgo(db_mainConcepts().lastSaveWas)))); } public Object serveBotDemo(Req req, String js) { return hhtml(hhead(htitle(heading) + loadJQuery2() + botDemoHeadStuff()) + hbody(hjavascript(js))); } public String botDemoHeadStuff() { return ""; } public Object handleLogout(Req req) { cdelete(req.auth); if (redirectOnLogout) return hrefresh(req.uri); return null; } } static public class ExecutedStep extends Concept { static final public String _fieldOrder = "step conversation msg"; public Ref step = new Ref(); public Ref conversation = new Ref(); public Msg msg; } static public class InputHandled extends Concept { static final public String _fieldOrder = "input conversation msg inputHandler handled"; public String input; public Ref conversation = new Ref(); public Msg msg; public Ref inputHandler = new Ref(); public boolean handled = false; } abstract static public class BotStep extends Concept { public String comment; public boolean run(Conversation conv) { return false; } public ScheduledAction nextStepAction(Conversation conv) { return new Action_NextStep(conv, conv.executedSteps); } public String fullToString() { return toString(); } public double preTypingDelay() { return 0; } public boolean isUndoBoundary() { return false; } } static public class Sequence extends BotStep { public RefL steps = new RefL(); public String toString() { return "Sequence " + quoteOr(comment, "(unnamed)") + spaceRoundBracketed(nSteps(steps)); } public boolean run(Conversation conv) { syncAdd(conv.stack, new ActiveSequence(this)); conv.change(); return true; } } static public class BotRandomAction extends BotStep { public RefL actions = new RefL(); public String toString() { return "Random Action " + appendBracketed(comment) + (empty(actions) ? " [empty]" : ": " + first(actions) + (l(actions) == 1 ? "" : " + " + n2(l(actions) - 1) + " more")); } public boolean run(Conversation conv) { BotStep step = random(actions); if (step == null) return true; return step.run(conv); } } static public class BotMessage extends BotStep { public String text; public String specialPurpose; public boolean disableInput = false; static public String _fieldOrder = "text specialPurpose"; public String toString() { return toString(40); } public String toString(int shorten) { return "Message" + spacePlusRoundBracketedIfNempty(comment) + ": " + newLinesToSpaces2(shorten(text, shorten)); } public String fullToString() { return toString(Integer.MAX_VALUE); } public boolean run(Conversation conv) { Msg msg = new Msg(false, text); msg.out = new Out(); msg.out.disableInput = disableInput; conv.add(msg); return true; } public double preTypingDelay() { return botMod().typingDelayForText(text); } } abstract static public class AbstractBotImage extends BotStep { public String altText; public boolean run(Conversation conv) { botMod().addReplyToConvo(conv, () -> himgsrc(imageURL(), "title", altText, "alt", altText, "class", "chat_contentImage")); return true; } abstract public String imageURL(); public double preTypingDelay() { return botMod().settings().botTypingDelay; } } static public class BotImage extends AbstractBotImage { public String imageURL, altText; static public String _fieldOrder = "imageURL"; public String imageURL() { return imageURL; } public String toString() { return "Image" + spacePlusRoundBracketedIfNempty(comment) + ": " + imageURL; } } static public class UploadedImage extends AbstractBotImage { public String imageURL() { return botMod().convertToAbsoluteURL(botMod().baseLink + "/uploaded-image/" + id); } public File imageFile() { return newFile(botMod().uploadedImagesDir(), id + ".png"); } public String toString() { return "Image" + spacePlusRoundBracketedIfNempty(altText) + spacePlusRoundBracketedIfNempty(comment); } public void delete() { if (concepts() == db_mainConcepts()) deleteFile(imageFile()); super.delete(); } public BufferedImage getImage() { return loadImage2(imageFile()); } } static public class UploadedSound extends Concept { public String comment; public String mimeType = mp3mimeType(); public String soundURL() { return botMod().convertToAbsoluteURL(botMod().baseLink + "/uploaded-sound/" + id); } public File soundFile() { return newFile(botMod().uploadedSoundsDir(), id + ".mp3"); } public String toString() { return "Sound" + spacePlusRoundBracketedIfNempty(comment); } public void delete() { if (concepts() == db_mainConcepts()) deleteFile(soundFile()); super.delete(); } } static public class UploadedFile extends Concept { static final public String _fieldOrder = "name comment mimeType liveURI"; public String name, comment, mimeType, liveURI; public String downloadURL() { return downloadURL(null); } public String downloadURL(String contentType) { return botMod().convertToAbsoluteURL(appendQueryToURL(botMod().baseLink + "/uploaded-file/" + id + (empty(name) ? "" : "/" + urlencode(name)), "ct", contentType)); } final public File getFile() { return theFile(); } public File theFile() { return newFile(botMod().uploadedFilesDir(), id + ".png"); } public String toString() { return "File " + spacePlusRoundBracketedIfNempty(name) + spacePlusRoundBracketedIfNempty(comment); } public void delete() { if (concepts() == db_mainConcepts()) deleteFile(theFile()); super.delete(); } } static public class BotDoNothing extends BotStep { public boolean run(Conversation conv) { return false; } public String toString() { return "Do nothing"; } } static public class BotSendTyping extends BotStep { public boolean run(Conversation conv) { conv.botTyping = print("Bot typing", now()); return true; } } static public class BotGoBack extends BotStep { public boolean run(Conversation conv) { botMod().doUndo(conv); return false; } public String toString() { return "Go back one step"; } } static public class BotNewDialog extends BotStep { public boolean run(Conversation conv) { conv.newDialog(); return false; } public String toString() { return "New dialog"; } } static public class BotPause extends BotStep { public double seconds; public BotPause() { } public BotPause(double seconds) { this.seconds = seconds; } public boolean run(Conversation conv) { botMod().addScheduledAction(nextStepAction(conv), toMS(seconds)); return false; } public String toString() { return "Pause for " + (seconds == 1 ? "1 second" : formatDouble(seconds, 1) + " seconds"); } } static public class BotOutgoingQuestion extends BotStep implements IInputHandler { public String displayText; public String key; public String defaultValue; public String placeholder; public List buttons; public boolean allowFreeText = true; public boolean multipleChoice = false; public boolean radioButtons = false; public String multipleChoiceSeparator = ", "; public boolean optional = false; public String answerCheck; public RefL buttonActions = new RefL(); static public String _fieldOrder = "displayText key defaultValue placeholder buttons buttonActions allowFreeText multipleChoice optional answerCheck"; public String toString() { return "Question: " + orEmptyQuotes(displayText); } public List> buttonsWithActions() { return zipTwoListsToPairs_longer(buttons, buttonActions); } public boolean run(Conversation conv) { String text = botMod().rewriteBotMessage(conv, displayText); Msg msg = new Msg(false, text); msg.out = makeMsgOut(); conv.add(msg); cset(conv, "inputHandler", this); return false; } public Out makeMsgOut() { Out out = new Out(); out.placeholder = or(placeholder, displayText); out.defaultInput = defaultValue; out.buttons = cloneList(buttons); out.multipleChoice = multipleChoice; out.multipleChoiceSeparator = multipleChoiceSeparator; out.radioButtons = radioButtons; if (eqic(answerCheck, "phone number") && botMod().phoneNumberSpecialInputField) out.javaScript = "$(\"#chat_message\").hide(); $(\"#chat_telephone, .iti\").show(); $(\"#chat_telephone\").val(\"\").focus();"; else if (!allowFreeText) { out.javaScript = jsDisableInputField(); if (empty(out.placeholder)) out.placeholder = " "; } return out; } public boolean handleInput(String s, Conversation conv) { print("BotOutgoingQuestion handleInput " + s); s = trim(s); String theKey = or2(key, htmldecode_dropAllTags(trim(displayText))); if (nempty(theKey) && !eq(theKey, "-")) syncPut(conv.answers, theKey, s); conv.change(); if (eqic(answerCheck, "email address") && !isValidEmailAddress_simple(s)) { handleValidationFail(conv, "bad email address"); return true; } if (eqic(answerCheck, "phone number") && !botMod().checkPhoneNumber(s)) { handleValidationFail(conv, "bad phone number"); return true; } conv.removeInputHandler(this); int idx = indexOfIC(trimAll(lmap(__76 -> dropStuffBeforeVerticalBar(__76), buttons)), s); print("Button index of " + quote(s) + " in " + sfu(buttons) + " => " + idx); BotStep target = get(buttonActions, idx); print("Button action: " + target); if (target != null) conv.callSubroutine(target); print("Scheduling next step in " + conv); conv.scheduleNextStep(); return true; } public double preTypingDelay() { return empty(displayText) ? 0 : botMod().typingDelayForText(displayText); } public void handleValidationFail(Conversation conv, String purpose) { BotMessage msg = botMod().messageForPurpose(purpose); String text = or2(or2(msg == null ? null : msg.text, getOrKeep(botMod().specialPurposes, purpose)), "Invalid input, please try again"); printVars_str("handleValidationFail", "purpose", purpose, "msg", msg, "text", text); Msg m = new Msg(); m.text = text; m.out = makeMsgOut(); conv.add(m); cset(conv, "inputHandler", this); return; } public boolean isUndoBoundary() { return true; } } static public class BotIdleMode extends BotStep { public String toString() { return "Idle Mode (wait indefinitely)"; } public boolean run(Conversation conv) { return false; } } static public class BotEndConversation extends BotStep { public String toString() { return "End Conversation (disable user input)"; } public boolean run(Conversation conv) { Msg msg = new Msg(false, ""); msg.out = new Out(); msg.out.javaScript = jsDisableInputField(); msg.out.placeholder = " "; conv.add(msg); return true; } } static public String jsDisableInputField() { return "$(\"#chat_message\").prop('disabled', true).attr('placeholder', '');"; } static public class BotSaveLead extends BotStep { public String toString() { return "Save Lead"; } public boolean run(Conversation conv) { Lead lead = cnew(Lead.class, "conversation", conv, "domain", conv.domainObj, "date", new Timestamp(now()), "answers", cloneMap(conv.answers)); botMod().onNewLead(lead); return true; } } static public class BotSaveFeedback extends BotStep { public String toString() { return "Save Conversation Feedback"; } public boolean run(Conversation conv) { cnew(ConversationFeedback.class, "conversation", conv, "domain", conv.domainObj, "date", new Timestamp(now()), "answers", filterKeys(conv.answers, swic$("Conversation Feedback:"))); return true; } } static public class BotClearStack extends BotStep { public boolean run(Conversation conv) { syncRemoveAllExceptLast(conv.stack); conv.change(); return true; } public String toString() { return "Clear Stack [forget all running procedures in conversation]"; } } static public class BotSwitchLanguage extends BotStep { public Ref language = new Ref(); public boolean run(Conversation conv) { cset(conv, "language", language); return true; } public String toString() { return "Switch to " + language; } } static public class UserKeyword extends Concept { static final public String _fieldOrder = "language pattern examples counterexamples action enabled priority precedence parsedPattern"; public Ref language = new Ref(); public String pattern; public List examples, counterexamples; public Ref action = new Ref(); public boolean enabled = true; public boolean priority = false; public int precedence; transient public MMOPattern parsedPattern; public void change() { parsedPattern = null; botMod().consistencyCheckResults = null; super.change(); } public MMOPattern parsedPattern() { if (parsedPattern == null) return parsedPattern = mmo2_parsePattern(pattern); return parsedPattern; } public String toString() { return "User Keyword: " + pattern; } public boolean matchWithTypos(String s) { return mmo2_matchWithTypos(parsedPattern(), s); } } static public class Language extends Concept { static final public String _fieldOrder = "languageName comment"; public String languageName; public String comment; public String toString() { return languageName + spaceRoundBracketed(comment); } } static public class Evt extends Concept { } static public class EvtMatchedUserKeyword extends Evt { static final public String _fieldOrder = "userKeyword msg"; public Ref userKeyword = new Ref(); public Msg msg; public EvtMatchedUserKeyword() { } public EvtMatchedUserKeyword(UserKeyword userKeyword, Msg msg) { this.userKeyword.set(userKeyword); this.msg = msg; } } static public class EvtJumpTo extends Evt { public Ref target = new Ref(); public EvtJumpTo() { } public EvtJumpTo(BotStep target) { this.target.set(target); } } static public class EvtCallSubroutine extends Evt { public Ref target = new Ref(); public EvtCallSubroutine() { } public EvtCallSubroutine(BotStep target) { this.target.set(target); } } abstract static public class AbstractAvatar extends Concept { abstract public Avatar getActualAvatar(); } static public class RandomAvatar extends AbstractAvatar { public Avatar getActualAvatar() { return random(filter(list(Avatar.class), a -> a.onShift())); } public String toString() { return "Choose a random avatar that is on shift"; } } static public class Avatar extends AbstractAvatar { static final public String _fieldOrder = "name comment shift image"; public String name, comment; public String shift; public Ref image = new Ref(); public Avatar getActualAvatar() { return this; } public boolean onShift() { List shifts = parseBusinessHours_pcall(shift); if (empty(shifts)) return true; shifts = splitBusinessHoursAtMidnight(shifts); int minute = minuteInDay(timeZone(botMod().timeZone)); return anyIntRangeContains(shifts, minute); } public String toString() { return empty(name) ? super.toString() : "Avatar " + name + appendBracketed(comment); } } static public class Out extends DynamicObject { public List buttons; public boolean multipleChoice, radioButtons; public String multipleChoiceSeparator; public String placeholder; public String defaultInput; public String javaScript; public boolean disableInput = false; } static public class Msg extends DynamicObject { public long time; public boolean fromUser = false; public Worker fromWorker; public String text; public Out out; public List labels; public Msg() { } public Msg(boolean fromUser, String text) { this.text = text; this.fromUser = fromUser; time = now(); } public Msg(String text, boolean fromUser) { this.fromUser = fromUser; this.text = text; time = now(); } public String toString() { return (fromUser ? "User" : "Bot") + ": " + text; } } static public class AuthedDialogID extends Concept { static final public String _fieldOrder = "cookie master restrictedToDomain loggedIn lastSeen"; public String cookie; public boolean master = false; public Ref restrictedToDomain = new Ref(); public Worker loggedIn; public long lastSeen; public String domain() { return !restrictedToDomain.has() ? null : restrictedToDomain.get().domainAndPath; } public Ref user = new Ref(); public boolean userMode = false; public User user() { return user.get(); } } static public class ActiveSequence { public Sequence originalSequence; public List steps; public int stepIndex; public ActiveSequence() { } public ActiveSequence(BotStep step) { if (step instanceof Sequence) { steps = cloneList(((Sequence) step).steps); originalSequence = (Sequence) step; } else steps = ll(step); steps = botMod().addTypingDelays(steps); } public boolean done() { return stepIndex >= l(steps); } public BotStep currentStep() { return get(steps, stepIndex); } public void nextStep() { ++stepIndex; } public String toString() { return (stepIndex >= l(steps) ? "DONE " : "Step " + (stepIndex + 1) + "/" + l(steps) + " of ") + (originalSequence != null ? str(originalSequence) : squareBracket(joinWithComma(steps))); } } static public class UndoState { public List stack; public UndoState() { } public UndoState(List stack) { this.stack = stack; } public String toString() { return "UndoState " + stack; } } static public class Conversation extends Concept { static final public String _fieldOrder = "cookie ip country domain domainObj oldDialogs msgs lastPing botOn notificationsOn worker userTyping botTyping testMode nextActionTime userMessageProcessed newDialogTriggered dryRun avatar stack undoStates executedSteps inputHandler language answers botConfig events reloadCounter"; public String cookie, ip, country, domain; public Ref domainObj = new Ref(); public List> oldDialogs = new ArrayList(); public List msgs = new ArrayList(); public long lastPing; public boolean botOn = true; public boolean notificationsOn = true; public Worker worker; transient volatile public long userTyping, botTyping; public boolean testMode = false; public long nextActionTime = Long.MAX_VALUE; public long userMessageProcessed; public int newDialogTriggered = -1; transient public boolean dryRun = false; public Ref avatar = new Ref(); public List stack = new ArrayList(); public List undoStates; public int executedSteps; public IInputHandler inputHandler; public Ref language = new Ref(); public Map answers = litcimap(); public Map botConfig; public RefL events = new RefL(); public int reloadCounter; public void add(Msg m) { m.text = trim(m.text); syncAdd(msgs, m); botMod().noteConversationChange(); change(); vmBus_send("chatBot_messageAdded", mc(), this, m); } public int allCount() { return archiveSize() + syncL(msgs); } public int archiveSize() { return syncLengthLevel2(oldDialogs) + syncL(oldDialogs); } public List allMsgs() { return concatLists_syncIndividual(syncListPlus(oldDialogs, msgs)); } public long lastMsgTime() { Msg m = last(msgs); return m == null ? 0 : m.time; } public void incReloadCounter() { cset(this, "reloadCounter", reloadCounter + 1); } public void turnBotOff() { cset(this, "botOn", false); botMod().noteConversationChange(); } public void turnBotOn() { cset(this, "botOn", true, "worker", null); String backMsg = botMod().getCannedAnswer("#botBack", this); if (empty(msgs) || lastMessageIsFromUser() || !eq(last(msgs).text, backMsg)) add(new Msg(backMsg, false)); botMod().noteConversationChange(); } public boolean lastMessageIsFromUser() { return nempty(msgs) && last(msgs).fromUser; } public void newDialog() { if (syncNempty(msgs)) syncAdd(oldDialogs, msgs); cset(this, "msgs", new ArrayList()); syncClear(answers); syncClear(stack); syncClear(undoStates); dropScheduledActions(); change(); print("newDialog " + archiveSize() + "/" + allCount()); vmBus_send("chatBot_clearedSession", mc(), this); } public void dropScheduledActions() { deleteConcepts(ScheduledActionOnConversation.class, "conv", this); } public void jumpTo(BotStep step) { syncPopLast(stack); print("Jumping to " + step); noteEvent(new EvtJumpTo(step)); if (step == null) return; syncAdd(stack, new ActiveSequence(step)); change(); } public void callSubroutine(BotStep step) { if (step == null) return; noteEvent(new EvtCallSubroutine(step)); print("Calling subroutine " + step); syncAdd(stack, new ActiveSequence(step)); change(); } public void removeInputHandler(IInputHandler h) { if (inputHandler == h) cset(this, "inputHandler", null); } public void scheduleNextStep() { botMod().addScheduledAction(new Action_NextStep(this)); } public void noteEvent(Concept event) { events.add(event); } public boolean isActive() { return lastPing + botMod().activeConversationTimeout() >= now(); } public String botImg() { if (avatar.has()) return avatar.get().image.get().imageURL(); else return botMod().botImageForDomain(domainObj.get()); } public void addUndoState() { UndoState state = new UndoState(syncShallowCloneElements(stack)); print("Made undo state: " + state); undoStates = syncAddOrCreate(undoStates, state); change(); } public Ref mirrorPost = new Ref(); public Ref detailedMirrorPost = new Ref(); public void change() { super.change(); ((DynGazelleRocks) botMod()).rstUpdateMirrorPosts.add(this); } public void updateMirrorPost() { if (isDeleted()) return; if (!mirrorPost.has() && syncNempty(msgs)) cset(Conversation.this, "mirrorPost", cnew(UserPost.class, "title", "Conversation " + id, "type", "Conversation Mirror", "creator", ((DynGazelleRocks) botMod()).internalUser(), "botInfo", "Conversation Mirror Bot")); cset(mirrorPost.get(), "text", lines_rtrim(msgs)); if (!detailedMirrorPost.has() && syncNempty(msgs)) cset(Conversation.this, "detailedMirrorPost", cnew(UserPost.class, "title", "Conversation " + id + " with details", "type", "Detailed Conversation Mirror", "creator", ((DynGazelleRocks) botMod()).internalUser(), "botInfo", "Conversation Mirror Bot")); cset(detailedMirrorPost.get(), "text", indentedStructure(msgs)); } public void delete() { cdelete(mirrorPost.get()); super.delete(); } } abstract static public class ScheduledAction extends Concept implements Runnable { public long time; } abstract static public class ScheduledActionOnConversation extends ScheduledAction { public Ref conv = new Ref(); } static public class Action_NextStep extends ScheduledActionOnConversation { public int executedSteps = -1; public Action_NextStep() { } public Action_NextStep(Conversation conv) { this.conv.set(conv); } public Action_NextStep(Conversation conv, int executedSteps) { this.conv.set(conv); this.executedSteps = executedSteps; } public void run() { nextStep(conv.get(), executedSteps); } } static public class OnNewDialog extends ScheduledActionOnConversation { public OnNewDialog() { } public OnNewDialog(Conversation conv) { this.conv.set(conv); } public void run() { botMod().startMainScript(conv.get()); } } static public void nextStep(Conversation conv) { nextStep(conv, -1); } static public void nextStep(Conversation conv, int expectedExecutedSteps) { if (expectedExecutedSteps >= 0 && conv.executedSteps != expectedExecutedSteps) return; while (licensed()) { if (empty(conv.stack)) return; ActiveSequence seq = syncLast(conv.stack); boolean done = seq.done(); printVars_str("Active sequence", "conv", conv, "seq", seq, "done", done, "stackSize", syncL(conv.stack)); if (done) { syncPopLast(conv.stack); continue; } BotStep step = seq.currentStep(); if (botMod().enableUndoStates && step.isUndoBoundary()) conv.addUndoState(); seq.nextStep(); ++conv.executedSteps; conv.change(); if (!executeStep(step, conv)) { print("Step returned false: " + step); break; } } } static public boolean executeStep(BotStep step, Conversation conv) { if (step == null || conv == null) return false; print("Executing step " + step + " in " + conv); ExecutedStep executed = null; if (botMod().recordExecutionsAndInputs) executed = cnew(ExecutedStep.class, "step", step, "conversation", conv); Msg lastMsg = syncLast(conv.msgs); boolean result = step.run(conv); Msg newMsg = syncLast(conv.msgs); if (newMsg != null && !newMsg.fromUser && newMsg != lastMsg) cset(executed, "msg", newMsg); return result; } static public class OnUserMessage extends ScheduledActionOnConversation { public OnUserMessage() { } public OnUserMessage(Conversation conv) { this.conv.set(conv); } public void run() { Conversation conv = this.conv.get(); Msg msg = syncLast(conv.msgs); if (msg == null || !msg.fromUser) return; print("OnUserMessage: " + msg); if (eqic(msg.text, "!back")) { botMod().doUndo(conv); return; } if (botMod().handleGeneralUserInput(conv, msg, true)) return; IInputHandler inputHandler = conv.inputHandler; if (inputHandler != null) { InputHandled rec = null; String input = msg.text; if (botMod().recordExecutionsAndInputs) rec = cnew(InputHandled.class, "inputHandler", inputHandler, "conversation", conv, "msg", msg, "input", input); boolean result = conv.inputHandler.handleInput(input, conv); cset(rec, "handled", result); if (result) return; } botMod().handleGeneralUserInput(conv, msg, false); } } static public class Domain extends Concept { public String domainAndPath; public String tenantID; public Ref botImage = new Ref(); public String botName; public Ref avatar = new Ref(); public String headerColorLeft, headerColorRight; public Boolean autoOpenBot; public Ref mainScript = new Ref(); public String password = aGlobalID(); static public String _fieldOrder = "domainAndPath botImage mainScript"; public String toString() { return domainAndPath; } } static public class Form extends Concept { public String name; public RefL steps = new RefL(); public String toString() { return name; } } static public class DeliveredDomain extends Concept { public String domain; } static public class CannedAnswer extends Concept { public String hashTag, text; } static public String text(CannedAnswer a) { return a == null ? null : a.text; } static public class Lead extends Concept { static final public String _fieldOrder = "domain conversation date answers"; public Ref domain = new Ref(); public Ref conversation = new Ref(); public Timestamp date; public Map answers; } static public class ConversationFeedback extends Concept { static final public String _fieldOrder = "domain conversation date answers"; public Ref domain = new Ref(); public Ref conversation = new Ref(); public Timestamp date; public Map answers; } static public class Settings extends Concept { static final public String _fieldOrder = "mainDomainName botTypingDelay botTypingDelayPerWord botTypingMaxDelay preferredCountryCodes multiLanguageMode notificationSound talkToBotOnlyWithAuth enableWorkerChat defaultLanguage mailLeadsTo leadMailSubject"; public String mainDomainName; public double botTypingDelay; public double botTypingDelayPerWord; public double botTypingMaxDelay; public String preferredCountryCodes; public boolean multiLanguageMode = false; public Ref notificationSound = new Ref(); public boolean talkToBotOnlyWithAuth = false; public boolean enableWorkerChat = false; public Ref defaultLanguage = new Ref(); public String mailLeadsTo; public String leadMailSubject = "A new lead occurred in your chat bot"; } static public interface IInputHandler { public boolean handleInput(String s, Conversation conv); } static public DynNewBot2 botMod() { return (DynNewBot2) dm_current_mandatory(); } static public class ShowComboBoxForm { public String desc; public String itemDesc; public List items; public String defaultValue; public IVF1 action; public JComboBox cb; public String selected() { return selectedItem(cb); } final public void show() { run(); } public void run() { cb = jComboBox(items, defaultValue); showFormTitled(desc, "", jlabel(desc), itemDesc, cb, runnableThread(new Runnable() { public void run() { try { String item = selected(); printVars("item", item, "action", action); if (nempty(item)) action.get(item); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String item = selected();\r\n printVars(+item, +action);\r\n if (ne..."; } })); } } static public class ReliableSingleThread_Multi { public IVF1 processObject; public int delay; public ReliableSingleThread_Multi(IVF1 processObject) { this.processObject = processObject; } public ReliableSingleThread_Multi(int delay, IVF1 processObject) { this.processObject = processObject; this.delay = delay; } public ReliableSingleThread_Multi(int delay, IVF1 processObject, F0 enter) { this.processObject = processObject; this.delay = delay; setEnter(enter); } public Set changedObjects = synchroSet(); public ReliableSingleThread rst = new ReliableSingleThread(new Runnable() { public void run() { try { process(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "process();"; } }); public void add(A a) { if (changedObjects.add(a)) rst.trigger(); } public void addAll(Iterable l) { for (A a : unnullForIteration(l)) { ping(); add(a); } } final public void process() { sleep(delay); for (A object : syncCloneAndClearList(changedObjects)) { ping(); pcallF(processObject, object); } } public void setEnter(F0 enter) { rst.enter = enter; } } static public interface IVar extends IF0 { public void set(A a); public A get(); default public boolean has() { return get() != null; } default public void clear() { set(null); } } static public class Pair implements Comparable> { public A a; public B b; public Pair() { } public Pair(A a, B b) { this.b = b; this.a = a; } public int hashCode() { return hashCodeFor(a) + 2 * hashCodeFor(b); } public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Pair)) return false; Pair t = (Pair) o; return eq(a, t.a) && eq(b, t.b); } public String toString() { return "<" + a + ", " + b + ">"; } public int compareTo(Pair p) { if (p == null) return 1; int i = ((Comparable) a).compareTo(p.a); if (i != 0) return i; return ((Comparable) b).compareTo(p.b); } } static public class CountryDialCode implements IFieldsToList { public String country; public String countryCode; public String dialCode; public CountryDialCode() { } public CountryDialCode(String country, String countryCode, String dialCode) { this.dialCode = dialCode; this.countryCode = countryCode; this.country = country; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + country + ", " + countryCode + ", " + dialCode + ")"; } public boolean equals(Object o) { if (!(o instanceof CountryDialCode)) return false; CountryDialCode __1 = (CountryDialCode) o; return eq(country, __1.country) && eq(countryCode, __1.countryCode) && eq(dialCode, __1.dialCode); } public int hashCode() { int h = 240284435; h = boostHashCombine(h, _hashCode(country)); h = boostHashCombine(h, _hashCode(countryCode)); h = boostHashCombine(h, _hashCode(dialCode)); return h; } public Object[] _fieldsToList() { return new Object[] { country, countryCode, dialCode }; } } static public class StringTree2 { public A leafValue; public HashMap> children = new HashMap(); public A get() { return leafValue; } public StringTree2 get(String s) { return children.get(s); } public StringTree2 getOrAdd(String s) { StringTree2 t = children.get(s); if (t == null) children.put(s, t = new StringTree2()); return t; } } static public interface IMeta { public void _setMeta(Object meta); public Object _getMeta(); default public IAutoCloseableF0 _tempMetaMutex() { return new IAutoCloseableF0() { public Object get() { return IMeta.this; } public void close() { } }; } } static public class ReliableSingleThread implements Runnable { public boolean _isTransient() { return true; } public Object runnable; public String name = "Single Thread"; public boolean cancelBeforeTrigger = false; public boolean waitBetweenCancelAndTrigger = false; public F0 enter; public int cancelTimeOut = 10000; public boolean trigger = false; public Thread thread; public WeakReference threadBeingCancelled; public List inserts = syncL(); public ReliableSingleThread(Object runnable) { this.runnable = runnable; } public void trigger() { go(); } synchronized public void go() { if (cancelBeforeTrigger) cancelAndPossiblyWait(); trigger = true; if (!running()) { AutoCloseable __1 = callF(enter); try { thread = startThread(name, new Runnable() { public void run() { try { AutoCloseable __2 = callF(enter); try { _run(); } finally { _close(__2); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp callF(enter);\r\n _run();"; } }); } finally { _close(__1); } } } public void run() { go(); } public void get() { go(); } synchronized public boolean running() { return thread != null; } public void triggerAndWait() { trigger(); waitUntilDone(); } public void waitUntilDone() { while (running()) sleep(1); } public void _run() { try { while (licensed()) { Thread oldThread; synchronized (this) { var currentInserts = syncGetAndClear(inserts); pcallFAll(currentInserts); if (!trigger) { thread = null; break; } oldThread = getWeakRef(threadBeingCancelled); trigger = false; } if (oldThread != null && oldThread != currentThread()) oldThread.join(cancelTimeOut); pcallF(runnable); } } catch (Exception __e) { throw rethrow(__e); } } synchronized public void cancel() { if (thread == null) return; threadBeingCancelled = new WeakReference(thread); cancelAndInterruptThread(thread); thread = null; } public void cancelAndWait() { Thread _thread; synchronized (this) { if (thread == null) return; _thread = thread; threadBeingCancelled = new WeakReference(thread); thread = null; } cancelAndInterruptThread(_thread); } public void cancelAndTrigger() { cancelAndPossiblyWait(); trigger(); } synchronized public boolean triggered() { return trigger; } public void cleanMeUp() { cancel(); } public ReliableSingleThread cancelBeforeTrigger() { cancelBeforeTrigger = true; return this; } public void cancelAndPossiblyWait() { if (waitBetweenCancelAndTrigger) cancel(); } public void insert(Runnable r) { inserts.add(r); trigger(); } } static public class Scorer { public double score, total; public List successes, errors; public boolean verboseFailures, verboseAll; final public void add(double score) { addZeroToOne(score); } public void addZeroToOne(double score) { ++total; this.score += clamp(score, 0, 1); } public void addZeroToOneError(double error) { addZeroToOne(1 - error); } public void addError() { add(false); } public void addError(A info) { add(false, info); } public void error(A info) { addError(info); } public void addOK() { add(true); } public void addOK(A info) { add(true, info); } public void ok() { addOK(); } public void ok(A info) { addOK(info); } public boolean add(boolean correct) { ++total; if (correct) ++score; return correct; } public boolean add(boolean correct, A info) { main.add(correct ? successes : errors, info); if (verboseAll || verboseFailures && !correct) _print((correct ? "[GOOD] " : "[BAD] ") + info); return add(correct); } public void eq(Object a, Object b) { if (_eq(a, b)) add(true); else add(false, (A) (a + " != " + b)); } public void print() { main.print(toString()); } public String toString() { return formatDouble(ratioToPercent(score, total), 1) + "% correct (n=" + formatDouble(total, 1) + ")"; } public double get() { return ratioToPercent(score, total); } public double percentScore() { return get(); } public double score() { return get(); } public boolean allCorrect() { return score == total; } public void add(Scorer scorer) { if (scorer == null) return; total += scorer.total; score += scorer.score; addAll(successes, scorer.successes); addAll(errors, scorer.errors); } public void collectErrors() { errors = new ArrayList(); } public void collectSuccesses() { successes = new ArrayList(); } } static public class MMOPattern { static public class Phrase extends MMOPattern implements IFieldsToList { public String phrase; public boolean quoted = false; public Phrase() { } public Phrase(String phrase, boolean quoted) { this.quoted = quoted; this.phrase = phrase; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + phrase + ", " + quoted + ")"; } public boolean equals(Object o) { if (!(o instanceof Phrase)) return false; Phrase __1 = (Phrase) o; return eq(phrase, __1.phrase) && eq(quoted, __1.quoted); } public int hashCode() { int h = -1905095975; h = boostHashCombine(h, _hashCode(phrase)); h = boostHashCombine(h, _hashCode(quoted)); return h; } public Object[] _fieldsToList() { return new Object[] { phrase, quoted }; } } static public class And extends MMOPattern implements IFieldsToList { public List l; public And() { } public And(List l) { this.l = l; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + l + ")"; } public boolean equals(Object o) { if (!(o instanceof And)) return false; And __2 = (And) o; return eq(l, __2.l); } public int hashCode() { int h = 65975; h = boostHashCombine(h, _hashCode(l)); return h; } public Object[] _fieldsToList() { return new Object[] { l }; } } static public class Or extends MMOPattern implements IFieldsToList { public List l; public Or() { } public Or(List l) { this.l = l; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + l + ")"; } public boolean equals(Object o) { if (!(o instanceof Or)) return false; Or __3 = (Or) o; return eq(l, __3.l); } public int hashCode() { int h = 2563; h = boostHashCombine(h, _hashCode(l)); return h; } public Object[] _fieldsToList() { return new Object[] { l }; } } static public class Not extends MMOPattern implements IFieldsToList { public MMOPattern p; public Not() { } public Not(MMOPattern p) { this.p = p; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + p + ")"; } public boolean equals(Object o) { if (!(o instanceof Not)) return false; Not __4 = (Not) o; return eq(p, __4.p); } public int hashCode() { int h = 78515; h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] { p }; } } static public class Weighted extends MMOPattern implements IFieldsToList { static final public String _fieldOrder = "weight p"; public double weight; public MMOPattern p; public Weighted() { } public Weighted(double weight, MMOPattern p) { this.p = p; this.weight = weight; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + weight + ", " + p + ")"; } public boolean equals(Object o) { if (!(o instanceof Weighted)) return false; Weighted __5 = (Weighted) o; return weight == __5.weight && eq(p, __5.p); } public int hashCode() { int h = -446368457; h = boostHashCombine(h, _hashCode(weight)); h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] { weight, p }; } } static public class StartOfLine extends MMOPattern implements IFieldsToList { public MMOPattern p; public StartOfLine() { } public StartOfLine(MMOPattern p) { this.p = p; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + p + ")"; } public boolean equals(Object o) { if (!(o instanceof StartOfLine)) return false; StartOfLine __6 = (StartOfLine) o; return eq(p, __6.p); } public int hashCode() { int h = -326863539; h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] { p }; } } static public class EndOfLine extends MMOPattern implements IFieldsToList { public MMOPattern p; public EndOfLine() { } public EndOfLine(MMOPattern p) { this.p = p; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + p + ")"; } public boolean equals(Object o) { if (!(o instanceof EndOfLine)) return false; EndOfLine __7 = (EndOfLine) o; return eq(p, __7.p); } public int hashCode() { int h = -810372346; h = boostHashCombine(h, _hashCode(p)); return h; } public Object[] _fieldsToList() { return new Object[] { p }; } } } static public class ConceptsRefChecker { public Concepts cc; public List errors = new ArrayList(); public boolean veryVerbose = false; static public class Err { } static public class ErrNoBackRef extends Err implements IFieldsToList { static final public String _fieldOrder = "ref dest"; public Concept.Ref ref; public Concept dest; public ErrNoBackRef() { } public ErrNoBackRef(Concept.Ref ref, Concept dest) { this.dest = dest; this.ref = ref; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + ref + ", " + dest + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrNoBackRef)) return false; ErrNoBackRef __1 = (ErrNoBackRef) o; return eq(ref, __1.ref) && eq(dest, __1.dest); } public int hashCode() { int h = -1351603866; h = boostHashCombine(h, _hashCode(ref)); h = boostHashCombine(h, _hashCode(dest)); return h; } public Object[] _fieldsToList() { return new Object[] { ref, dest }; } } static public class ErrSuperfluousBackRef extends Err implements IFieldsToList { static final public String _fieldOrder = "ref dest"; public Concept.Ref ref; public Concept dest; public ErrSuperfluousBackRef() { } public ErrSuperfluousBackRef(Concept.Ref ref, Concept dest) { this.dest = dest; this.ref = ref; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + ref + ", " + dest + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrSuperfluousBackRef)) return false; ErrSuperfluousBackRef __2 = (ErrSuperfluousBackRef) o; return eq(ref, __2.ref) && eq(dest, __2.dest); } public int hashCode() { int h = 1840777816; h = boostHashCombine(h, _hashCode(ref)); h = boostHashCombine(h, _hashCode(dest)); return h; } public Object[] _fieldsToList() { return new Object[] { ref, dest }; } } static public class ErrDuplicateRef extends Err implements IFieldsToList { public Concept c; public ErrDuplicateRef() { } public ErrDuplicateRef(Concept c) { this.c = c; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrDuplicateRef)) return false; ErrDuplicateRef __3 = (ErrDuplicateRef) o; return eq(c, __3.c); } public int hashCode() { int h = 1148352877; h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { c }; } } static public class ErrNullRef extends Err implements IFieldsToList { public Concept c; public ErrNullRef() { } public ErrNullRef(Concept c) { this.c = c; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrNullRef)) return false; ErrNullRef __4 = (ErrNullRef) o; return eq(c, __4.c); } public int hashCode() { int h = 209467527; h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { c }; } } static public class ErrMissingRef extends Err implements IFieldsToList { public Concept c; public Concept.Ref ref; public ErrMissingRef() { } public ErrMissingRef(Concept c, Concept.Ref ref) { this.ref = ref; this.c = c; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + c + ", " + ref + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrMissingRef)) return false; ErrMissingRef __5 = (ErrMissingRef) o; return eq(c, __5.c) && eq(ref, __5.ref); } public int hashCode() { int h = 1969969266; h = boostHashCombine(h, _hashCode(c)); h = boostHashCombine(h, _hashCode(ref)); return h; } public Object[] _fieldsToList() { return new Object[] { c, ref }; } } static public class ErrSuperfluousRef extends Err implements IFieldsToList { public Concept c; public Concept.Ref ref; public ErrSuperfluousRef() { } public ErrSuperfluousRef(Concept c, Concept.Ref ref) { this.ref = ref; this.c = c; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + c + ", " + ref + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrSuperfluousRef)) return false; ErrSuperfluousRef __6 = (ErrSuperfluousRef) o; return eq(c, __6.c) && eq(ref, __6.ref); } public int hashCode() { int h = 762378943; h = boostHashCombine(h, _hashCode(c)); h = boostHashCombine(h, _hashCode(ref)); return h; } public Object[] _fieldsToList() { return new Object[] { c, ref }; } } static public class ErrDanglingSource extends Err implements IFieldsToList { static final public String _fieldOrder = "ref dest"; public Concept.Ref ref; public Concept dest; public ErrDanglingSource() { } public ErrDanglingSource(Concept.Ref ref, Concept dest) { this.dest = dest; this.ref = ref; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + ref + ", " + dest + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrDanglingSource)) return false; ErrDanglingSource __7 = (ErrDanglingSource) o; return eq(ref, __7.ref) && eq(dest, __7.dest); } public int hashCode() { int h = 666937292; h = boostHashCombine(h, _hashCode(ref)); h = boostHashCombine(h, _hashCode(dest)); return h; } public Object[] _fieldsToList() { return new Object[] { ref, dest }; } } static public class ErrDanglingDestination extends Err implements IFieldsToList { static final public String _fieldOrder = "ref dest"; public Concept.Ref ref; public Concept dest; public ErrDanglingDestination() { } public ErrDanglingDestination(Concept.Ref ref, Concept dest) { this.dest = dest; this.ref = ref; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + ref + ", " + dest + ")"; } public boolean equals(Object o) { if (!(o instanceof ErrDanglingDestination)) return false; ErrDanglingDestination __8 = (ErrDanglingDestination) o; return eq(ref, __8.ref) && eq(dest, __8.dest); } public int hashCode() { int h = -1158731011; h = boostHashCombine(h, _hashCode(ref)); h = boostHashCombine(h, _hashCode(dest)); return h; } public Object[] _fieldsToList() { return new Object[] { ref, dest }; } } public ConceptsRefChecker() { } public ConceptsRefChecker(Concepts cc) { this.cc = cc; } public List run() { errors.clear(); if (cc == null) return errors; Collection concepts = cc.allConcepts(); if (veryVerbose) print("Checking " + nConcepts(concepts)); for (Concept c : concepts) try { Object badElement = firstElementNotSubclassing(c.backRefs, Concept.Ref.class); if (badElement != null) { print("Bad element in backRefs of " + c + ": " + badElement); continue; } for (Concept.Ref ref : cloneList(c.backRefs)) { if (ref.get() != c) errors.add(new ErrSuperfluousBackRef(ref, c)); if (ref.concept()._concepts != cc) errors.add(new ErrDanglingSource(ref, c)); } Collection refs = c._refs(); badElement = firstElementNotSubclassing(refs, Concept.Ref.class); if (badElement != null) { print("Bad element in backRefs of " + c + ": " + badElement); continue; } if (!allUnique(refs)) errors.add(new ErrDuplicateRef(c)); if (contains(refs, null)) errors.add(new ErrNullRef(c)); refs = nonNulls(refs); Collection actualRefs = scanConceptForRefs(c); for (Concept.Ref ref : listMinusSet(refs, actualRefs)) errors.add(new ErrSuperfluousRef(c, ref)); for (Concept.Ref ref : listMinusSet(actualRefs, refs)) errors.add(new ErrMissingRef(c, ref)); for (Concept.Ref ref : refs) if (ref.has()) { if (!contains(ref.get().backRefs, ref)) errors.add(new ErrNoBackRef(ref, c)); if (ref.get()._concepts != cc) errors.add(new ErrDanglingDestination(ref, c)); } } catch (Throwable e) { _handleException(e); print("Error processing concept " + c); } return errors; } public List errors() { return errors; } public String fixAll() { List out = new ArrayList(); for (Err err : reversed(cloneAndClear(errors))) { try { out.add("Processing " + err); if (err instanceof ErrNoBackRef) { ((ErrNoBackRef) err).ref.index(); out.add(" reference added"); } else if (err instanceof ErrSuperfluousRef) { ((ErrSuperfluousRef) err).ref.unindexAndDrop(); out.add(" reference dropped"); } else if (err instanceof ErrDanglingSource) { ((ErrDanglingSource) err).ref.get()._removeBackRef(((ErrDanglingSource) err).ref); out.add(" reference removed from destination"); } else if (err instanceof ErrDanglingDestination) { ((ErrDanglingDestination) err).ref.get()._removeBackRef(((ErrDanglingDestination) err).ref); out.add(" reference removed from destination"); } else if (err instanceof ErrMissingRef) { ((ErrMissingRef) err).ref.registerRef(); out.add(" reference registered"); } else if (err instanceof ErrSuperfluousBackRef) { ((ErrSuperfluousBackRef) err).dest._removeBackRef(((ErrSuperfluousBackRef) err).ref); out.add(" backreference dropped"); } else out.add(" TODO - fix not implemented"); } catch (Throwable __e) { _handleException(__e); } } return lines(out); } public String runAndFixAll() { run(); return fixAll(); } } static public class Timestamp implements Comparable, IFieldsToList { public long date; public Timestamp(long date) { this.date = date; } public boolean equals(Object o) { if (!(o instanceof Timestamp)) return false; Timestamp __1 = (Timestamp) o; return date == __1.date; } public int hashCode() { int h = 2059094262; h = boostHashCombine(h, _hashCode(date)); return h; } public Object[] _fieldsToList() { return new Object[] { date }; } public Timestamp() { date = now(); } public String toString() { return formatLocalDateWithSeconds(date); } public int compareTo(Timestamp t) { return t == null ? 1 : cmp(date, t.date); } } abstract static public class DynPrintLogAndEnabled extends DynPrintLog { public JComponent visualize() { return dm_visualizeWithEnabled(super.visualize()); } volatile public boolean enabled = true; transient public JPanel buttons; transient public SingleComponentPanel scpStretcherControl; public JComponent visualizeWithoutEnabled() { return super.visualize(); } public JComponent dm_visualizeWithEnabled(JComponent main) { return centerAndSouthWithMargins(main, wrapControlArea()); } public JComponent wrapControlArea() { return makeControlArea(); } public JPanel makeControlArea() { if (scpStretcherControl == null) scpStretcherControl = singleComponentPanel(); buttons = jrightalignedline(makeEnabledCheckBox()); return centerAndEastWithMargin(scpStretcherControl, buttons); } static public JCheckBox makeEnabledCheckBox() { return dm_fieldCheckBox("enabled"); } public void setEnabled(boolean b) { setField("enabled", b); } final public void addControls(Component... components) { addToControlArea(components); } public void addToControlArea(Component... components) { addComponentsFirst(buttons, components); } final public void addControl(Component component) { addButton(component); } public void addButton(Component component) { addComponentsFirst(buttons, component); } public void setMainControl(JComponent control) { scpSet(scpStretcherControl, control); } } static public class ScoredSearcher { public int maxResults = 1000; public List preparedTerms; public Map scores = new HashMap(); public ScoredSearcher() { } public ScoredSearcher(String query, Object... __) { maxResults = optPar("maxResults", __, maxResults); setQuery(query); } public void setQuery(String query) { preparedTerms = scoredSearch_prepare(query); } public void put(A object, String s) { putUnlessZero(scores, object, scoredSearch_score(s, preparedTerms)); } public void put(A object, Collection fields) { add(object, scoreFields(fields)); } public void putWithWeights(A object, Collection> fields) { scoredSearch_scoreWeighted2(fields, preparedTerms); } public int scoreFields(Collection fields) { return scoredSearch_score(fields, preparedTerms); } public int score(String text) { return scoredSearch_score(text, preparedTerms); } public void add(A object) { put(object, str(object)); } public void add(A object, Collection fields) { put(object, fields); } public void put(A object, double score) { add(object, score); } public void add(A object, double score) { putUnlessZero(scores, object, score); } public List get() { return takeFirst(maxResults, keysSortedByValuesDesc(scores)); } public List> withScores() { return map(get(), a -> scoredWithMapValue(scores, a)); } public A best() { return keyWithHighestValue(scores); } } static public class Not implements IFieldsToList, Transformable, Visitable { public A a; public Not() { } public Not(A a) { this.a = a; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + a + ")"; } public boolean equals(Object o) { if (!(o instanceof Not)) return false; Not __0 = (Not) o; return eq(a, __0.a); } public int hashCode() { int h = 78515; h = boostHashCombine(h, _hashCode(a)); return h; } public Object[] _fieldsToList() { return new Object[] { a }; } public Object transformUsing(IF1 f) { return new Not((A) f.get(a)); } public void visitUsing(IVF1 f) { f.get(a); } public Boolean get(Object o) { return not((Boolean) callF(a, o)); } } static public class And implements IFieldsToList, Transformable, Visitable { public A a; public A b; public And() { } public And(A a, A b) { this.b = b; this.a = a; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + a + ", " + b + ")"; } public boolean equals(Object o) { if (!(o instanceof And)) return false; And __0 = (And) o; return eq(a, __0.a) && eq(b, __0.b); } public int hashCode() { int h = 65975; h = boostHashCombine(h, _hashCode(a)); h = boostHashCombine(h, _hashCode(b)); return h; } public Object[] _fieldsToList() { return new Object[] { a, b }; } public Object transformUsing(IF1 f) { return new And((A) f.get(a), (A) f.get(b)); } public void visitUsing(IVF1 f) { f.get(a); f.get(b); } } static public interface IAutoCloseableF0 extends IF0, AutoCloseable { } static public class Scored extends Var { public float score; public Scored() { } public Scored(A a, float score) { super(a); this.score = score; } public Scored(A a, double score) { super(a); this.score = (float) score; } public float score() { return score; } public String toString() { return toIntPercent(score) + "%: " + str(get()); } } static public interface Visitable { public void visitUsing(IVF1 f); } static public interface Transformable { public Object transformUsing(IF1 f); } static public boolean isAbstract(Class c) { return (c.getModifiers() & Modifier.ABSTRACT) != 0; } static public boolean isAbstract(Method m) { return (m.getModifiers() & Modifier.ABSTRACT) != 0; } static public boolean reflection_isForbiddenMethod(Method m) { return m.getDeclaringClass() == Object.class && eqOneOf(m.getName(), "finalize", "clone", "registerNatives"); } static public void multiMapPut(Map> map, A a, B b) { List l = map.get(a); if (l == null) map.put(a, l = new ArrayList()); l.add(b); } static public void multiMapPut(MultiMap mm, A key, B value) { if (mm != null && key != null && value != null) mm.put(key, value); } static public Field makeAccessible(Field f) { try { f.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, f); } return f; } static public Method makeAccessible(Method m) { try { m.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, m); } return m; } static public Constructor makeAccessible(Constructor c) { try { c.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, c); } return c; } static public Set allInterfacesImplementedBy(Class c) { if (c == null) return null; HashSet set = new HashSet(); allInterfacesImplementedBy_find(c, set); return set; } static public void allInterfacesImplementedBy_find(Class c, Set set) { if (c.isInterface() && !set.add(c)) return; do { for (Class intf : c.getInterfaces()) allInterfacesImplementedBy_find(intf, set); } while ((c = c.getSuperclass()) != null); } static public Method findMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args); } static public boolean findMethod_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static public boolean call_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) print("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) { Object arg = args[i]; if (!(arg == null ? !types[i].isPrimitive() : isInstanceX(types[i], arg))) { if (debug) print("Bad parameter " + i + ": " + arg + " vs " + types[i]); return false; } } return true; } static public Method findStaticMethod(Class c, String method, Object... args) { Class _c = c; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (!m.getName().equals(method)) continue; if ((m.getModifiers() & Modifier.STATIC) == 0 || !findStaticMethod_checkArgs(m, args)) continue; return m; } c = c.getSuperclass(); } return null; } static public boolean findStaticMethod_checkArgs(Method m, Object[] args) { Class[] types = m.getParameterTypes(); if (types.length != args.length) return false; for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) return false; return true; } static public File programSecretFile(String progID, String fileName) { return secretProgramFile(progID, fileName); } static public File programSecretFile(String fileName) { return secretProgramFile(fileName); } static public boolean fileExists(String path) { return path != null && new File(path).exists(); } static public boolean fileExists(File f) { return f != null && f.exists(); } static public String loadTextFile(String fileName) { return loadTextFile(fileName, null); } static public String loadTextFile(File f, String defaultContents) { return loadTextFile(f, defaultContents, "UTF-8"); } static public String loadTextFile(File f, String defaultContents, String encoding) { try { checkFileNotTooBigToRead(f); if (f == null || !f.exists()) return defaultContents; FileInputStream fileInputStream = new FileInputStream(f); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, encoding); return loadTextFile(inputStreamReader); } catch (Exception __e) { throw rethrow(__e); } } public static String loadTextFile(File fileName) { return loadTextFile(fileName, null); } static public String loadTextFile(String fileName, String defaultContents) { return fileName == null ? defaultContents : loadTextFile(newFile(fileName), defaultContents); } static public String loadTextFile(Reader reader) throws IOException { StringBuilder builder = new StringBuilder(); try { char[] buffer = new char[1024]; int n; while (-1 != (n = reader.read(buffer))) builder.append(buffer, 0, n); } finally { reader.close(); } return str(builder); } static public File javaxSecretDir_dir; static public File javaxSecretDir() { return javaxSecretDir_dir != null ? javaxSecretDir_dir : new File(userHome(), "JavaX-Secret"); } static public File javaxSecretDir(String sub) { return newFile(javaxSecretDir(), sub); } static public String loadTextFileOrCreateWithRandomID(File f) { String id = trim(loadTextFile(f)); if (empty(id)) saveTextFile(f, id = aGlobalID()); return id; } static public SecretValue aSecretGlobalID() { return secretValueOrNull(aGlobalID()); } static public boolean syncNempty(Collection l) { return !syncEmpty(l); } static public Concept cnew(String name, Object... values) { return cnew(db_mainConcepts(), name, values); } static public Concept cnew(Concepts concepts, String name, Object... values) { Class cc = findClass(name); concepts_unlisted.set(true); Concept c; try { c = cc != null ? nuObject(cc) : new Concept(name); } finally { concepts_unlisted.set(null); } csetAll(c, values); concepts.register(c); return c; } static public A cnew(Class cc, Object... values) { return cnew(db_mainConcepts(), cc, values); } static public A cnew(Concepts concepts, Class cc, Object... values) { concepts_unlisted.set(true); A c; try { c = nuObject(cc); } finally { concepts_unlisted.set(null); } csetAll(c, values); concepts.register(c); return c; } static public String lines_rtrim(Collection lines) { return rtrim_fromLines(lines); } static public String indentedStructure(Object o) { return indentStructureString(struct(o)); } static public List cdelete(Class c, Object... params) { return deleteConcepts(c, params); } static public void cdelete(Concept c) { deleteConcept(c); } static public void cdelete(Collection c) { for (A a : cloneList(c)) cdelete(a); } static public int shorten_default = 100; static public String shorten(CharSequence s) { return shorten(s, shorten_default); } static public String shorten(CharSequence s, int max) { return shorten(s, max, "..."); } static public String shorten(CharSequence s, int max, String shortener) { if (s == null) return ""; if (max < 0) return str(s); return s.length() <= max ? str(s) : subCharSequence(s, 0, min(s.length(), max - l(shortener))) + shortener; } static public String shorten(int max, CharSequence s) { return shorten(s, max); } static public String escapeNewLines(String s) { return s == null ? null : fixNewLines(s).replace("\n", " | "); } static public List> zipTwoListsToPairs_lengthOfFirst(List l1, List l2) { int n = l(l1); List> out = emptyList(n); for (int i = 0; i < n; i++) addPair(out, l1.get(i), get(l2, i)); return out; } static public List pairsAWhereB(Iterable> c, IF1 pred) { return pairsA(filter(c, p -> pred.get(p.b))); } static public boolean eqic_unnull(String a, String b) { return eqic(unnull(a), unnull(b)); } static public A optCast(Class c, Object o) { return isInstance(c, o) ? (A) o : null; } static public long now_virtualTime; static public long now() { return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis(); } static public List syncInstancesOf(Iterable i, Class c) { if (i == null) return new ArrayList(); synchronized (i) { return collectInstances(i, c); } } static public List syncInstancesOf(Class c, Iterable i) { return syncInstancesOf(i, c); } static public boolean eqicOrSwicPlusSpace(String a, String b) { return swic(a, b) && (l(a) == l(b) || a.charAt(l(b)) == ' '); } static public String gazelleFavIconSnippet() { return "#1400504"; } static public String dm_require(String moduleLibID) { return dm_makeModule(moduleLibID); } static public AutoCloseable dm_vmBus_onMessage(final String msg, final VF1 onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static public AutoCloseable dm_vmBus_onMessage(final String msg, final IVF1 onMessage) { return dm_ownResource(vmBus_onMessage(msg, ivf1ToVF1(onMessage))); } static public AutoCloseable dm_vmBus_onMessage(final String msg, final IVF2 onMessage) { return dm_ownResource(vmBus_onMessage(msg, ivf2ToVF2(onMessage))); } static public AutoCloseable dm_vmBus_onMessage(String msg, final VF2 onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static public AutoCloseable dm_vmBus_onMessage(String msg, Runnable onMessage) { return dm_ownResource(vmBus_onMessage(msg, onMessage)); } static public double systemLoad() { double load = osMXBean().getSystemLoadAverage(); if (load < 0) return systemCPULoad(); return load; } static public ConceptFieldIndexCI indexConceptFieldCI(Class c, String field) { return indexConceptFieldCI(db_mainConcepts(), c, field); } static public ConceptFieldIndexCI indexConceptFieldCI(Concepts concepts, Class c, String field) { ConceptFieldIndexCI idx = getConceptFieldCIIndex(concepts, c, field); return idx != null ? idx : new ConceptFieldIndexCI(concepts, c, field); } static public void indexConceptFieldDesc(Class c, String field) { indexConceptFieldDesc(db_mainConcepts(), c, field); } static public void indexConceptFieldDesc(Concepts concepts, Class c, String field) { if (!isConceptFieldIndexed(concepts, c, field)) new ConceptFieldIndexDesc(concepts, c, field); } static public void printConceptIndices() { printConceptIndices(db_mainConcepts()); } static public void printConceptIndices(Concepts cc) { if (cc == null) return; Set> classes = joinSets(keys(cc.fieldIndices), keys(cc.ciFieldIndices)); print(n2(classes, "indexed class", "indexed classes") + "."); for (Class c : classes) { print("Indices on " + c + ":"); for (Map.Entry __1 : _entrySet(cc.fieldIndices.get(c))) { String field = __1.getKey(); IFieldIndex idx = __1.getValue(); print(" " + field + ": " + idx); } for (Map.Entry __0 : _entrySet(cc.ciFieldIndices.get(c))) { String field = __0.getKey(); IFieldIndex idx = __0.getValue(); print(" " + field + " [case-insensitive]: " + idx); } } } static public void onConceptsChange(Runnable r) { onConceptsChange(db_mainConcepts(), r); } static public void onConceptsChange(Concepts cc, Runnable r) { cc.addConceptIndex(simpleConceptIndex(r)); cc.onAllChanged.add(r); } static public int countConcepts(Concepts concepts, Class c, Object... params) { return concepts.countConcepts(c, params); } static public int countConcepts(Class c, Object... params) { return db_mainConcepts().countConcepts(c, params); } static public int countConcepts() { return db_mainConcepts().countConcepts(); } static public int countConcepts(String className) { return db_mainConcepts().countConcepts(className); } static public int countConcepts(Concepts concepts, String className) { return concepts.countConcepts(className); } static public int countConcepts(Concepts concepts) { return concepts.countConcepts(); } static public void _close(AutoCloseable c) { if (c != null) try { c.close(); } catch (Throwable e) { if (c instanceof javax.imageio.stream.ImageOutputStream) return; else throw rethrow(e); } } static public Set syncLinkedHashSet() { return synchroLinkedHashSet(); } static public List syncMap(Object f, Map map) { return syncMap(map, f); } static public List syncMap(Map map, Object f) { return map(cloneLinkedHashMap(map), f); } static public Map syncMap() { return synchroHashMap(); } static public Map syncMap(Map map) { return synchronizedMap(map); } static public WeakReference weakRef(A a) { return newWeakReference(a); } static public void setFieldToIVF1Proxy(Object o, String field, IVF1 target) { setFieldToSingleMethodProxy(o, field, target, "get"); } static public String rcall_string(String method, Object o, Object... args) { return (String) rcall(method, o, args); } static public void pcallFAll(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) pcallF(f, args); } static public void pcallFAll(Iterator it, Object... args) { while (it.hasNext()) pcallF(it.next(), args); } static volatile public PersistableThrowable _handleException_lastException; static public List _handleException_onException = synchroList(ll((IVF1) (__1 -> printStackTrace2(__1)))); static public boolean _handleException_showThreadCancellations = false; static public void _handleException(Throwable e) { _handleException_lastException = persistableThrowable(e); Throwable e2 = innerException(e); if (e2.getClass() == RuntimeException.class && eq(e2.getMessage(), "Thread cancelled.") || e2 instanceof InterruptedException) { if (_handleException_showThreadCancellations) System.out.println(getStackTrace_noRecord(e2)); return; } for (Object f : cloneList(_handleException_onException)) try { callF(f, e); } catch (Throwable e3) { try { printStackTrace2(e3); } catch (Throwable e4) { System.out.println(getStackTrace(e3)); System.out.println(getStackTrace(e4)); } } } static public B mapGet(Map map, A a) { return map == null || a == null ? null : map.get(a); } static public B mapGet(A a, Map map) { return map == null || a == null ? null : map.get(a); } static public Object eval(String text, Collection callableFunctions) { return new Eval(callableFunctions).eval(text); } static public Object eval(String text) { return new Eval().eval(text); } static public Set eval_standardsafefunctions = lithashset("bigint", "compareTo"); static public class Eval { public Collection callableFunctions; public boolean allowReadingStaticFields = false; public HashMap variables = new HashMap(); public List tok; public Object _null = new Object(); public Eval(Collection callableFunctions) { this.callableFunctions = callableFunctions; } public Eval() { callableFunctions = eval_standardsafefunctions; } public void setVar(String id, Object value) { variables.put(id, or(value, _null)); } public Object eval(String text) { tok = javaTok(text); List e = jparse(text, "exp"); return evalExp(e); } public Object evalExp(List e) { String cl = getString(e, 2); if (eq(cl, "quoted")) return unquote(get(tok, (int) get(e, 0))); if (eq(cl, "identifier")) { String id = get(tok, (int) get(e, 0)); Object val = variables.get(id); if (val != null) return val == _null ? null : val; if (allowReadingStaticFields) return get(getMainClass(), id); else throw fail("Unknown variable: " + id); } if (eq(cl, "call")) { return evalCall(e, getMainClass()); } if (eq(cl, "methodcall")) { List e_exp = (List) (get(e, 4)); List e_call = (List) (get(e, 5)); Object obj = evalExp(e_exp); return evalCall(e_call, obj); } throw fail("woot exp: " + structure(e)); } public Object evalCall(List e, Object obj) { List e_name = (List) (get(e, 4)); List e_args = (List) (get(e, 5)); String fname = get(tok, (int) get(e_name, 0)); List args = evalArgs(e_args); return callMethod(obj, fname, args); } public List evalArgs(List e) { return litlist(evalExp(e)); } public Object callMethod(Object obj, String fname, List args) { boolean mayCall = mayCallFunction(fname); if (!hasMethodNamed(obj, fname)) throw fail("Method not defined in " + getClassName(obj) + (mayCall ? "" : ", also not callable") + ": " + fname); if (!mayCallFunction(fname)) throw fail("Not allowed to call method: " + fname); return call(obj, fname, toObjectArray(args)); } public boolean mayCallFunction(String fname) { return callableFunctions.contains(fname); } } static public String jsDollarVars(String s, Object... __) { return replaceDollarVars_js(s, __); } static public Object dm_call(Object moduleOrID, String method, Object... args) { Object mod = dm_getModule(moduleOrID); if (mod == null) return null; AutoCloseable __1 = dm_enter(mod); try { return call_withVarargs(mod, method, args); } finally { _close(__1); } } static public String jsonEncode(Object o) { StringBuilder buf = new StringBuilder(); jsonEncode(o, buf); return str(buf); } static public void jsonEncode(Object o, StringBuilder buf) { if (o == null) buf.append("null"); else if (o instanceof String) buf.append(quote((String) o)); else if (o instanceof Number || o instanceof Boolean) buf.append(o); else if (o instanceof Map) { Map map = (Map) o; buf.append("{"); boolean first = true; for (Object key : keys(map)) { if (first) first = false; else buf.append(","); buf.append(quote((String) key)); buf.append(":"); jsonEncode(map.get(key), buf); } buf.append("}"); } else if (o instanceof Collection) { Collection l = (Collection) o; buf.append("["); boolean first = true; for (Object element : l) { if (first) first = false; else buf.append(","); jsonEncode(element, buf); } buf.append("]"); } else throw fail("Unknown object for JSON encoding: " + className(o)); } static public AutoCloseable tempAdd(final Collection l, final A a) { if (l == null || l.contains(a)) return null; l.add(a); return new AutoCloseable() { public String toString() { return "l.remove(a);"; } public void close() throws Exception { l.remove(a); } }; } static public boolean cleanUp_interruptThreads = false; static public void cleanUp(Object c) { if (c == null) return; if (c instanceof AutoCloseable) { close_pcall((AutoCloseable) c); return; } if (c instanceof java.util.Timer) { ((java.util.Timer) c).cancel(); return; } if (c instanceof Collection) { cleanUp((Collection) c); return; } if (c instanceof Map) { for (Object o : keys((Map) c)) cleanUp(o); for (Object o : values((Map) c)) cleanUp(o); ((Map) c).clear(); return; } try { preCleanUp(c); setOpt(c, "ping_pauseAll", false); innerCleanUp(c); List androids = (List) getOpt(c, "record_list"); for (Object android : unnull(androids)) pcallOpt(android, "dispose"); List classes = (List) (getOpt(c, "hotwire_classes")); if (classes != null) for (WeakReference cc : classes) { try { cleanUp(cc.get()); } catch (Throwable __e) { _handleException(__e); } } if (cleanUp_interruptThreads) { List threads = registeredThreads(c); if (nempty(threads)) { print("cleanUp: Interrupting " + n2(threads, "thread") + ": " + joinWithComma(allToString(threads))); interruptThreads(threads); } } } catch (Throwable __e) { _handleException(__e); } setOpt(c, "cleaningUp_flag", false); if (c instanceof Class && ((Class) c).getName().equals("main")) retireClassLoader(((Class) c).getClassLoader()); } static public void cleanUp(Collection l) { if (l == null) return; for (Object c : l) cleanUp(c); l.clear(); } static public Map syncWeakHashMap() { return newWeakHashMap(); } static public void closeAllKeysAndClear(Map map) { closeAllAndClear(keys(map)); } static public A set(A o, String field, Object value) { if (o == null) return null; if (o instanceof Class) set((Class) o, field, value); else try { Field f = set_findField(o.getClass(), field); makeAccessible(f); smartSet(f, o, value); } catch (Exception e) { throw new RuntimeException(e); } return o; } static public void set(Class c, String field, Object value) { if (c == null) return; try { Field f = set_findStaticField(c, field); makeAccessible(f); smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static public Field set_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static public Field set_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } static public void set(BitSet bs, int idx) { { if (bs != null) bs.set(idx); } } static public Object rcall(String method, Object o, Object... args) { return call_withVarargs(o, method, args); } static volatile public StringBuffer local_log = new StringBuffer(); static volatile public Appendable print_log = local_log; static volatile public int print_log_max = 1024 * 1024; static volatile public int local_log_max = 100 * 1024; static public boolean print_silent = false; static public Object print_byThread_lock = new Object(); static volatile public ThreadLocal print_byThread; static volatile public Object print_allThreads; static volatile public Object print_preprocess; static public void print() { print(""); } static public A print(String s, A o) { print(combinePrintParameters(s, o)); return o; } static public A print(A o) { ping_okInCleanUp(); if (print_silent) return o; String s = o + "\n"; print_noNewLine(s); return o; } static public void print_noNewLine(String s) { try { Object f = getThreadLocal(print_byThread_dontCreate()); if (f == null) f = print_allThreads; if (f != null) if (isFalse(f instanceof F1 ? ((F1) f).get(s) : callF(f, s))) return; } catch (Throwable e) { System.out.println(getStackTrace(e)); } print_raw(s); } static public void print_raw(String s) { if (print_preprocess != null) s = (String) callF(print_preprocess, s); s = fixNewLines(s); Appendable loc = local_log; Appendable buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); System.out.print(s); vmBus_send("printed", mc(), s); } static public void print_autoRotate() { } static public A proxy(Class intrface, final Object target) { if (target == null) return null; if (isInstance(intrface, target)) return (A) target; return (A) java.lang.reflect.Proxy.newProxyInstance(intrface.getClassLoader(), new Class[] { intrface }, new proxy_InvocationHandler(target)); } static public A proxy(Object target, Class intrface) { return proxy(intrface, target); } static public AutoCloseable tempSetTL(ThreadLocal tl, A a) { return tempSetThreadLocal(tl, a); } static public AutoCloseable tempSetTL(x30_pkg.x30_util.BetterThreadLocal tl, A a) { return tempSetThreadLocalIfNecessary(tl, a); } static public long toLong(Object o) { if (o instanceof Number) return ((Number) o).longValue(); if (o instanceof String) return parseLong((String) o); return 0; } static public A getConceptOpt(Class cc, long id) { return getConceptOpt(db_mainConcepts(), cc, id); } static public A getConceptOpt(Concepts concepts, Class cc, long id) { return concepts == null ? null : optCast(cc, concepts.getConcept(id)); } static public Map jsonDecodeMap(String s) { Object o = jsonDecode(s); if (o instanceof List && empty((List) o)) return new HashMap(); if (o instanceof Map) return (Map) o; else throw fail("Not a JSON map: " + s); } static public boolean syncAdd(Collection c, A b) { if (c == null) return false; synchronized (collectionMutex(c)) { return c.add(b); } } static public void syncAdd(List l, int idx, A b) { if (l != null) synchronized (collectionMutex(l)) { l.add(idx, b); } } static public Pair pair(A a, B b) { return new Pair(a, b); } static public Pair pair(A a) { return new Pair(a, a); } static public String trim(String s) { return s == null ? null : s.trim(); } static public String trim(StringBuilder buf) { return buf.toString().trim(); } static public String trim(StringBuffer buf) { return buf.toString().trim(); } static public String dropParamFromURL(String url, String key) { Map params = paramsFromURL(url); if (!containsKey(params, key)) return url; params.remove(key); return addAnchorToURL(appendParamsToURL(urlWithoutQueryAndAnchor(url), params), anchorFromURL(url)); } static public Lock dbLock() { return db_mainConcepts().lock; } static public Lock dbLock(Concepts cc) { return cc == null ? null : cc.lock; } static public Lock dbLock(Concept c) { return dbLock(c == null ? null : c._concepts); } static public 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); } } catch (Exception __e) { throw rethrow(__e); } } static public void lock(Lock lock, String msg) { print("Locking: " + msg); lock(lock); } static public void lock(Lock lock, String msg, long timeout) { print("Locking: " + msg); lockOrFail(lock, timeout); } static public ReentrantLock lock() { return fairLock(); } static public boolean hasConceptIC(Class c, Object... params) { return hasConceptWhereIC(c, params); } static public boolean hasConceptIC(Concepts cc, Class c, Object... params) { return hasConceptWhereIC(cc, c, params); } static public boolean regexpContainsIC(String pat, String s) { return regexpFindsIC(pat, s); } static public 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 public void vmBus_send(String msg) { vmBus_send(msg, (Object) null); } static public String hrefresh(String target) { return hrefresh(0, target); } static public String hrefresh(double seconds) { return hrefresh(seconds, ""); } static public String hrefresh(double seconds, String target) { return tag("meta", "", "http-equiv", "refresh", "content", iceil(seconds) + (nempty(target) ? "; url=" + target : "")); } static public void unlock(Lock lock, String msg) { if (lock == null) return; lock.unlock(); vmBus_send("unlocked", lock, "thread", currentThread()); print("Unlocked: " + msg); } static public void unlock(Lock lock) { if (lock == null) return; lock.unlock(); vmBus_send("unlocked", lock, "thread", currentThread()); } static public String hhtml(Object contents) { return containerTag("html", contents); } static public String hhead(Object contents) { return tag("head", contents); } static public String htitle(String title) { return hfulltag("title", htmlencode_noQuotes(title)); } static public String hsansserif() { return hcss("body { font-family: Sans-Serif; }"); } static public String hmobilefix() { return ""; } static public String hmobilefix(String html) { return hAddToHead(html, hmobilefix()); } static public String hresponstable() { return hcss_responstable(); } static public String hbody(Object contents, Object... params) { return tag("body", contents, params); } static public String hfullcenter(Object contents, Object... __) { return tag("table", tr(td(contents, "align", "center")), paramsPlus(__, "width", "100%", "height", "100%")); } static public String h3_htmlEncode(Object contents, Object... params) { return h3(htmlEncode2(str(contents)), params); } static public String hpostform(Object contents, Object... params) { return tag("form", contents, concatArrays(new Object[] { "method", "POST" }, params)); } static public String hhidden(String name, Object value, Object... params) { return tag("input", "", concatArrays(new Object[] { "type", "hidden", "name", name, "value", value }, params)); } static public String hhidden(Map map, String... keys) { return hiddenFields(map, keys); } static public String tr(Object contents) { return tag("tr", contents); } static public String td(Object contents, Object... params) { return hfulltag("td", contents, params); } static public String td() { return td(""); } static public String htmlEncode2_nlToBr(String s) { return htmlEncode_nlToBr(s); } static public String td_valignTop(Object contents, Object... params) { return tdTop(contents, params); } static public String hinputfield(String name, Object... params) { return htextinput(name, params); } static public String hpassword(String name, Object... params) { return hpasswordfield(name, params); } static public String hpassword(String name) { return hpasswordfield(name); } static public String hsubmit(String text, Object... params) { return tag("input", "", concatArrays(new Object[] { "type", "submit", "value", text }, params)); } static public String hsubmit() { return hsubmit("Submit"); } static public boolean swic(String a, String b) { return startsWithIgnoreCase(a, b); } static public boolean swic(String a, String b, Matches m) { if (!swic(a, b)) return false; m.m = new String[] { substring(a, l(b)) }; return true; } static public Object serve404() { return subBot_serve404(); } static public Object serve404(String msg) { return subBot_serve404(msg); } static public Object serveWithContentType(String text, String contentType) { return serveByteArray(toUtf8(text), contentType); } static public Object serveText(Object s) { return call(getMainBot(), "serveByteArray", toUtf8(str(s)), "text/plain; charset=utf8"); } static public Object addHeader(String header, String value, Object response) { call(response, "addHeader", header, value); return response; } static public Object serveJSON(Object... data) { return serveJSON_shallowLineBreaks(jsonPrepareData(data)); } static public List lmap(IF1 f, Iterable l) { return lambdaMap(f, l); } static public List lmap(IF1 f, A[] l) { return lambdaMap(f, l); } static public long conceptID(Concept c) { return c == null ? 0 : c.id; } static public long conceptID(Concept.Ref ref) { return conceptID(cDeref(ref)); } static public LinkedHashMap litorderedmap(Object... x) { LinkedHashMap map = new LinkedHashMap(); litmap_impl(map, x); return map; } static public String dropSlashPrefix(String s) { return dropLeadingSlash(s); } static public String hjs(String script) { return hjs(script, (Object[]) null); } static public String hjs(String script, Object... __) { return hjavascript(script, __); } static public String hjs(JS script) { return hjs(script, (Object[]) null); } static public String hjs(JS script, Object... __) { return hjavascript(script == null ? null : script.get(), __); } static public String jsQuote(String s) { return javascriptQuote(s); } static public String or2(String a, String b) { return nempty(a) ? a : b; } static public String or2(String a, String b, String c) { return or2(or2(a, b), c); } static public String p(Object contents, Object... params) { return hfulltag("p", contents, params) + "\n"; } static public String p() { return p(""); } static public String renderConceptDate(Concept cc) { if (cc == null) return ""; String c = formatLocalDateWithSeconds(cc.created); String m = formatLocalDateWithSeconds(cc._modified); String s = "Created " + c; if (neq(c, m)) s += ", modified " + m; return s; } static public String targetBlank(String link, Object contents, Object... params) { return hrefBlank(link, contents, params); } static public boolean eqicOneOf(String s, String... l) { for (String x : l) if (eqic(s, x)) return true; return false; } static public String p_vbar(String... items) { return p_vbar(asList(items)); } static public String p_vbar(Collection items, Object... __) { return pUnlessEmpty(joinNemptiesWithVBar(items), __); } static public ArrayList cloneList(Iterable l) { return l instanceof Collection ? cloneList((Collection) l) : asList(l); } static public ArrayList cloneList(Collection l) { if (l == null) return new ArrayList(); synchronized (collectionMutex(l)) { return new ArrayList(l); } } static public String ul(String... list) { return ul(asList(list)); } static public String ul(Collection list, Object... params) { StringBuilder buf = new StringBuilder(); int i = indexOf(params, null); if (i == -1) i = l(params); for (Object s : withoutNulls(list)) buf.append(tag("li", s, subArray(params, i + 1))).append("\n"); return containerTag("ul", buf, subArray(params, 0, i)) + "\n"; } static public List mapPairsToList(Iterable> l, F2 f) { List x = emptyList(l); if (l != null) for (Pair p : l) x.add(callF(f, p.a, p.b)); return x; } static public List mapPairsToList(Iterable> l, IF2 f) { List x = emptyList(l); if (l != null) for (Pair p : l) x.add(f.get(p.a, p.b)); return x; } static public List mapPairsToList(Object f, Iterable> l) { List x = emptyList(l); if (l != null) for (Pair p : l) x.add(callF(f, p.a, p.b)); return x; } static public String html_showLineFeedsForPRE(String html) { return replace(html, "\n", unicode_newLineArrow() + "\n"); } static public String div(Object contents, Object... params) { return hfulltag("div", contents, params); } static public String div() { return div(""); } static public BigInteger div(BigInteger a, BigInteger b) { return a.divide(b); } static public BigInteger div(BigInteger a, int b) { return a.divide(bigint(b)); } static public double div(double a, double b) { return a / b; } static public String sourceCodeToHTML_noEncode(String html) { return "
" + html + "
"; } static public String hstyle_sourceCodeLikeInRepo() { return "padding-left: 1em; padding-top: 0.5em; padding-bottom: 0.5em; background-color: #EEEEEE; border-style: solid; border-color: #666666; border-width: 1px 0px 1px 0px;"; } static public
List reversed(Iterable l) { return reversedList(l); } static public List reversed(A[] l) { return reversedList(asList(l)); } static public String reversed(String s) { return reversedString(s); } static public Pair, List> filterAntiFilter(Iterable c, Object pred) { List yes = new ArrayList(); List no = new ArrayList(); if (c != null) for (A o : c) (isTrue(callF(pred, o)) ? yes : no).add(o); return pair(yes, no); } static public Pair, List> filterAntiFilter(Iterable c, IF1 pred) { return filterAntiFilter(c, (Object) pred); } static public Pair, List> filterAntiFilter(IF1 pred, Iterable c) { return filterAntiFilter(c, pred); } static public Pair, List> filterAntiFilter(Object pred, Iterable c) { return filterAntiFilter(c, pred); } static public A highestBy(Iterable l, Object f) { return highestByFunction(l, f); } static public A highestBy(Object f, Iterable l) { return highestByFunction(f, l); } static public A highestBy(Iterable l, IF1 f) { return highestByFunction(f, l); } static public A highestBy(IF1 f, A[] l) { return highestBy(f, asList(l)); } static public A highestBy(IF1 f, Iterable l) { return highestByFunction(f, l); } static public List filter(Iterable c, Object pred) { if (pred instanceof F1) return filter(c, (F1) pred); List x = new ArrayList(); if (c != null) for (Object o : c) if (isTrue(callF(pred, o))) x.add(o); return x; } static public List filter(Object pred, Iterable c) { return filter(c, pred); } static public List filter(Iterable c, F1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(F1 pred, Iterable c) { return filter(c, pred); } static public List filter(Iterable c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(B[] c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(IF1 pred, Iterable c) { return filter(c, pred); } static public String squareBracketIfNempty(String s) { return empty(s) ? "" : squareBracket(s); } static public boolean cic(Collection l, String s) { return containsIgnoreCase(l, s); } static public boolean cic(Collection l, Symbol s) { return contains(l, s); } static public boolean cic(String[] l, String s) { return containsIgnoreCase(l, s); } static public boolean cic(String s, char c) { return containsIgnoreCase(s, c); } static public boolean cic(String a, String b) { return containsIgnoreCase(a, b); } static public String hbuttonLink(String url, String text, Object... params) { return hbuttonOnClick(text, "location.href=" + jsQuote(url) + ";", params); } static public String nLines(long n) { return n2(n, "line"); } static public String nLines(Collection l) { return nLines(l(l)); } static public String nLines(String s) { return nLines(countLines(s)); } static public int countLines(String s) { return l(toLines(s)); } static public String p_alignRight(String s, Object... params) { return p(s, params_stylePlus(params, "text-align: right")); } static public String small(Object contents, Object... params) { return tag("small", contents, params); } static public String span_title(String title, Object contents) { return spanTitle(title, contents); } static public String regexpReplace(String s, String pat, Object f) { return regexReplace(s, pat, f); } static public String regexpReplace(String s, String pat, IF1 f) { return regexReplace(s, pat, f); } static public String gazelle_postMentionRegexp() { return regexpCaseInsensitivePrefix() + "\\bpost\\s+(\\d+)"; } static public List sortedByCalculatedField(Iterable c, Object f) { return sortByCalculatedField(c, f); } static public List sortedByCalculatedField(Object f, Iterable c) { return sortedByCalculatedField(c, f); } static public List sortedByCalculatedField(IF1 f, Iterable c) { return sortedByCalculatedField(c, f); } static public List sortedByCalculatedField(Iterable c, IF1 f) { List l = cloneList(c); sort(l, new Comparator() { public int compare(A a, A b) { return stdcompare(f.get(a), f.get(b)); } }); return l; } static public List instancesOf(Iterable i, Class c) { return collectInstances(i, c); } static public List instancesOf(Class c, Iterable i) { return collectInstances(c, i); } static public List allBackRefs(Concept c) { IdentityHashMap l = new IdentityHashMap(); if (c != null && c.backRefs != null) for (Concept.Ref r : cloneList(c.backRefs)) l.put(r.concept(), true); return keysList(l); } static public String hAddToHead(String html, String tag) { List tok = htmlTok(html); List head = first(findContainerTag(tok, "head")); if (head == null) return tag + html; head.set(2, addLineBreak(tag) + head.get(2)); return join(tok); } static public String hInitWebSocket(Object... __) { String wsVar = optPar("wsVar", __, "ws"); String onOpen = (String) (optPar("onOpen", __)); String onMessage = (String) (optPar("onMessage", __)); String readyMsg = optPar("readyMsg", __, "WebSocket ready!"); return hreconnectingWebSockets() + hscript("\r\n var wsReady = false;\r\n var wsInitialMsgs = [];\r\n var wsVerbose = false;\r\n var " + wsVar + " = new ReconnectingWebSocket(((window.location.protocol === \"https:\") ? \"wss://\" : \"ws://\") + window.location.host + \"/\");\r\n \r\n " + wsVar + ".onopen = function(event) {\r\n wsReady = true;\r\n console.log(" + jsQuote(readyMsg) + ");\r\n wsInitialMsgs.forEach(function(msg) {\r\n if (wsVerbose) console.log(\"Sending initial msg: \" + msg);\r\n ws.send(msg);\r\n });\r\n " + jsDropTrailingComments(onOpen) + " };\r\n \r\n " + wsVar + ".onmessage = function(event) {\r\n " + unnull(onMessage) + "\r\n };\r\n \r\n // add an initial message to send when websocket opens\r\n // also send it now if ws is open already\r\n function wsInitialMsg(msg) {\r\n wsInitialMsgs.push(msg);\r\n if (wsReady) {\r\n if (wsVerbose) console.log(\"Sending initial msg: \" + msg);\r\n ws.send(msg);\r\n }\r\n }\r\n "); } static public String div_vbar(String... items) { return div_vbar(asList(items)); } static public String div_vbar(Collection items, Object... params) { return divUnlessEmpty(joinNemptiesWithVBar(items), params); } static public A getVar(IF0 v) { return v == null ? null : v.get(); } static public A uniq(Class c, Object... params) { return uniqueConcept(c, params); } static public A uniq(Concepts cc, Class c, Object... params) { return uniqueConcept(cc, c, params); } static public A conceptWhereCI(Class c, Object... params) { return findConceptWhereCI(c, params); } static public Concept conceptWhereCI(String c, Object... params) { return findConceptWhereCI(db_mainConcepts(), c, params); } static public A conceptWhereCI(Concepts concepts, Class c, Object... params) { return findConceptWhereCI(concepts, c, params); } static public Concept conceptWhereCI(Concepts concepts, String c, Object... params) { return findConceptWhereCI(concepts, c, params); } static public String assertMD5(String s) { return assertPossibleMD5(s); } static public String postPage(String url, Object... params) { return doPost(litmap(params), url); } static public String md5(String text) { try { if (text == null) return "-"; return bytesToHex(md5_impl(toUtf8(text))); } catch (Exception __e) { throw rethrow(__e); } } static public String md5(byte[] data) { if (data == null) return "-"; return bytesToHex(md5_impl(data)); } static public byte[] md5_impl(byte[] data) { try { return MessageDigest.getInstance("MD5").digest(data); } catch (Exception __e) { throw rethrow(__e); } } static public String md5(File file) { return md5OfFile(file); } static public List itemPlus(A a, Collection l) { return itemPlusList(a, l); } static public Map applyFunctionToValue(IF1 f, A key, Map map) { return applyFunctionToMapValue(key, f, map); } static public Map applyFunctionToValue(IF1 f, Map map, A... keys) { for (A key : unnullForIteration(keys)) applyFunctionToValue(f, key, map); return map; } static public String joinWithBR(Iterable l) { return join("
\n", l); } static public String joinWithBR(String... l) { return joinWithBR(asList(l)); } static public
List padList(List l, int w) { return padList(l, w, null); } static public List padList(List l, int w, A a) { if (l(l) >= w) return l; List x = cloneList(l); while (l(x) < w) x.add(a); return x; } static public Concept getConcept(long id) { return db_mainConcepts().getConcept(id); } static public Concept getConcept(Concepts concepts, long id) { return concepts.getConcept(id); } static public A getConcept(Class cc, long id) { return getConcept(db_mainConcepts(), cc, id); } static public A getConcept(Concepts concepts, Class cc, long id) { Concept c = concepts.getConcept(id); if (c == null) return null; if (!isInstance(cc, c)) throw fail("Can't convert concept: " + getClassName(c) + " -> " + getClassName(cc) + " (" + id + ")"); return (A) c; } static public void remove(List l, int i) { if (l != null && i >= 0 && i < l(l)) l.remove(i); } static public void remove(Collection l, A a) { if (l != null) l.remove(a); } static public B remove(Map map, Object a) { return map == null ? null : map.remove(a); } static public void listSet(List l, int i, A a, A emptyElement) { if (i < 0) return; while (i >= l(l)) l.add(emptyElement); l.set(i, a); } static public void listSet(List l, int i, A a) { listSet(l, i, a, null); } static public Map cgetAll_cloneLists(Concept c, Collection fields) { return mapToValues(fields, f -> cloneIfList(cget(c, f))); } static public Set> _entrySet(Map map) { return map == null ? Collections.EMPTY_SET : map.entrySet(); } static public void printVars_str(Object... params) { print(renderVars_str(params)); } static public MetaTransformer defaultMetaTransformer() { return metaTransformer_transformableAndList(); } static public A printStruct(String prefix, A a) { printStructure(prefix, a); return a; } static public A printStruct(A a) { printStructure(a); return a; } static public void logStructure(File logFile, Object o) { logQuoted(logFile, structure(o)); } static public void logStructure(String fileName, Object o) { logStructure(getProgramFile(fileName), o); } static public void logStructure(String progID, String fileName, Object o) { logStructure(getProgramFile(progID, fileName), o); } static public String joinNemptiesWithVBar(String... strings) { return joinNempties(" | ", strings); } static public String joinNemptiesWithVBar(Collection strings) { return joinNempties(" | ", strings); } static public Collection conceptsWhereIC(Class c, Object... params) { return findConceptsWhereCI(c, params); } static public List conceptsWhereIC(String c, Object... params) { return findConceptsWhereCI(c, params); } static public Collection conceptsWhereIC(Concepts concepts, Class c, Object... params) { return findConceptsWhereCI(concepts, c, params); } static public List conceptsWhereIC(Concepts concepts, String c, Object... params) { return findConceptsWhereCI(concepts, c, params); } static public String hscript(String script) { return hjavascript(script); } static public String replaceVars(String s, Map map) { return empty(map) ? s : join(replaceVars(javaTok(s), map)); } static public List replaceVars(List tok, Map map) { if (empty(map)) return tok; tok = cloneList(tok); for (Map.Entry __0 : _entrySet(map)) { String var = __0.getKey(); Object val = __0.getValue(); jreplace(tok, var, str(val)); } return tok; } static public String replaceVars(String s, Object... params) { return replaceVars(s, paramsToMap(params)); } static public long parseFirstLong(String s) { return parseLong(jextract("", s)); } static public String firstWhereFirstLongIs(Collection l, long i) { return firstThat(l, s -> parseFirstLong(s) == i); } static public String htitledSectionWithDiv(String title, Object contents, Object... __) { String backgroundColor = "#fff"; String labelStyle = "width: auto; float: top; position: relative; top: -.6em; left:15px; background-color: " + backgroundColor; String innerDivStyle = stringPar("innerDivStyle", __); String innerDivClass = stringPar("innerDivClass", __); String innerDivID = (String) (optPar("innerDivID", __)); __ = paramsMinus(__, "innerDivStyle", "innerDivID", "innerDivClass"); return div(htag("label", b(" " + title + " "), "style", labelStyle) + div(contents, "style", joinNemptiesWithSemicolon(innerDivStyle, "padding-left: 15px"), "class", joinNemptiesWithSpace("sectionContents", innerDivClass), "id", innerDivID), params_stylePlus("border: 2px solid", __)); } static public String hsnippetimg_scaleToWidth(int width, String imageID, int originalWidth, int originalHeight, Object... params) { return hsnippetimg(imageID, paramsPlus(params, "width", width, "height", calcHeight(originalWidth, originalHeight, width))); } static public String himgsnippet(String imageID, Object... params) { return hsnippetimg(imageID, params); } static public String hjssrc(String src) { return hjavascript_src(src); } static public String span(Object contents, Object... params) { return hfulltag("span", contents, params); } static public String span() { return span(""); } static public String renderHowLongAgoPlusModified(long timestamp, long timestamp2, Object... __) { String spacer = optPar("spacer", __, ", modified "); if (timestamp2 == 0) timestamp2 = timestamp; String s = renderHowLongAgo(timestamp); String s2 = renderHowLongAgo(timestamp2); return eq(s, s2) ? s : s + ", modified " + s2; } static public String appendQueryToURL(String url, Map params) { if (url == null) return null; String data = makePostData(params); if (empty(data)) return url; int idx = smartIndexOf(url, '#'); String url2 = takeFirst(url, idx); return url2 + (url2.contains("?") ? "&" : "?") + data + substring(url, idx); } static public String appendQueryToURL(String url, Object... data) { return appendQueryToURL(url, paramsToMap(data)); } static public List gazelle_navLinks(String baseLink, String searchQuery, Object... __) { boolean withTeam = optPar("withTeam", __, true); boolean withStats = optPar("withStats", __, true); boolean flat = boolPar("flat", __); List more = ll(ahref(baseLink + "/deletedPosts", "Deleted Posts")); return llNonNulls(flattenStringArray2(ahref(baseLink + "/crud/UserPost?cmd=new", "New Post"), searchQuery != null ? hform(hinputfield("q", searchQuery, "style", "width: 75px") + " " + hsubmit("Search"), "style", "display: inline", "action", baseLink + "/search") : ahref(baseLink + "/search", "Search"), ahref(baseLink + "/rootPosts", "Root Posts"), ahref(baseLink + "/allPosts", "All Posts"), ahref(baseLink + "/latestPosts", "Latest Posts"), ahref(baseLink + "/latestModifiedPosts", "Latest Changes"), ahref(baseLink + "/mainPosts", "Main Posts"), !withTeam ? null : ahref(baseLink + "/team", "Team"), flat ? more : hPopDownButton(flattenStringArray2(!withStats ? null : ahref(baseLink + "/stats", "Stats"), more)))); } static public Object[] paramsPlus(Object[] a1, Object... a2) { if (a2 == null) return a1; if (a1 == null) return a2; if (l(a1) == 1 && a1[0] instanceof Map) return new Object[] { mapPlus((Map) a1[0], a2) }; assertEvenLength(a1); assertEvenLength(a2); Map map = paramsToOrderedMap(a1); int n = l(a2); for (int i = 0; i < n; i += 2) { Object key = a2[i]; if (key != null) map.put(key, a2[i + 1]); } return mapToParams(map); } static public Object[] paramsPlus(Map a1, Object... a2) { return paramsPlus(new Object[] { a1 }, a2); } static public List listMinusSet(Iterable l, Collection stuff) { if (l == null) return null; if (empty(stuff)) return asList(l); Set set = asSet(stuff); List l2 = new ArrayList(); for (A a : l) if (!set.contains(a)) l2.add(a); return l2; } static public List listMinusSet(Iterable l, Collection stuff, Collection stuff2) { return listMinusSet(listMinusSet(l, stuff), stuff2); } static public > B addAllAndReturnCollection(B c, Collection b) { if (c != null && b != null) c.addAll(b); return c; } static public > B addAllAndReturnCollection(B c, A... b) { addAll(c, b); return c; } static public Object cget(Object c, String field) { c = derefRef(c); Object o = getOpt(c, field); return derefRef(o); } static public Object cget(String field, Object c) { return cget(c, field); } static public Map mapToValues(Iterable l, Object f) { return mapKeyAndFunction(l, f); } static public Map mapToValues(Object f, Iterable l) { return mapKeyAndFunction(f, l); } static public Map mapToValues(Iterable l, IF1 f) { return mapKeyAndFunction(f, l); } static public Map mapToValues(IF1 f, Iterable l) { return mapKeyAndFunction(f, l); } static public Map mapToValues(Map map, IF2 f) { return mapKeyAndFunction(map, f); } static public File programFile(String name) { return prepareProgramFile(name); } static public File programFile(String progID, String name) { return prepareProgramFile(progID, name); } static public List> syncMapToPairs(Map map) { if (map == null) return new ArrayList(); synchronized (collectionMutex(map)) { return mapToPairs(map); } } static public String regexpFirstGroupIC(String pat, String s) { Matcher m = regexpIC(pat, s); if (m.find()) return m.group(1); else return null; } static public Map safeUnstructMapAllowingClasses(String s, Class... allowedClasses) { return (Map) safeUnstructureAllowingClasses(s, allowedClasses); } static public Map putAll(Map a, Map b) { if (a != null && b != null) a.putAll(b); return a; } static public MultiMap putAll(MultiMap a, Map b) { if (a != null) a.putAll((Map) b); return a; } static public Map putAll(Map a, Object... b) { if (a != null) litmap_impl(a, b); return a; } static public List uniquifyAndSortAlphaNum(Collection l) { return sortedAlphaNum(uniquify(l)); } static public List allToUpper(Collection l) { List x = new ArrayList(l(l)); if (l != null) for (String s : l) x.add(upper(s)); return x; } static public List asForPairsWithB(B b, Iterable> l) { List out = new ArrayList(); for (Pair p : unnullForIteration(l)) if (eq(pairB(p), b)) out.add(pairA(p)); return out; } static public List asForPairsWithB(Iterable> l, B b) { return asForPairsWithB(b, l); } static public String replaceDollarVars(String s, Object... params) { if (empty(params)) return s; Map vars = mapKeys(__77 -> dropDollarPrefix(__77), (Map) litcimap(params)); return replaceDollarVars_dyn(s, var -> strOrNull(vars.get(var))); } static public String replaceDollarVars(String s, IF1 f) { return replaceDollarVars_dyn(s, f); } static public String nPosts(long n) { return n2(n, "post"); } static public String nPosts(Collection l) { return nPosts(l(l)); } static public String nPosts(Map map) { return nPosts(l(map)); } static public String n2(long l) { return formatWithThousands(l); } static public String n2(Collection l) { return n2(l(l)); } static public String n2(Map map) { return n2(l(map)); } static public String n2(double l, String singular) { return empty(singular) ? str(l) : n2(l, singular, singular + "s"); } static public String n2(double l, String singular, String plural) { if (fraction(l) == 0) return n2((long) l, singular, plural); else return l + " " + plural; } static public String n2(long l, String singular, String plural) { return n_fancy2(l, singular, plural); } static public String n2(long l, String singular) { return empty(singular) ? n2(l) : n_fancy2(l, singular, singular + "s"); } static public String n2(Collection l, String singular) { return n2(l(l), singular); } static public String n2(Collection l, String singular, String plural) { return n_fancy2(l, singular, plural); } static public String n2(Map m, String singular, String plural) { return n_fancy2(m, singular, plural); } static public String n2(Map m, String singular) { return n2(l(m), singular); } static public String n2(long[] a, String singular) { return n2(l(a), singular); } static public String n2(Object[] a, String singular) { return n2(l(a), singular); } static public String n2(Object[] a, String singular, String plural) { return n_fancy2(a, singular, plural); } static public String n2(MultiSet ms, String singular, String plural) { return n_fancy2(ms, singular, plural); } static public String formatDoubleX(double d, int digits) { return formatDoubleFull(d, digits); } static public String str_toM(long l) { return n2(toM(l)) + " MB"; } static public List listToTopTenCI(Collection l) { return asCIMultiSet(l).highestFirst(); } static public String makePostData(Map map) { StringBuilder buf = new StringBuilder(); for (Map.Entry e : castMapToMapO(map).entrySet()) { String key = (String) (e.getKey()); Object val = e.getValue(); if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode((value))); } } return str(buf); } static public String makePostData(Object... params) { StringBuilder buf = new StringBuilder(); int n = l(params); for (int i = 0; i + 1 < n; i += 2) { String key = (String) (params[i]); Object val = params[i + 1]; if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode((value))); } } return str(buf); } static public A uniqCI(Class c, Object... params) { return uniqueConcept(db_mainConcepts(), c, params); } static public A uniqCI(Concepts cc, Class c, Object... params) { AutoCloseable __1 = tempDBLock(cc); try { params = expandParams(c, params); A x = findConceptWhereCI(cc, c, params); if (x == null) { x = unlisted(c); csetAll(x, params); cc.register(x); } return x; } finally { _close(__1); } } static public boolean fileNempty(File f) { return fileNotEmpty(f); } static public String roundBracket(String s) { return "(" + s + ")"; } static public String roundBracket(Object s) { return roundBracket(str(s)); } static public Map decodeHQuery(String query) { Map map = new HashMap(); for (String s : splitAtAmpersand(query)) { int i = s.indexOf('='); if (i >= 0) map.put(urldecode(s.substring(0, i)), urldecode(s.substring(i + 1))); } return map; } static public ThreadLocal doPost_silently = new ThreadLocal(); static public ThreadLocal doPost_timeout = new ThreadLocal(); static public ThreadLocal> doPost_extraHeaders = new ThreadLocal(); static public String doPost(String url, Map urlParameters) { return doPost(urlParameters, url); } static public String doPost(Map urlParameters, String url) { return doPost(makePostData(urlParameters), url); } static public String doPost(String urlParameters, String url) { try { URL _url = new URL(url); ping(); return doPost(urlParameters, _url.openConnection(), _url); } catch (Exception __e) { throw rethrow(__e); } } static public String doPost(String urlParameters, URLConnection conn, URL url) { try { boolean silently = isTrue(optParam(doPost_silently)); Long timeout = optParam(doPost_timeout); Map extraHeaders = optPar(doPost_extraHeaders); setHeaders(conn); for (String key : keys(extraHeaders)) { conn.setRequestProperty(key, extraHeaders.get(key)); } int l = lUtf8(urlParameters); if (!silently) print("Sending POST request: " + hideCredentials(url) + " (" + l + " bytes)"); if (timeout != null) setURLConnectionTimeouts(conn, timeout); ((HttpURLConnection) conn).setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("Content-Length", str(l)); OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); writer.write(urlParameters); writer.flush(); String contents = loadPage_utf8(conn, url, false); writer.close(); return contents; } catch (Exception __e) { throw rethrow(__e); } } static public String regexpReplace_direct(String s, String pat, String replacement) { Matcher m = regexp(pat, s); return regexpReplace_direct(m, replacement); } static public String regexpReplace_direct(Matcher m, String replacement) { StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, replacement); m.appendTail(buf); return str(buf); } static public A conceptWhereIC(Class c, Object... params) { return findConceptWhereCI(c, params); } static public Concept conceptWhereIC(String c, Object... params) { return findConceptWhereCI(db_mainConcepts(), c, params); } static public A conceptWhereIC(Concepts concepts, Class c, Object... params) { return findConceptWhereCI(concepts, c, params); } static public Concept conceptWhereIC(Concepts concepts, String c, Object... params) { return findConceptWhereCI(concepts, c, params); } static public Map parseColonPropertyCIMap(String text) { return parseColonProperties(text, ciMap()); } static public int iround(double d) { return (int) Math.round(d); } static public int iround(Number n) { return iround(toDouble(n)); } static public double hoursToSeconds(double hours) { return hours * 60 * 60; } static public double favIconCacheHours() { return 24; } static public Object favIconHeaders(Object response) { call(response, "addHeader", "Cache-Control", "public, max-age=" + iround(hoursToSeconds(favIconCacheHours()))); return response; } static public Object subBot_serveFile(File file) { return call(getMainBot(), "serveFile", file); } static public Object subBot_serveFile(File file, String mimeType) { return call(getMainBot(), "serveFile", file, mimeType); } static public String faviconMimeType() { return "image/x-icon"; } static public File loadLibrary(String snippetID) { return loadBinarySnippet(snippetID); } static public String gazelle_textURL(long postID) { return gazelle_server() + "text/" + postID; } static public String afterLastEquals(String s) { return s == null ? null : substring(s, s.lastIndexOf('=') + 1); } static public List listMinus(Collection l, Object... stuff) { if (l == null) return null; List l2 = similarEmptyList(l); Set set = lithashset(stuff); for (Object o : l) if (!set.contains(o)) l2.add(o); return l2; } static public boolean infoMessage_alwaysOnTop = true; static public double infoMessage_defaultTime = 5.0; static public JWindow infoMessage(String text) { return infoMessage(text, infoMessage_defaultTime); } static public JWindow infoMessage(final String text, final double seconds) { printHidingCredentials(text); return infoMessage_noprint(text, seconds); } static public JWindow infoMessage_noprint(String text) { return infoMessage_noprint(text, infoMessage_defaultTime); } static public JWindow infoMessage_noprint(final String _text, final double seconds) { final String text = hideCredentials(_text); if (empty(text)) return null; logQuotedWithDate(infoBoxesLogFile(), text); if (isHeadless()) return null; return (JWindow) swingAndWait(new F0() { public Object get() { try { final JWindow window = showWindow(infoMessage_makePanel(text)); window.setSize(300, 150); moveToTopRightCorner(window); if (infoMessage_alwaysOnTop) window.setAlwaysOnTop(true); if (vmBus_noObjections("shouldShowInfoBox", window, text)) window.setVisible(true); if (seconds != 0) disposeWindowAfter(iround(seconds * 1000), window); return window; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final JWindow window = showWindow(infoMessage_makePanel(text));\r\n window.s..."; } }); } static public JWindow infoMessage(Throwable e) { printStackTrace(e); return infoMessage(exceptionToStringShort(e)); } static public Thread startThread(Object runnable) { return startThread(defaultThreadName(), runnable); } static public Thread startThread(String name, Object runnable) { runnable = wrapAsActivity(runnable); return startThread(newThread(toRunnable(runnable), name)); } static public Thread startThread(Thread t) { _registerThread(t); t.start(); return t; } static public void printVars(Object... params) { printVars_str(params); } static public boolean swingConfirm(Component owner, String msg) { return confirmOKCancel(owner, msg); } static public boolean swingConfirm(String msg) { return confirmOKCancel(msg); } static public Object[] objectArrayPlus(Object[] a1, Object... a2) { return arrayPlus(a1, a2); } static public Runnable runnableThread(final Runnable r) { return new Runnable() { public void run() { try { startThread(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "startThread(r)"; } }; } static public Object postJSONPage(String url, Object... params) { return jsonDecode(postPage(url, params)); } static public int _hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static public Set> entrySet(Map map) { return _entrySet(map); } static public void put(Map map, A a, B b) { if (map != null) map.put(a, b); } static public void put(List l, int i, A a) { if (l != null && i >= 0 && i < l(l)) l.set(i, a); } static public Method hashMap_findKey_method; static public A hashMap_findKey(HashMap map, Object key) { try { if (hashMap_findKey_method == null) hashMap_findKey_method = findMethodNamed(HashMap.class, "getNode"); Map.Entry entry = (Map.Entry) hashMap_findKey_method.invoke(map, hashMap_internalHash(key), key); return entry == null ? null : entry.getKey(); } catch (Exception __e) { throw rethrow(__e); } } static public TreeMap ciMap() { return caseInsensitiveMap(); } static public String shortClassName_dropNumberPrefix(Object o) { return dropNumberPrefix(shortClassName(o)); } static public int boostHashCombine(int a, int b) { return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2)); } static public List replaceIC(List l, String a, String b) { List l2 = new ArrayList(); for (int i = 0; i < l(l); i++) { String s = l.get(i); l2.add(eqic(s, a) ? b : s); } return l2; } static public String replaceIC(String s, String a, String b) { return s.replaceAll("(?i)" + patternQuote(a), quoteReplacement(b)); } static public List htmlTok(String s) { return htmlcoarsetok(s); } static public List charRangesOfHTMLComments(String html) { return charRangesOfHTMLComments(htmlTok(html)); } static public List charRangesOfHTMLComments(List tok) { List l = new ArrayList(); int pos = 0; for (int idx = 0; idx < l(tok); idx++) { String t = tok.get(idx); if (even(idx)) { int i = 0; while ((i = indexOf(t, "", i + 4); l.add(intRange(pos + i, pos + j + 3)); i = j + 3; } } pos += l(t); } return l; } static public String htmlCommentContents(String s) { return trim(dropPrefixSuffix("", trim(s))); } static public int indexOfMatches(String pat, List l) { return indexOfMatches(pat, l, null); } static public int indexOfMatches(String pat, List l, Matches m) { return indexOfMatches(pat, l, 0, m); } static public int indexOfMatches(String pat, List l, int i) { return indexOfMatches(pat, l, i, null); } static public int indexOfMatches(String pat, List l, int i, Matches m) { for (int n = l(l); i < n; i++) if (match(pat, l.get(i), m)) return i; return -1; } static public boolean warn_on = true; static public ThreadLocal> warn_warnings = new ThreadLocal(); static public void warn(String s) { if (warn_on) print("Warning: " + s); } static public void warn(String s, List warnings) { warn(s); if (warnings != null) warnings.add(s); addToCollection(warn_warnings.get(), s); } static public String nEntries(long n) { return n2(n, "entry", "entries"); } static public String nEntries(Collection l) { return nEntries(l(l)); } static public String nEntries(Map map) { return nEntries(l(map)); } static public void addPair(Collection> c, A a, B b) { if (c != null) c.add(pair(a, b)); } static public IntRange intRange(int start, int end) { return new IntRange(start, end); } static public String lines(Iterable lines) { return fromLines(lines); } static public String lines(Object[] lines) { return fromLines(asList(lines)); } static public List lines(String s) { return toLines(s); } static public String lines(Iterable l, IF1 f) { return mapToLines(l, f); } static public void pnlStruct(Object o) { if (o instanceof Collection) pnlStruct((Collection) o); else if (o instanceof Map) pnlStruct((Map) o); else if (o != null) pnlStruct(ll(o)); } static public > B pnlStruct(B l) { pnlStruct((Iterable) l); return l; } static public Iterable pnlStruct(Iterable l) { return pnlStruct("", l); } static public Iterable pnlStruct(String prefix, Iterable l) { int i = 0; if (l != null) for (A a : l) print(prefix + (++i) + ". " + struct_noStringSharing(a)); return l; } static public A[] pnlStruct(A[] l) { pnlStruct(asList(l)); return l; } static public Map pnlStruct(Map map) { pnl(map(map, new F2() { public Object get(A a, B b) { try { return sfu(a) + " = " + sfu(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "sfu(a) + \" = \" + sfu(b)"; } })); return map; } static public String replaceCharRanges(String text, List> replacements) { if (empty(replacements)) return text; replacements = sortByPairsA(replacements); int iChar = 0, i = 0; StringBuilder buf = new StringBuilder(); while (i < l(replacements)) { Pair p = replacements.get(i++); buf.append(substring(text, iChar, p.a.start)); buf.append(p.b); iChar = p.a.end; } if (iChar < l(text)) buf.append(substring(text, iChar)); return str(buf); } static public List callFAll(Collection l, Object... args) { return callF_all(l, args); } static public String hTitleClean(String title) { return htmldecode(dropTagsAndHTMLComments(title)); } static public String nemptyLines(Iterable l) { return lines(nempties(allToStrOrNull(l))); } static public String nemptyLines(Object... l) { return nemptyLinesLL(l); } static public String ahref_possiblyTargetBlank(String link, Object contents, boolean targetBlank, Object... params) { return ahref(link, contents, targetBlank ? paramsPlus(params, "target", "_blank") : params); } static public String ahref_possiblyTargetBlank(boolean targetBlank, String link, Object contents, Object... params) { return ahref_possiblyTargetBlank(link, contents, targetBlank, params); } static public void forEach(Iterable l, IVF1 f) { if (f != null && l != null) for (A a : l) callF(f, a); } static public void forEach(IVF1 f, Iterable l) { forEach(l, f); } static public void forEach(A[] l, IVF1 f) { if (f != null && l != null) for (A a : l) callF(f, a); } static public A setAll(A o, Map fields) { if (fields == null) return o; for (String field : keys(fields)) set(o, field, fields.get(field)); return o; } static public A setAll(A o, Object... values) { failIfOddCount(values); for (int i = 0; i + 1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i + 1]; set(o, field, value); } return o; } static public Object[] filterParams(Object[] params, Object... keys) { Set set = asSet(keys); List l = new ArrayList(); for (int i = 0; i < l(params); i += 2) if (contains(set, params[i])) { l.add(params[i]); l.add(params[i + 1]); } return asObjectArray(l); } static public void add(BitSet bs, int i) { bs.set(i); } static public boolean add(Collection c, A a) { return c != null && c.add(a); } static public void add(Container c, Component x) { addToContainer(c, x); } static public Object lambdaToToString(IF0 x) { return x == null ? null : new Object() { public String toString() { return str(x.get()); } }; } static public boolean notNullOrEmptyString(Object o) { return o != null && !eq(o, ""); } static public A setTitle(A c, String title) { return setFrameTitle(c, title); } static public A setTitle(String title, A c) { return setFrameTitle(c, title); } static public String getClientIPFromHeaders(Map headers) { if (headers == null) return null; String remoteAddr = (String) (headers.get("remote-addr")); String client = (String) (headers.get("x-forwarded-for")); if (nempty(client)) remoteAddr += "," + client; return remoteAddr; } static public RuntimeException unimplemented() { throw fail("TODO"); } static public RuntimeException unimplemented(String msg) { throw fail("TODO: " + msg); } static public StringTree2 stringTree2_javaTok(Map entries) { StringTree2 tree = new StringTree2(); for (String key : keys(entries)) addToStringTree(tree, javaTokC(key), entries.get(key)); return tree; } static public int javaTok_n, javaTok_elements; static public boolean javaTok_opt = false; static public List javaTok(String s) { ++javaTok_n; ArrayList tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0; while (i < l) { int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !regionMatches(s, j, "*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(javaTok_substringN(s, i, j)); i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' && Character.isJavaIdentifierStart(d) && i + 2 < l && "'\\".indexOf(s.charAt(i + 2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { int c2 = s.charAt(j); if (c2 == opener || c2 == '\n' && opener == '\'') { ++j; break; } else if (c2 == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j < l && !regionMatches(s, j, "]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !regionMatches(s, j, "]=]")); j = Math.min(j + 3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static public List javaTok(List tok) { return javaTokWithExisting(join(tok), tok); } static public void putMultipleKeys(Map map, Collection keys, B value) { if (map == null || keys == null) return; for (A key : keys) map.put(key, value); } static public List allPlus(final int x, List l) { return map(l, new F1() { public Integer get(Integer i) { try { return i + x; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "i+x"; } }); } static public List jfindAll(List tok, String pat) { return jfindAll(tok, pat, null); } static public List jfindAll(List tok, String pat, ITokCondition condition) { return jfindAll(tok, jfind_preprocess(javaTok(pat)), condition); } static public List jfindAll(List tok, List tokPat) { return jfindAll(tok, tokPat, null); } static public List jfindAll(List tok, List tokPat, ITokCondition condition) { TokCondition cond = toTokCondition(condition); String[] toks = toStringArray(codeTokensOnly(tokPat)); int i = -1; List l = new ArrayList(); while ((i = findCodeTokens(tok, i + 1, false, toks, cond)) >= 0) l.add(i); return l; } static public boolean isIdentifier(String s) { return isJavaIdentifier(s); } static public boolean isQuoted(String s) { if (isNormalQuoted(s)) return true; return isMultilineQuoted(s); } static public List tok_subListWithoutBorderNTokens(List tok, int i, int j) { List tok2 = cloneSubList(tok, i & (~1), j | 1); tok2.set(0, ""); tok2.set(l(tok2) - 1, ""); return tok2; } static public String tok_expandIfQuoted(String s) { return applyTranspilationFunction(__78 -> tok_expandIfQuoted(__78), s); } static public void tok_expandIfQuoted(List tok) { jreplace(tok, "if || ", "if (matchOneOf(s, m, $2, $5))"); jreplace_dyn(tok, "if ", new F2, Integer, String>() { public String get(List tok, Integer cIdx) { try { String s = unquote(tok.get(cIdx + 2)); List l = new ArrayList(); for (String pat : splitAtJavaToken(s, "|")) { if (pat.contains("...")) l.add("matchX(" + quote(trim(pat)) + ", s, m)"); else if (javaTok(pat).contains("*")) l.add("match(" + quote(trim(pat)) + ", s, m)"); else l.add("match(" + quote(trim(pat)) + ", s)"); } return "if (" + join(" || ", l) + ")"; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S s = unquote(tok.get(cIdx+2));\r\n //print(\"multimatch: \" + quote(s));\r\n ..."; } }, new TokCondition() { public boolean get(final List tok, final int i) { return javaTokC(unquote(tok.get(i + 3))).contains("|"); } }); tok_transpileIfQuoted_dollarVars(tok); jreplace(tok, "if ", "if (find3plusRestsX($2, s, m))", new TokCondition() { public boolean get(final List tok, final int i) { return startsAndEndsWith(unquote(tok.get(i + 3)), "..."); } }); jreplace(tok, "if ", "if (matchStartX($2, s, m))", new TokCondition() { public boolean get(final List tok, final int i) { return unquote(tok.get(i + 3)).endsWith("..."); } }); jreplace(tok, "if ", "if (match($2, s))", new TokCondition() { public boolean get(final List tok, final int i) { return !javaTokC(unquote(tok.get(i + 3))).contains("*"); } }); jreplace(tok, "if ", "if (match($2, s, m))"); jreplace(tok, "if match ", "if (match($3, s, m))"); } static public void doublePut(Map map, A key1, A key2, B value) { map.put(key1, value); map.put(key2, value); } static public boolean isSingleQuoteIdentifier(String s) { if (l(s) < 2 || s.charAt(0) != '\'' || !Character.isJavaIdentifierStart(s.charAt(1))) return false; for (int i = 2; i < l(s); i++) if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; return true; } static public String fromSingleQuoteIdentifier(String s) { return isSingleQuoteIdentifier(s) ? substring(s, 1) : s; } static public boolean tok_tokenBeforeLonelyReturnValue(List tok, int i) { String t = get(tok, i); if (l(t) == 1 && "{};".contains(t) || eq(t, "else")) return true; if (!eq(t, ")")) return false; int level = 0; while (i > 0) { if (eq(tok.get(i), ")")) ++level; if (eq(tok.get(i), "(")) --level; if (level == 0) return eq(get(tok, i - 2), "if"); i -= 2; } return false; } static public void mapPut(Map map, A key, B value) { if (map != null && key != null && value != null) map.put(key, value); } static public void mapPut(Map map, Pair p) { if (map != null && p != null) map.put(p.a, p.b); } static public boolean eqGet(List l, int i, Object o) { return eq(get(l, i), o); } static public boolean eqGet(Map map, A key, Object o) { return eq(mapGet(map, key), o); } static public List codeTokens(List tok) { return codeTokensOnly(tok); } static public Pair stringTreeLeafValue2(StringTree2 tree, List items) { int i = 0; while (tree != null && i < l(items)) { if (tree.leafValue != null) return pair(tree.leafValue, i); tree = tree.children.get(items.get(i)); ++i; } return null; } static public void mapPutInRange(Map map, int start, int end, A value) { if (map != null && value != null) for (int i = start; i < end; i++) map.put(i, value); } static public String neatMechListURL(String listName) { return "http://botcompany.de/mech/raw/list/" + urlencode(listName); } static public String unquote(String s) { if (s == null) return null; if (startsWith(s, '[')) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i + 1, s.length() - i - 1); } } if (s.length() > 1) { char c = s.charAt(0); if (c == '\"' || c == '\'') { int l = endsWith(s, c) ? s.length() - 1 : s.length(); StringBuilder sb = new StringBuilder(l - 1); for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } sb.append((char) Integer.parseInt(code, 8)); continue; } switch(nextChar) { case '\"': ch = '\"'; break; case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\'': ch = '\''; break; case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt("" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); sb.append(Character.toChars(code)); i += 5; continue; default: ch = nextChar; } i++; } sb.append(ch); } return sb.toString(); } } return s; } static public boolean getSnippetTitles_verbose = false; static public Map getSnippetTitles(Collection ids) { try { if (empty(ids)) return new HashMap(); String url = tb_mainServer() + "/tb-int/get-titles.php"; String ids2 = join(" ", parseSnippetIDs(ids)); return trimValues(transformKeys(jsonDecodeMap(doPost(mapPlus(standardCredentialsMap(), "ids", ids2), url)), new F1() { public Object get(String id) { try { return fsI(id); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "fsI(id)"; } })); } catch (Exception __e) { throw rethrow(__e); } } static public Collection values(Map map) { return map == null ? emptyList() : map.values(); } static public Collection values(Object map) { return values((Map) map); } static public Collection values(MultiMap mm) { return mm == null ? emptyList() : concatLists(values(mm.data)); } static public String dottedSpan(String contents, String title) { return span(contents, "title", title, "style", "border-bottom: dotted 1px"); } static public String htmlencode(Object o) { return htmlencode(str(o)); } static public String htmlencode(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { int cp = s.codePointAt(i); out.append("&#x"); out.append(intToHex_flexLength(cp)); out.append(';'); i += Character.charCount(cp) - 1; } else out.append(c); } return out.toString(); } static public String dropPrefix(String prefix, String s) { return s == null ? null : s.startsWith(prefix) ? s.substring(l(prefix)) : s; } static public String fsI(String id) { return formatSnippetID(id); } static public String fsI(long id) { return formatSnippetID(id); } static public ThreadLocal dynamize_linkParams = new ThreadLocal(); static public String dynamize_noEncode(String html) { List tok = htmlTok(html); Pattern p = Pattern.compile(regexp_findSnippetIDs()); for (int i = 0; i < l(tok); i += 2) { Matcher m = p.matcher(tok.get(i).replace("&#", "&~~~")); StringBuffer buf = new StringBuffer(); while (m.find()) { String id = m.group(1); String link = m.group(); try { link = ahref(snippetLink(id), link, concatArrays(new Object[] { "title", getSnippetTitle_cached(id) }, dynamize_linkParams.get())); } catch (Throwable __e) { _handleException(__e); } mreplace(m, buf, link); } m.appendTail(buf); String s = str(buf).replace("&~~~", "&#"); tok.set(i, s); } dynamize_linkParams.set(null); return join(tok); } static public boolean isURL(String s) { return startsWithOneOf(s, "http://", "https://", "file:"); } static public String longSnippetLink(String id) { return tb_mainServer() + "/tb/show-snippet.php?id=" + parseSnippetID(id); } static public long psI(String snippetID) { return parseSnippetID(snippetID); } static public Map stdFunctions_cached_map; static public Lock stdFunctions_cached_lock = lock(); static public Map stdFunctions_cached() { Lock __0 = stdFunctions_cached_lock; lock(__0); try { if (stdFunctions_cached_map == null) stdFunctions_cached_map = stdFunctions_uncached(); return stdFunctions_cached_map; } finally { unlock(__0); } } static synchronized public void stdFunctions_clearCache() { stdFunctions_cached_map = null; } static public Map standardClassesMap() { String sc = loadSnippet("#1003674"); Map map = new HashMap(); for (String line : tlft_j(sc)) { int idx = line.indexOf('/'); map.put(line.substring(0, idx), line.substring(idx + 1)); } return map; } static public boolean startsWithOneOf(String s, String... l) { for (String x : l) if (startsWith(s, x)) return true; return false; } static public boolean startsWithOneOf(String s, Matches m, String... l) { for (String x : l) if (startsWith(s, x, m)) return true; return false; } static public boolean tok_whitespaceContainsJavaComments(String s) { int l = l(s) - 1; for (int j = 0; j < l; j++) if (s.charAt(j) == '/') { char d = s.charAt(j + 1); if (d == '*' || d == '/') return true; } return false; } static public boolean stdEq2(Object a, Object b) { if (a == null) return b == null; if (b == null) return false; if (a.getClass() != b.getClass()) return false; for (String field : allFields(a)) if (neq(getOpt(a, field), getOpt(b, field))) return false; return true; } static public int stdHash2(Object a) { if (a == null) return 0; return stdHash(a, toStringArray(allFields(a))); } static public Set keySet(Map map) { return map == null ? new HashSet() : map.keySet(); } static public Set keySet(Object map) { return keys((Map) map); } static public Set keySet(MultiSet ms) { return ms.keySet(); } static public Set keySet(MultiMap mm) { return mm.keySet(); } static public int keysSize(MultiMap mm) { return lKeys(mm); } static public A reverseGet(List l, int idx) { if (l == null || idx < 0) return null; int n = l(l); return idx < n ? l.get(n - 1 - idx) : null; } static public Map cloneMap(Map map) { if (map == null) return new HashMap(); synchronized (map) { return map instanceof TreeMap ? new TreeMap((TreeMap) map) : map instanceof LinkedHashMap ? new LinkedHashMap(map) : new HashMap(map); } } static public List cloneMap(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : cloneList(l)) x.add(f.get(o)); return x; } static public String ukTimeZone_string() { return "Europe/London"; } static public ReliableSingleThread dm_rst(Runnable r) { return dm_rst(dm_current_mandatory(), r); } static public ReliableSingleThread dm_rst(DynModule mod, Runnable r) { return dm_rst(mod, new ReliableSingleThread(r)); } static public ReliableSingleThread dm_rst(DynModule mod, ReliableSingleThread rst) { rst.enter = dm_rEnter(mod); return rst; } static public Set syncWeakSet() { return synchroWeakHashSet(); } static public void dm_setModuleName(Object module, String name) { dm_callModule(module, "setModuleName", name); } static public void dm_setModuleName(String name) { dm_setModuleName(dm_current_mandatory_generic(), name); } static public void dm_assertFirstSibling() { if (!dm_isFirstSiblingModule(dm_current_mandatory_generic())) throw fail("Don't start this module (" + dm_moduleLibID() + ") multiple times. This instance will exit."); } static public String standardTimeZone_name = "Europe/Berlin"; static public String standardTimeZone() { return standardTimeZone_name; } static public String dbProgramID() { return getDBProgramID(); } static public FixedRateTimer dm_doEvery(long delay, Runnable r) { return dm_ownTimer(doEvery(delay, delay, dm_rEnter(r))); } static public FixedRateTimer dm_doEvery(long delay, long firstDelay, Runnable r) { return dm_ownTimer(doEvery(delay, firstDelay, dm_rEnter(r))); } static public FixedRateTimer dm_doEvery(double initialSeconds, double delaySeconds, Runnable r) { return dm_ownTimer(doEvery(initialSeconds, delaySeconds, dm_rEnter(r))); } static public FixedRateTimer dm_doEvery(double delaySeconds, Runnable r) { return dm_ownTimer(doEvery(delaySeconds, dm_rEnter(r))); } static public void ensureConceptClassesAreIndexed(Collection classes) { for (Class c : unnullForIteration(classes)) ensureConceptClassIsIndexed(c); } static public JButton jPopDownButton_noText(final Object... menuParams) { return toolTip("Additional commands", jPopDownButton("", menuParams)); } static public Object[] litobjectarray(Object... l) { return litObjectArray(l); } static public String appendParamsToURL(String url, Map params) { return appendQueryToURL(url, params); } static public String appendParamsToURL(String url, Object... data) { return appendQueryToURL(url, data); } static public void vmBus_logMethodCall(String methodName, Object... argsOrVars) { vmBus_send("method_" + methodName, objectArrayPlus_inFront(argsOrVars, "thread", currentThread())); } static public String html(Object contents) { return fixHTML(contents); } static public A printStackTrace(A e) { print(getStackTrace(e)); return e; } static public void printStackTrace() { printStackTrace(new Throwable()); } static public void printStackTrace(String msg) { printStackTrace(new Throwable(msg)); } static public void printStackTrace(String msg, Throwable e) { printStackTrace(new Throwable(msg, e)); } static public Object subBot_serve500() { return call(getMainBot(), "serve500"); } static public Object subBot_serve500(String msg) { return call(getMainBot(), "serve500", msg); } static public Object subBot_serve500(Throwable error) { return subBot_serve500(renderStackTrace(error)); } static public String getStackTrace(Throwable throwable) { lastException(throwable); return getStackTrace_noRecord(throwable); } static public String getStackTrace_noRecord(Throwable throwable) { StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer)); return hideCredentials(writer.toString()); } static public String getStackTrace() { return getStackTrace_noRecord(new Throwable()); } static public String getStackTrace(String msg) { return getStackTrace_noRecord(new Throwable(msg)); } static public void htmlencode_forParams_useV2() { htmlencode_forParams_useV2.set(true); } static public void change() { callOpt(getOptMC("mainConcepts"), "allChanged"); } static public Map mapPlus(Map m, Object... data) { m = cloneMap(m); litmap_impl(m, data); return m; } static public Map mapMinus(Map map, Object... keys) { if (empty(keys)) return map; Map m2 = cloneMap(map); for (Object key : keys) m2.remove(key); return m2; } static public String aGlobalID() { return randomID(globalIDLength()); } static public String aGlobalID(Random random) { return randomID(random, globalIDLength()); } static public AutoCloseable temp_printPrefix(String prefix) { Object oldValue = print_byThread(); print_setPrefixForThread(prefix); return new AutoCloseable() { public String toString() { return "print_byThread().set(oldValue);"; } public void close() throws Exception { print_byThread().set(oldValue); } }; } static public Map decodeURIParams(String query) { return decodeHQuery(query); } static public boolean cset_trueIfChanged(Concept c, Object... values) { try { return cset(c, values) != 0; } catch (Exception __e) { throw rethrow(__e); } } static public Object subBot_serveFile_maxCache(File file) { return subBot_maxCacheHeaders(subBot_serveFile(file)); } static public Object subBot_serveFile_maxCache(File file, String mimeType) { return subBot_maxCacheHeaders(subBot_serveFile(file, mimeType)); } static public String dropAfterSlash(String s) { if (s == null) return null; int i = s.indexOf('/'); return i < 0 ? s : rtrim(substring(s, 0, i)); } static public String binaryMimeType() { return "application/octet-stream"; } static public Object subBot_maxCacheHeaders(Object response) { return callMainBot("maxCacheHeaders", response); } static public Object serveInputStream(InputStream in, String mimeType) { return subBot_serveInputStream(in, mimeType); } static public BufferedInputStream bufferedFileInputStream(File f) { return bufferedInputStream(f); } static public BufferedInputStream bufferedFileInputStream(File f, int bufSize) { try { return new BufferedInputStream(new FileInputStream(f), bufSize); } catch (Exception __e) { throw rethrow(__e); } } static public String rawLink(String pageName) { return "/" + parseSnippetID(getProgramID()) + "/raw" + addPrefix("/", pageName); } static public String rawLink() { return "/" + parseSnippetID(getProgramID()) + "/raw"; } static public String rawLink(String pageName, String contents) { return ahref(rawLink(pageName), contents); } static public String webChatBotLogsHTML2(final String baseLink, final Map params) { return withDBLock(new F0() { public String get() { try { List l = new ArrayList(); for (Conversation conv : sortByCalculatedFieldDesc(list(Conversation.class), new F1() { public Object get(Conversation c) { try { return empty(c.msgs) ? c.created : last(c.msgs).time; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "empty(c.msgs) ? c.created : last(c.msgs).time"; } })) { List> dialogs = reversed(unnull(conv.oldDialogs)); if (l(conv.msgs) > 1) l.add(webChatBotLogsHTML_formatDialog(str(conv.id), conv.msgs)); int i = 2; for (List msgs : dialogs) if (l(msgs) > 1) l.add(webChatBotLogsHTML_formatDialog(conv.id + "/" + (i++), msgs)); } int perPage = 50, n = parseIntOpt(params.get("n")); return h3_htitle("Chat Logs") + pageNav2(baseLink, l(l), n, perPage, "n") + ul(subList(l, n, n + perPage), null, "style", "margin-top: 1em"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new L l;\r\n for (Conversation conv : sortByCalculatedFieldDesc(list Conv..."; } }); } static public String jsonEncode_breakAtLevels(Object o) { return jsonEncode_breakAtLevels(5, o); } static public String jsonEncode_breakAtLevels(int levels, Object o) { StringBuilder buf = new StringBuilder(); jsonEncode_breakAtLevels(levels, o, buf, 1); return str(buf); } static public void jsonEncode_breakAtLevels(int levels, Object o, StringBuilder buf, int level) { if (o == null) buf.append("null"); else if (o instanceof String) buf.append(quote((String) o)); else if (o instanceof Number || o instanceof Boolean) buf.append(o); else if (o instanceof Map) { Map map = (Map) o; buf.append("{"); boolean first = true; for (Object key : keys(map)) { if (first) first = false; else buf.append(","); if (level == 1) buf.append("\n" + spaces(level * 2)); buf.append(quote((String) key)); buf.append(":"); jsonEncode_breakAtLevels(levels, map.get(key), buf, level + 1); } if (level <= levels) buf.append("\n" + spaces((level - 1) * 2)); buf.append("}"); } else if (o instanceof Collection) { Collection l = (Collection) o; buf.append("["); boolean first = true; for (Object element : l) { if (first) first = false; else buf.append(","); if (level <= levels) buf.append("\n" + spaces(level * 2)); jsonEncode_breakAtLevels(levels, element, buf, level + 1); } if (level <= levels) buf.append("\n" + spaces((level - 1) * 2)); buf.append("]"); } else throw fail("Unknown object for JSON encoding: " + className(o)); } static public List allToString(Iterable c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static public List allToString(Object[] c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static public String fileInfo(File f) { return renderFileInfo(f); } static public String fileInfo(String f) { return renderFileInfo(newFile(f)); } static public File backupConceptsNow() { return backupConceptsNow(db_mainConcepts()); } static public File backupConceptsNow(Concepts cc) { if (cc == null) return null; File f1 = cc.conceptsFile(); File f2 = fileInSameDir(f1, "backups/concepts.structure" + (cc.useGZIP ? ".gz" : "") + ".backup" + ymd_minus_hms()); return copyFile(f1, f2); } static public String hhtml_title_body(String title, Object bodyContents, Object... bodyParams) { return hhtml_head_title_body(title, bodyContents, bodyParams); } static public String nMessages(long n) { return n2(n, "message"); } static public String nMessages(Collection l) { return nMessages(l(l)); } static public String hstylesheetsrc(String src) { return tag("link", "", "rel", "stylesheet", "href", src); } static public long sysNow() { ping(); return System.nanoTime() / 1000000; } static public int parseInt(String s) { return emptyString(s) ? 0 : Integer.parseInt(s); } static public int parseInt(char c) { return Integer.parseInt(str(c)); } static public int toInt(Object o) { if (o == null) return 0; if (o instanceof Number) return ((Number) o).intValue(); if (o instanceof String) return parseInt((String) o); if (o instanceof Boolean) return boolToInt((Boolean) o); throw fail("woot not int: " + getClassName(o)); } static public int toInt(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static public List cloneSubList(List l, int startIndex, int endIndex) { return newSubList(l, startIndex, endIndex); } static public List cloneSubList(List l, int startIndex) { return newSubList(l, startIndex); } static volatile public boolean sleep_noSleep = false; static public void sleep(long ms) { ping(); if (ms < 0) return; if (isAWTThread() && ms > 100) throw fail("Should not sleep on AWT thread"); try { Thread.sleep(ms); } catch (Exception e) { throw new RuntimeException(e); } } static public void sleep() { try { if (sleep_noSleep) throw fail("nosleep"); print("Sleeping."); sleepQuietly(); } catch (Exception __e) { throw rethrow(__e); } } static public Object serveJSON_breakAtLevels(int levels, Object... data) { return serveText(jsonEncode_breakAtLevels(levels, jsonPrepareData(data))); } static public Boolean trueOrNull(Boolean b) { return eq(b, false) ? null : b; } static public String or2_trim(String a, String b) { a = trim(a); if (nempty(a)) return a; return trim(b); } static public String or2_trim(String a, String b, String c) { return or2_trim(or2_trim(a, b), c); } static public String hcss(Object contents) { if (contents instanceof String && isRelativeOrAbsoluteURL((String) contents)) return hstylesheetsrc((String) contents); else return htag("style", contents); } static public String hexColorToCSSRGB(String hex) { return empty(hex) ? null : "rgb(" + joinWithComma(rgbToIntList(new RGB(hex))) + ")"; } static public String stringIf(boolean b, String s) { return stringIfTrue(b, s); } static public String stringIf(String s, boolean b) { return stringIf(b, s); } static public String loadSnippet_cached(String id) { return loadSnippet_simpleCache(id); } static public String urlencode(String x) { try { return URLEncoder.encode(unnull(x), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } static public String lower(String s) { return s == null ? null : s.toLowerCase(); } static public char lower(char c) { return Character.toLowerCase(c); } static public String psI_str(String snippetID) { return str(psI(snippetID)); } static public String jsBool(boolean b) { return b ? "true" : "false"; } static public String hreplaceTitle(String html, String newTitle) { return hreplacetag(html, "title", htitle(newTitle)); } static public Object subBot_serveJavaScript(String html) { return subBot_serveWithContentType(html, "text/javascript"); } static public A conceptWhere(Class c, Object... params) { return findConceptWhere(c, params); } static public A conceptWhere(Concepts cc, Class c, Object... params) { return findConceptWhere(cc, c, params); } static public String urldecode(String x) { try { return URLDecoder.decode(unnull(x), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } static public Map guessMimeTypeFromFileName_map = litmap(".css", "text/css", ".js", "text/javascript"); static public String guessMimeTypeFromFileName(String name) { return guessMimeTypeFromFileName(name, binaryMimeType()); } static public String guessMimeTypeFromFileName(String name, String defaultMimeType) { String __1 = guessMimeTypeFromFileName_map.get(fileExtension(name)); if (!empty(__1)) return __1; return or2(URLConnection.guessContentTypeFromName(name), defaultMimeType); } static public String afterLastSlash(String s) { if (s == null) return null; int i = s.lastIndexOf('/'); return i < 0 ? s : substring(s, i + 1); } static public String hhtml_head_title_body(String title, Object bodyContents, Object... bodyParams) { return hhtml(hhead(htitle(title)) + "\n" + hbody(bodyContents, bodyParams)); } static public String h2(String s, Object... params) { return tag("h2", s, params); } static public String hcss_linkColorInherit() { return hcss("a { color: inherit; }"); } static public Collection conceptsWhere(Class c, Object... params) { return findConceptsWhere(c, params); } static public Collection conceptsWhere(String c, Object... params) { return findConceptsWhere(c, params); } static public Collection conceptsWhere(Concepts concepts, Class c, Object... params) { return findConceptsWhere(concepts, c, params); } static public List replace(List l, A a, A b) { for (int i = 0; i < l(l); i++) if (eq(l.get(i), a)) l.set(i, b); return l; } static public List replace(A a, A b, List l) { return replace(l, a, b); } static public String replace(String s, String a, String b) { return s == null ? null : a == null || b == null ? s : s.replace(a, b); } static public String replace(String s, char a, char b) { return s == null ? null : s.replace(a, b); } static public String ymd_minus_hm() { return ymd() + "-" + hhmm(); } static public Object serveCSVWithFileName(String fileName, String text) { Object response = serveWithContentType(text, "text/csv"); call(response, "addHeader", "Content-Disposition", "inline; filename=\"" + fileName + "\""); return response; } static public ThreadLocal htmlTable2_cellEncoder = new ThreadLocal(); static public String htmlTable2(Object data, Object... __) { boolean htmlEncode = optPar("htmlEncode", __, true); boolean useBr = boolPar("useBr", __); Map paramsByColName = (Map) (optPar("paramsByColName", __)); Object[] tableParams = (Object[]) (optPar("tableParams", __)); Object[] trParams = (Object[]) (optPar("trParams", __)); Object[] tdParams = (Object[]) (optPar("tdParams", __)); Map replaceHeaders = (Map) (optPar("replaceHeaders", __)); boolean noHeader = boolPar("noHeader", __); List> rows = new ArrayList(); List cols = new ContentsIndexedList(); if (data instanceof List) { for (Object x : (List) data) { try { rows.add(dataToTable_makeRow(x, cols)); } catch (Throwable __e) { _handleException(__e); } } } else if (data instanceof Map) { Map map = (Map) data; for (Object key : map.keySet()) { Object value = map.get(key); rows.add(litlist(structureOrText(key), structureOrText(value))); } } else print("Unknown data type: " + data); int w = 0; for (List row : rows) w = max(w, l(row)); StringBuilder buf = new StringBuilder(); buf.append(hopeningtag("table", paramsPlus(tableParams, "border", html_valueLessParam())) + "\n"); if (!noHeader) { buf.append("\n"); for (String cell : padList(cols, w, "")) buf.append(" " + htmlTable2_encodeCell(getOrKeep(replaceHeaders, cell), htmlEncode, useBr) + "\n"); buf.append("\n"); } for (List row : rows) { buf.append(hopeningtag("tr", trParams)); int i = 0; for (String cell : padList(row, w, "")) { String col = get(cols, i++); Object[] params = paramsPlus(tdParams, mapGet(paramsByColName, col)); buf.append(" " + tag("td", htmlTable2_encodeCell(cell, htmlEncode, useBr), params) + "\n"); } buf.append("\n"); } buf.append("\n"); return buf.toString(); } static public String htmlTable2_encodeCell(String cell, boolean useHtmlEncode, boolean useBr) { if (htmlTable2_cellEncoder.get() != null) return (String) callF(htmlTable2_cellEncoder.get(), cell); if (useHtmlEncode) cell = htmlEncode2(cell); if (useBr) cell = nlToBr(cell); return cell; } static public NavigableMap emojiShortNameMap_cache; static public NavigableMap emojiShortNameMap() { if (emojiShortNameMap_cache == null) emojiShortNameMap_cache = emojiShortNameMap_load(); return emojiShortNameMap_cache; } static public NavigableMap emojiShortNameMap_load() { NavigableMap map = ciMap(); for (Map m : rawEmojisList()) { String shortName = (String) (m.get("shortname")); String emoji = (String) (m.get("emoji")); if (startsWith(shortName, ":")) map.put(shortName, emoji); } return map; } static public String pre(Object contents, Object... params) { return tag("pre", contents, params); } static public void tt() { typeWriterConsole(); } static public String tt(Object contents, Object... params) { return tag("tt", contents, params); } static public String hjavascript_src_withType(String src, Object... __) { return hfulltag("script", "", paramsPlus_inFront(__, "src", src, "type", "text/javascript")); } static public String htableRaw2(List data, List paramsTable, List paramsTR, List paramsTD) { StringBuilder buf = new StringBuilder(); for (List row : data) { buf.append(hopeningTag("tr", toObjectArray(paramsTR))); for (Object cell : row) buf.append(htd(cell, toObjectArray(paramsTD))).append("\n"); buf.append("\n"); } return htag("table", buf, toObjectArray(paramsTable)); } static public List nonNulls(Iterable l) { return withoutNulls(l); } static public List nonNulls(A[] l) { return withoutNulls(l); } static public Map nonNulls(Map map) { return withoutNulls(map); } static public List listZIP(File inZip) { return listZip(inZip); } static public String appendSlash(String s) { return addSlash(s); } static public byte[] loadBinaryFromZip(File inZip, String fileName) { try { ZipFile zip = new ZipFile(inZip); try { ZipEntry entry = zip.getEntry(fileName); if (entry == null) return null; InputStream fin = zip.getInputStream(entry); ByteArrayOutputStream baos = new ByteArrayOutputStream(); copyStream(fin, baos); fin.close(); return baos.toByteArray(); } finally { zip.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean fileContentsIs(File f, byte[] data) { try { if (isFile(f) != (data != null)) return false; int l = l(data); if (fileSize(f) != l) return false; BufferedInputStream in = bufferedFileInputStream(f); try { for (int ofs = 0; ofs < l; ofs++) if (data[ofs] != (byte) in.read()) return false; return true; } finally { _close(in); } } catch (Exception __e) { throw rethrow(__e); } } public static byte[] saveBinaryFile(String fileName, byte[] contents) { try { File file = new File(fileName); File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = fileName + "_temp"; FileOutputStream fileOutputStream = newFileOutputStream(tempFileName); fileOutputStream.write(contents); fileOutputStream.close(); if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (!new File(tempFileName).renameTo(file)) throw new IOException("Can't rename " + tempFileName + " to " + fileName); vmBus_send("wroteFile", file); return contents; } catch (Exception __e) { throw rethrow(__e); } } static public byte[] saveBinaryFile(File fileName, byte[] contents) { return saveBinaryFile(fileName.getPath(), contents); } static public void touchConcept(Concept c) { if (c != null) c.change(); } static public String nChanges(long n) { return n2(n, "change"); } static public String nChanges(Collection l) { return nChanges(l(l)); } static public String squareBracket(String s) { return "[" + s + "]"; } static public String hcss_responstableForForms() { return hcss("\r\n .responstableForForms {\r\n margin: 1em 0;\r\n /*width: 100%;*/\r\n overflow: hidden;\r\n background: #FFF;\r\n color: #024457;\r\n border-radius: 10px;\r\n border: 1px solid #167F92;\r\n }\r\n \r\n .responstableForForms tr {\r\n border: 1px solid #D9E4E6;\r\n }\r\n .responstableForForms tr:nth-child(odd) {\r\n background-color: #EAF3F3;\r\n }\r\n .responstableForForms th {\r\n display: none;\r\n border: 1px solid #FFF;\r\n background-color: #167F92;\r\n color: #FFF;\r\n padding: 1em;\r\n }\r\n .responstableForForms th:first-child {\r\n display: table-cell;\r\n text-align: center;\r\n }\r\n .responstableForForms th:nth-child(2) {\r\n display: table-cell;\r\n }\r\n .responstableForForms th:nth-child(2) span {\r\n display: none;\r\n }\r\n .responstableForForms th:nth-child(2):after {\r\n content: attr(data-th);\r\n }\r\n @media (min-width: 480px) {\r\n .responstableForForms th:nth-child(2) span {\r\n display: block;\r\n }\r\n .responstableForForms th:nth-child(2):after {\r\n display: none;\r\n }\r\n }\r\n .responstableForForms td {\r\n display: block;\r\n word-wrap: break-word;\r\n /*max-width: 7em;*/\r\n }\r\n .responstableForForms td:first-child {\r\n display: table-cell;\r\n text-align: center;\r\n border-right: 1px solid #D9E4E6;\r\n }\r\n @media (min-width: 480px) {\r\n .responstableForForms td {\r\n border: 1px solid #D9E4E6;\r\n }\r\n }\r\n .responstableForForms th, .responstableForForms td {\r\n text-align: left;\r\n margin: .5em 1em;\r\n }\r\n @media (min-width: 480px) {\r\n .responstableForForms th, .responstableForForms td {\r\n display: table-cell;\r\n padding: 1em;\r\n }\r\n }\r\n "); } static public String loadJQuery2() { return ""; } static public String hjs_selectize() { return "\r\n \r\n \r\n "; } static public JavaScript hjs_copyToClipboard() { return new JavaScript("\r\n const copyToClipboard = str => {\r\n const el = document.createElement('textarea');\r\n el.value = str;\r\n el.setAttribute('readonly', '');\r\n el.style.position = 'absolute';\r\n el.style.left = '-9999px';\r\n document.body.appendChild(el);\r\n const selected =\r\n document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;\r\n el.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(el);\r\n if (selected) {\r\n document.getSelection().removeAllRanges();\r\n document.getSelection().addRange(selected);\r\n }\r\n };\r\n "); } static public String hNotificationPopups() { return hStylesheetSnippet_maxCache("#1029723") + hjssnippet_maxCache("#1029726") + hjs("\r\n function successNotification(text) {\r\n window.createNotification({ theme: 'success', showDuration: 3000 })({ message: text });\r\n }\r\n \r\n function errorNotification(text) {\r\n window.createNotification({ theme: 'error', showDuration: 3000 })({ message: text });\r\n }\r\n "); } static public String joinWithVBar(Iterable l) { return join(" | ", l); } static public String joinWithVBar(String... l) { return joinWithVBar(asList(l)); } static public boolean neqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return false; return true; } static public boolean isConceptList(Object o) { if (!(o instanceof List)) return false; List l = (List) o; for (Object x : l) if (!(x instanceof Concept)) return false; return true; } static public String joinMap(Object f, Iterable l) { return join(map(f, l)); } static public String joinMap(Iterable l, Object f) { return joinMap(f, l); } static public String joinMap(Iterable l, IF1 f) { return joinMap(f, l); } static public String joinMap(IF1 f, Iterable l) { return join(map(f, l)); } static public String joinMap(String separator, Map map, IF2 f) { return join(separator, map(map, f)); } static public String htmlEncode_nlToBr_withIndents(String s) { return nlToBr_withIndents(htmlEncode(s)); } static public int indexOfPred(List l, Object pred) { for (int i = 0; i < l(l); i++) if (checkCondition(pred, l.get(i))) return i; return -1; } static public int indexOfPred(List l, IF1 pred) { return indexOfPred(l, (Object) pred); } static public String hcrud_mergeTables(String table1, String table2, String connector) { List tok1 = htmlTok(table1), tok2 = htmlTok(table2); List tbl1 = first(findContainerTag(tok1, "table")); List tbl2 = first(findContainerTag(tok2, "table")); if (tbl1 == null) return table2; if (tbl2 == null) return table1; List> rows1 = findContainerTag(tbl1, "tr"); List> rows2 = findContainerTag(tbl2, "tr"); print("rows1: " + l(rows1) + ", rows2: " + l(rows2)); int nRows = max(l(rows1), l(rows2)); List rows = new ArrayList(); for (int i = 0; i < nRows; i++) { List row1 = dropFirstTwoAndLastTwo(get(rows1, i)); List row2 = dropFirstTwoAndLastTwo(get(rows2, i)); row2 = dropFirst(row2, indexOfIC(row2, "") + 1); rows.add(tr(join(concatLists(row1, ll(td(connector)), row2)))); } replaceTokens(tbl1, 2, l(tbl1) - 2, lines(rows)); return join(tok1); } static public void addInFront(List c, A a) { addFirst(c, a); } static public String hjs_imgUploadBase64Encoder() { return hscript("\r\n var imgConverted = false;\r\n \r\n function submitWithImageConversion(form) {\r\n console.log(\"imgConverted: \" + imgConverted + \", form: \" + form);\r\n if (imgConverted) return true;\r\n imgConverted = true;\r\n var file = $('#imgUploader')[0].files[0];\r\n if (file == null) return true;\r\n var reader = new FileReader();\r\n\r\n // delay form submit until reader is done\r\n reader.onloadend = function () {\r\n var b64 = reader.result.replace(/^data:.+;base64,/, '');\r\n $(\"#f_img_base64\").val(b64);\r\n console.log(\"Got base64 data: \" + b64.length);\r\n setTimeout(function() {\r\n $(form).submit();\r\n }, 1000);\r\n };\r\n\r\n reader.readAsDataURL(file);\r\n return false;\r\n }\r\n "); } static public String himageupload(Object... params) { return hfileupload(paramsPlus(params, "accept", "image/png,image/jpeg,image/gif")); } static public String hhiddenWithIDAndName(String idAndName) { return hhiddenWithIDAndName(idAndName, null); } static public String hhiddenWithIDAndName(String idAndName, Object value, Object... params) { return tag("input", "", paramsPlus(params, "type", "hidden", "id", idAndName, "name", idAndName, "value", value)); } static public String hjs_fileUploadBase64Encoder() { return hscript("\r\n var fileConverted = false;\r\n \r\n function submitWithFileConversion(form) {\r\n if (fileConverted) return true;\r\n fileConverted = true;\r\n var file = $('#fileUploader')[0].files[0];\r\n if (file == null) return true;\r\n var reader = new FileReader();\r\n\r\n // delay form submit until reader is done\r\n reader.onloadend = function () {\r\n var b64 = reader.result.replace(/^data:.+;base64,/, '');\r\n $(\"#f_file_base64\").val(b64);\r\n console.log(\"Got base64 data: \" + b64.length);\r\n setTimeout(function() {\r\n $(form).submit();\r\n }, 1000);\r\n };\r\n\r\n reader.readAsDataURL(file);\r\n return false;\r\n }\r\n "); } static public String haudioUpload(Object... params) { return hfileupload(paramsPlus(params, "accept", joinWithComma(mp3mimeType(), oggMimeType(), wavMimeType(), m4aMimeType()))); } static public Object[] litparams(Object... l) { int n = 0, n1 = l(l); for (int i = 0; i < n1; i += 2) if (l[i] != null && l[i + 1] != null) ++n; if (n == 0) return null; Object[] params = new Object[n * 2]; int j = 0; for (int i = 0; i < n1; i += 2) { Object key = l[i], value = l[i + 1]; if (key != null && value != null) { params[j++] = key; params[j++] = value; } } return params; } static public String hfileupload(Object... params) { return hinputtag("", paramsPlus_noOverwrite(params, "type", "file", "name", "thefile")); } static public boolean isSubclassOf(Class a, Class b) { return isSubclass(a, b); } static public String hPopDownButton(String... entries) { String id = "dropdown-" + aGlobalID(), outerID = "outer-" + id; String onclick = replaceDollarVars("\r\n var x = document.getElementById($id);\r\n x.style.display = window.getComputedStyle(x).display === \"none\" ? \"block\" : \"none\";\r\n console.log(\"popup \" + id + \" display: \" + x.style.display);\r\n ", "$id", jsQuote(id)); return hstyle(replaceDollarVars("\r\n #$id ul {\r\n list-style-type: none;\r\n margin: 0;\r\n padding: 0;\r\n width: 200px;\r\n background-color: #f1f1f1;\r\n }\r\n \r\n #$id {\r\n position: absolute;\r\n display:none;\r\n background-color: #f9f9f9;\r\n width:auto;\r\n height:200px;\r\n overflow: auto;\r\n \r\n min-width: 160px;\r\n box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);\r\n \r\n z-index: 99;\r\n }\r\n \r\n #$id li a {\r\n text-decoration: none;\r\n color: #000;\r\n }\r\n\r\n #$id li { \r\n display: block;\r\n border-bottom: 1px solid #555;\r\n padding: 8px 16px;\r\n color: #000;\r\n }\r\n " + "\r\n #$id li:hover, #$id li:hover > a {\r\n background-color: #3399ff;\r\n color: white;\r\n }\r\n ", "$id", id)) + hdiv(span(htmlEncode2(unicode_smallDownPointingTriangle()), "onclick", onclick) + hdiv(ul(entries), "id", id), "style", "position: relative; display: inline-block; cursor: context-menu", "id", outerID) + hscript(replaceDollarVars("\r\n if (typeof $ !== 'undefined')\r\n $('body').click(function(e) {\r\n //console.log(\"target=\" + e.target + \", outerID=$outerID\");\r\n if (!$(e.target).closest('#$outerID').length) {\r\n //console.log(\"hiding $id\");\r\n $(\"#$id\").hide();\r\n }\r\n });\r\n ", "id", id, "outerID", outerID)); } static public String hPopDownButton(Collection entries) { return hPopDownButton(toStringArray(entries)); } static public List sortedByConceptID(Collection c) { return sortedByCalculatedField(__79 -> conceptID(__79), c); } static public List takeFirst(List l, int n) { return l(l) <= n ? l : newSubListOrSame(l, 0, n); } static public List takeFirst(int n, List l) { return takeFirst(l, n); } static public String takeFirst(int n, String s) { return substring(s, 0, n); } static public String takeFirst(String s, int n) { return substring(s, 0, n); } static public CharSequence takeFirst(int n, CharSequence s) { return subCharSequence(s, 0, n); } static public List takeFirst(int n, 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 public List takeFirst(int n, Iterable i) { if (i == null) return null; return i == null ? null : takeFirst(n, i.iterator()); } static public List takeFirst(int n, IterableIterator i) { return takeFirst(n, (Iterator) i); } static public int[] takeFirst(int n, int[] a) { return takeFirstOfIntArray(n, a); } static public String addParamsToURL(String url, Map params) { return appendQueryToURL(url, params); } static public String addParamsToURL(String url, Object... data) { return appendQueryToURL(url, data); } static public Class _getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; } } static public Class _getClass(Object o) { return o == null ? null : o instanceof Class ? (Class) o : o.getClass(); } static public Class _getClass(Object realm, String name) { try { return classLoaderForObject(realm).loadClass(classNameToVM(name)); } catch (ClassNotFoundException e) { return null; } } static public String shortClassName(Object o) { if (o == null) return null; Class c = o instanceof Class ? (Class) o : o.getClass(); String name = c.getName(); return shortenClassName(name); } static public String targetBlankIf(String link, Object contents, boolean targetBlank, Object... params) { return ahref_possiblyTargetBlank(link, contents, targetBlank, params); } static public String targetBlankIf(boolean targetBlank, String link, Object contents, Object... params) { return ahref_possiblyTargetBlank(targetBlank, link, contents, params); } static public Set joinSets(Collection... l) { Set set = similarEmptySet(first(l)); for (Collection o : l) if (o != null) set.addAll(o); return set; } static public String shortName(Object o) { return shortClassName(o); } static public A replaceIfEquals(A a, A b, A c) { return replaceIfEqual(a, b, c); } static public String className(Object o) { return getClassName(o); } static public Type type_LS() { return new ParameterizedTypeImpl(null, List.class, String.class); } static public List tlft(String s) { return toLinesFullTrim(s); } static public List tlft(File f) { return toLinesFullTrim(f); } static public String b(Object contents, Object... params) { return tag("b", contents, params); } static public String ol_htmlEncode(String... list) { return ol_htmlEncode(asList(list)); } static public String ol_htmlEncode(List list, Object... params) { return ol_htmlEncode((Collection) list, params); } static public String ol_htmlEncode(Collection list, Object... params) { return ol(lmap(__80 -> htmlEncode2(__80), list), params); } static public void replaceMap(Map dest, Map src) { if (dest == src) return; dest.clear(); dest.putAll(src); } static public String formatLocalDateWithMinutes(long time) { return localDateWithMinutes(time); } static public String formatLocalDateWithMinutes() { return localDateWithMinutes(); } static public String renderColonProperties(Map map) { return formatColonProperties(map); } static public String renderColonProperties(List> l) { return formatColonProperties(l); } static public String ol(String... list) { return ol(asList(list)); } static public String ol(List list, Object... params) { StringBuilder buf = new StringBuilder(); int i = indexOf(params, null); if (i == -1) i = l(params); for (String s : withoutNulls(list)) buf.append(tag("li", s, subArray(params, i + 1))).append("\n"); return containerTag("ol", buf, subArray(params, 0, i)) + "\n"; } static public String pnlToStringWithEmptyLines_rtrim(Iterable l) { return rtrim(pnlToStringWithEmptyLines(l)); } static public String himg(String src, Object... params) { return tag("img", "", arrayPlus(params, "src", isSnippetID(src) ? snippetImageLink(src) : src)); } static public String himg(BufferedImage img, Object... params) { return himg(dataURL(jpegMimeType(), toJPEG(img)), params); } static public String hcrud_imagePreviewStyle() { return "max-width: 200px; max-height: 100px; width: auto; height: auto"; } static public String toK_str(long l) { return str_toK(l); } static public long fileSize(String path) { return getFileSize(path); } static public long fileSize(File f) { return getFileSize(f); } static public void saveFileVerbose(File f, byte[] data) { saveBinaryFileVerbose(f, data); } static public byte[] base64decode(String s) { byte[] alphaToInt = base64decode_base64toint; int sLen = s.length(); int numGroups = sLen / 4; if (4 * numGroups != sLen) throw new IllegalArgumentException("String length must be a multiple of four."); int missingBytesInLastGroup = 0; int numFullGroups = numGroups; if (sLen != 0) { if (s.charAt(sLen - 1) == '=') { missingBytesInLastGroup++; numFullGroups--; } if (s.charAt(sLen - 2) == '=') missingBytesInLastGroup++; } byte[] result = new byte[3 * numGroups - missingBytesInLastGroup]; int inCursor = 0, outCursor = 0; for (int i = 0; i < numFullGroups; i++) { int ch0 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); int ch1 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); int ch2 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); int ch3 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4)); result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2)); result[outCursor++] = (byte) ((ch2 << 6) | ch3); } if (missingBytesInLastGroup != 0) { int ch0 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); int ch1 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4)); if (missingBytesInLastGroup == 1) { int ch2 = base64decode_base64toint(s.charAt(inCursor++), alphaToInt); result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2)); } } return result; } static public int base64decode_base64toint(char c, byte[] alphaToInt) { int result = alphaToInt[c]; if (result < 0) throw new IllegalArgumentException("Illegal character " + c); return result; } static final public byte[] base64decode_base64toint = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; static public String beforeColonOrAll(String s) { return takeFirst(smartIndexOf(s, ':'), s); } static public Object withDBLock(Object r) { Lock __0 = db_mainConcepts().lock; lock(__0); try { return callF(r); } finally { unlock(__0); } } static public A withDBLock(F0 r) { return (A) withDBLock((Object) r); } static public Object withDBLock(Concepts concepts, Object r) { Lock __1 = concepts.lock; lock(__1); try { return callF(r); } finally { unlock(__1); } } static public A withDBLock(Concepts concepts, F0 r) { return (A) withDBLock(concepts, (Object) r); } static public A withDBLock(Concept concept, IF0 r) { return (A) withDBLock(concept._concepts, r); } static public double elapsedSeconds_timestamp(long time) { return toSeconds(now() - time); } static public String div_floatRight(Object contents, Object... params) { return div(contents, params_stylePlus("float: right", params)); } static public String hbutton(String text, Object... params) { return hfulltag("button", text, params); } static public String htmlEncode2_gen(Object o) { return htmlEncode2(strOrEmpty(o)); } static public TreeSet litciset(String... items) { TreeSet set = caseInsensitiveSet(); for (String a : items) set.add(a); return set; } static public TreeSet litciset(Symbol... items) { TreeSet set = treeSet(); for (Symbol a : items) set.add(a); return set; } static public int countPred(Iterable c, Object pred) { return nfilter(c, pred); } static public int countPred(Object pred, Iterable c) { return nfilter(pred, c); } static public int countPred(Iterable c, IF1 pred) { return nfilter(c, pred); } static public String nConversations(long n) { return n2(n, "conversation"); } static public String nConversations(Collection l) { return nConversations(l(l)); } static public String nConversations(Map map) { return nConversations(l(map)); } static public File secretProgramFile(String progID, String fileName) { return new File(getSecretProgramDir(progID), fileName); } static public File secretProgramFile(String fileName) { return secretProgramFile(getProgramID(), fileName); } static public String pUnlessEmpty(String s, Object... __) { return empty(s) ? "" : p(s, __); } static public String joinNemptiesWithSpace(String... strings) { return joinNempties(" ", strings); } static public String joinNemptiesWithSpace(Collection strings) { return joinNempties(" ", strings); } static public ContentsIndexedList ciContentsIndexedList() { return new ContentsIndexedList(ciMap()); } static public Map mapPlus_inFront(Map m, Object... data) { LinkedHashMap m2 = new LinkedHashMap(); litmap_impl(m2, data); putAll(m2, m); return m2; } static public int addAndReturnIndex(List l, A a) { if (l == null) return -1; int idx = l.size(); l.add(a); return idx; } static public String formatCSVFileForExcel2(List rows) { String sep = "|"; return windowsLineBreaks("sep=" + sep + "\n" + mapToLines_rtrim(rows, row -> join(sep, map(row, col -> replace(newLinesToSpaces(str(col)), sep, " "))))); } static public Set putSetElementsFirst(Collection cl, Collection elements) { Set inputSet = asSet(cl); LinkedHashSet set = new LinkedHashSet(); for (A a : unnullForIteration(elements)) if (contains(inputSet, a)) set.add(a); addAll(set, cl); return set; } static public Set putSetElementsFirst(Collection cl, A... elements) { return putSetElementsFirst(cl, asList(elements)); } static public Cache> countryDialCodesMultiMap_cache = new Cache<>(() -> countryDialCodesMultiMap_load()); static public MultiMap countryDialCodesMultiMap() { return countryDialCodesMultiMap_cache.get(); } static public MultiMap countryDialCodesMultiMap_load() { return treeMultiMapIndexByField("dialCode", countryDialCodes()); } static public List splitAtComma_trim(String s) { return nempties(trimAll(splitAtComma(s))); } static public String dialCodeStringForCountryCode(String countryCode) { CountryDialCode cdc = countryDialCodeByCountryCode(countryCode); return cdc == null ? null : cdc.dialCode; } static public List mapToLines(Map map) { List l = new ArrayList(); for (Object key : keys(map)) l.add(str(key) + " = " + str(map.get(key))); return l; } static public String mapToLines(Map map, Object f) { return lines(map(map, f)); } static public String mapToLines(Object f, Map map) { return lines(map(map, f)); } static public String mapToLines(Object f, Iterable l) { return lines(map(f, l)); } static public String mapToLines(Iterable l, IF1 f) { return mapToLines((Object) f, l); } static public String mapToLines(IF1 f, Iterable l) { return mapToLines((Object) f, l); } static public String mapToLines(Map map, IF2 f) { return lines(map(map, f)); } static public String mapToLines(IF1 f, A data1, A... moreData) { return lines(map(f, data1, moreData)); } static public List collectSorted(Iterable c, String field) { return sorted(collect(c, field)); } static public List collectSorted(String field, Iterable c) { return collectSorted(c, field); } static public List concatMap(Object f, Iterable l) { return concatLists(map(f, l)); } static public List concatMap(Iterable l, Object f) { return concatMap(f, l); } static public List concatMap(Object f, Object[] l) { return concatLists(map(f, l)); } static public List concatMap(Object[] l, Object f) { return concatMap(f, l); } static public > List concatMap(Iterable l, IF1 f) { return concatMap(l, (Object) f); } static public > List concatMap(IF1 f, Iterable l) { return concatMap(l, f); } static public String dropPrefix_trim(String prefix, String s) { return dropPrefixTrim(prefix, s); } static public String formatLocalDateWithSeconds(long time) { return localDateWithSeconds(time); } static public String formatLocalDateWithSeconds() { return localDateWithSeconds(); } static public String imageSnippetURLOrEmptyGIF(String snippetID) { return empty(snippetID) ? smallestTransparentGIFDataURI() : snippetImageURL(snippetID); } static public Scorer scorerWithSuccessesAndErrors() { Scorer scorer = new Scorer(); scorer.successes = new ArrayList(); scorer.errors = new ArrayList(); return scorer; } static public List sortByFieldDesc(Collection c, final String field) { return sortedByFieldDesc(c, field); } static public List sortByFieldDesc(String field, Collection c) { return sortedByFieldDesc(field, c); } static public Object[] onlyNonNullParams(Object... params) { List out = new ArrayList(); for (int i = 0; i + 1 < l(params); i += 2) if (params[i] != null && params[i + 1] != null) { out.add(params[i]); out.add(params[i + 1]); } return toObjectArray(out); } static public A lowestConceptByField(Class c, String field) { return lowestConceptByField(db_mainConcepts(), c, field); } static public A lowestConceptByField(Concepts concepts, Class c, String field) { IFieldIndex index = concepts.getFieldIndex(c, field); if (index instanceof ConceptFieldIndexDesc) { Map.Entry e = ((NavigableMap) ((ConceptFieldIndexDesc) index).valueToObject.data).lastEntry(); return e == null ? null : (A) first((Collection) e.getValue()); } return lowestByField(field, concepts.list(c)); } static public java.util.Timer doAfter(long delay, Object r) { return doLater(delay, r); } static public java.util.Timer doAfter(double delaySeconds, Object r) { return doLater(delaySeconds, r); } static public A registerConcept(A c) { return registerConcept(db_mainConcepts(), c); } static public A registerConcept(Concepts cc, A c) { { if (cc != null) cc.register(c); } return c; } static public void indexConceptField(Class c, String field) { indexConceptField(db_mainConcepts(), c, field); } static public void indexConceptField(Concepts concepts, Class c, String field) { if (!isConceptFieldIndexed(concepts, c, field)) new ConceptFieldIndex(concepts, c, field); } static public void db() { conceptsAndBot(); } static public void db(Integer autoSaveInterval) { conceptsAndBot(autoSaveInterval); } static public void indexConceptFields(Object... params) { int i = 0; Concepts concepts; if (first(params) instanceof Concepts) { concepts = (Concepts) first(params); ++i; } else concepts = db_mainConcepts(); for (; i < l(params); i += 2) indexConceptField(concepts, (Class) params[i], (String) params[i + 1]); } static public A assertNotNull(A a) { assertTrue(a != null); return a; } static public A assertNotNull(String msg, A a) { assertTrue(msg, a != null); return a; } static public A assertNotNull(Scorer scorer, String msg, A a) { if (scorer == null) return assertNotNull(msg, a); if (a == null) { print("BAD - " + msg + " is null: " + a); scorer.add(false); } else { print("OK, " + msg + " not null: " + a); scorer.add(true); } return a; } static public void indexSingletonConcept(Concepts cc, Class c) { indexConceptField(cc, c, "_dummy"); } static public void indexSingletonConcept(Class c) { indexSingletonConcept(db_mainConcepts(), c); } static public Object subBot_noCacheHeaders(Object r) { call(r, "addHeader", "Cache-Control", "no-cache, must-revalidate, max-age=0"); return r; } static public Object subBot_serveHTML(Object html) { return subBot_serveWithContentType(str(html), "text/html"); } static public String nlToBr(String s) { return s.replace("\n", "
\n"); } static public String html_emojisToUnicode(String s) { return join(mapNonCodeTokens(__81 -> emojisToUnicode(__81), htmlTok(s))); } static public
A last(List l) { return empty(l) ? null : l.get(l.size() - 1); } static public char last(String s) { return empty(s) ? '#' : s.charAt(l(s) - 1); } static public int last(int[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static public double last(double[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static public A last(A[] a) { return l(a) != 0 ? a[l(a) - 1] : null; } static public A last(Iterator it) { A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static public A last(Collection l) { if (l == null) return null; if (l instanceof List) return (A) last((List) l); if (l instanceof SortedSet) return (A) last((SortedSet) l); Iterator it = iterator(l); A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static public A last(SortedSet l) { return l == null ? null : l.last(); } static public A last(CompactLinkedHashSet set) { return set == null ? null : set.last(); } static public int randomID_defaultLength = 12; static public String randomID(int length) { return makeRandomID(length); } static public String randomID(Random r, int length) { return makeRandomID(r, length); } static public String randomID() { return randomID(randomID_defaultLength); } static public String randomID(Random r) { return randomID(r, randomID_defaultLength); } static public String fullRawLink(String pageName) { return (subBot_isHttps() ? "https" : "http") + "://" + domain() + rawLink(pageName); } static public String unicode_undoArrow() { return unicodeFromCodePoint(0x21B6); } static public String htmldecode_dropAllTags(String html) { return htmldecode(dropAllTags(html)); } static public List splitAtVerticalBar(String s) { return s == null ? new ArrayList() : trimAll(asList(s.split("\\|"))); } static public A second(List l) { return get(l, 1); } static public A second(Iterable l) { if (l == null) return null; Iterator it = iterator(l); if (!it.hasNext()) return null; it.next(); return it.hasNext() ? it.next() : null; } static public A second(A[] bla) { return bla == null || bla.length <= 1 ? null : bla[1]; } static public B second(Pair p) { return p == null ? null : p.b; } static public A second(Producer p) { if (p == null) return null; if (p.next() == null) return null; return p.next(); } static public char second(String s) { return charAt(s, 1); } static public B second(Either e) { return e == null ? null : e.bOpt(); } static public String hbuttonOnClick_returnFalse(String text, String onClick, Object... params) { return hfulltag("button", text, paramsPlus(params, "onclick", addSuffix(trim(onClick), ";") + " return false;")); } static public String stringUnless(boolean b, String s) { return b ? "" : s; } static public List text_multipleChoiceSplit(String input, String multipleChoiceSeparator) { return trimAll(splitAt(input, dropSpaces(multipleChoiceSeparator))); } static public TreeSet asCISet(Iterable c) { return toCaseInsensitiveSet(c); } static public TreeSet asCISet(String... x) { return toCaseInsensitiveSet(x); } static public boolean contains(Collection c, Object o) { return c != null && c.contains(o); } static public boolean contains(Iterable it, Object a) { if (it != null) for (Object o : it) if (eq(a, o)) return true; return false; } static public boolean contains(Object[] x, Object o) { if (x != null) for (Object a : x) if (eq(a, o)) return true; return false; } static public boolean contains(String s, char c) { return s != null && s.indexOf(c) >= 0; } static public boolean contains(String s, String b) { return s != null && s.indexOf(b) >= 0; } static public boolean contains(BitSet bs, int i) { return bs != null && bs.get(i); } static public boolean contains(Producer p, A a) { if (p != null && a != null) while (true) { A x = p.next(); if (x == null) break; if (eq(x, a)) return true; } return false; } static public String hcheckbox(String name, boolean checked, Object... params) { return tag("input", "", paramsPlus(params, "type", "checkbox", "name", name, checked ? "checked" : null, "1")); } static public String hcheckbox(String name) { return hcheckbox(name, false); } static public String hcheckbox(String name, String text) { return hcheckboxWithText(name, text); } static public String unicode_crossProduct() { return unicodeFromCodePoint(0x2A2F); } static public String timeInTimeZoneWithOptionalDate_24(String timezone, long time) { return timeInTimeZoneWithOptionalDate_24(timeZone(timezone), time); } static public String timeInTimeZoneWithOptionalDate_24(TimeZone timezone, long time) { SimpleDateFormat format = simpleDateFormat("yyyy/MM/dd", timezone); String date = format.format(time); boolean needDate = neq(date, format.format(now())); return (needDate ? date + " " : "") + timeInTimeZone(timezone, time); } static public String hhead_title(String title) { return hhead(htitle(title)); } static public String jsBackLink() { return "javascript:history.go(-1)"; } static public File javaxDataDir_dir; static public File javaxDataDir() { return javaxDataDir_dir != null ? javaxDataDir_dir : new File(userHome(), "JavaX-Data"); } static public File javaxDataDir(String... subs) { return newFile(javaxDataDir(), subs); } static public boolean any(Object pred, Iterable l) { if (l != null) for (A a : l) if (isTrue(callF(pred, a))) return true; return false; } static public boolean any(IF1 pred, Iterable l) { return any((Object) pred, l); } static public boolean any(Iterable l, IF1 pred) { return any(pred, l); } static public boolean any(A[] l, IF1 pred) { if (l != null) for (A a : l) if (pred.get(a)) return true; return false; } static public boolean any(Iterable l) { if (l != null) for (Boolean a : l) if (isTrue(a)) return true; return false; } static public String ipToCountry2020_safe(String ip) { try { return or2(ipToCountry2020(ip), "?"); } catch (Throwable __e) { _handleException(__e); } return "?"; } static public String replaceSquareBracketVars(String s, Object... params) { if (empty(params)) return s; Map vars = mapKeys(__82 -> deSquareBracket(__82), (Map) litcimap(params)); return regexpReplaceIC(s, "\\[(.+?)\\]", matcher -> { String var = matcher.group(1); Object val = vars.get(var); return val == null ? matcher.group() : str(val); }); } static public List trimAll(Collection l) { List l2 = new ArrayList(); if (l != null) for (String s : l) l2.add(trim(s)); return l2; } static public List splitAt(String s, String splitter) { if (empty(splitter)) return null; List parts = new ArrayList(); int i = 0; if (s != null) while (i < l(s)) { int j = indexOf(s, splitter, i); if (j < 0) j = l(s); parts.add(substring(s, i, j)); i = j + l(splitter); } return parts; } static public String dropSpaces(String s) { return unnull(s).replace(" ", ""); } static public A lastThat(List l, Object pred) { for (int i = l(l) - 1; i >= 0; i--) { A a = l.get(i); if (checkCondition(pred, a)) return a; } return null; } static public A lastThat(Object pred, List l) { return lastThat(l, pred); } static public A lastThat(IF1 pred, List l) { return lastThat((Object) pred, l); } static public A lastThat(List l, IF1 pred) { return lastThat(pred, l); } static public File programDir_mine; static public File programDir() { return programDir(getProgramID()); } static public File programDir(String snippetID) { boolean me = sameSnippetID(snippetID, programID()); if (programDir_mine != null && me) return programDir_mine; File dir = new File(javaxDataDir(), formatSnippetIDOpt(snippetID)); if (me) { String c = caseID(); if (nempty(c)) dir = newFile(dir, c); } return dir; } static public File programDir(String snippetID, String subPath) { return new File(programDir(snippetID), subPath); } static public File newFile(File base, String... names) { for (String name : names) base = new File(base, name); return base; } static public File newFile(String name) { return name == null ? null : new File(name); } static public File newFile(String base, String... names) { return newFile(newFile(base), names); } static public String addSlashPrefix(String s) { return addPrefix("/", s); } static public boolean confirmOKCancel(final Component owner, final String msg) { return isTrue(swingAndWait(new F0() { public Object get() { try { return JOptionPane.showConfirmDialog(owner, msg, "JavaX", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret JOptionPane.showConfirmDialog(owner,\r\n msg, \"JavaX\", JOptionPane.OK_..."; } })); } static public boolean confirmOKCancel(String msg) { return confirmOKCancel(null, msg); } static public JTextField jtextfield() { return jTextField(); } static public JTextField jtextfield(String text) { return jTextField(text); } static public JTextField jtextfield(Object o) { return jTextField(o); } static public JPanel showFormTitled2(String title, Object... parts) { return showFormTitled_customLayout(formLayouter1(), title, parts); } static public String gtt(JTextComponent c) { return getTextTrim(c); } static public String gtt(JComboBox cb) { return getTextTrim(cb); } static public JWindow infoBox(String text) { return infoMessage(text); } static public JWindow infoBox(String text, double seconds) { return infoMessage(text, seconds); } static public JWindow infoBox(Throwable e) { return infoMessage(e); } static public File saveTextFile(String fileName, String contents) throws IOException { CriticalAction action = beginCriticalAction("Saving file " + fileName + " (" + l(contents) + " chars)"); try { File file = new File(fileName); mkdirsForFile(file); String tempFileName = fileName + "_temp"; File tempFile = new File(tempFileName); if (contents != null) { if (tempFile.exists()) try { String saveName = tempFileName + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (contents != null) if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); vmBus_send("wroteFile", file); return file; } finally { action.done(); } } static public File saveTextFile(File fileName, String contents) { try { saveTextFile(fileName.getPath(), contents); return fileName; } catch (Exception __e) { throw rethrow(__e); } } static public void inputText(final String msg, final Object action) { inputText(msg, "", action); } static public void inputText(final String msg, final String defaultText, final Object action) { final Object threadInfo = _threadInfo(); swingLater(new Runnable() { public void run() { try { final JTextField tf = jtextfield(defaultText); String title = joinStrings(" | ", msg, programName()); JComponent form = showFormTitled(title, unnull(msg), tf, new Runnable() { public void run() { try { vmBus_send("inputtingText_OK", threadInfo, msg, tf); callF_thread(action, getTextTrim(tf)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "vmBus_send(\"inputtingText_OK\", threadInfo, msg, tf);\r\n callF_thread(ac..."; } }); renameSubmitButton(form, "OK"); vmBus_send("inputtingText", threadInfo, msg, tf); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final JTextField tf = jtextfield(defaultText);\r\n String title = joinString..."; } }); } static public void inputText(String msg, String defaultText, IVF1 action) { inputText(msg, defaultText, (Object) action); } static public void inputText(String msg, IVF1 action) { inputText(msg, (Object) action); } static public Object subBot_serveRedirect(String url) { return call(getMainBot(), "serveRedirect", url); } static public String htmlQuery(Map params) { return empty(params) ? "" : "?" + makePostData(params); } static public String htmlQuery(Object... data) { return empty(data) ? "" : "?" + makePostData(data); } static public String html_evaluateIfTags(String html, IF1 pred) { List tok = htmlTok(html); boolean anyChange = false; while (true) { ping(); List ifTag = first(findContainerTag(tok, "if")); if (ifTag == null) break; anyChange = true; int iElse = indexOfIC(ifTag, ""); boolean val = pred.get(htmlTagFullParamString(second(ifTag))); if (val) { if (iElse >= 0) clearTokens(ifTag, iElse, l(ifTag) - 2); } else { clearTokens(ifTag, 2, iElse < 0 ? l(ifTag) - 2 : iElse + 1); } clearToken(ifTag, 1); clearToken(ifTag, l(ifTag) - 2); } return anyChange ? join(tok) : html; } static public String dropDollarPrefix(String s) { return dropPrefix("$", s); } static public String replaceDollarVars_dyn(String s, IF1 f) { if (f == null) return s; return regexpReplaceIC(s, "\\$(\\w+)", matcher -> { String var = matcher.group(1); String val = f.get(var); return val == null ? matcher.group() : str(val); }); } static public A syncGet(List l, int idx) { if (l == null || idx < 0) return null; synchronized (l) { return idx < l(l) ? l.get(idx) : null; } } static public B syncGet(Map map, A a) { if (map == null) return null; synchronized (map) { return map.get(a); } } static public String serveSnippetURL(String snippetID) { return "https://botcompany.de/serve/" + psI(snippetID); } static public IterableIterator> iterateWithIndex1(Collection l) { return iterateListWithIndex(l, 1); } static public IterableIterator> iterateWithIndex1(A[] l) { return iterateListWithIndex(asVirtualList(l), 1); } static public A pairA(Pair p) { return p == null ? null : p.a; } static public B pairB(Pair p) { return p == null ? null : p.b; } static public String ulIfNempty(Collection list, Object... params) { return empty(list) ? "" : ul(list, params); } static public String ahref_unstyled(String link, Object contents, Object... params) { if (link == null) return str(contents); return ahref(link, contents, paramsPlus(params, "style", unparseCSSParameter(mapPlus_noOverwrite(parseCSSParameter(stringPar("style", params)), "text-decoration", "none", "color", "inherit")))); } static public String prependSquareBracketed(Object o) { String s = str(o); return empty(s) ? "" : squareBracketed(s) + " "; } static public int countWords(String s) { return numberOfWords2(s); } static public List dropHTMLTags(List tok) { return dropAllTags(tok); } static public String dropHTMLTags(String html) { return dropAllTags(html); } static public boolean isValidInternationalPhoneNumber(String s) { InternationalPhoneValidator v = new InternationalPhoneValidator(s); v.run(); if (v.error != null) print(v.error); return v.valid; } static public String formatColonProperties(Map map) { return mapToLines(__83 -> joinPairWithColon(__83), mapToPairs(map)); } static public String formatColonProperties(List> l) { return mapToLines(__84 -> joinPairWithColon(__84), l); } static public void sendMailThroughScript(String senderInfo, String from, String to, String subject, String text) { List l = splitAt(senderInfo, "#"); if (l(l) != 2) throw fail("Bad mail sender info"); String url = first(l), pw = second(l); print("Sending mail through " + url); print("From: " + from); print("To: " + to); print("Subject: " + subject); print("Text:"); printIndent("> ", text); assertStartsWith("OK", postPage(url, "pw", pw, "from", from, "to", to, "subject", subject, "text", text)); } static public Lock appendToFile_lock = lock(); static public boolean appendToFile_keepOpen = false; static public HashMap appendToFile_writers = new HashMap(); static public void appendToFile(String path, String s) { try { Lock __0 = appendToFile_lock; lock(__0); try { mkdirsForFile(new File(path)); path = getCanonicalPath(path); Writer writer = appendToFile_writers.get(path); if (writer == null) { writer = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(path, true), "UTF-8")); if (appendToFile_keepOpen) appendToFile_writers.put(path, writer); } writer.write(s); if (!appendToFile_keepOpen) writer.close(); } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } static public void appendToFile(File path, String s) { if (path != null) appendToFile(path.getPath(), s); } static public void cleanMeUp_appendToFile() { AutoCloseable __3 = tempCleaningUp(); try { Lock __1 = appendToFile_lock; lock(__1); try { closeAllWriters(values(appendToFile_writers)); appendToFile_writers.clear(); } finally { unlock(__1); } } finally { _close(__3); } } static public A syncNextToLast(List l) { if (l == null) return null; synchronized (l) { return nextToLast(l); } } static public void syncRemoveLast(List l) { if (l != null) synchronized (l) { removeLast(l); } } static public void syncRemoveLast(List l, int n) { if (l != null) synchronized (l) { removeLast(l, n); } } static public void syncRemoveLast(int n, List l) { syncRemoveLast(l, n); } static public void syncReplaceCollection(Collection dest, Collection src) { if (dest == src) return; synchronized (collectionMutex(dest)) { dest.clear(); if (src != null) dest.addAll(src); } } static public List flattenList2(Object... a) { List l = new ArrayList(); if (a != null) for (Object x : a) if (x instanceof Collection) for (Object sub : (Collection) x) l.addAll(flattenList2(sub)); else if (x != null) l.add(x); return l; } static public Set asSet(Object[] array) { HashSet set = new HashSet(); for (Object o : array) if (o != null) set.add(o); return set; } static public Set asSet(String[] array) { TreeSet set = new TreeSet(); for (String o : array) if (o != null) set.add(o); return set; } static public Set asSet(Iterable l) { if (l instanceof Set) return (Set) l; HashSet set = new HashSet(); for (A o : unnull(l)) if (o != null) set.add(o); return set; } static public Set asSet(MultiSet ms) { return ms == null ? null : ms.asSet(); } static public String dropUriPrefix(String prefix, String uri) { prefix = dropTrailingSlash(prefix); if (empty(prefix)) return uri; if (eq(uri, prefix) || startsWith(uri, prefix + "/")) return substring(uri, l(prefix)); return uri; } static public String nTests(long n) { return n2(n, "test"); } static public String nTests(Collection l) { return nTests(l(l)); } static public String nErrors(long n) { return n2(n, "error"); } static public String nErrors(Collection l) { return nErrors(l(l)); } static public String nErrors(Map map) { return nErrors(l(map)); } static public String hjs_markRowMagic(Object... __) { String color = optPar("color", __, "#99f"); return hjs(replaceDollarVars("\r\n var rowMagic_hash = window.location.hash.substr(1);\r\n if (rowMagic_hash)\r\n $(\"a[name=\" + rowMagic_hash + \"]\").closest('tr').css({ 'background-color' : '$color'});\r\n ", "color", color)); } static public String hcomment(String text) { return hcommentSafe(text); } static public String renderVars_struct(Object... params) { List l = new ArrayList(); for (int i = 0; i + 1 < l(params); i += 2) l.add(params[i] + "=" + struct(params[i + 1]) + ". "); return trim(join(l)); } static public Map allConceptFieldsAsMap(Concept c) { Map map = new HashMap(); for (String field : unnullForIteration(conceptFields(c))) map.put(field, cget(c, field)); return map; } static public String renderVars_str(Object... params) { List l = new ArrayList(); int i = 0; if (odd(l(params))) { l.add(strOrNull(first(params))); ++i; } for (; i + 1 < l(params); i += 2) l.add(params[i] + "=" + params[i + 1]); return trim(joinWithComma(l)); } static public String hreconnectingWebSockets() { return hjavascript_src_snippet(hreconnectingWebSockets_snippetID()); } static public String js_evalOnWebSocketMessage() { return "\r\n function(event) {\r\n var data = JSON.parse(event.data);\r\n if (data.eval) {\r\n if (wsVerbose) console.log(\"Evaluating: \" + data.eval);\r\n var geval = eval; // use global scope\r\n geval(data.eval);\r\n if (wsVerbose) console.log(\"Evaluated.\");\r\n } else\r\n if (wsVerbose) console.log(\"WebSocket incoming: \" + event.data);\r\n }\r\n "; } static public int conceptCount(Concepts concepts, Class c, Object... params) { return countConcepts(concepts, c, params); } static public int conceptCount(Class c, Object... params) { return countConcepts(c, params); } static public int conceptCount() { return countConcepts(); } static public int conceptCount(String className) { return countConcepts(className); } static public int conceptCount(Concepts concepts, String className) { return countConcepts(concepts, className); } static public int conceptCount(Concepts concepts) { return countConcepts(concepts); } static public File conceptsFile(String progID) { return getProgramFile(progID, conceptsFileName()); } static public File conceptsFile() { return conceptsFile(dbProgramID()); } static public String renderDBLoadTime() { return renderDBLoadTime(db_mainConcepts()); } static public String renderDBLoadTime(Concepts cc) { if (cc == null) return null; return cc.loadTook < 0 ? "unknown" : n2(cc.loadTook) + " ms"; } static public String renderDBSaveTime() { return renderDBSaveTime(db_mainConcepts()); } static public String renderDBSaveTime(Concepts cc) { if (cc == null) return null; return cc.lastSaveTook < 0 ? "unknown" : n2(cc.lastSaveTook) + " ms"; } static public String renderHowLongAgo(Timestamp ts) { return renderHowLongAgo(timestampToLong(ts)); } static public String renderHowLongAgo(long timestamp) { if (timestamp == 0) return "never"; int seconds = howManySecondsAgo(timestamp); if (seconds <= 0) return "just now"; if (seconds < 60) return n2(seconds, "second") + " ago"; int minutes = iround(seconds / 60.0); if (minutes < 60) return n2(minutes, "minute") + " ago"; int hours = iround(minutes / 60.0); if (hours < 24) return n2(hours, "hour") + " ago"; int days = iround(hours / 24.0); return n2(days, "day") + " ago"; } static public String hjavascript(String scriptOrURL, Object... __) { if (isRelativeOrAbsoluteURL(scriptOrURL) && !startsWithOneOf(scriptOrURL, "//", "/*")) return hjavascript_src(scriptOrURL, __); else return tag("script", scriptOrURL, paramsPlus(__, "type", "text/javascript")); } static public String toString(Object o) { return strOrNull(o); } static public String quoteOr(String s, String whenEmpty) { return empty(s) ? whenEmpty : quote(s); } static public String spaceRoundBracketed(String s) { return spacePlusRoundBracketedIfNempty(s); } static public String nSteps(long n) { return n2(n, "step"); } static public String nSteps(Collection l) { return nSteps(l(l)); } static public String appendBracketed(Object o) { String b = strOrNull(o); return empty(b) ? "" : "" + " (" + b + ")"; } static public String appendBracketed(String a, String b) { return a + appendBracketed(b); } static public Random random_random = new Random(); static public int random(int n) { return random(random_random, n); } static public int random(int n, Random r) { return random(r, n); } static public int random(Random r, int n) { return n <= 0 ? 0 : r.nextInt(n); } static public double random(double max) { return random() * max; } static public double random() { return random_random.nextInt(100001) / 100000.0; } static public double random(double min, double max) { return min + random() * (max - min); } static public int random(int min, int max) { return min + random(max - min); } static public int random(int min, int max, Random r) { return random(r, min, max); } static public int random(Random r, int min, int max) { return min + random(r, max - min); } static public A random(List l) { return oneOf(l); } static public A random(Collection c) { if (c instanceof List) return random((List) c); int i = random(l(c)); return collectionGet(c, i); } static public int random(IntRange r) { return random(r.start, r.end); } static public Pair random(Map map) { return entryToPair(random(entries(map))); } static public String spacePlusRoundBracketedIfNempty(String s) { return nempty(s) ? " " + roundBracket(s) : ""; } static public String newLinesToSpaces2(String s) { return newLinesToSpaces_trim(s); } static public String himgsrc(String src, Object... params) { return tag("img", "", arrayPlus(params, "src", src)); } static public boolean deleteFile(File file) { return file != null && file.delete(); } static public BufferedImage loadImage2(String snippetIDOrURL) { return loadBufferedImage(snippetIDOrURL); } static public BufferedImage loadImage2(File file) { return loadBufferedImage(file); } static public String mp3mimeType() { return "audio/mpeg"; } static public long toMS(double seconds) { return (long) (seconds * 1000); } static public String formatDouble(double d, int digits) { String format = digits <= 0 ? "0" : "0." + rep(digits, '#'); return decimalFormatEnglish(format, d); } static public String formatDouble(double d) { return str(d); } static public String orEmptyQuotes(String s) { return or2(s, "\"\""); } static public List> zipTwoListsToPairs_longer(List l1, List l2) { int n = max(l(l1), l(l2)); List> out = emptyList(n); for (int i = 0; i < n; i++) addPair(out, _get(l1, i), _get(l2, i)); return out; } static public B syncPut(Map map, A key, B value) { if (map == null) return null; synchronized (map) { return map.put(key, value); } } static public boolean isValidEmailAddress_simple(String s) { return l(s) <= 254 && regexpMatches("^\\S+@\\S+(\\.[^\\.\\s]+)+$", s); } static public int indexOfIC(List a, String b) { return indexOfIgnoreCase(a, b); } static public int indexOfIC(List a, String b, int i) { return indexOfIgnoreCase(a, b, i); } static public int indexOfIC(String a, String b) { return indexOfIgnoreCase(a, b); } static public int indexOfIC(String a, String b, int i) { return indexOfIgnoreCase(a, b, i); } static public String dropStuffBeforeVerticalBar(String s) { int i = indexOf(s, '|'); return i < 0 ? s : substring(s, i + 1); } static public String sfu(Object o) { return structureForUser(o); } static public A getOrKeep(Map map, A a) { if (map == null) return a; A v = map.get(a); return v != null ? v : a; } static public Map filterKeys(Map map, Object f) { return filterMapByFunctionOnKey(map, f); } static public Map filterKeys(Object f, Map map) { return filterMapByFunctionOnKey(f, map); } static public Map filterKeys(IF1 f, Map map) { return filterMapByFunctionOnKey((Object) f, map); } static public Map filterKeys(Map map, IF1 f) { return filterKeys(f, map); } static public IF1 swic$(String prefix) { return s -> swic(s, prefix); } static public void syncRemoveAllExceptLast(List l) { if (l == null) return; synchronized (collectionMutex(l)) { removeSubList(l, 0, l(l) - 1); } } static public MMOPattern mmo2_parsePattern(String s) { s = trim(tok_deRoundBracket(trim(s))); List tok = javaTokWithBrackets(s); List l = tok_splitAtComma(tok); if (l(l) > 1) return new MMOPattern.Or(lambdaMap(__85 -> mmo2_parsePattern(__85), l)); l = tok_splitAtPlus(tok); if (l(l) > 1) return new MMOPattern.And(lambdaMap(__86 -> mmo2_parsePattern(__86), l)); if (startsWith(s, "!")) return new MMOPattern.Not(mmo2_parsePattern(dropFirst(s))); if (startsWith(s, "^")) return new MMOPattern.StartOfLine(mmo2_parsePattern(dropFirst(s))); if (endsWith(s, "$")) return new MMOPattern.EndOfLine(mmo2_parsePattern(dropLast(s))); l = tok_splitAtAsterisk(tok); if (l(l) == 2) return new MMOPattern.Weighted(parseDouble(second(l)), mmo2_parsePattern(first(l))); return new MMOPattern.Phrase(unquote(s), isQuoted(s)); } static public boolean mmo2_matchWithTypos(String pattern, String s) { return mmo2_matchWithTypos(pattern, s, 1); } static public boolean mmo2_matchWithTypos(String pattern, String s, int maxTypos) { return mmo2_matchWithTypos(mmo2_parsePattern(pattern), s, maxTypos); } static public boolean mmo2_matchWithTypos(MMOPattern pattern, String s) { return mmo2_matchWithTypos(pattern, s, 1); } static public boolean mmo2_matchWithTypos(MMOPattern pattern, String s, int maxTypos) { if (maxTypos == 0) return mmo2_match(pattern, s); Integer score = mmo2_levenWithSwapsScore(pattern, s); return score != null && score <= maxTypos; } static public List parseBusinessHours_pcall(String s) { try { return parseBusinessHours(s); } catch (Throwable __e) { _handleException(__e); } return null; } static public List splitBusinessHoursAtMidnight(List l) { return concatLists(map(l, r -> r.end < r.start && r.start > 12 ? ll(intRange(r.start, 24 * 60), intRange(0, r.end)) : ll(r))); } static public int minuteInDay() { return minuteInDay(java.util.Calendar.getInstance()); } static public int minuteInDay(java.util.Calendar c) { return hours(c) * 60 + minutes(c); } static public int minuteInDay(long time) { return minuteInDay(calendarFromTime(time)); } static public int minuteInDay(TimeZone tz) { return minuteInDay(now(), tz); } static public int minuteInDay(long time, TimeZone tz) { return minuteInDay(calendarFromTime(time, tz)); } static public TimeZone timeZone(String name) { return TimeZone.getTimeZone(name); } static public boolean anyIntRangeContains(Iterable ranges, int i) { return any(ranges, r -> intRangeContains(r, i)); } static public int syncL(Collection l) { if (l == null) return 0; synchronized (collectionMutex(l)) { return l.size(); } } static public int syncL(Map map) { if (map == null) return 0; synchronized (collectionMutex(map)) { return map.size(); } } static public List syncL() { return syncList(); } static public int syncLengthLevel2(Collection l) { int sum = 0; for (Collection c : cloneList(l)) sum += syncL(c); return sum; } static public List concatLists_syncIndividual(Iterable... lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) syncAddAll(l, list); return l; } static public List concatLists_syncIndividual(Collection> lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) syncAddAll(l, list); return l; } static public List syncListPlus(Collection l, A... more) { if (l == null) return asList(more); synchronized (collectionMutex(l)) { return concatLists(l, asList(more)); } } static public void syncClear(Collection c) { if (c != null) synchronized (collectionMutex(c)) { c.clear(); } } static public void syncClear(Map map) { if (map != null) synchronized (collectionMutex(map)) { map.clear(); } } static public void deleteConcepts(Collection conceptsOrIDs) { db_mainConcepts().deleteConcepts(asList(conceptsOrIDs)); } static public List deleteConcepts(Class c, Object... params) { return deleteConcepts(db_mainConcepts(), c, params); } static public List deleteConcepts(Concepts cc, Class c, Object... params) { List l = asList(findConceptsWhere(cc, c, params)); deleteConcepts(l); return l; } static public void deleteConcepts(Class c, IF1 pred) { deleteConcepts(db_mainConcepts(), c, pred); } static public void deleteConcepts(Concepts cc, Class c, IF1 pred) { deleteConcepts(filter(list(cc, c), pred)); } static public List deleteConcepts(Concepts cc) { return deleteConcepts(cc, Concept.class); } static public A syncPopLast(List l) { if (l == null) return null; synchronized (l) { return popLast(l); } } static public List syncPopLast(int n, List l) { if (l == null) return null; synchronized (l) { return popLast(n, l); } } static public List syncShallowCloneElements(List l) { return syncLambdaMap(__87 -> shallowClone(__87), l); } static public List syncAddOrCreate(List l, A a) { if (l == null) l = syncList(); l.add(a); return l; } static public A syncLast(List l) { if (l == null) return null; synchronized (l) { return last(l); } } static public String selectedItem(JList l) { return getSelectedItem(l); } static public String selectedItem(JComboBox cb) { return getSelectedItem(cb); } static public Class run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static public JComboBox jComboBox(final String... items) { return jcombobox(items); } static public JComboBox jComboBox(Collection items) { return jcombobox(items); } static public JComboBox jComboBox(Collection items, String selectedItem) { return jcombobox(items, selectedItem); } static public int showForm_defaultGap = 4; static public int showForm_gapBetweenColumns = 10; static public JPanel showFormTitled(final String title, final Object... _parts) { JDesktopPane desktop = mainDesktopPane(); if (desktop != null) return showInternalFrameFormTitled(desktop, title, _parts); return swing(new F0() { public JPanel get() { try { final Var frame = new Var(); JPanel panel = showForm_makePanel(false, _parts); frame.set(showForm_makeFrame(title, panel)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final new Var frame;\r\n JPanel panel = showForm_makePanel(false, _p..."; } }); } static public JPanel showForm_makePanel(Boolean internalFrame, Object... _parts) { List out = showForm_arrange1(showForm_makeComponents(internalFrame, _parts)); return vstackWithSpacing(out, showForm_defaultGap); } static public JLabel jlabel(final String text) { return swingConstruct(BetterLabel.class, text); } static public JLabel jlabel() { return jlabel(" "); } static public Set synchroSet() { return synchroHashSet(); } static public Set synchroSet(Set set) { return Collections.synchronizedSet(set); } static public Object process(String processorID, Object in) { return process(processorID, in, "in"); } static public Object process(String processorID, Object in, String outVar) { try { Class processor = hotwire(processorID); set(processor, "in", in); call(processor, "main", new Object[] { new String[0] }); return get(processor, outVar); } catch (Exception e) { throw new RuntimeException("Error in #" + parseSnippetID(processorID), e); } } static public List syncCloneAndClearList(Collection l) { if (l == null) return emptyList(); synchronized (collectionMutex(l)) { List l2 = cloneList(l); l.clear(); return l2; } } static public Object pcallF(Object f, Object... args) { return pcallFunction(f, args); } static public A pcallF(F0 f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { return null; } } static public B pcallF(F1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { return null; } } static public void pcallF(VF1 f, A a) { try { { if (f != null) f.get(a); } } catch (Throwable __e) { _handleException(__e); } } static public A pcallF(IF0 f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { return null; } } static public B pcallF(IF1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { return null; } } static public int hashCodeFor(Object a) { return a == null ? 0 : a.hashCode(); } static public Class _run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static public List syncGetAndClear(Collection l) { return syncCloneAndClearList(l); } static public A getWeakRef(Reference ref) { return ref == null ? null : ref.get(); } static public void cancelAndInterruptThread(Thread t) { if (t == null) return; cancelThread(t); t.interrupt(); } static public float clamp(float x, float a, float b) { return x < a ? a : x > b ? b : x; } static public double clamp(double x, double a, double b) { return x < a ? a : x > b ? b : x; } static public int clamp(int x, int a, int b) { return x < a ? a : x > b ? b : x; } static public long clamp(long x, long a, long b) { return x < a ? a : x > b ? b : x; } static public A _print(String s, A a) { return print(s, a); } static public A _print(A a) { return print(a); } static public void _print() { print(); } static public boolean _eq(Object a, Object b) { return eq(a, b); } static public double ratioToPercent(double x, double y) { return x * 100 / y; } static public String nConcepts(long n) { return n2(n, "concept"); } static public String nConcepts(Collection l) { return nConcepts(l(l)); } static public String nConcepts(Map map) { return nConcepts(l(map)); } static public Object firstElementNotSubclassing(Iterable l, Class c) { return firstThat(l, o -> !isInstanceOf(o, c)); } static public boolean allUnique(Collection l) { return l(uniquify(l)) == l(l); } static public Collection scanConceptForRefs(Concept c) { Set refs = new HashSet(); if (c != null) for (Object o : values(objectToMap(c))) { if (o instanceof Concept.Ref) refs.add((Concept.Ref) o); else if (o instanceof Concept.RefL) addAll(refs, ((Concept.RefL) o).l); } return refs; } static public List cloneAndClear(Collection l) { return cloneAndClearList(l); } static public int cmp(Number a, Number b) { return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue()); } static public int cmp(double a, double b) { return a < b ? -1 : a == b ? 0 : 1; } static public int cmp(int a, int b) { return a < b ? -1 : a == b ? 0 : 1; } static public int cmp(long a, long b) { return a < b ? -1 : a == b ? 0 : 1; } static public int cmp(Object a, Object b) { if (a == null) return b == null ? 0 : -1; if (b == null) return 1; return ((Comparable) a).compareTo(b); } static public A optPar(ThreadLocal tl, A defaultValue) { A a = tl.get(); if (a != null) { tl.set(null); return a; } return defaultValue; } static public A optPar(ThreadLocal tl) { return optPar(tl, null); } static public Object optPar(Object[] params, String name) { return optParam(params, name); } static public Object optPar(String name, Object[] params) { return optParam(params, name); } static public Object optPar(String name, Map params) { return optParam(name, params); } static public A optPar(Object[] params, String name, A defaultValue) { return optParam(params, name, defaultValue); } static public A optPar(String name, Object[] params, A defaultValue) { return optParam(params, name, defaultValue); } static public List scoredSearch_prepare(String query) { return map(__88 -> replacePlusWithSpace(__88), splitAtSpace(query)); } static public void putUnlessZero(Map map, A key, int value) { if (map != null && key != null && value != 0) map.put(key, value); } static public void putUnlessZero(Map map, A key, double value) { if (map != null && key != null && value != 0) map.put(key, value); } static public int scoredSearch_score(Iterable l, List words) { int score = 0; if (l != null) for (String s : l) score += scoredSearch_score(s, words); return score; } static public int scoredSearch_score(String s, List words) { int score = 0; if (nempty(s)) for (String word : unnullForIteration(words)) score += scoredSearch_score_single(s, word); return score; } static public int scoredSearch_score(String s, String query) { return scoredSearch_score(s, scoredSearch_prepare(query)); } static public double scoredSearch_scoreWeighted2(Collection> l, List words) { double score = 0; if (l != null) for (Pair __0 : l) { String s = pairA(__0); double weight = pairB(__0); score += scoredSearch_score(s, words) * weight; } return score; } static public List keysSortedByValuesDesc(final Map map) { List l = new ArrayList(map.keySet()); sort(l, mapComparatorDesc(map)); return l; } static public Scored scoredWithMapValue(Map map, A a) { return new Scored(a, toDouble(mapGet(map, a))); } static public A keyWithHighestValue(Map map) { return keyWithBiggestValue(map); } static public Boolean not(Boolean b) { return b == null ? null : !b; } static public int toIntPercent(double ratio) { return roundToInt(ratio * 100); } static public int toIntPercent(float ratio) { return toIntPercent((double) ratio); } static public AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) { return print_byThread().get() == null ? tempInterceptPrint(f) : null; } static public Method findMethod_cached(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { _MethodCache cache = callOpt_getCache((Class) o); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (isStaticMethod(m) && findMethod_checkArgs(m, args, false)) return m; return null; } else { _MethodCache cache = callOpt_getCache(o.getClass()); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (findMethod_checkArgs(m, args, false)) return m; return null; } } catch (Exception __e) { throw rethrow(__e); } } static public ThreadLocal> checkFileNotTooBigToRead_tl = new ThreadLocal(); static public void checkFileNotTooBigToRead(File f) { callF(checkFileNotTooBigToRead_tl.get(), f); } static public String _userHome; static public String userHome() { if (_userHome == null) return actualUserHome(); return _userHome; } static public File userHome(String path) { return new File(userDir(), path); } static public SecretValue secretValueOrNull(A a) { return a == null ? null : new SecretValue(a); } static public boolean syncEmpty(Collection l) { if (l == null) return true; synchronized (l) { return l.isEmpty(); } } static public HashMap findClass_cache = new HashMap(); static public Class findClass(String name) { synchronized (findClass_cache) { if (findClass_cache.containsKey(name)) return findClass_cache.get(name); if (!isJavaIdentifier(name)) return null; Class c; try { c = Class.forName("main$" + name); } catch (ClassNotFoundException e) { c = null; } findClass_cache.put(name, c); return c; } } static public Object nuObject(String className, Object... args) { try { return nuObject(classForName(className), args); } catch (Exception __e) { throw rethrow(__e); } } static public A nuObject(Class c, Object... args) { try { if (args.length == 0) return nuObjectWithoutArguments(c); Constructor m = nuObject_findConstructor(c, args); makeAccessible(m); return (A) m.newInstance(args); } catch (Exception __e) { throw rethrow(__e); } } static public Constructor nuObject_findConstructor(Class c, Object... args) { for (Constructor m : c.getDeclaredConstructors()) { if (!nuObject_checkArgs(m.getParameterTypes(), args, false)) continue; return m; } throw fail("Constructor " + c.getName() + getClasses(args) + " not found" + (args.length == 0 && (c.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0 ? " - hint: it's a non-static class!" : "")); } static public boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) { if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static public int csetAll(Concept c, Object... values) { return cset(c, values); } static public int csetAll(Iterable l, Object... values) { int n = 0; for (Concept c : unnullForIteration(l)) n += cset(c, values); return n; } static public String rtrim_fromLines(Collection lines) { StringBuilder buf = new StringBuilder(); if (lines != null) { boolean first = true; for (Object line : lines) { if (first) first = false; else buf.append('\n'); buf.append(str(line)); } } return buf.toString(); } static public String indentStructureString(String s) { return indentStructureString(100, s); } static public String indentStructureString(int levels, String s) { if (s == null) return null; List tok = javaTokForStructure(s); StringBuilder buf = new StringBuilder(); int indent = 0; levels = clampToInt(levels * 2L); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (isOpeningBracket(t)) { int j = i + 5; if (containsClosingBracket(subList(tok, i + 2, i + 5))) { buf.append(joinSubList(tok, i, j)); i = j - 1; } else { indent += 2; buf.append(t); if (indent <= levels) buf.append("\n").append(spaces(indent)); } } else if (isClosingBracket(t)) { indent -= 2; if (indent < levels) buf.append("\n").append(spaces(indent)); buf.append(t); } else if (indent <= levels && eq(t, ",")) { buf.append(t).append("\n").append(spaces(indent)); i++; } else buf.append(t); } return str(buf); } static public void deleteConcept(long id) { db_mainConcepts().deleteConcept(id); } static public void deleteConcept(Concepts concepts, long id) { concepts.deleteConcept(id); } static public void deleteConcept(Concept c) { if (c != null) c.delete(); } static public void deleteConcept(Concept.Ref ref) { if (ref != null) deleteConcept(ref.get()); } static public CharSequence subCharSequence(CharSequence s, int x) { return subCharSequence(s, x, s == null ? 0 : s.length()); } static public CharSequence subCharSequence(CharSequence s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; if (x >= s.length()) return ""; if (y < x) y = x; if (y > s.length()) y = s.length(); return s.subSequence(x, y); } static public String fixNewLines(String s) { int i = indexOf(s, '\r'); if (i < 0) return s; int l = s.length(); StringBuilder out = new StringBuilder(l); out.append(s, 0, i); for (; i < l; i++) { char c = s.charAt(i); if (c != '\r') out.append(c); else { out.append('\n'); if (i + 1 < l && s.charAt(i + 1) == '\n') ++i; } } return out.toString(); } static public List pairsA(Collection> l) { return firstOfPairs(l); } static public boolean isInstance(Class type, Object arg) { return type.isInstance(arg); } static public List collectInstances(Iterable i, Class c) { List l = new ArrayList(); if (i == null) return l; c = primitiveToBoxedTypeOpt(c); for (Object o : i) if (isInstance(c, o)) l.add(o); return l; } static public List collectInstances(Class c, Iterable i) { return collectInstances(i, c); } static public String dm_makeModule(String moduleLibID) { return (String) dm_callOS("makeModule", moduleLibID); } static public A dm_ownResource(A resource) { dm_currentModuleMandatory().ownResource(resource); return resource; } static public AutoCloseable vmBus_onMessage(String msg, IVF1 onMessage) { return vmBus_onMessage(msg, ivf1ToVF1(onMessage)); } static public AutoCloseable vmBus_onMessage(final String msg, final VF1 onMessage) { Map map = vm_busListenersByMessage_live(); synchronized (map) { Set listeners = map.get(msg); if (listeners == null) map.put(msg, listeners = syncIdentityHashSet()); return tempAdd(listeners, new VF2() { public void get(String _msg, Object arg) { try { callF(onMessage, arg); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, arg)"; } }); } } static public AutoCloseable vmBus_onMessage(String msg, final VF2 onMessage) { return vmBus_onMessage(msg, new VF1() { public void get(Object[] o) { try { callF(onMessage, first(o), second(o)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, first(o), second(o));"; } }); } static public AutoCloseable vmBus_onMessage(String msg, final IVF2 onMessage) { return vmBus_onMessage(msg, new VF1() { public void get(Object[] o) { try { callF(onMessage, first(o), second(o)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(onMessage, first(o), second(o));"; } }); } static public AutoCloseable vmBus_onMessage(String msg, Runnable onMessage) { return vmBus_onMessage(msg, runnableToVF1(onMessage)); } static public VF1 ivf1ToVF1(IVF1 f) { return f == null ? null : new VF1() { public void get(A a) { try { f.get(a); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.get(a)"; } }; } static public VF2 ivf2ToVF2(IVF2 f) { return f == null ? null : new VF2() { public void get(A a, B b) { try { f.get(a, b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.get(a, b)"; } }; } static public java.lang.management.OperatingSystemMXBean osMXBean() { return ManagementFactory.getOperatingSystemMXBean(); } static public double systemCPULoad() { return advancedOSMXBean().getSystemCpuLoad(); } static public ConceptFieldIndexCI getConceptFieldCIIndex(Class c, String field) { return getConceptFieldCIIndex(db_mainConcepts(), c, field); } static public ConceptFieldIndexCI getConceptFieldCIIndex(Concepts concepts, Class c, String field) { return (ConceptFieldIndexCI) concepts.getCIFieldIndex(c, field); } static public boolean isConceptFieldIndexed(Class c, String field) { return isConceptFieldIndexed(db_mainConcepts(), c, field); } static public boolean isConceptFieldIndexed(Concepts concepts, Class c, String field) { return concepts.getFieldIndex(c, field) != null; } static public IConceptIndex simpleConceptIndex(final Runnable r) { return new IConceptIndex() { public void update(Concept c) { pcallF(r); } public void remove(Concept c) { pcallF(r); } }; } static public Set synchroLinkedHashSet() { return Collections.synchronizedSet(new CompactLinkedHashSet()); } static public LinkedHashMap cloneLinkedHashMap(Map map) { return map == null ? new LinkedHashMap() : new LinkedHashMap(map); } static public Map synchroHashMap() { return synchronizedMap(new HashMap()); } static public Map synchronizedMap() { return synchroMap(); } static public Map synchronizedMap(Map map) { return synchroMap(map); } static public WeakReference newWeakReference(A a) { return a == null ? null : new WeakReference(a); } static public void setFieldToSingleMethodProxy(Object o, String field, Object target, String methodName) { if (o == null || target == null) return; Class type = fieldType(o, field); if (type == null) throw fail("Field " + field + " not found in " + className(o)); set(o, field, singleObjectMethodProxy(type, target, methodName)); } static public List synchroList() { return synchroList(new ArrayList()); } static public List synchroList(List l) { return Collections.synchronizedList(l); } static public Throwable printStackTrace2(Throwable e) { print(getStackTrace2(e)); return e; } static public void printStackTrace2() { printStackTrace2(new Throwable()); } static public void printStackTrace2(String msg) { printStackTrace2(new Throwable(msg)); } static public PersistableThrowable persistableThrowable(Throwable e) { return e == null ? null : new PersistableThrowable(e); } static public Throwable innerException(Throwable e) { return getInnerException(e); } static public Object jparse_parser; static synchronized public List jparse(String text, String className) { if (jparse_parser == null) { jparse_parser = run_overBot("#1002369"); setOpt(jparse_parser, "keepRules", true); } Object parseResult = call(jparse_parser, "jparse", text); return (List) call(parseResult, "explain", className); } static public String getString(Map map, Object key) { return map == null ? null : (String) map.get(key); } static public String getString(List l, int idx) { return (String) get(l, idx); } static public String getString(Object o, Object key) { if (o instanceof Map) return getString((Map) o, key); if (key instanceof String) return (String) getOpt(o, (String) key); throw fail("Not a string key: " + getClassName(key)); } static public String getString(String key, Object o) { return getString(o, (Object) key); } static public ArrayList litlist(A... a) { ArrayList l = new ArrayList(a.length); for (A x : a) l.add(x); return l; } static public boolean hasMethodNamed(Object obj, String method) { if (obj == null) return false; if (obj instanceof Class) return hasMethodNamed((Class) obj, method); return hasMethodNamed(obj.getClass(), method); } static public boolean hasMethodNamed(Class c, String method) { while (c != null) { for (Method m : c.getDeclaredMethods()) if (m.getName().equals(method)) return true; c = c.getSuperclass(); } return false; } static public String replaceDollarVars_js(String s, Object... __) { Map vars = paramsToMap_withNulls(__); if (empty(vars)) return s; var vars2 = mapKeys(__89 -> dropDollarPrefix(__89), vars); return replaceDollarVars_dyn(s, var -> { if (!vars2.containsKey(var)) return null; Object value = vars2.get(var); return jsonEncode_extended(value); }); } static public Object dm_getModule(Object moduleOrID) { if (moduleOrID == null || eq(moduleOrID, "")) return null; if (isString(moduleOrID) && isIdentifier(((String) moduleOrID))) return dm_getService(((String) moduleOrID)); if (isStringOrIntOrLong(moduleOrID)) return dm_callOS("getDynModuleByID", str(moduleOrID)); return dm_resolveModule(moduleOrID); } static public AutoCloseable dm_enter(Object mod) { return (AutoCloseable) callOpt(dm_getModule(mod), "enter"); } static public void close_pcall(AutoCloseable c) { if (c != null) { try { c.close(); } catch (Throwable __e) { _handleException(__e); } } } static public void preCleanUp(Object c) { if (c instanceof Collection) { for (Object o : ((Collection) c)) preCleanUp(o); return; } callOpt(c, "licensed_off"); setOpt(c, "ping_anyActions", true); setOpt(c, "cleaningUp_flag", true); } static public void innerCleanUp(Object c) { if (!isFalse(pcallOpt(c, "cleanMeUp"))) for (String name : sorted(methodsStartingWith(c, "cleanMeUp_"))) try { callOpt(c, name); } catch (Throwable e) { print("Error cleaning up: " + programID(c)); _handleException(e); } } static public void innerCleanUp() { innerCleanUp(mc()); } static public Object pcallOpt(Object o, String method, Object... args) { try { return callOpt(o, method, args); } catch (Throwable __e) { _handleException(__e); } return null; } static public List registeredThreads(Object o) { Map map = (Map) (getOpt(o, "_registerThread_threads")); if (map == null) return ll(); map.size(); synchronized (map) { return asList(keys(map)); } } static public List registeredThreads() { _registerThread_threads.size(); return asList(keys(_registerThread_threads)); } static public void interruptThreads(Collection threads) { for (Thread t : unnull(threads)) interruptThread(t); } static public void interruptThreads(Class mainClass) { interruptThreads(registeredThreads(mainClass)); } static public void retireClassLoader(ClassLoader cl) { if (isJavaXClassLoader(cl)) setOptAll(cl, "retired", true, "retiredMarker", new DefunctClassLoader()); } static public void closeAllAndClear(Collection l) { if (l == null) return; for (AutoCloseable c : cloneList(l)) { try { close(c); } catch (Throwable __e) { _handleException(__e); } } l.clear(); } static public void smartSet(Field f, Object o, Object value) throws Exception { try { f.set(o, value); } catch (Exception e) { Class type = f.getType(); if (type == int.class && value instanceof Long) { f.set(o, ((Long) value).intValue()); return; } if (type == boolean.class && value instanceof String) { f.set(o, isTrueOrYes(((String) value))); return; } if (type == LinkedHashMap.class && value instanceof Map) { f.set(o, asLinkedHashMap((Map) value)); return; } try { if (f.getType() == Concept.Ref.class) { f.set(o, ((Concept) o).new Ref((Concept) value)); return; } if (o instanceof Concept.Ref) { f.set(o, ((Concept.Ref) o).get()); return; } } catch (Throwable _e) { } throw e; } } static public String combinePrintParameters(String s, Object o) { return (endsWithLetterOrDigit(s) ? s + ": " : s) + o; } static public Object getThreadLocal(Object o, String name) { ThreadLocal t = (ThreadLocal) (getOpt(o, name)); return t != null ? t.get() : null; } static public A getThreadLocal(ThreadLocal tl) { return tl == null ? null : tl.get(); } static public A getThreadLocal(ThreadLocal tl, A defaultValue) { return or(getThreadLocal(tl), defaultValue); } static public ThreadLocal print_byThread_dontCreate() { return print_byThread; } static public boolean isFalse(Object o) { return eq(false, o); } static public void print_append(Appendable buf, String s, int max) { try { synchronized (buf) { buf.append(s); if (buf instanceof StringBuffer) rotateStringBuffer(((StringBuffer) buf), max); else if (buf instanceof StringBuilder) rotateStringBuilder(((StringBuilder) buf), max); } } catch (Exception __e) { throw rethrow(__e); } } static public AutoCloseable tempSetThreadLocal(final ThreadLocal tl, A a) { if (tl == null) return null; final A prev = setThreadLocal(tl, a); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); } }; } static public AutoCloseable tempSetThreadLocalIfNecessary(ThreadLocal tl, A a) { if (tl == null) return null; A prev = tl.get(); if (eq(prev, a)) return null; tl.set(a); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); } }; } static public AutoCloseable tempSetThreadLocalIfNecessary(x30_pkg.x30_util.BetterThreadLocal tl, A a) { if (tl == null) return null; A prev = tl.get(); if (eq(prev, a)) return null; tl.set(a); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); } }; } static public Object jsonDecode(String text) { return new jsonDecode_Y(text).parse(); } static public class jsonDecode_Y { public String text; public List tok; public boolean useOrderedMaps = false; public int i = 1; public jsonDecode_Y(String text) { this.text = text; tok = jsonTok(text); } transient public IF1 fail; public RuntimeException fail(String msg) { return fail != null ? fail.get(msg) : fail_base(msg); } final public RuntimeException fail_fallback(IF1 _f, String msg) { return _f != null ? _f.get(msg) : fail_base(msg); } public RuntimeException fail_base(String msg) { return main.fail(msg); } public Object parse() { if (l(tok) == 1) return null; return parseExpr(); } public Object parseExpr() { String t = tok.get(i); if (t.startsWith("\"") || t.startsWith("'")) { String s = unquote(tok.get(i)); i += 2; return s; } if (t.equals("{")) return parseMap(); if (t.equals("[")) return this.parseList(); if (t.equals("null")) { i += 2; return null; } if (t.equals("false")) { i += 2; return false; } if (t.equals("true")) { i += 2; return true; } boolean minus = false; if (t.equals("-")) { minus = true; i += 2; t = get(tok, i); } if (isInteger(t)) { int j = i; i += 2; if (eqOneOf(get(tok, i), ".", "e", "E")) { while (isInteger(get(tok, i)) || eqOneOf(get(tok, i), ".", "e", "E", "-")) i += 2; double d = parseDouble(joinSubList(tok, j, i - 1)); if (minus) d = -d; return d; } else { long l = parseLong(t); return boxedIntOrLong(minus ? -l : l); } } throw fail("Unknown token " + (i + 1) + ": " + t + ": " + text); } public Object parseList() { consume("["); List list = new ArrayList(); while (!tok.get(i).equals("]")) { list.add(parseExpr()); if (tok.get(i).equals(",")) i += 2; } consume("]"); return list; } public Object parseMap() { consume("{"); Map map = useOrderedMaps ? new LinkedHashMap() : new TreeMap(); while (!tok.get(i).equals("}")) { String key = unquote(tok.get(i)); i += 2; consume(":"); Object value = parseExpr(); map.put(key, value); if (tok.get(i).equals(",")) i += 2; } consume("}"); return map; } public void consume(String s) { if (!tok.get(i).equals(s)) { String prevToken = i - 2 >= 0 ? tok.get(i - 2) : ""; String nextTokens = join(tok.subList(i, Math.min(i + 4, tok.size()))); throw fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")"); } i += 2; } } static public Object collectionMutex(List l) { return l; } static public Object collectionMutex(Object o) { if (o instanceof List) return o; String c = className(o); if (eq(c, "java.util.TreeMap$KeySet")) c = className(o = getOpt(o, "m")); else if (eq(c, "java.util.HashMap$KeySet")) c = className(o = get_raw(o, "this$0")); if (eqOneOf(c, "java.util.TreeMap$AscendingSubMap", "java.util.TreeMap$DescendingSubMap")) c = className(o = get_raw(o, "m")); return o; } static public Map paramsFromURL(String url) { return decodeHQuery(getQueryFromURL(url)); } static public boolean containsKey(Map map, A key) { return map != null && map.containsKey(key); } static public String addAnchorToURL(String url, String anchor) { int i = smartIndexOf(url, '#'); url = takeFirst(url, i); if (nempty(anchor)) url += "#" + anchor; return url; } static public String urlWithoutQueryAndAnchor(String url) { return takeFirst(url, min(smartIndexOf(url, "?"), smartIndexOf(url, "#"))); } static public String anchorFromURL(String url) { return substring(url, smartIndexOf(url, "#")); } static public Map vm_threadInterruptionReasonsMap() { return vm_generalWeakSubMap("Thread interruption reasons"); } static public String strOr(Object o, String ifNull) { return o == null ? ifNull : str(o); } static public void lockOrFail(Lock lock, long timeout) { try { ping(); 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 public ReentrantLock fairLock() { return new ReentrantLock(true); } static public boolean hasConceptWhereIC(Class c, Object... params) { return conceptWhereIC(c, params) != null; } static public boolean hasConceptWhereIC(Concepts cc, Class c, Object... params) { return conceptWhereIC(cc, c, params) != null; } static public boolean regexpFindsIC(String pat, String s) { return regexpIC(pat, s).find(); } static public Object vmBus_wrapArgs(Object... args) { return empty(args) ? null : l(args) == 1 ? args[0] : args; } static public void pcallFAll_minimalExceptionHandling(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) { ping(); pcallF_minimalExceptionHandling(f, args); } } static public void pcallFAll_minimalExceptionHandling(Iterator it, Object... args) { while (it.hasNext()) { ping(); pcallF_minimalExceptionHandling(it.next(), args); } } static public Set vm_busListeners_live_cache; static public Set vm_busListeners_live() { if (vm_busListeners_live_cache == null) vm_busListeners_live_cache = vm_busListeners_live_load(); return vm_busListeners_live_cache; } static public Set vm_busListeners_live_load() { return vm_generalIdentityHashSet("busListeners"); } static public Map vm_busListenersByMessage_live_cache; static public Map vm_busListenersByMessage_live() { if (vm_busListenersByMessage_live_cache == null) vm_busListenersByMessage_live_cache = vm_busListenersByMessage_live_load(); return vm_busListenersByMessage_live_cache; } static public Map vm_busListenersByMessage_live_load() { return vm_generalHashMap("busListenersByMessage"); } static public int iceil(double d) { return (int) Math.ceil(d); } static public String containerTag(String tag) { return containerTag(tag, ""); } static public String containerTag(String tag, Object contents, Object... params) { String openingTag = hopeningTag(tag, params); String s = str(contents); return openingTag + s + ""; } static public String hcss_responstable() { return hcss("\r\n .responstable {\r\n margin: 1em 0;\r\n width: 100%;\r\n overflow: visible;\r\n background: #FFF;\r\n color: #024457;\r\n border-radius: 10px;\r\n border: 1px solid #167F92;\r\n }\r\n \r\n .responstable tr {\r\n border: 1px solid #D9E4E6;\r\n }\r\n .responstable tr:nth-child(odd) {\r\n background-color: #EAF3F3;\r\n }\r\n .responstable th {\r\n display: none;\r\n border: 1px solid #FFF;\r\n background-color: #167F92;\r\n color: #FFF;\r\n padding: 1em;\r\n }\r\n .responstable th:first-child {\r\n display: table-cell;\r\n text-align: center;\r\n }\r\n .responstable th:nth-child(2) {\r\n display: table-cell;\r\n }\r\n .responstable th:nth-child(2) span {\r\n display: none;\r\n }\r\n .responstable th:nth-child(2):after {\r\n content: attr(data-th);\r\n }\r\n @media (min-width: 480px) {\r\n .responstable th:nth-child(2) span {\r\n display: block;\r\n }\r\n .responstable th:nth-child(2):after {\r\n display: none;\r\n }\r\n }\r\n .responstable td {\r\n display: block;\r\n word-wrap: break-word;\r\n max-width: 7em;\r\n }\r\n .responstable td:first-child {\r\n display: table-cell;\r\n text-align: center;\r\n border-right: 1px solid #D9E4E6;\r\n }\r\n @media (min-width: 480px) {\r\n .responstable td {\r\n border: 1px solid #D9E4E6;\r\n }\r\n }\r\n .responstable th, .responstable td {\r\n text-align: left;\r\n margin: .5em 1em;\r\n }\r\n @media (min-width: 480px) {\r\n .responstable th, .responstable td {\r\n display: table-cell;\r\n padding: 1em;\r\n }\r\n }\r\n "); } static public String 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 public String hiddenFields(Map map, String... keys) { return hiddenFields(map, asList(keys)); } static public String htmlEncode_nlToBr(String s) { return nlToBr(htmlEncode2(s)); } static public String tdTop(Object contents, Object... params) { return tag("td", contents, arrayPlus(params, "valign", "top")); } static public String htextinput(String name, Object... params) { Object value = ""; if (odd(l(params))) { value = params[0]; params = dropFirst(params); } params = html_massageAutofocusParam(params); return tag("input", "", concatArrays(new Object[] { "type", "text", "name", name, "value", value }, params)); } static public String htextinput(String name) { return htextinput(name, ""); } static public String hpasswordfield(String name, Object... params) { Object value = ""; if (odd(l(params))) { value = params[0]; params = dropFirst(params); } params = html_massageAutofocusParam(params); return tag("input", "", concatArrays(new Object[] { "type", "password", "name", name, "value", value }, params)); } static public String hpasswordfield(String name) { return hpasswordfield(name, ""); } static public boolean startsWithIgnoreCase(String a, String b) { return regionMatchesIC(a, 0, b, 0, b.length()); } static public Object subBot_serve404() { return call(getMainBot(), "serve404"); } static public Object subBot_serve404(String msg) { return call(getMainBot(), "serve404", msg); } static public Object serveByteArray(byte[] data, String mimeType) { return subBot_serveByteArray(data, mimeType); } static public byte[] toUtf8(String s) { try { return s.getBytes(utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } static public Object mainBot; static public Object getMainBot() { return mainBot; } static public Object serveJSON_shallowLineBreaks(Object data) { return serveText(jsonEncode_shallowLineBreaks(data)); } static public Object jsonPrepareData(Object... data) { if (l(data) == 1) return data[0]; return litorderedmap(data); } static public List lambdaMap(IF1 f, Iterable l) { return map(l, f); } static public List lambdaMap(IF1 f, A[] l) { return map(l, f); } static public A cDeref(Concept.Ref ref) { return ref == null ? null : ref.get(); } static public String dropLeadingSlash(String s) { return dropPrefix("/", s); } static public String javascriptQuote(String s) { return quote(s); } static public String hrefBlank(String link, Object contents, Object... params) { return empty(link) ? strOrEmpty(contents) : tag("a", contents, concatArrays(new Object[] { "href", link, "target", "_blank" }, params)); } static public List withoutNulls(Iterable l) { if (l instanceof List) if (!containsNulls((List) l)) return ((List) l); List l2 = new ArrayList(); for (A a : l) if (a != null) l2.add(a); return l2; } static public Map withoutNulls(Map map) { Map map2 = similarEmptyMap(map); for (A a : keys(map)) if (a != null) { B b = map.get(a); if (b != null) map2.put(a, b); } return map2; } static public List withoutNulls(A[] l) { List l2 = new ArrayList(); if (l != null) for (A a : l) if (a != null) l2.add(a); return l2; } static public int[] subArray(int[] b, int start, int end) { int[] x = new int[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public byte[] subArray(byte[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start >= end) return new byte[0]; byte[] x = new byte[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public short[] subArray(short[] b, int start, int end) { if (start <= 0 && end >= l(b)) return b; short[] x = new short[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public float[] subArray(float[] b, int start, int end) { float[] x = new float[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public Object[] subArray(Object[] b, int start) { return subArray(b, start, l(b)); } static public Object[] subArray(Object[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start >= end) return new Object[0]; Object[] x = new Object[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public String unicode_newLineArrow() { return charToString(0x21b5); } static public BigInteger bigint(String s) { return new BigInteger(s); } static public BigInteger bigint(long l) { return BigInteger.valueOf(l); } static public List reversedList(Iterable l) { List x = cloneList(l); Collections.reverse(x); return x; } static public String reversedString(String s) { return reverseString(s); } static public A highestByFunction(Iterable l, Object f) { A best = null; Object bestValue = null; if (l != null) for (A a : l) { Object val = callF(f, a); if (best == null || cmp(val, bestValue) > 0) { best = a; bestValue = val; } } return best; } static public A highestByFunction(Object f, Iterable l) { return highestByFunction(l, f); } static public A highestByFunction(IF1 f, Iterable l) { return highestByFunction(l, (Object) f); } static public A highestByFunction(Iterable l, IF1 f) { return highestByFunction(f, l); } static public boolean containsIgnoreCase(Collection l, String s) { if (l != null) for (String x : l) if (eqic(x, s)) return true; return false; } static public boolean containsIgnoreCase(String[] l, String s) { if (l != null) for (String x : l) if (eqic(x, s)) return true; return false; } static public boolean containsIgnoreCase(String s, char c) { return indexOfIgnoreCase(s, String.valueOf(c)) >= 0; } static public boolean containsIgnoreCase(String a, String b) { return indexOfIgnoreCase(a, b) >= 0; } static public String hbuttonOnClick(String text, String onClick, Object... params) { return hfulltag("button", text, paramsPlus(params, "onClick", onClick)); } static public IterableIterator toLines(File f) { return linesFromFile(f); } static public List toLines(String s) { List lines = new ArrayList(); if (s == null) return lines; int start = 0; while (true) { int i = toLines_nextLineBreak(s, start); if (i < 0) { if (s.length() > start) lines.add(s.substring(start)); break; } lines.add(s.substring(start, i)); if (s.charAt(i) == '\r' && i + 1 < s.length() && s.charAt(i + 1) == '\n') i += 2; else ++i; start = i; } return lines; } static public int toLines_nextLineBreak(String s, int start) { int n = s.length(); for (int i = start; i < n; i++) { char c = s.charAt(i); if (c == '\r' || c == '\n') return i; } return -1; } static public Object[] params_stylePlus(Map params, String style) { return paramsPlus(params, "style", joinNemptiesWithSemicolon(stringPar("style", params), style)); } static public Object[] params_stylePlus(Object[] params, String style) { return paramsPlus(params, "style", joinNemptiesWithSemicolon(stringPar("style", params), style)); } static public Object[] params_stylePlus(String style, Object... params) { return params_stylePlus(params, style); } static public String spanTitle(String title, Object contents) { return empty(title) ? str(contents) : span(contents, "title", title); } static public String regexReplace(String s, String pat, Object f) { Matcher m = Pattern.compile(pat).matcher(s); return regexReplace(m, f); } static public String regexReplace(String s, String pat, String replacement) { return regexpReplace_direct(s, pat, replacement); } static public String regexReplace(Matcher m, Object f) { StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, m.quoteReplacement(str(callF(f, m)))); m.appendTail(buf); return str(buf); } static public String regexReplace(String s, String pat, IF1 f) { return regexReplace(s, pat, (Object) f); } static public String regexpCaseInsensitivePrefix() { return "(?i)"; } static public List sortByCalculatedField(Iterable c, final Object f) { List l = cloneList(c); sort(l, new Comparator() { public int compare(A a, A b) { return stdcompare(callF(f, a), callF(f, b)); } }); return l; } static public void sort(T[] a, Comparator c) { if (a != null) Arrays.sort(a, c); } static public void sort(T[] a) { if (a != null) Arrays.sort(a); } static public void sort(int[] a) { if (a != null) Arrays.sort(a); } static public void sort(List a, Comparator c) { if (a != null) Collections.sort(a, c); } static public void sort(List a) { if (a != null) Collections.sort(a); } static public int stdcompare(Number a, Number b) { return cmp(a, b); } static public int stdcompare(String a, String b) { return cmp(a, b); } static public int stdcompare(long a, long b) { return a < b ? -1 : a > b ? 1 : 0; } static public int stdcompare(Object a, Object b) { return cmp(a, b); } static public List keysList(Map map) { return cloneListSynchronizingOn(keys(map), map); } static public List keysList(MultiSet ms) { return ms == null ? null : keysList(ms.map); } static public List> findContainerTag(List tok, String tag) { List> l = new ArrayList(); for (int i = 1; i < l(tok); i += 2) if (isOpeningTag(tok.get(i), tag)) { int j, level = 1; for (j = i + 2; j < tok.size(); j += 2) if (isOpeningTag(tok.get(j), tag)) ++level; else if (isTag(tok.get(j), "/" + tag)) { --level; if (level == 0) { l.add(subList(tok, i - 1, j + 2)); break; } } i = j; } return l; } static public List> findContainerTag(String html, String tag) { return findContainerTag(htmlTok(html), tag); } static public String addLineBreak(String s) { return addSuffix(s, "\n"); } static public String jsDropTrailingComments(String s) { return javaTokDropTrailingN(s); } static public String divUnlessEmpty(String s, Object... params) { return empty(s) ? "" : div(s, params); } static public A uniqueConcept(Class c, Object... params) { return uniqueConcept(db_mainConcepts(), c, params); } static public A uniqueConcept(Concepts cc, Class c, Object... params) { AutoCloseable __1 = tempDBLock(cc); try { params = expandParams(c, params); A x = findConceptWhere(cc, c, params); if (x == null) { x = unlisted(c); csetAll(x, params); cc.register(x); } else { } return x; } finally { _close(__1); } } static public A findConceptWhereCI(Class c, Object... params) { return findConceptWhereCI(db_mainConcepts(), c, params); } static public A findConceptWhereCI(Concepts concepts, Class c, Object... params) { params = expandParams(c, params); Lowest>> bestIndex = new Lowest(); if (concepts.ciFieldIndices != null) for (int i = 0; i < l(params); i += 2) { ping(); Object val = params[i + 1]; IFieldIndex index = concepts.getCIFieldIndex(c, (String) params[i]); if (index != null) { Collection l = index.getAll(val); bestIndex.put(() -> l, l(l)); } if (concepts.useBackRefsForSearches && val instanceof Concept) { bestIndex.put(() -> findBackRefs(((Concept) val), c), ((Concept) val)._backRefCount()); } } if (bestIndex.has()) { Collection l = bestIndex.get().get(); if (l(params) == 2) return first(l); for (A x : l) { ping(); if (checkConceptFieldsIC(x, params)) return x; } return null; } else { for (A x : concepts.list(c)) { ping(); if (checkConceptFieldsIC(x, params)) return x; } return null; } } static public Concept findConceptWhereCI(Concepts concepts, String c, Object... params) { for (Concept x : concepts.list(c)) { ping(); if (checkConceptFieldsIC(x, params)) return x; } return null; } static public String assertPossibleMD5(String s) { if (!possibleMD5(s)) throw fail("Not an MD5 signature: " + s); return s; } public static String bytesToHex(byte[] bytes) { return bytesToHex(bytes, 0, bytes.length); } public static String bytesToHex(byte[] bytes, int ofs, int len) { StringBuilder stringBuilder = new StringBuilder(len * 2); for (int i = 0; i < len; i++) { String s = "0" + Integer.toHexString(bytes[ofs + i]); stringBuilder.append(s.substring(s.length() - 2, s.length())); } return stringBuilder.toString(); } static public boolean md5OfFile_verbose = false; static public String md5OfFile(String path) { return md5OfFile(newFile(path)); } static public String md5OfFile(File f) { try { if (!f.exists()) return "-"; if (md5OfFile_verbose) print("Getting MD5 of " + f); MessageDigest md5 = MessageDigest.getInstance("MD5"); FileInputStream in = new FileInputStream(f); try { byte[] buf = new byte[65536]; int l; while (true) { l = in.read(buf); if (l <= 0) break; md5.update(buf, 0, l); } return bytesToHex(md5.digest()); } finally { _close(in); } } catch (Exception __e) { throw rethrow(__e); } } static public Map applyFunctionToMapValue(A key, Object f, Map map) { if (map.containsKey(key)) map.put(key, (B) callF(f, map.get(key))); return map; } static public Object cloneIfList(Object o) { return o instanceof List ? cloneList((List) o) : o; } static public MetaTransformer metaTransformer_transformableAndList() { return new MetaTransformer(new MetaTransformer.StructureHandler() { public Object transform(Object o, IF1 recurse) { if (o instanceof Transformable) return ((Transformable) o).transformUsing(recurse); if (o instanceof List) return map_ping(recurse, ((List) o)); return null; } public void visit(Object o, IVF1 recurse) { if (o instanceof Visitable) ((Visitable) o).visitUsing(recurse); else if (o instanceof List) for (Object x : ((List) o)) { ping(); recurse.get(x); } } }); } static public A printStructure(String prefix, A o) { if (endsWithLetter(prefix)) prefix += ": "; print(prefix + structureForUser(o)); return o; } static public A printStructure(A o) { print(structureForUser(o)); return o; } static public void logQuoted(String logFile, String line) { logQuoted(getProgramFile(logFile), line); } static public void logQuoted(File logFile, String line) { appendToFile(logFile, quote(line) + "\n"); } static public File getProgramFile(String progID, String fileName) { if (new File(fileName).isAbsolute()) return new File(fileName); return new File(getProgramDir(progID), fileName); } static public File getProgramFile(String fileName) { return getProgramFile(getProgramID(), fileName); } static public String joinNempties(String sep, Object... strings) { return joinStrings(sep, strings); } static public String joinNempties(String sep, Iterable strings) { return joinStrings(sep, strings); } static public Collection findConceptsWhereCI(Class c, Object... params) { return findConceptsWhereCI(db_mainConcepts(), c, params); } static public List findConceptsWhereCI(String c, Object... params) { return findConceptsWhereCI(db_mainConcepts(), c, params); } static public Collection findConceptsWhereCI(Concepts concepts, Class c, Object... params) { Collection l = findConceptsWhereCI_noParent(concepts, c, params); if (concepts.parent == null) return l; return concatCollections_conservative(l, findConceptsWhereCI(concepts.parent, c, params)); } static public Collection findConceptsWhereCI_noParent(Concepts concepts, Class c, Object... params) { params = expandParams(c, params); if (concepts.ciFieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getCIFieldIndex(c, (String) params[i]); if (index != null) { Collection rawList = index.getAll(params[i + 1]); params = dropEntryFromParams(params, i); if (params == null) return rawList; List l = new ArrayList(); for (A x : rawList) if (checkConceptFieldsIC(x, params)) l.add(x); return l; } } return filterConceptsIC(concepts.list(c), params); } static public List findConceptsWhereCI(Concepts concepts, String c, Object... params) { return filterConceptsIC(concepts.list(c), params); } static public String jreplace(String s, String in, String out) { return jreplace(s, in, out, null); } static public String jreplace(String s, String in, String out, Object condition) { List tok = javaTok(s); return jreplace(tok, in, out, condition) ? join(tok) : s; } static public boolean jreplace(List tok, String in, String out) { return jreplace(tok, in, out, false, true, null); } static public boolean jreplace(List tok, String in, String out, Object condition) { return jreplace(tok, in, out, false, true, condition); } static public boolean jreplace(List tok, String in, String out, IF2, Integer, Boolean> condition) { return jreplace(tok, in, out, (Object) condition); } static public boolean jreplace(List tok, String in, String out, boolean ignoreCase, boolean reTok, Object condition) { String[] toks = javaTokForJFind_array(in); int lTokin = toks.length * 2 + 1; boolean anyChange = false; int i = -1; for (int n = 0; n < 10000; n++) { i = findCodeTokens(tok, i + 1, ignoreCase, toks, condition); if (i < 0) return anyChange; List subList = tok.subList(i - 1, i + lTokin - 1); String expansion = jreplaceExpandRefs(out, subList); int end = i + lTokin - 2; clearAllTokens(tok, i, end); tok.set(i, expansion); if (reTok) reTok(tok, i, end); i = end; anyChange = true; } throw fail("woot? 10000! " + quote(in) + " => " + quote(out)); } static public boolean jreplace_debug = false; static public Map paramsToMap(Object... params) { int n = l(params); if (l(params) == 1 && params[0] instanceof Map) return (Map) params[0]; LinkedHashMap map = new LinkedHashMap(); for (int i = 0; i + 1 < n; i += 2) mapPut(map, params[i], params[i + 1]); return map; } static public String jextract(String pat, String s) { return jextract(pat, javaTok(s)); } static public String jextract(String pat, List tok) { List tokpat = javaTok(pat); jfind_preprocess(tokpat); int i = jfind(tok, tokpat); if (i < 0) return null; int j = i + l(tokpat) - 2; return joinSubList(tok, i, j); } static public String stringPar(Object[] params, String name) { return stringOptPar(params, name); } static public String stringPar(String name, Object[] params) { return stringOptPar(params, name); } static public String stringPar(String name, Map params) { return (String) optPar(name, params); } static public String stringPar(String name, Object[] params, String defaultValue) { return optPar(name, params, defaultValue); } static public Object[] paramsMinus(Object[] a1, Object... keys) { return paramsWithout(a1, keys); } static public String joinNemptiesWithSemicolon(String... strings) { return joinNempties("; ", strings); } static public String joinNemptiesWithSemicolon(Collection strings) { return joinNempties("; ", strings); } static public String hsnippetimg(String imageID, Object... params) { return himg(snippetImageLink(imageID), params); } static public int calcHeight(int w, int h, int newWidth) { return iround(doubleRatio(h, w) * newWidth); } static public String hjavascript_src(String src, Object... __) { return hfulltag("script", "", paramsPlus(__, "src", src)); } static public boolean boolPar(ThreadLocal tl) { return boolOptParam(tl); } static public boolean boolPar(Object[] __, String name) { return boolOptParam(__, name); } static public boolean boolPar(String name, Object[] __) { return boolOptParam(__, name); } static public boolean boolPar(String name, Map __) { return boolOptParam(name, __); } static public boolean boolPar(String name, Object[] params, boolean defaultValue) { return optParam(params, name, defaultValue); } static public List llNonNulls(A... a) { List l = new ArrayList(); for (A x : a) if (x != null) l.add(x); return l; } static public String[] flattenStringArray2(Object... a) { List l = new ArrayList(); if (a != null) for (Object x : a) if (x instanceof String[]) l.addAll(asList((String[]) x)); else if (x instanceof Collection) l.addAll((Collection) x); else l.add(x); return asStringArray(l); } static public String hform(Object contents, Object... params) { return htag("form", contents, params); } static public Object[] assertEvenLength(Object[] a) { assertTrue(even(l(a))); return a; } static public LinkedHashMap paramsToOrderedMap(Object... params) { return asLinkedHashMap(paramsToMap(params)); } static public Object derefRef(Object o) { if (o instanceof Concept.Ref) o = ((Concept.Ref) o).get(); return o; } static public A derefRef(Concept.Ref r) { return r == null ? null : r.get(); } static public Map mapKeyAndFunction(Iterable l, Object f) { return mapKeyAndFunction(f, l); } static public Map mapKeyAndFunction(Object f, Iterable l) { HashMap map = new HashMap(); if (l != null) for (Object o : l) map.put(o, callF(f, o)); return map; } static public Map mapKeyAndFunction(Map map, IF2 f) { HashMap map2 = new HashMap(); if (map != null) for (Map.Entry __0 : _entrySet(map)) { A key = __0.getKey(); B value = __0.getValue(); map2.put(key, callF(f, key, value)); } return map2; } static public Map mapKeyAndFunction(Iterable l, IF1 f) { return mapKeyAndFunction(f, l); } static public File prepareProgramFile(String name) { return mkdirsForFile(getProgramFile(name)); } static public File prepareProgramFile(String progID, String name) { return mkdirsForFile(getProgramFile(progID, name)); } static public List> mapToPairs(Map map) { List> l = emptyList(l(map)); if (map != null) for (Map.Entry e : map.entrySet()) l.add(pair(e.getKey(), e.getValue())); return l; } static public Matcher regexpIC(Pattern pat, String s) { return pat.matcher(unnull(s)); } static public Matcher regexpIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static public Pattern regexpIC(String pat) { return compileRegexpIC(pat); } static public Object safeUnstructureAllowingClasses(String s, Class... allowedClasses) { final Set allowedClassesSet = mapToSet(__90 -> className(__90), allowedClasses); Object classFinder = new F1() { public Object get(String name) { try { if (!allowedClassesSet.contains(name)) throw fail("Class not allowed to unstructure: " + name); return classForName(name); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!allowedClassesSet.contains(name)) fail(\"Class not allowed to unstructure..."; } }; return unstructure(s, false, classFinder); } static public List sortedAlphaNum(Collection c) { return sorted(c, new AlphanumComparator()); } static public List uniquify(Collection l) { return uniquifyList(l); } static public String upper(String s) { return s == null ? null : s.toUpperCase(); } static public char upper(char c) { return Character.toUpperCase(c); } static public Map mapKeys(Object func, Map map) { Map m = similarEmptyMap(map); for (Object key : keys(map)) m.put(callF(func, key), map.get(key)); return m; } static public Map mapKeys(Map map, Object func) { return mapKeys(func, map); } static public Map mapKeys(Map map, IF1 func) { return mapKeys(map, (Object) func); } static public Map mapKeys(IF1 func, Map map) { return mapKeys(map, func); } static public String strOrNull(Object o) { return o == null ? null : str(o); } static public String formatWithThousands(long l) { return formatWithThousandsSeparator(l); } static public double fraction(double d) { return d % 1; } static public String n_fancy2(long l, String singular, String plural) { return formatWithThousandsSeparator(l) + " " + trim(l == 1 ? singular : plural); } static public String n_fancy2(Collection l, String singular, String plural) { return n_fancy2(l(l), singular, plural); } static public String n_fancy2(Map m, String singular, String plural) { return n_fancy2(l(m), singular, plural); } static public String n_fancy2(Object[] a, String singular, String plural) { return n_fancy2(l(a), singular, plural); } static public String n_fancy2(MultiSet ms, String singular, String plural) { return n_fancy2(l(ms), singular, plural); } static public String formatDoubleFull(double d, int digits) { String format = digits <= 0 ? "0" : "0." + rep(digits, '0'); return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d); } static public long toM(long l) { return (l + 1024 * 1024 - 1) / (1024 * 1024); } static public String toM(long l, int digits) { return formatDouble(toM_double(l), digits); } static public MultiSet asCIMultiSet(Iterable l) { MultiSet ms = new MultiSet(); ms.map = ciMap(); ms.addAll(l); return ms; } static public Map castMapToMapO(Map map) { return map; } static public AutoCloseable tempDBLock(Concepts concepts) { return tempLock(concepts.lock); } static public AutoCloseable tempDBLock() { return tempDBLock(db_mainConcepts()); } static public Object[] expandParams(Class c, Object[] params) { if (l(params) == 1) params = new Object[] { singleFieldName(c), params[0] }; else warnIfOddCount(params); return params; } static public A unlisted(Class c, Object... args) { concepts_unlisted.set(true); try { return nuObject(c, args); } finally { concepts_unlisted.set(null); } } static public Concept unlisted(String name, Object... args) { Class cc = findClass(name); concepts_unlisted.set(true); try { return cc != null ? nuObject(cc) : new Concept(name); } finally { concepts_unlisted.set(null); } } static public boolean fileNotEmpty(File f) { return isFile(f) && fileSize(f) > 0; } static public List splitAtAmpersand(String s) { return s == null ? emptyList() : asList(s.split("&")); } static public A optParam(ThreadLocal tl, A defaultValue) { return optPar(tl, defaultValue); } static public A optParam(ThreadLocal tl) { return optPar(tl); } static public Object optParam(String name, Map params) { return mapGet(params, name); } static public A optParam(Object[] opt, String name, A defaultValue) { int n = l(opt); if (n == 1 && opt[0] instanceof Map) { Map map = (Map) (opt[0]); return map.containsKey(name) ? (A) map.get(name) : defaultValue; } if (!even(l(opt))) throw fail("Odd parameter length"); for (int i = 0; i < l(opt); i += 2) if (eq(opt[i], name)) return (A) opt[i + 1]; return defaultValue; } static public Object optParam(Object[] opt, String name) { return optParam(opt, name, null); } static public Object optParam(String name, Object[] params) { return optParam(params, name); } static public void setHeaders(URLConnection con) throws IOException { String computerID = getComputerID_quick(); if (computerID != null) try { con.setRequestProperty("X-ComputerID", computerID); con.setRequestProperty("X-OS", System.getProperty("os.name") + " " + System.getProperty("os.version")); } catch (Throwable e) { } } static public int lUtf8(String s) { return l(utf8(s)); } static public String hideCredentials(URL url) { return url == null ? null : hideCredentials(str(url)); } static public String hideCredentials(String url) { try { if (startsWithOneOf(url, "http://", "https://") && isAGIBlueDomain(hostNameFromURL(url))) return url; } catch (Throwable e) { print("HideCredentials", e); } return url.replaceAll("([&?])(_pass|key|cookie)=[^&\\s\"]*", "$1$2="); } static public String hideCredentials(Object o) { return hideCredentials(str(o)); } static public URLConnection setURLConnectionTimeouts(URLConnection con, long timeout) { con.setConnectTimeout(toInt(timeout)); con.setReadTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout || con.getReadTimeout() != timeout) print("Warning: Timeouts not set by JDK."); return con; } static public Matcher regexp(String pat, String s) { return regexp(compileRegexp(pat), unnull(s)); } static public Matcher regexp(java.util.regex.Pattern pat, String s) { return pat.matcher(unnull(s)); } static public java.util.regex.Pattern regexp(String pat) { return compileRegexp(pat); } static public Map parseColonProperties(String text) { return parseColonProperties(text, new LinkedHashMap()); } static public Map parseColonProperties(String text, Map map) { for (String s : tlft(text)) { int i = indexOf(s, ':'); if (i > 0) map.put(trimSubstring(s, 0, i), trimSubstring(s, i + 1)); } return map; } static public double toDouble(Object o) { if (o instanceof Number) return ((Number) o).doubleValue(); if (o instanceof BigInteger) return ((BigInteger) o).doubleValue(); if (o instanceof String) return parseDouble((String) o); if (o == null) return 0.0; throw fail(o); } static public File loadBinarySnippet(String snippetID) { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadBinarySnippet_noResourceLoader(snippetID); } static public File loadBinarySnippet_noResourceLoader(String snippetID) { try { long id = parseSnippetID(snippetID); if (isImageServerSnippet(id)) return loadImageAsFile(snippetID); File f = DiskSnippetCache_getLibrary(id); if (fileSize(f) == 0) f = loadDataSnippetToFile_noResourceLoader(snippetID); return f; } catch (Exception __e) { throw rethrow(__e); } } static public String gazelle_server() { return "https://gazelle.rocks/"; } static public List similarEmptyList(Collection m) { return new ArrayList(); } static public A printHidingCredentials(A o) { print(hideCredentials(str(o))); return o; } static public void logQuotedWithDate(String s) { logQuotedWithTime(s); } static public void logQuotedWithDate(String logFile, String s) { logQuotedWithTime(logFile, s); } static public void logQuotedWithDate(File logFile, String s) { logQuotedWithTime(logFile, s); } static public File infoBoxesLogFile() { return new File(javaxDataDir(), "Logs/infoBoxes.txt"); } static public JWindow showWindow(Component c) { JWindow w = new JWindow(); w.add(wrap(c)); return w; } static public JPanel infoMessage_makePanel(String text) { final JTextArea ta = wrappedTextArea(text); onClick(ta, new Runnable() { public void run() { try { disposeWindow(ta); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "disposeWindow(ta)"; } }); int size = 14; if (l(text) <= 50) size *= 2; else if (l(text) < 100) size = iround(size * 1.5); ta.setFont(typeWriterFont(size)); JScrollPane sp = jscroll(ta); return withMargin(sp); } static public int moveToTopRightCorner_inset = 20; static public A moveToTopRightCorner(A a) { return moveToTopRightCorner(moveToTopRightCorner_inset, moveToTopRightCorner_inset, a); } static public A moveToTopRightCorner(int insetX, int insetY, A a) { Window w = getWindow(a); if (w != null) w.setLocation(getScreenSize().width - w.getWidth() - insetX, insetY); return a; } static public boolean vmBus_noObjections(String msg, Object... args) { return !vmBus_anyFalse(msg, args); } static public A disposeWindowAfter(int delay, final A w) { if (w != null) swingLater(delay, new Runnable() { public void run() { try { w.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "w.dispose();"; } }); return w; } static public A disposeWindowAfter(A w, double seconds) { return disposeWindowAfter(toMS_int(seconds), w); } static public A disposeWindowAfter(double seconds, A w) { return disposeWindowAfter(w, seconds); } static public String exceptionToStringShort(Throwable e) { lastException(e); e = getInnerException(e); String msg = hideCredentials(unnull(e.getMessage())); if (msg.indexOf("Error") < 0 && msg.indexOf("Exception") < 0) return baseClassName(e) + prependIfNempty(": ", msg); else return msg; } static public String defaultThreadName_name; static public String defaultThreadName() { if (defaultThreadName_name == null) defaultThreadName_name = "A thread by " + programID(); return defaultThreadName_name; } static public 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..."; } }; } static public Thread newThread(Object runnable) { return new BetterThread(_topLevelErrorHandling(toRunnable(runnable))); } static public Thread newThread(Object runnable, String name) { if (name == null) name = defaultThreadName(); return new BetterThread(_topLevelErrorHandling(toRunnable(runnable)), name); } static public Thread newThread(String name, Object runnable) { return newThread(runnable, name); } static public Map _registerThread_threads; static public Object _onRegisterThread; static public Thread _registerThread(Thread t) { if (_registerThread_threads == null) _registerThread_threads = newWeakHashMap(); _registerThread_threads.put(t, true); vm_generalWeakSubMap("thread2mc").put(t, weakRef(mc())); callF(_onRegisterThread, t); return t; } static public void _registerThread() { _registerThread(Thread.currentThread()); } static public Method findMethodNamed(Object obj, String method) { if (obj == null) return null; if (obj instanceof Class) return findMethodNamed((Class) obj, method); return findMethodNamed(obj.getClass(), method); } static public Method findMethodNamed(Class c, String method) { while (c != null) { for (Method m : c.getDeclaredMethods()) if (m.getName().equals(method)) { makeAccessible(m); return m; } c = c.getSuperclass(); } return null; } static public int hashMap_internalHash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } static public String dropNumberPrefix(String s) { return dropFirst(s, indexOfNonDigit(s)); } static public String patternQuote(String s) { return s.length() == 0 ? "" : Pattern.quote(s); } static public String quoteReplacement(String s) { return Matcher.quoteReplacement(s); } static public List htmlcoarsetok(String s) { List tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0; while (i < l) { int j = i; char c; while (j < l) { if (s.charAt(j) != '<') ++j; else if (s.substring(j, Math.min(j + 4, l)).equals("")); j = Math.min(j + 3, l); } else { char d = charAt(s, j + 1); if (d == '/' || isLetter(d)) break; else ++j; } } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); if (c == '<') { ++j; while (j < l && s.charAt(j) != '>') ++j; if (j < l) ++j; } tok.add(s.substring(i, j)); i = j; } if ((tok.size() & 1) == 0) tok.add(""); return tok; } static public boolean even(int i) { return (i & 1) == 0; } static public boolean even(long i) { return (i & 1) == 0; } static public boolean even(BigInteger n) { return even(n.intValue()); } static public String dropPrefixSuffix(String prefix, String s) { return dropPrefixSuffix(prefix, prefix, s); } static public String dropPrefixSuffix(String prefix, String suffix, String s) { return dropPrefix(prefix, dropSuffix(suffix, s)); } static public boolean addToCollection(Collection c, A a) { return c != null && c.add(a); } static public String fromLines(Iterable lines) { StringBuilder buf = new StringBuilder(); if (lines != null) for (Object line : lines) buf.append(str(line)).append('\n'); return buf.toString(); } static public String fromLines(String... lines) { return fromLines(asList(lines)); } static public String struct_noStringSharing(Object o) { structure_Data d = new structure_Data(); d.noStringSharing = true; return structure(o, d); } static public A pnl(A l) { return pnl("", l); } static public A pnl(String prefix, A l) { printNumberedLines(prefix, l); return l; } static public A[] pnl(A[] l) { return pnl("", l); } static public A[] pnl(String prefix, A[] l) { printNumberedLines(prefix, l); return l; } static public A pnl(A map) { printNumberedLines(map); return map; } static public A pnl(String prefix, A map) { printNumberedLines(prefix, map); return map; } static public String pnl(String s) { printNumberedLines(lines(s)); return s; } static public MultiSet pnl(MultiSet ms) { pnl(ms == null ? null : ms.asMap()); return ms; } static public MultiMap pnl(MultiMap mm) { pnl(mm == null ? null : mm.asMap()); return mm; } static public List> sortByPairsA(Collection> l) { return pairsSortedByA(l); } static public List callF_all(Collection l, Object... args) { return map(l, f -> callF(f, args)); } static public String htmldecode(final String input) { if (input == null) return null; final int MIN_ESCAPE = 2; final int MAX_ESCAPE = 6; StringWriter writer = null; int len = input.length(); int i = 1; int st = 0; while (true) { while (i < len && input.charAt(i - 1) != '&') i++; if (i >= len) break; int j = i; while (j < len && j < i + MAX_ESCAPE + 1 && input.charAt(j) != ';') j++; if (j == len || j < i + MIN_ESCAPE || j == i + MAX_ESCAPE + 1) { i++; continue; } if (input.charAt(i) == '#') { int k = i + 1; int radix = 10; final char firstChar = input.charAt(k); if (firstChar == 'x' || firstChar == 'X') { k++; radix = 16; } try { int entityValue = Integer.parseInt(input.substring(k, j), radix); if (writer == null) writer = new StringWriter(input.length()); writer.append(input.substring(st, i - 1)); if (entityValue > 0xFFFF) { final char[] chrs = Character.toChars(entityValue); writer.write(chrs[0]); writer.write(chrs[1]); } else { writer.write(entityValue); } } catch (NumberFormatException ex) { i++; continue; } } else { CharSequence value = htmldecode_lookupMap().get(input.substring(i, j)); if (value == null) { i++; continue; } if (writer == null) writer = new StringWriter(input.length()); writer.append(input.substring(st, i - 1)); writer.append(value); } st = j + 1; i = st; } if (writer != null) { writer.append(input.substring(st, len)); return writer.toString(); } return input; } static public HashMap htmldecode_lookupMap_cache; static public HashMap htmldecode_lookupMap() { if (htmldecode_lookupMap_cache == null) htmldecode_lookupMap_cache = htmldecode_lookupMap_load(); return htmldecode_lookupMap_cache; } static public HashMap htmldecode_lookupMap_load() { var map = new HashMap(); for (CharSequence[] seq : htmldecode_escapes()) map.put(seq[1].toString(), seq[0]); return map; } static public List dropTagsAndHTMLComments(List tok) { return dropHTMLComments(dropTags(tok)); } static public String dropTagsAndHTMLComments(String html) { return join(dropTagsAndHTMLComments(htmlTok(html))); } static public List nempties(Collection c) { return filterNempty(c); } static public List allToStrOrNull(Iterable c) { return lmap(__91 -> strOrNull(__91), c); } static public List allToStrOrNull(Object... c) { return lmap(__92 -> strOrNull(__92), c); } static public String nemptyLinesLL(Object... l) { return nemptyLines(ll(l)); } static public void failIfOddCount(Object... list) { if (odd(l(list))) throw fail("Odd list size: " + list); } static public Object[] asObjectArray(Collection l) { return toObjectArray(l); } static public void addToContainer(Container a, Component... b) { if (a == null) return; { swing(new Runnable() { public void run() { try { for (Component c : unnullForIteration(b)) if (c != null) a.add(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (Component c : unnullForIteration(b))\r\n if (c != null) \r\n a.a..."; } }); } } static public A setFrameTitle(A c, final String title) { final Frame f = getAWTFrame(c); if (f != null) { swing(new Runnable() { public void run() { try { f.setTitle(title); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.setTitle(title);"; } }); } return c; } static public A setFrameTitle(String title, A c) { return setFrameTitle(c, title); } static public JFrame setFrameTitle(String title) { Object f = getOpt(mc(), "frame"); if (f instanceof JFrame) return setFrameTitle((JFrame) f, title); return null; } static public void addToStringTree(StringTree2 tree, List tokC, A leafValue) { if (leafValue == null) return; if (empty(tokC)) { tree.leafValue = leafValue; return; } String s = first(tokC); StringTree2 t = tree.getOrAdd(s); addToStringTree(t, dropFirst(tokC), leafValue); } static public List javaTokC(String s) { if (s == null) return null; int l = s.length(); ArrayList tok = new ArrayList(); int i = 0; while (i < l) { int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); i = j; } return tok; } static public boolean regionMatches(String a, int offsetA, String b, int offsetB, int len) { return a != null && b != null && a.regionMatches(offsetA, b, offsetB, len); } static public boolean regionMatches(String a, int offsetA, String b) { return regionMatches(a, offsetA, b, 0, l(b)); } static public String javaTok_substringN(String s, int i, int j) { if (i == j) return ""; if (j == i + 1 && s.charAt(i) == ' ') return " "; return s.substring(i, j); } static public String javaTok_substringC(String s, int i, int j) { return s.substring(i, j); } static public List javaTokWithExisting(String s, List existing) { ++javaTok_n; int nExisting = javaTok_opt && existing != null ? existing.size() : 0; ArrayList tok = existing != null ? new ArrayList(nExisting) : new ArrayList(); int l = s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' && Character.isJavaIdentifierStart(d) && i + 2 < l && "'\\".indexOf(s.charAt(i + 2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else ++j; if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static public boolean javaTokWithExisting_isCopyable(String t, String s, int i, int j) { return t.length() == j - i && s.regionMatches(i, t, 0, j - i); } static public int jfind(String s, String in) { return jfind(javaTok(s), in); } static public int jfind(List tok, String in) { return jfind(tok, 1, in); } static public int jfind(List tok, int startIdx, String in) { return jfind(tok, startIdx, in, null); } static public int jfind(List tok, String in, Object condition) { return jfind(tok, 1, in, condition); } static public int jfind(List tok, String in, ITokCondition condition) { return jfind(tok, 1, in, condition); } static public int jfind(List tok, int startIndex, String in, ITokCondition condition) { return jfind(tok, startIndex, in, (Object) condition); } static public int jfind(List tok, int startIdx, String in, Object condition) { return jfind(tok, startIdx, javaTokForJFind_array(in), condition); } static public int jfind(List tok, List tokin) { return jfind(tok, 1, tokin); } static public int jfind(List tok, int startIdx, List tokin) { return jfind(tok, startIdx, tokin, null); } static public int jfind(List tok, int startIdx, String[] tokinC, Object condition) { return findCodeTokens(tok, startIdx, false, tokinC, condition); } static public int jfind(List tok, int startIdx, List tokin, Object condition) { return jfind(tok, startIdx, codeTokensAsStringArray(tokin), condition); } static public List jfind_preprocess(List tok) { for (String type : litlist("quoted", "id", "int")) replaceSublist(tok, ll("<", "", type, "", ">"), ll("<" + type + ">")); replaceSublist(tok, ll("\\", "", "*"), ll("\\*")); return tok; } static public TokCondition toTokCondition(ITokCondition condition) { return condition == null ? null : condition instanceof TokCondition ? (TokCondition) condition : new TokCondition() { public boolean get(List tok, int i) { return condition.get(tok, i); } }; } static public String[] toStringArray(Collection c) { String[] a = new String[l(c)]; Iterator it = c.iterator(); for (int i = 0; i < l(a); i++) a[i] = it.next(); return a; } static public String[] toStringArray(Object o) { if (o instanceof String[]) return (String[]) o; else if (o instanceof Collection) return toStringArray((Collection) o); else throw fail("Not a collection or array: " + getClassName(o)); } static public List codeTokensOnly(List tok) { int n = l(tok); List l = emptyList(n / 2); for (int i = 1; i < n; i += 2) l.add(tok.get(i)); return l; } static public int findCodeTokens(List tok, String... tokens) { return findCodeTokens(tok, 1, false, tokens); } static public int findCodeTokens(List tok, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, 1, ignoreCase, tokens); } static public int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, startIdx, ignoreCase, tokens, null); } static public HashSet findCodeTokens_specials = lithashset("*", "", "", "", "\\*"); static public int findCodeTokens_bails, findCodeTokens_nonbails; static public interface findCodeTokens_Matcher { public boolean get(String token); } static public int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String[] tokens, Object condition) { int end = tok.size() - tokens.length * 2 + 2, nTokens = tokens.length; int i = startIdx | 1; if (i >= end) return -1; String firstToken = tokens[0]; if (!ignoreCase && !findCodeTokens_specials.contains(firstToken)) { while (i < end && !firstToken.equals(tok.get(i))) i += 2; } findCodeTokens_Matcher[] matchers = new findCodeTokens_Matcher[nTokens]; for (int j = 0; j < nTokens; j++) { String p = tokens[j]; findCodeTokens_Matcher matcher; if (p.equals("*")) matcher = t -> true; else if (p.equals("")) matcher = t -> isQuoted(t); else if (p.equals("")) matcher = t -> isIdentifier(t); else if (p.equals("")) matcher = t -> isInteger(t); else if (p.equals("\\*")) matcher = t -> t.equals("*"); else if (ignoreCase) matcher = t -> eqic(p, t); else matcher = t -> t.equals(p); matchers[j] = matcher; } outer: for (; i < end; i += 2) { for (int j = 0; j < nTokens; j++) if (!matchers[j].get(tok.get(i + j * 2))) continue outer; if (condition == null || checkTokCondition(condition, tok, i - 1)) return i; } return -1; } static public boolean isNormalQuoted(String s) { int l = l(s); if (!(l >= 2 && s.charAt(0) == '"' && lastChar(s) == '"')) return false; int j = 1; while (j < l) if (s.charAt(j) == '"') return j == l - 1; else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; return false; } static public boolean isMultilineQuoted(String s) { if (!startsWith(s, "[")) return false; int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; return i < s.length() && s.charAt(i) == '['; } static public String applyTranspilationFunction(IVF1> f, String s) { if (f == null) return s; List tok = javaTok(s); f.get(tok); return join(tok); } static public String jreplace_dyn(String s, String in, Object out) { return jreplace_dyn(s, in, out, null); } static public String jreplace_dyn(String s, String in, Object out, Object condition) { List tok = javaTok(s); jreplace_dyn(tok, in, out, condition); return join(tok); } static public boolean jreplace_dyn(List tok, String in, Object out) { return jreplace_dyn(tok, in, out, false, true, null); } static public boolean jreplace_dyn(List tok, String in, IF2, Integer, String> out) { return jreplace_dyn(tok, in, (Object) out); } static public boolean jreplace_dyn(List tok, String in, IF2, Integer, String> out, IF2, Integer, Boolean> condition) { return jreplace_dyn(tok, in, (Object) out, (Object) condition); } static public boolean jreplace_dyn(List tok, String in, Object out, Object condition) { return jreplace_dyn(tok, in, out, false, true, condition); } static public boolean jreplace_dyn(List tok, String in, Object out, boolean ignoreCase, boolean reTok, Object condition) { List tokin = javaTok(in); jfind_preprocess(tokin); String[] toks = toStringArray(codeTokensOnly(tokin)); boolean anyChange = false; for (int n = 0; n < 10000; n++) { int i = findCodeTokens(tok, 1, ignoreCase, toks, condition); if (i < 0) return anyChange; String expansion = (String) (callF(out, tok, i)); int end = i + l(tokin) - 2; clearAllTokens(tok, i, end); tok.set(i, expansion); if (reTok) reTok(tok, i, end); anyChange = true; } throw fail("woot? 10000! " + quote(in) + " => " + quote(out)); } static public List splitAtJavaToken(String s, String splitToken) { return splitByJavaToken(s, splitToken); } static public void tok_transpileIfQuoted_dollarVars(List tok) { jreplace_dyn(tok, "if ", new F2, Integer, String>() { public String get(List tok, Integer cIdx) { try { String pat = unquote(tok.get(cIdx + 2)); List vars = new ArrayList(); String pat2 = dollarVarsToStars(pat, vars); int iCurly = cIdx + 4; tok_statementToBlock(tok, iCurly); tokAppend_reTok(tok, iCurly, joinWithSpace(mapWithIndexStartingAt1(vars, (i, var) -> ("S " + var + " = $" + i + ";")))); return ("if (match(" + (quote(pat2)) + ", s, m))"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S pat = unquote(tok.get(cIdx+2));\r\n new LS vars;\r\n S pat2 = dollarVarsT..."; } }, new TokCondition() { public boolean get(final List tok, final int i) { return containsDollarVars(unquote(tok.get(i + 3))); } }); } static public boolean startsAndEndsWith(String a, char c) { return startsWith(a, c) && endsWith(a, c) && l(a) >= 2; } static public boolean startsAndEndsWith(String a, String b) { return startsWith(a, b) && endsWith(a, b) && l(a) >= l(b) * 2; } static public String tb_mainServer_default = "https://code.botcompany.de:9898"; static public Object tb_mainServer_override; static public String tb_mainServer() { if (tb_mainServer_override != null) return (String) callF(tb_mainServer_override); return trim(loadTextFile(tb_mainServer_file(), tb_mainServer_default)); } static public File tb_mainServer_file() { return getProgramFile("#1001638", "mainserver.txt"); } static public boolean tb_mainServer_isDefault() { return eq(tb_mainServer(), tb_mainServer_default); } public static List parseSnippetIDs(Collection snippetIDs) { List l = new ArrayList(); for (String id : snippetIDs) l.add(str(parseSnippetID(id))); return l; } static public Map trimValues(Map map) { Map map2 = similarEmptyMap(map); for (A key : keys(map)) map2.put(key, trim(map.get(key))); return map2; } static public Map transformKeys(Map map, Object f) { HashMap m = new HashMap(); for (Object key : keys(map)) m.put(callF(f, key), map.get(key)); return m; } static public Map standardCredentialsMap() { String user = standardCredentialsUser(); String pass = standardCredentialsPass(); if (nempty(user) && nempty(pass)) return litmap("_user", user, "_pass", pass); return litmap(); } static public String regexp_findSnippetIDs() { return "(?:#|\\blib\\s+|(?:^|\\n)\\s*!)([0-9]+)"; } static public String snippetLink(String id) { return empty(id) ? id : snippetLink(parseSnippetID(id)); } static public String snippetLink(long id) { return "https://code.botcompany.de/" + id; } static public SnippetTitles getSnippetTitle_cached_cache = new SnippetTitles(); static public String getSnippetTitle_cached(String id) { return getSnippetTitle_cached_cache.get(id); } static public void getSnippetTitle_cached_put(String id, String title) { getSnippetTitle_cached_cache.put(id, title); } static public boolean getSnippetTitle_cached_has(String id) { return getSnippetTitle_cached_cache.has(id); } static public String getSnippetTitle_cached_probe(String id) { return getSnippetTitle_cached_cache.probe(id); } static public void mreplace(Matcher m, StringBuffer buf, String s) { m.appendReplacement(buf, Matcher.quoteReplacement(s)); } static public Map stdFunctions_uncached() { return stdFunctions_uncached(new HashMap()); } static public Map stdFunctions_uncached(Map map) { parseStdFunctionsList(loadSnippetSilently("#1006654"), map); parseStdFunctionsList(loadSnippetSilently("#761"), map); return map; } static public List tlft_j(String text) { return toLinesFullTrim_java(text); } static public Map> allFields_cache = weakHashMap(); static public Set allFields(Object o) { if (o == null) return emptySet(); Class _c = _getClass(o); Set fields = allFields_cache.get(_c); if (fields == null) allFields_cache.put(_c, fields = asTreeSet(keys(getOpt_getFieldMap(o)))); return fields; } static public int stdHash(Object a, String... fields) { if (a == null) return 0; int hash = getClassName(a).hashCode(); for (String field : fields) hash = boostHashCombine(hash, hashCode(getOpt(a, field))); return hash; } static public int lKeys(MultiMap mm) { return mm == null ? 0 : mm.keysSize(); } static public F0 dm_rEnter() { return dm_rEnter(dm_current()); } static public F0 dm_rEnter(DynModule mod) { return mod == null ? null : new F0() { public AutoCloseable get() { try { return mod.enter(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret mod.enter();"; } }; } static public Runnable dm_rEnter(Runnable r) { return dm_rEnter(dm_current(), r); } static public Runnable dm_rEnter(DynModule mod, Runnable r) { return mod == null || r == null ? r : new Runnable() { public void run() { try { AutoCloseable __1 = mod.enter(); try { r.run(); } finally { _close(__1); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp mod.enter(); r.run();"; } }; } static public Set synchroWeakHashSet() { return Collections.newSetFromMap((Map) newWeakHashMap()); } static public Object dm_callModule(Object moduleOrID, String method, Object... args) { Object mod = dm_getModule(moduleOrID); if (mod == null) return null; AutoCloseable __1 = dm_enter(mod); try { return call(mod, method, args); } finally { _close(__1); } } static public boolean dm_isFirstSiblingModule_debug = false; static public boolean dm_isFirstSiblingModule(Object mod) { String libID = dm_moduleLibID(mod); if (libID == null) return false; List siblings = dm_modulesWithLibID(libID); if (dm_isFirstSiblingModule_debug) printVars("libID", libID, "siblings", siblings); if (empty(siblings)) return true; return eq(dm_moduleID(mod), lowestByAlphaNum(siblings)); } static public String dm_moduleLibID() { return programID() + "/" + shortClassName(dm_current_mandatory_generic()); } static public String dm_moduleLibID(Object mod) { if (mod == null) return null; mod = dm_getModule(mod); if (hasSuperclassShortNamed(mod, "DynModule")) return programID(mod) + "/" + shortClassName(mod); return null; } static public void dm_ownTimer(Object resource, Object closerHelper) { call(dm_current_generic(), "ownTimer", resource, closerHelper); } static public A dm_ownTimer(A resource) { call(dm_current_generic(), "ownTimer", resource); return resource; } static public FixedRateTimer doEvery(long delay, final Object r) { return doEvery(delay, delay, r); } static public FixedRateTimer doEvery(long delay, long firstDelay, final Object r) { FixedRateTimer timer = new FixedRateTimer(shorten(programID() + ": " + r, 80)); timer.scheduleAtFixedRate(smartTimerTask(r, timer, toInt(delay)), toInt(firstDelay), toInt(delay)); return vmBus_timerStarted(timer); } static public FixedRateTimer doEvery(double initialSeconds, double delaySeconds, final Object r) { return doEvery(toMS(delaySeconds), toMS(initialSeconds), r); } static public FixedRateTimer doEvery(double delaySeconds, final Object r) { return doEvery(toMS(delaySeconds), r); } static public void ensureConceptClassIsIndexed(Class c) { ensureConceptClassIsIndexed(db_mainConcepts(), c); } static public void ensureConceptClassIsIndexed(Concepts cc, Class c) { if (cc != null && c != null && !isConceptClassIndexed(cc, c)) indexRandomConceptField(cc, c); } static public A toolTip(A c, final Object toolTip) { return setToolTipText(c, toolTip); } static public A toolTip(Object toolTip, A c) { return setToolTipText(toolTip, c); } static public JButton jPopDownButton(String text, final Object... menuParams) { return jbutton((empty(text) ? "" : text + " ") + unicode_downPointingTriangle(), new Runnable() { public void run() { try { JPopupMenu menu = new JPopupMenu(); int emptyCount = menu.getComponentCount(); String position = (String) (optPar_ignoreOddLength("position", menuParams)); fillJPopupMenu(menu, paramsWithout(menuParams, "position")); if (menu.getComponentCount() != emptyCount) { JButton btn = heldInstance(JButton.class); int x = 0; if (eq(position, "center")) x = (btn.getWidth() - getPreferredWidth(menu)) / 2; else if (eq(position, "right")) x = btn.getWidth() - getPreferredWidth(menu); menu.show(btn, x, btn.getHeight()); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new JPopupMenu menu;\r\n int emptyCount = menu.getComponentCount();\r\n Str..."; } }); } static public Object[] litObjectArray(Object... l) { return l; } static public Object[] objectArrayPlus_inFront(Object[] a1, Object... a2) { return concatArrays(a2, a1); } static public String fixHTML(Object contents) { String s = str(contents); return hhtml(hbody(s)); } static public String renderStackTrace(StackTraceElement[] st) { return stackTraceToString(st); } static public String renderStackTrace(Throwable e) { return stackTraceToString(e); } static public String renderStackTrace(String msg) { return renderStackTrace(new Throwable(msg)); } static volatile public PersistableThrowable lastException_lastException; static public PersistableThrowable lastException() { return lastException_lastException; } static public void lastException(Throwable e) { lastException_lastException = persistableThrowable(e); } static public Object getOptMC(String field) { return getOpt(mc(), field); } static public int globalIDLength() { return 16; } static public ThreadLocal print_byThread() { synchronized (print_byThread_lock) { if (print_byThread == null) print_byThread = new ThreadLocal(); } return print_byThread; } static public void print_setPrefixForThread(final String prefix) { interceptPrintInThisThread(empty(prefix) ? null : new _PrintIndent(prefix)); } public static String rtrim(String s) { if (s == null) return null; int i = s.length(); while (i > 0 && " \t\r\n".indexOf(s.charAt(i - 1)) >= 0) --i; return i < s.length() ? s.substring(0, i) : s; } static public Object callMainBot(String method, Object... args) { return call(mainBot(), method, args); } static public Object subBot_serveInputStream(InputStream in, String mimeType) { return call(mainBot(), "serveInputStream", in, mimeType); } static public int bufferedInputStream_bufferSize = 65536; static public BufferedInputStream bufferedInputStream(int bufSize, File f) { try { return bufferedInputStream(bufSize, newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static public BufferedInputStream bufferedInputStream(File f) { try { return bufferedInputStream(newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static public BufferedInputStream bufferedInputStream(InputStream in) { return new BufferedInputStream(in, bufferedInputStream_bufferSize); } static public BufferedInputStream bufferedInputStream(int bufSize, InputStream in) { return new BufferedInputStream(in, bufSize); } static public String addPrefix(String prefix, String s) { return s.startsWith(prefix) ? s : prefix + s; } static public List sortByCalculatedFieldDesc(Collection c, final Object f) { return sortByCalculatedFieldDesc_inPlace(cloneList(c), f); } static public List sortByCalculatedFieldDesc(Object f, Collection c) { return sortByCalculatedFieldDesc(c, f); } static public List sortByCalculatedFieldDesc(Iterable c, IF1 f) { List l = cloneList(c); sort(l, new Comparator() { public int compare(A a, A b) { return stdcompare(f.get(b), f.get(a)); } }); return l; } static public List sortByCalculatedFieldDesc(IF1 f, Iterable c) { return sortByCalculatedFieldDesc(c, f); } static public String webChatBotLogsHTML() { return withDBLock(new F0() { public String get() { try { List l = new ArrayList(); for (Conversation conv : sortByCalculatedFieldDesc(list(Conversation.class), new F1() { public Object get(Conversation c) { try { return empty(c.msgs) ? c.created : last(c.msgs).time; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "empty(c.msgs) ? c.created : last(c.msgs).time"; } })) { List> dialogs = reversed(unnull(conv.oldDialogs)); l.add(webChatBotLogsHTML_formatDialog(str(conv.id + "/" + (l(dialogs) + 1)), conv.msgs)); int i = l(dialogs); for (List msgs : dialogs) l.add(webChatBotLogsHTML_formatDialog(conv.id + "/" + (i--), msgs)); } return h3_htitle("Chat Logs") + ul(l, null, "style", "margin-top: 1em"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new L l;\r\n for (Conversation conv : sortByCalculatedFieldDesc(list Conv..."; } }); } static public String webChatBotLogsHTML_formatDialog(String id, List msgs) { long startTime = collectMinLong(msgs, "time"); long endTime = collectMaxLong(msgs, "time"); List lc = new ArrayList(); for (Msg m : msgs) if (m.fromUser) lc.add("U: " + i(htmlencode(m.text))); else lc.add("B: " + htmlencode(m.text)); String time1 = formatDateAndTime(startTime); String time2 = formatDateAndTime(endTime); time2 = shortenEndTime(time2, time1); return id + " [" + htmlencode(time1) + " - " + htmlencode(time2) + "]" + ul(lc); } static public int parseIntOpt(String s) { return parseIntOpt(s, 0); } static public int parseIntOpt(String s, int defValue) { return isInteger(s) ? parseInt(s) : defValue; } static public String h3_htitle(String s) { return htitle(s) + h3(s); } static public String pageNav2(String baseLink, int count, int value, int step, String nVar, Object... __) { List l = new ArrayList(); baseLink = unnull(baseLink) + (contains(baseLink, "?") ? "&" : "?") + urlencode(nVar) + "="; if (value > 0) l.add(ahref(baseLink + max(0, value - step), stringPar("leftArrow", __, htmlencode(unicode_leftPointingTriangle())))); for (int i = 0; i < count; i += step) { int n = i / step + 1; if (pageNav2_showPage(value, i, step, count)) if (value == i) l.add(b(n)); else l.add(ahref(baseLink + i, n)); } if (value + step < count) l.add(ahref(baseLink + (value + step), stringPar("rightArrow", __, htmlencode(unicode_rightPointingTriangle())))); return p("Pages: " + lines(l)); } static public boolean pageNav2_showPage(int actual, int i, int step, int count) { int diff = abs(actual - i) / step; return i == 0 || i >= (count - 1) / step * step || diff <= 10 || diff <= 100 && ((i / step) % 10) == 9 || diff <= 1000 && ((i / step) % 100) == 99 || ((i / step) % 1000) == 999; } static public String spaces(int n) { return rep(' ', n); } static public String renderFileInfo(File f) { return f == null ? "-" : f2s(f) + " " + (f.isFile() ? "(file, " + n2(fileSize(f)) + " bytes)" : f.isDirectory() ? "(dir)" : "(not found)"); } static public File fileInSameDir(File f, String newName) { return newFile(parentFile(f), newName); } static public String ymd_minus_hms() { return ymd() + "-" + hms(); } static public File copyFile(File src, File dest) { try { FileInputStream inputStream = new FileInputStream(src.getPath()); FileOutputStream outputStream = newFileOutputStream(dest.getPath()); try { copyStream(inputStream, outputStream); inputStream.close(); } finally { outputStream.close(); } return dest; } catch (Exception __e) { throw rethrow(__e); } } static public boolean emptyString(String s) { return s == null || s.length() == 0; } static public int boolToInt(boolean b) { return b ? 1 : 0; } static public List newSubList(List l, int startIndex, int endIndex) { return cloneList(subList(l, startIndex, endIndex)); } static public List newSubList(List l, int startIndex) { return cloneList(subList(l, startIndex)); } static public Object sleepQuietly_monitor = new Object(); static public void sleepQuietly() { try { assertFalse(isAWTThread()); synchronized (sleepQuietly_monitor) { sleepQuietly_monitor.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean isRelativeOrAbsoluteURL(String s) { return isAbsoluteURL(s) || isRelativeURL(s); } static public List rgbToIntList(RGB rgb) { return rgb == null ? null : ll(rgb.redInt(), rgb.greenInt(), rgb.blueInt()); } static public String stringIfTrue(boolean b, String s) { return b ? s : ""; } static public ExpiringMap2 loadSnippet_simpleCache_map = new ExpiringMap2(10000); static public Lock loadSnippet_simpleCache_lock = lock(); static public int loadSnippet_simpleCache_timeout = 60000; static public String loadSnippet_simpleCache(String id) { if (id == null) return null; Lock __0 = loadSnippet_simpleCache_lock; lock(__0); try { id = fsI(id); String src = loadSnippet_simpleCache_map.get(id); if (src != null) return src; Integer oldTimeout = setThreadLocal(loadPage_forcedTimeout_byThread, loadSnippet_simpleCache_timeout); try { src = loadSnippet(id); if (src != null) loadSnippet_simpleCache_map.put(id, src); return src; } finally { loadPage_forcedTimeout_byThread.set(oldTimeout); } } finally { unlock(__0); } } static public String hreplacetag(String html, String tag, String newTag) { List tok = htmlcoarsetok(html); List> tags = findContainerTag(tok, tag); if (empty(tags)) return html; List theTag = first(tags); List actualTag = subList(theTag, 1, l(theTag) - 1); return join(replaceSubList(cloneList(tok), actualTag, litlist(newTag))); } static public Object subBot_serveWithContentType(String text, String contentType) { return callMainBot("serveByteArray", toUtf8(unnull(text)), contentType); } static public A findConceptWhere(Class c, Object... params) { return findConceptWhere(db_mainConcepts(), c, params); } static public A findConceptWhere(Concepts concepts, Class c, Object... params) { ping(); params = expandParams(c, params); if (concepts.fieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getFieldIndex(c, (String) params[i]); if (index != null) { for (A x : index.getAll(params[i + 1])) if (checkConceptFields(x, params)) return x; return null; } } for (A x : concepts.list(c)) if (checkConceptFields(x, params)) return x; return null; } static public Concept findConceptWhere(Concepts concepts, String c, Object... params) { for (Concept x : concepts.list(c)) if (checkConceptFields(x, params)) return x; return null; } static public String fileExtension(File f) { if (f == null) return null; return fileExtension(f.getName()); } static public String fileExtension(String s) { return substring(s, smartLastIndexOf(s, '.')); } static public Collection findConceptsWhere(Class c, Object... params) { return findConceptsWhere(db_mainConcepts(), c, params); } static public Collection findConceptsWhere(String c, Object... params) { return findConceptsWhere(db_mainConcepts(), c, params); } static public Collection findConceptsWhere(Concepts concepts, Class c, Object... params) { ping(); params = expandParams(c, params); if (concepts.fieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getFieldIndex(c, (String) params[i]); if (index != null) { Collection rawList = index.getAll(params[i + 1]); params = dropEntryFromParams(params, i); if (params == null) return rawList; List l = new ArrayList(); for (A x : rawList) if (checkConceptFields(x, params)) l.add(x); return l; } } return filterConcepts(concepts.list(c), params); } static public Collection findConceptsWhere(Concepts concepts, String c, Object... params) { return filterConcepts(concepts.list(c), params); } static public String ymd() { return ymd(now()); } static public String ymd(long now) { return year(now) + formatInt(month(now), 2) + formatInt(dayOfMonth(now), 2); } static public String ymd(long now, TimeZone tz) { return year(now, tz) + formatInt(month(now, tz), 2) + formatInt(dayOfMonth(now, tz), 2); } static public String hhmm() { return hhmm(now()); } static public String hhmm(long time) { return new SimpleDateFormat("HHmm").format(time); } static public String htmlEncode(String s) { return htmlencode(s); } static public ThreadLocal dataToTable_useStruct = threadLocalWithDefault(true); static public void dataToTable_dynSet(List l, int i, Object s) { while (i >= l.size()) l.add(""); l.set(i, s); } static public List dataToTable_makeRow(Object x, List cols) { if (instanceOf(x, "DynamicObject")) x = get_raw(x, "fieldValues"); if (x instanceof Map) { Map m = (Map) x; List row = new ArrayList(); for (Object _field : keysWithoutHidden(m)) { String field = (String) _field; Object value = m.get(field); int col = cols.indexOf(field); if (col < 0) { cols.add(field); col = cols.size() - 1; } dataToTable_dynSet(row, col, dataToTable_wrapValue(value)); } return row; } if (x instanceof List) return allToString((List) x); return litlist(structureOrText(x)); } static public Object dataToTable_wrapValue(Object o) { if (o instanceof BufferedImage) return o; if (o instanceof MakesBufferedImage) return ((MakesBufferedImage) o).getBufferedImage(); if (o instanceof RGBImage) return o; if (o instanceof Boolean) return o; return dataToTable_useStruct.get() ? structureOrTextForUser(o) : strOrNull(o); } static public String structureOrText(Object o) { return o instanceof String ? (String) o : structure(o); } static public String hopeningtag(String tag, Map params) { return hopeningTag(tag, params); } static public String hopeningtag(String tag, Object... params) { return hopeningTag(tag, params); } static public List rawEmojisList() { return (List) jsonDecodeMap(loadTextFile(loadLibrary("#1400427"))).get("emojis"); } static public void typeWriterConsole() { if (isHeadless()) return; Font f = typeWriterFont(); consoleFont(f); consoleInputFont(f); } static public Object[] paramsPlus_inFront(Object[] a1, Object... a2) { return paramsPlus(a2, a1); } static public String htd(Object contents, Object... params) { return htag("td", contents, params); } static public List listZip(File inZip) { return listZipFile(inZip); } static public List listZip(String inZip) { return listZipFile(inZip); } static public String addSlash(String s) { return empty(s) || s.endsWith("/") ? s : s + "/"; } static public void copyStream(InputStream in, OutputStream out) { try { byte[] buf = new byte[65536]; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean isFile(File f) { return f != null && f.isFile(); } static public boolean isFile(String path) { return isFile(newFile(path)); } static public FileOutputStream newFileOutputStream(File path) throws IOException { return newFileOutputStream(path.getPath()); } static public FileOutputStream newFileOutputStream(String path) throws IOException { return newFileOutputStream(path, false); } static public FileOutputStream newFileOutputStream(File path, boolean append) throws IOException { return newFileOutputStream(path.getPath(), append); } static public FileOutputStream newFileOutputStream(String path, boolean append) throws IOException { mkdirsForFile(path); FileOutputStream f = new FileOutputStream(path, append); _registerIO(f, path, true); return f; } static public String hStylesheetSnippet_maxCache(String snippetID) { return tag("link", "", "rel", "stylesheet", "type", "text/css", "href", snippetRawURL_maxCache(snippetID, "text/css")); } static public String hjssnippet_maxCache(String snippetID) { return hfulltag("script", "", "src", snippetRawURL_maxCache(snippetID, "text/javascript")); } static public String nlToBr_withIndents(String s) { s = nlToBr(s); StringBuilder buf = new StringBuilder(); int i = 0; while (i < l(s)) { while (charAt(s, i) == ' ') { ++i; buf.append(" "); } int j = smartIndexOf(s, i, '\n') + 1; buf.append(substring(s, i, j)); i = j; } return str(buf); } static public List dropFirstTwoAndLastTwo(List l) { return dropFirstAndLast(2, l); } static public String[] dropFirst(int n, String[] a) { return drop(n, a); } static public String[] dropFirst(String[] a) { return drop(1, a); } static public Object[] dropFirst(Object[] a) { return drop(1, a); } static public List dropFirst(List l) { return dropFirst(1, l); } static public List dropFirst(int n, Iterable i) { return dropFirst(n, toList(i)); } static public List dropFirst(Iterable i) { return dropFirst(toList(i)); } static public List dropFirst(int n, List l) { return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size())); } static public List dropFirst(List l, int n) { return dropFirst(n, l); } static public String dropFirst(int n, String s) { return substring(s, n); } static public String dropFirst(String s, int n) { return substring(s, n); } static public String dropFirst(String s) { return substring(s, 1); } static public void replaceTokens(List tok, IntRange r, String s) { replaceTokens(tok, r.start, r.end, s); } static public void replaceTokens(List tok, int i, int j, String s) { clearAllTokens(tok, i + 1, j); tok.set(i, s); } static public void replaceTokens(List tok, String s) { clearAllTokens(tok, 1, l(tok)); tok.set(0, s); } static public void addFirst(List c, A a) { if (c != null) c.add(0, a); } static public String oggMimeType() { return "audio/ogg"; } static public String wavMimeType() { return "audio/wav"; } static public String m4aMimeType() { return "audio/mp4"; } static public String hinputtag(Object contents, Object... params) { return htag("input", contents, params); } static public Object[] paramsPlus_noOverwrite(Object[] a1, Object... a2) { if (a2 == null) return a1; if (a1 == null) return a2; if (l(a1) == 1 && a1[0] instanceof Map) return new Object[] { mapPlus((Map) a1[0], a2) }; assertEvenLength(a1); assertEvenLength(a2); Map map = paramsToOrderedMap(a1); int n = l(a2); for (int i = 0; i < n; i += 2) mapPut_noOverwrite(map, a2[i], a2[i + 1]); return mapToParams(map); } static public boolean isSubclass(Class a, Class b) { return a != null && b != null && b.isAssignableFrom(a); } static public String hstyle(Object contents) { return hcss(contents); } static public String hdiv(Object contents, Object... params) { return div(contents, params); } static public String unicode_smallDownPointingTriangle() { return charToString(0x25BE); } static public List newSubListOrSame(List l, int startIndex) { return newSubListOrSame(l, startIndex, l(l)); } static public List newSubListOrSame(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = max(0, startIndex); endIndex = min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return cloneList(l.subList(startIndex, endIndex)); } static public List newSubListOrSame(List l, IntRange r) { return newSubListOrSame(l, r.start, r.end); } static public int[] takeFirstOfIntArray(int[] b, int n) { return subIntArray(b, 0, n); } static public int[] takeFirstOfIntArray(int n, int[] b) { return takeFirstOfIntArray(b, n); } static public ClassLoader classLoaderForObject(Object o) { if (o instanceof ClassLoader) return ((ClassLoader) o); if (o == null) return null; return _getClass(o).getClassLoader(); } static public String classNameToVM(String name) { return name.replace(".", "$"); } static public String shortenClassName(String name) { if (name == null) return null; int i = lastIndexOf(name, "$"); if (i < 0) i = lastIndexOf(name, "."); return i < 0 ? name : substring(name, i + 1); } static public Set similarEmptySet(Iterable m) { if (m instanceof TreeSet) return new TreeSet(((TreeSet) m).comparator()); if (m instanceof LinkedHashSet) return new LinkedHashSet(); return new HashSet(); } static public Set similarEmptySet(Map m) { if (m instanceof TreeMap) return new TreeSet(((TreeMap) m).comparator()); if (m instanceof LinkedHashMap) return new LinkedHashSet(); return new HashSet(); } static public A replaceIfEqual(A a, A b, A c) { return eq(a, b) ? c : a; } static public List toLinesFullTrim(String s) { List l = new ArrayList(); for (String line : toLines(s)) if (nempty(line = trim(line))) l.add(line); return l; } static public List toLinesFullTrim(File f) { List l = new ArrayList(); for (String line : linesFromFile(f)) if (nempty(line = trim(line))) l.add(line); return l; } static public String localDateWithMinutes(long time) { SimpleDateFormat format = simpleDateFormat_local("yyyy/MM/dd HH:mm"); return format.format(time); } static public String localDateWithMinutes() { return localDateWithMinutes(now()); } static public String pnlToStringWithEmptyLines(Iterable l) { return pnlToString(map(l, o -> o + "\n")); } static public String snippetImageLink(String snippetID) { return snippetImageURL(snippetID); } static public String dataURL(String mimeType, byte[] data) { return "data:" + mimeType + ";base64," + base64(data); } static public String jpegMimeType() { return "image/jpeg"; } static public byte[] toJPEG(BufferedImage img) { try { ByteArrayOutputStream stream = new ByteArrayOutputStream(); ImageIO.write(dropAlphaChannelFromBufferedImage(img), "jpeg", stream); return stream.toByteArray(); } catch (Exception __e) { throw rethrow(__e); } } static public byte[] toJPEG(File f) { return toJPEG(loadImage2(f)); } static public String str_toK(long l) { return n2(toK(l)) + " K"; } static public void saveBinaryFileVerbose(File f, byte[] data) { boolean exists = f.exists(); saveBinaryFile(f, data); print((!exists ? "Created" : "Updated") + " file " + f2s(f) + " (" + f.length() + " bytes)"); } static public double toSeconds(long ms) { return ms / 1000.0; } static public String toSeconds(long ms, int digits) { return formatDouble(toSeconds(ms), digits); } static public double toSeconds(double ms) { return ms / 1000.0; } static public String toSeconds(double ms, int digits) { return formatDouble(toSeconds(ms), digits); } static public TreeSet caseInsensitiveSet() { return caseInsensitiveSet_treeSet(); } static public TreeSet caseInsensitiveSet(Collection c) { return caseInsensitiveSet_treeSet(c); } static public TreeSet treeSet() { return new TreeSet(); } static public int nfilter(Iterable c, IF1 pred) { return nfilter(pred, c); } static public int nfilter(IF1 pred, Iterable c) { int n = 0; if (c != null) for (A o : c) if (pred.get(o)) ++n; return n; } static public int nfilter(Iterable c, Object pred) { int n = 0; if (c != null) for (Object o : c) if (isTrue(callF(pred, o))) ++n; return n; } static public int nfilter(Object pred, Iterable c) { return nfilter(c, pred); } static public File getSecretProgramDir() { return getSecretProgramDir(actualProgramID()); } static public File getSecretProgramDir(String snippetID) { if (empty(snippetID)) return javaxSecretDir(); return newFile(javaxSecretDir(), formatSnippetID(snippetID)); } static public String windowsLineBreaks(String s) { return s == null ? null : s.replaceAll("(? String mapToLines_rtrim(Iterable l, IF1 f) { return mapToLines_rtrim(f, l); } static public String newLinesToSpaces(String s) { return s == null ? null : fixNewLines(s).replace("\n", " "); } static public MultiMap treeMultiMapIndexByField(Collection c, String field) { MultiMap map = treeMultiMap(); for (Object a : c) { Object val = getOpt(a, field); if (val != null) map.put(val, a); } return map; } static public MultiMap treeMultiMapIndexByField(String field, Collection c) { return treeMultiMapIndexByField(c, field); } static public Cache> countryDialCodes_cache = new Cache<>(() -> countryDialCodes_load()); static public List countryDialCodes() { return countryDialCodes_cache.get(); } static public List countryDialCodes_load() { return sortedByField("dialCode", filter(c -> nempty(c.dialCode), map((List>) loadJSONFile(loadLibrary("#1400429")), m -> new CountryDialCode(m.get("name"), m.get("code"), m.get("dial_code"))))); } static public List splitAtComma(String s) { return empty(s) ? emptyList() : asList(s.split(",")); } static public CountryDialCode countryDialCodeByCountryCode(String countryCode) { return objectWhere(countryDialCodes(), "countryCode", upper(countryCode)); } static public List sorted(Collection c, Object comparator) { List l = cloneList(c); sort(l, makeComparator(comparator)); return l; } static public List sorted(Collection c) { List l = cloneList(c); sort(l); return l; } static public List sorted(Comparator comparator, Collection c) { List l = cloneList(c); sort(l, comparator); return l; } static public List collect(Iterable c, String field) { return collectField(c, field); } static public List collect(String field, Iterable c) { return collectField(c, field); } static public String dropPrefixTrim(String prefix, String s) { return trim(dropPrefix(prefix, s)); } static public String localDateWithSeconds(long time) { SimpleDateFormat format = simpleDateFormat_local("yyyy/MM/dd HH:mm:ss"); return format.format(time); } static public String localDateWithSeconds() { return localDateWithSeconds(now()); } static public String smallestTransparentGIFDataURI() { return "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; } static public String snippetImageURL(long snippetID) { return snippetImageURL(fsI(snippetID)); } static public String snippetImageURL(String snippetID) { return snippetImageURL(snippetID, "png"); } static public String snippetImageURL(String snippetID, String contentType) { if (snippetID == null || isURL(snippetID)) return snippetID; long id = parseSnippetID(snippetID); String url; if (isImageServerSnippet(id)) url = imageServerLink(id); else url = "https://botcompany.de/img/" + id; return url; } static public List sortedByFieldDesc(Collection c, String field) { List l = new ArrayList(c); sort(l, descFieldComparator(field)); return l; } static public List sortedByFieldDesc(String field, Collection c) { return sortedByFieldDesc(c, field); } static public A lowestByField(Iterable l, String field) { A lowest = null; Object lowestValue = null; for (A a : unnull(l)) { Object val = getOpt(a, field); if (lowest == null || cmp(val, lowestValue) < 0) { lowest = a; lowestValue = val; } } return lowest; } static public A lowestByField(String field, Iterable l) { return lowestByField(l, field); } static public java.util.Timer doLater(long delay, final Object r) { ping(); final java.util.Timer timer = new java.util.Timer(); timer.schedule(timerTask(r, timer), delay); return vmBus_timerStarted(timer); } static public java.util.Timer doLater(double delaySeconds, final Object r) { return doLater(toMS(delaySeconds), r); } volatile static public boolean conceptsAndBot_running = false; static public boolean conceptsAndBot_thinOnStart = true; static public void conceptsAndBot() { conceptsAndBot(null); } static public void conceptsAndBot(Integer autoSaveInterval) { if (conceptsAndBot_running) return; conceptsAndBot_running = true; Concepts cc = db_mainConcepts(); try { if (cc.useFileLock) { if (!cc.fileLock().tryToLock()) { ensureDBNotRunning(dbBotStandardName()); cc.fileLock().forceLock(); } } else ensureDBNotRunning(dbBotStandardName()); } catch (Throwable _e) { cc.dontSave = true; throw rethrow(_e); } cc.persist(autoSaveInterval); dbBot(false); if (conceptsAndBot_thinOnStart) { try { thinAProgramsBackups(getDBProgramID(), true); } catch (Throwable __e) { _handleException(__e); } } } static public List mapNonCodeTokens(Object f, List l) { List out = emptyList(l); for (int i = 0; i < l(l); i++) { Object o = l.get(i); out.add(even(i) ? callF(f, o) : o); } return out; } static public List mapNonCodeTokens(List l, Object f) { return mapNonCodeTokens(f, l); } static public List mapNonCodeTokens(List tok, IF1 f) { return mapNonCodeTokens(tok, (Object) f); } static public List mapNonCodeTokens(IF1 f, List tok) { return mapNonCodeTokens(tok, f); } static public String emojisToUnicode(String s) { return regexReplace(s, ":(\\w+):", matcher -> lookupOrKeep(emojiShortNameMap(), matcher.group())); } static public String makeRandomID(int length) { return makeRandomID(length, defaultRandomGenerator()); } static public String makeRandomID(int length, Random random) { char[] id = new char[length]; for (int i = 0; i < id.length; i++) id[i] = (char) ((int) 'a' + random.nextInt(26)); return new String(id); } static public String makeRandomID(Random r, int length) { return makeRandomID(length, r); } static public boolean subBot_isHttps() { Object httpd = subBot_httpd(); return eqOneOf(httpd, getOpt(mainBot(), "serveHttps_server"), getOpt(mainBot(), "serveHttpsWithWebsockets_server")) || contains((Collection) getOpt(mainBot(), "serveHttpsWithWebsockets_multiplePorts_servers"), httpd); } static public String domain() { return domainName(); } static public String unicodeFromCodePoint(int codePoint) { return codePointToString(codePoint); } static public List dropAllTags(List tok) { List list = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && t.startsWith("<")) { list.set(list.size() - 1, list.get(list.size() - 1) + tok.get(i + 1)); ++i; } else list.add(t); } return list; } static public String dropAllTags(String html) { return join(dropAllTags(htmlcoarsetok(html))); } static public char charAt(String s, int i) { return s != null && i >= 0 && i < s.length() ? s.charAt(i) : '\0'; } static public String addSuffix(String s, String suffix) { return s == null || s.endsWith(suffix) ? s : s + suffix; } static public TreeSet toCaseInsensitiveSet(Iterable c) { if (isCISet(c)) return (TreeSet) c; TreeSet set = caseInsensitiveSet(); addAll(set, c); return set; } static public TreeSet toCaseInsensitiveSet(String... x) { TreeSet set = caseInsensitiveSet(); addAll(set, x); return set; } static public String hcheckboxWithText(String name, String text, boolean checked, Object... params) { String id = randomID(); return hcheckbox(name, checked, paramsPlus(params, "id", id)) + " " + hlabelFor(id, htmlEncode2(text)); } static public String hcheckboxWithText(String name, String text) { return hcheckboxWithText(name, text, false); } static public java.text.SimpleDateFormat simpleDateFormat(String format, TimeZone timeZone) { java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(format); sdf.setTimeZone(timeZone); return sdf; } static public String timeInTimeZone(String timeZone) { return timeInTimeZone(timeZone, now()); } static public String timeInTimeZone(String timeZone, long time) { return simpleDateFormat_timeZone("HH:mm", timeZone).format(time); } static public String timeInTimeZone(TimeZone timeZone, long time) { return simpleDateFormat("HH:mm", timeZone).format(time); } static public String ipToCountry2020_dataSnippetID = "#1400400"; static public Map ipToCountry2020_cache = mruCache(100); static public Lock ipToCountry2020_lock = lock(); static public File ipToCountry2020_dataDir() { return javaxCachesDir("ipToCountry2020"); } static public String ipToCountry2020(String ip) { return ipToCountry2020(ipToInt(ip)); } static public String ipToCountry2020(long ipNum) { return mapGetOrCreate(ipToCountry2020_cache, ipNum, () -> ipToCountry2020_uncached(ipNum)); } static public String ipToCountry2020_uncached(long ipNum) { { Lock __0 = ipToCountry2020_lock; lock(__0); try { if (directoryEmpty(ipToCountry2020_dataDir())) unzipSnippet(ipToCountry2020_dataSnippetID, ipToCountry2020_dataDir()); } finally { unlock(__0); } } String line = pairB(binarySearchForLineInTextFile(newFile(ipToCountry2020_dataDir(), "IP2LOCATION-LITE-DB1.CSV"), s -> { List l = tok_splitAtComma_unquote(s); long a = parseLongOpt(first(l)), b = parseLongOpt(second(l)); return ipNum > b ? 1 : ipNum < a ? -1 : 0; })); return get(tok_splitAtComma_unquote(line), 2); } static public String deSquareBracket(String s) { if (startsWith(s, "[") && endsWith(s, "]")) return substring(s, 1, l(s) - 1); return s; } static public String regexpReplaceIC(String s, String pat, Object f) { return regexReplaceIC(s, pat, f); } static public String regexpReplaceIC(String s, String pat, String replacement) { return regexReplaceIC(s, pat, replacement); } static public String regexpReplaceIC(String s, String pat, IF1 f) { return regexReplaceIC(s, pat, f); } static public JTextField jTextField() { return jTextField(""); } static public JTextField jTextField(final String text) { return swing(new F0() { public JTextField get() { try { JTextField tf = new JTextField(unnull(text)); standardTextFieldPopupMenu(tf); jenableUndoRedo(tf); tf.selectAll(); return tf; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JTextField tf = new JTextField(unnull(text));\r\n standardTextFieldPopupMenu..."; } }); } static public JTextField jTextField(Object o) { return jTextField(strOrEmpty(o)); } static public JPanel showFormTitled_customLayout(final F1 layouter, final String title, final Object... parts) { return showFormTitled_customArrangement(false, new F1, JPanel>() { public JPanel get(List components) { try { return customLayoutPanel(layouter, components); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "customLayoutPanel(layouter, components)"; } }, title, parts); } static public int formLayouter1_yPlus = 5; static public int formLayouter1_fixer2 = 0; static public F1 formLayouter1() { final int yplus = formLayouter1_yPlus, fixer2 = formLayouter1_fixer2; return new F1() { public Dimension get(Container parent) { try { List l = getComponents(parent); BitSet bigOnes = new BitSet(); for (int i = 0; i < l(l); i++) if (containsATextArea(l.get(i))) add(bigOnes, i); int nBigOnes = bigOnes.cardinality(); int mandatoryHeight = totalPreferredHeight(listWithoutIndicesInBitSet(l, bigOnes)); int gap = 4, outerSpacing = 5; Dimension size = parent.getSize(); int gapsAndMargins = outerSpacing * 2 - (l(l) - 1) * gap; int totalSpace = size.height - gapsAndMargins - fixer2; int liberalSpace = totalSpace - mandatoryHeight; double perBigOne = doubleRatio(liberalSpace, nBigOnes); double y = outerSpacing; for (int i = 0; i < l(l); i++) { Component c = l.get(i); boolean big = contains(bigOnes, i); double h = big ? perBigOne : c.getPreferredSize().height; int actualY = iround(y); c.setBounds(10, actualY, size.width - outerSpacing * 2, iround(y + h) - actualY); y += h + gap; } Dimension pref = componentsBoundingSize(parent, outerSpacing); if (parent.getHeight() <= 0) { int tph = totalPreferredHeight(l); pref.height = tph + gapsAndMargins + yplus; } return pref; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "L l = getComponents(parent);\r\n new BitSet bigOnes;\r\n for i o..."; } }; } static public String getTextTrim(JTextComponent c) { return trim(getText(c)); } static public String getTextTrim(JComboBox cb) { return trim(getText(cb)); } static public String getTextTrim(JComponent c) { if (c instanceof JLabel) return trim(((JLabel) c).getText()); if (c instanceof JComboBox) return getTextTrim((JComboBox) c); return getTextTrim((JTextComponent) c); } static public List beginCriticalAction_inFlight = synchroList(); static public class CriticalAction { public String description; public CriticalAction() { } public CriticalAction(String description) { this.description = description; } public void done() { beginCriticalAction_inFlight.remove(this); } } static public CriticalAction beginCriticalAction(String description) { ping(); CriticalAction c = new CriticalAction(description); beginCriticalAction_inFlight.add(c); return c; } static public void cleanMeUp_beginCriticalAction() { int n = 0; while (nempty(beginCriticalAction_inFlight)) { int m = l(beginCriticalAction_inFlight); if (m != n) { n = m; try { print("Waiting for " + n2(n, "critical actions") + ": " + join(", ", collect(beginCriticalAction_inFlight, "description"))); } catch (Throwable __e) { _handleException(__e); } } sleepInCleanUp(10); } } public static File mkdirsForFile(File file) { File dir = file.getParentFile(); if (dir != null) { dir.mkdirs(); if (!dir.isDirectory()) if (dir.isFile()) throw fail("Please delete the file " + f2s(dir) + " - it is supposed to be a directory!"); else throw fail("Unknown IO exception during mkdirs of " + f2s(file)); } return file; } public static String mkdirsForFile(String path) { mkdirsForFile(new File(path)); return path; } static public void swingLater(long delay, final Object r) { javax.swing.Timer timer = new javax.swing.Timer(toInt(delay), actionListener(wrapAsActivity(r))); timer.setRepeats(false); timer.start(); } static public void swingLater(Object r) { SwingUtilities.invokeLater(toRunnable(r)); } static public String joinStrings(String sep, Object... strings) { return joinStrings(sep, Arrays.asList(strings)); } static public String joinStrings(String sep, Iterable strings) { StringBuilder buf = new StringBuilder(); for (Object o : unnull(strings)) { String s = strOrNull(o); if (nempty(s)) { if (nempty(buf)) buf.append(sep); buf.append(s); } } return str(buf); } static public String programName() { return getProgramName(); } static public void callF_thread(final Object f, final Object... args) { if (f != null) { startThread(new Runnable() { public void run() { try { callF(f, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(f, args);"; } }); } } static public A renameSubmitButton(A form, String newName) { renameButton(form, showFormSubmitButtonName(), newName); return form; } static public A renameSubmitButton(String newName, A form) { return renameSubmitButton(form, newName); } static public String htmlTagFullParamString(String tag) { int i = indexOfSpaceEtc(tag); return trimSubstring(i, dropSuffix(">", tag)); } static public void clearTokens(List tok) { clearAllTokens(tok); } static public void clearTokens(List tok, int i, int j) { clearAllTokens(tok, i, j); } static public void clearTokens(List tok, IntRange r) { clearAllTokens(tok, r.start, r.end); } static public void clearToken(List tok, int i) { tok.set(i, ""); } static public IterableIterator> iterateListWithIndex(Collection l) { return iterateListWithIndex(l, 0); } static public IterableIterator> iterateListWithIndex(Collection l, int startAt) { return iff(new Object() { public Iterator it = iterator(l); public int i = startAt; public Object get() { if (!it.hasNext()) return endMarker(); return pair(i++, it.next()); } }); } static public List asVirtualList(A[] a) { return wrapArrayAsList(a); } static public String unparseCSSParameter(Map map) { return joinWithSemicolon(map(map, new F2() { public String get(String key, String value) { try { return key + ": " + value; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "key + \": \" + value"; } })); } static public Map mapPlus_noOverwrite(Map m, Object... data) { m = cloneMap(m); litmap_impl_noOverwrite(m, data); return m; } static public Map parseCSSParameter(String s) { Map map = new LinkedHashMap(); for (String x : trimAll(splitAt(s, ";"))) { List y = trimAll(splitAtColon(x)); if (l(y) == 2) map.put(first(y), second(y)); } return map; } static public String squareBracketed(String s) { return "[" + s + "]"; } static public int numberOfWords2(String s) { return l(words2(s)); } static public String joinPairWithColon(Pair p) { return p == null ? "" : str(p.a) + ": " + str(p.b); } static public A printIndent(A o) { print(indentx(str(o))); return o; } static public A printIndent(String indent, A o) { print(indentx(indent, str(o))); return o; } static public void printIndent(int indent, Object o) { print(indentx(indent, str(o))); } static public void assertStartsWith(List a, List b) { if (!startsWith(a, b)) throw fail(a + " does not start with " + b); } static public void assertStartsWith(String a, String b) { if (!startsWith(a, b)) throw fail(quote(a) + " does not start with " + quote(b)); } static public String getCanonicalPath(File f) { try { return f == null ? null : f.getCanonicalPath(); } catch (Exception __e) { throw rethrow(__e); } } static public String getCanonicalPath(String path) { return getCanonicalPath(newFile(path)); } static public AutoCloseable tempCleaningUp() { return tempSetTL(ping_isCleanUpThread, true); } static public void closeAllWriters(Collection l) { for (Writer w : unnull(l)) { try { w.close(); } catch (Throwable __e) { _handleException(__e); } } } static public A nextToLast(List l) { return get(l, l(l) - 2); } static public void removeLast(List l) { if (!l.isEmpty()) l.remove(l(l) - 1); } static public void removeLast(List l, int n) { removeSubList(l, l(l) - n); } static public void removeLast(int n, List l) { removeLast(l, n); } static public String dropTrailingSlash(String s) { return dropSuffix("/", s); } static public String hcommentSafe(String text) { return hcomment_unescaped(contains(text, "-->") ? htmlencode(text) : text); } static public String[] conceptFields_drop = { "className", "fieldValues", "id", "created", "_modified", "refs", "backRefs", "_concepts" }; static public Set conceptFields(Concept c) { return setMinus(mergeSets(allNonStaticNonTransientFields(c), keys(c.fieldValues)), conceptFields_drop); } static public Set conceptFields(Class c) { return setMinus(allNonStaticNonTransientFields(c), conceptFields_drop); } static public boolean odd(int i) { return (i & 1) != 0; } static public boolean odd(long i) { return (i & 1) != 0; } static public boolean odd(BigInteger i) { return odd(toInt(i)); } static public String hjavascript_src_snippet(String snippetID, Object... __) { return hfulltag("script", "", paramsPlus(__, "src", snippetRawURL(snippetID, "text/javascript"))); } static public String hreconnectingWebSockets_snippetID() { return "#2000597"; } static public String conceptsFileName() { return "concepts.structure.gz"; } static public long timestampToLong(Timestamp ts) { return ts == null ? 0 : ts.date; } static public int howManySecondsAgo(long timestamp) { return iround(toSeconds(now() - timestamp)); } static public A oneOf(List l) { return empty(l) ? null : l.get(new Random().nextInt(l.size())); } static public char oneOf(String s) { return empty(s) ? '?' : s.charAt(random(l(s))); } static public String oneOf(String... l) { return oneOf(asList(l)); } static public A collectionGet(Collection c, int idx) { if (c == null || idx < 0 || idx >= l(c)) return null; if (c instanceof List) return listGet((List) c, idx); Iterator it = c.iterator(); for (int i = 0; i < idx; i++) if (it.hasNext()) it.next(); else return null; return it.hasNext() ? it.next() : null; } static public Pair entryToPair(Map.Entry e) { return mapEntryToPair(e); } static public Set> entries(Map map) { return _entrySet(map); } static public String newLinesToSpaces_trim(String s) { return s == null ? null : trim(s).replaceAll("\\s*\r?\n\\s*", " "); } static public boolean loadBufferedImage_useImageCache = true; static public BufferedImage loadBufferedImage(String snippetIDOrURLOrFile) { try { ping(); if (snippetIDOrURLOrFile == null) return null; if (isURL(snippetIDOrURLOrFile)) return imageIO_readURL(snippetIDOrURLOrFile); if (isAbsolutePath(snippetIDOrURLOrFile)) return loadBufferedImage(new File(snippetIDOrURLOrFile)); if (!isSnippetID(snippetIDOrURLOrFile)) throw fail("Not a URL or snippet ID or file: " + snippetIDOrURLOrFile); String snippetID = "" + parseSnippetID(snippetIDOrURLOrFile); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return loadBufferedImage(rl.loadLibrary(snippetID)); File dir = imageSnippetsCacheDir(); if (loadBufferedImage_useImageCache) { dir.mkdirs(); File file = new File(dir, snippetID + ".png"); if (file.exists() && file.length() != 0) try { return ImageIO.read(file); } catch (Throwable e) { e.printStackTrace(); } } String imageURL = snippetImageURL_http(snippetID); print("Loading image: " + imageURL); BufferedImage image = imageIO_readURL(imageURL); if (loadBufferedImage_useImageCache) { File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis()); ImageIO.write(image, "png", tempFile); tempFile.renameTo(new File(dir, snippetID + ".png")); } return image; } catch (Exception __e) { throw rethrow(__e); } } static public BufferedImage loadBufferedImage(File file) { return loadBufferedImageFile(file); } static public String rep(int n, char c) { return repeat(c, n); } static public String rep(char c, int n) { return repeat(c, n); } static public List rep(A a, int n) { return repeat(a, n); } static public List rep(int n, A a) { return repeat(n, a); } static public String decimalFormatEnglish(String format, double d) { return decimalFormatEnglish(format).format(d); } static public java.text.DecimalFormat decimalFormatEnglish(String format) { return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)); } static public A _get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static public Object _get(Object o, String field) { return get(o, field); } static public Object _get(String field, Object o) { return get(o, field); } static public A _get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } static public boolean regexpMatches(String pat, String s) { return pat != null && s != null && regexp(pat, s).matches(); } static public boolean regexpMatches(java.util.regex.Pattern pat, String s) { return pat != null && s != null && regexp(pat, s).matches(); } static public int indexOfIgnoreCase(List a, String b) { return indexOfIgnoreCase(a, b, 0); } static public int indexOfIgnoreCase(List a, String b, int i) { int n = a == null ? 0 : a.size(); for (; i < n; i++) if (eqic(a.get(i), b)) return i; return -1; } static public int indexOfIgnoreCase(String a, String b) { return indexOfIgnoreCase_manual(a, b); } static public int indexOfIgnoreCase(String a, String b, int i) { return indexOfIgnoreCase_manual(a, b, i); } static public String structureForUser(Object o) { return beautifyStructure(struct_noStringSharing(o)); } static public Map filterMapByFunctionOnKey(Map map, Object f) { Map m2 = similarEmptyMap(map); for (A a : keys(map)) { if (isTrue(callF(f, a))) m2.put(a, map.get(a)); } return m2; } static public Map filterMapByFunctionOnKey(Object f, Map map) { return filterMapByFunctionOnKey(map, f); } static public void removeSubList(List l, int from, int to) { if (l != null) subList(l, from, to).clear(); } static public void removeSubList(List l, int from) { if (l != null) subList(l, from).clear(); } static public String tok_deRoundBracket(String s) { return tok_isRoundBracketed(s) ? join(dropFirstThreeAndLastThree(javaTok(s))) : s; } static public List javaTokWithBrackets(String s) { return javaTokPlusBrackets(s); } static public List tok_splitAtComma(String s) { return tok_splitAtComma(javaTok(s)); } static public List tok_splitAtComma(List tok) { List out = new ArrayList(); for (int i = 0; i < l(tok); i++) { int j = smartIndexOf(tok, ",", i); out.add(joinSubList(tok, i + 1, j - 1)); i = j; } return out; } static public List tok_splitAtPlus(String s) { return tok_splitAtPlus(javaTokWithAllBrackets_cached(s)); } static public List tok_splitAtPlus(List tok) { return splitAtTokens(tok, "+"); } static public List tok_splitAtAsterisk(String s) { return tok_splitAtAsterisk(javaTokWithAllBrackets_cached(s)); } static public List tok_splitAtAsterisk(List tok) { return splitAtTokens(tok, "*"); } static public double parseDouble(String s) { return empty(s) ? 0.0 : Double.parseDouble(s); } static public boolean mmo2_match(MMOPattern pattern, String s) { return mmo2_match(pattern, s, false, false); } static public boolean mmo2_match(MMOPattern pattern, String s, boolean startOfLine, boolean endOfLine) { if (pattern == null) return false; String s2 = trim(s); if (pattern instanceof MMOPattern.StartOfLine) return mmo2_match(((MMOPattern.StartOfLine) pattern).p, s2, true, endOfLine); if (pattern instanceof MMOPattern.EndOfLine) return mmo2_match(((MMOPattern.EndOfLine) pattern).p, s2, startOfLine, true); if (pattern instanceof MMOPattern.Phrase) { String p = ((MMOPattern.Phrase) pattern).phrase; if (((MMOPattern.Phrase) pattern).quoted) return cicWithSmartWordBoundary(s2, p); if (startsWith(p, "#")) return eqic(p, s2); return match3_startOrEndOfLine(p, s2, startOfLine, endOfLine); } if (pattern instanceof MMOPattern.And) return all(((MMOPattern.And) pattern).l, pat -> mmo2_match(pat, s2, startOfLine, endOfLine)); if (pattern instanceof MMOPattern.Or) return any(((MMOPattern.Or) pattern).l, pat -> mmo2_match(pat, s2, startOfLine, endOfLine)); if (pattern instanceof MMOPattern.Not) return !mmo2_match(((MMOPattern.Not) pattern).p, s2, startOfLine, endOfLine); throw fail("what. " + pattern); } static public boolean mmo2_match(String pattern, String s) { return mmo2_match(mmo2_parsePattern(pattern), s); } static public Integer mmo2_levenWithSwapsScore(MMOPattern pattern, String s) { return mmo2_levenWithSwapsScore(pattern, s, false, false); } static public Integer mmo2_levenWithSwapsScore(MMOPattern pattern, String s, boolean startOfLine, boolean endOfLine) { String s2 = trim(s); if (pattern == null) return null; if (startsWith(s2, "#")) return null; if (pattern instanceof MMOPattern.StartOfLine) return mmo2_levenWithSwapsScore(((MMOPattern.StartOfLine) pattern).p, s2, true, endOfLine); if (pattern instanceof MMOPattern.EndOfLine) return mmo2_levenWithSwapsScore(((MMOPattern.EndOfLine) pattern).p, s2, startOfLine, true); if (pattern instanceof MMOPattern.Phrase) { if (((MMOPattern.Phrase) pattern).quoted) return mmo2_match(((MMOPattern.Phrase) pattern), s2) ? (Integer) 0 : null; String p = ((MMOPattern.Phrase) pattern).phrase; if (startsWith(p, "#")) return null; if (endsWith(p, "!")) return find3(p, s) ? 0 : null; else return find3_levenWithSwapsDistance(p, s2); } if (pattern instanceof MMOPattern.And) { int score = 0; for (MMOPattern pat : ((MMOPattern.And) pattern).l) { Integer score2 = mmo2_levenWithSwapsScore(pat, s2, startOfLine, endOfLine); if (score2 == null) return null; score += score2; } return score; } if (pattern instanceof MMOPattern.Or) { Integer min = null; for (MMOPattern pat : ((MMOPattern.Or) pattern).l) min = min_withNull(min, mmo2_levenWithSwapsScore(pat, s2, startOfLine, endOfLine)); return min; } if (pattern instanceof MMOPattern.Not) return mmo2_match(pattern, s2) ? 0 : null; throw fail("what. " + pattern); } static public Integer mmo2_levenWithSwapsScore(String pattern, String s) { return mmo2_levenWithSwapsScore(mmo2_parsePattern(pattern), s, false, false); } static public List parseBusinessHours(String s) { List parts = nempties(tok_splitAtComma(s)); return map(parts, part -> { List l = splitAtMinus(part); IntRange r = intRange(parseHourAndOptionalMinutesToMinutes(first(l)), parseHourAndOptionalMinutesToMinutes(second(l))); if (r.end < r.start && r.start <= 12 * 60 && r.end < 12 * 60) r.end += 12 * 60; return r; }); } static public int hours() { return hours(java.util.Calendar.getInstance()); } static public int hours(java.util.Calendar c) { return c.get(java.util.Calendar.HOUR_OF_DAY); } static public int hours(long time) { return hours(calendarFromTime(time)); } static public int hours(long time, TimeZone tz) { return hours(calendarFromTime(time, tz)); } static public int minutes() { return minutes(Calendar.getInstance()); } static public int minutes(Calendar c) { return c.get(Calendar.MINUTE); } static public java.util.Calendar calendarFromTime(long time, TimeZone tz) { java.util.Calendar c = java.util.Calendar.getInstance(tz); c.setTimeInMillis(time); return c; } static public java.util.Calendar calendarFromTime(long time) { java.util.Calendar c = java.util.Calendar.getInstance(); c.setTimeInMillis(time); return c; } static public boolean intRangeContains(IntRange r, int i) { return r != null && i >= r.start && i < r.end; } static public List syncList() { return synchroList(); } static public List syncList(List l) { return synchroList(l); } static public boolean syncAddAll(Collection c, Iterable b) { if (c == null || b == null) return false; synchronized (c) { return c.addAll(asCollection(b)); } } static public A popLast(List l) { return liftLast(l); } static public List popLast(int n, List l) { return liftLast(n, l); } static public List syncLambdaMap(IF1 f, Collection l) { if (l == null) return emptyList(); synchronized (collectionMutex(l)) { return map(l, f); } } static public A shallowClone(A o) { return (A) shallowClone_impl(o); } static public A shallowClone(A o, A emptyClone) { return copyFields(o, emptyClone); } static public Object shallowClone_impl(Object o) { if (o == null) return o; if (o instanceof List) return cloneList((List) o); if (o instanceof Map) return cloneMap((Map) o); if (o instanceof String || o instanceof Number || o instanceof Boolean) return o; if (o instanceof Object[]) { Object[] l = (Object[]) o; return l.clone(); } Class c = o.getClass(); final Object clone = nuEmptyObject(c); copyFields(o, clone); return clone; } static public String getSelectedItem(JList l) { return (String) l.getSelectedValue(); } static public String getSelectedItem(JComboBox cb) { return strOrNull(cb.getSelectedItem()); } static public Class hotwire(String src) { return hotwire(src, __1 -> mainClassNameForClassLoader(__1)); } static public Class hotwire(String src, IF1 calculateMainClass) { assertFalse(_inCore()); Class j = getJavaX(); if (isAndroid()) { synchronized (j) { List libraries = new ArrayList(); File srcDir = (File) call(j, "transpileMain", src, libraries); if (srcDir == null) throw fail("transpileMain returned null (src=" + quote(src) + ")"); Object androidContext = get(j, "androidContext"); return (Class) call(j, "loadx2android", srcDir, src); } } else { Class c = (Class) (call(j, "hotwire", src)); hotwire_copyOver(c); return c; } } static public A callMain(A c, String... args) { callOpt(c, "main", new Object[] { args }); return c; } static public void callMain() { callMain(mc()); } static public JComboBox jcombobox(final String... items) { return swing(new F0() { public JComboBox get() { try { return new JComboBox(items); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret new JComboBox(items);"; } }); } static public JComboBox jcombobox(Collection items) { return jcombobox(toStringArray(items)); } static public JComboBox jcombobox(Collection items, String selectedItem) { return selectItem(selectedItem, jcombobox(items)); } static public JDesktopPane mainDesktopPane_value; static public JDesktopPane mainDesktopPane() { return mainDesktopPane_value; } static public JPanel showInternalFrameFormTitled(final JDesktopPane desktop, final String title, final Object... _parts) { JPanel panel = showForm_makePanel(true, _parts); showForm_makeInternalFrame(desktop, title, panel); return panel; } static public JFrame showForm_makeFrame(String title, JPanel panel) { return handleEscapeKey(minFrameWidth(showPackedFrame(title, withMargin(panel)), 400)); } static public List showForm_arrange1(List> l) { int minW = showForm_leftWidth(l); List out = new ArrayList(); for (List row : l) out.add(westAndCenter(withRightMargin(showForm_gapBetweenColumns, jMinWidthAtLeast(minW, first(row))), second(row))); return out; } static public List> showForm_makeComponents(final Boolean internalFrame, Object... _parts) { List> l = new ArrayList(); List parts = asList(_parts); JButton submitButton = null; for (int i = 0; i < l(parts); i++) { final Object o = parts.get(i), next = get(parts, i + 1); if (o instanceof String && next instanceof Component) setComponentID((Component) next, (String) o); if (o instanceof Component || o instanceof String || next instanceof Component) { l.add(mapLL(__93 -> wrapForSmartAdd_jComponent(__93), o == null ? new JPanel() : o instanceof String ? humanizeFormLabel((String) o) : o, next)); if (next instanceof JButton && submitButton == null) submitButton = (JButton) next; i++; } else if (isRunnable(o)) l.add(mapLL(__94 -> wrapForSmartAdd_jComponent(__94), null, submitButton = jbutton(showFormSubmitButtonName(), new Runnable() { public void run() { try { Object result = call(o); print("Result of form runnable: " + result + ". Button: " + heldInstance(JButton.class)); if (neq(Boolean.FALSE, result)) { if (isTrue(internalFrame)) disposeInternalFrame(heldInstance(JButton.class)); else if (isFalse(internalFrame)) disposeFrame(heldInstance(JButton.class)); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Object result = call(o);\r\n print(\"Result of form runnable: \" + result ..."; } }))); else print("showForm: Unknown element type: " + getClassName(o)); } if (submitButton != null) { final JButton _submitButton = submitButton; onEnterInAllTextFields(concatLists(l), new Runnable() { public void run() { try { clickButton(_submitButton); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "clickButton(_submitButton)"; } }); } for (List row : l) { JComponent left = first(row); if (left instanceof JLabel) makeBold((JLabel) left).setVerticalAlignment(JLabel.TOP); } return l; } static public int vstackWithSpacing_default = 10; static public JPanel vstackWithSpacing(final List parts) { return vstackWithSpacing(parts, vstackWithSpacing_default); } static public JPanel vstackWithSpacing(final List parts, final int spacing) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets = new Insets(spacing / 2, 0, spacing / 2, 0); smartAddWithLayout(panel, gbc, toObjectArray(nonNulls(parts))); gbc.weighty = 1; gbc.insets = new Insets(0, 0, 0, 0); panel.add(jrigid(), gbc); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new GridBagLayout);\r\n new GridBagConstraints gbc..."; } }); } static public JPanel vstackWithSpacing(Component... parts) { return vstackWithSpacing(asList(parts), vstackWithSpacing_default); } static public JPanel vstackWithSpacing(int spacing, Component... parts) { return vstackWithSpacing(asList(parts), spacing); } static public A swingConstruct(final Class c, final Object... args) { return swing(new F0() { public A get() { try { return nuObject(c, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret nuObject(c, args);"; } }); } static public Set synchroHashSet() { return Collections.synchronizedSet(new HashSet()); } static public Object pcallFunction(Object f, Object... args) { try { return callFunction(f, args); } catch (Throwable __e) { _handleException(__e); } return null; } static public void cancelThread(Thread t) { if (t == null) return; ping(); synchronized (ping_actions) { ping_actions.put(t, "cancelled"); ping_anyActions = true; } } static public boolean isInstanceOf(Object o, Class type) { return type.isInstance(o); } static public Map objectToMap(Object o) { try { if (o instanceof Map) return (Map) o; TreeMap map = new TreeMap(); Class c = o.getClass(); while (c != Object.class) { Field[] fields = c.getDeclaredFields(); for (final Field field : fields) { if ((field.getModifiers() & Modifier.STATIC) != 0) continue; field.setAccessible(true); final Object value = field.get(o); if (value != null) map.put(field.getName(), value); } c = c.getSuperclass(); } if (o instanceof DynamicObject) putAll(map, ((DynamicObject) o).fieldValues); return map; } catch (Exception __e) { throw rethrow(__e); } } static public List> objectToMap(Iterable l) { if (l == null) return null; List x = new ArrayList(); for (Object o : l) x.add(objectToMap(o)); return x; } static public List cloneAndClearList(Collection l) { List l2 = cloneList(l); l.clear(); return l2; } static public String replacePlusWithSpace(String s) { return replace(s, '+', ' '); } static public List splitAtSpace(String s) { return empty(s) ? emptyList() : asList(s.split("\\s+")); } static public int scoredSearch_score_single(String s, String query) { int i = indexOfIC_underscore(s, query); if (i < 0) return 0; if (i > 0) return 1; return l(s) == l(query) ? 3 : 2; } static public Comparator mapComparatorDesc(final Map map) { return new Comparator() { public int compare(A a, A b) { return cmp(map.get(b), map.get(a)); } }; } static public A keyWithBiggestValue(Map map) { A best = null; Number bestScore = null; for (A key : keys(map)) { Number score = map.get(key); if (best == null || cmp(score, bestScore) > 0) { best = key; bestScore = score; } } return best; } static public int roundToInt(double d) { return (int) Math.round(d); } static public AutoCloseable tempInterceptPrint(F1 f) { return tempSetThreadLocal(print_byThread(), f); } static public String actualUserHome_value; static public String actualUserHome() { if (actualUserHome_value == null) { if (isAndroid()) actualUserHome_value = "/storage/emulated/0/"; else actualUserHome_value = System.getProperty("user.home"); } return actualUserHome_value; } static public File actualUserHome(String sub) { return newFile(new File(actualUserHome()), sub); } static public File userDir() { return new File(userHome()); } static public File userDir(String path) { return new File(userHome(), path); } static public Map classForName_cache = synchroHashMap(); static public Class classForName(String name) { return classForName(name, null); } static public Class classForName(String name, Object classFinder) { if (classForName_cache == null || classFinder != null) return classForName_uncached(name, classFinder); Class c = classForName_cache.get(name); if (c == null) classForName_cache.put(name, c = classForName_uncached(name, null)); return c; } static public Class classForName_uncached(String name, Object classFinder) { try { if (classFinder != null) return (Class) callF(classFinder, name); return Class.forName(name); } catch (Exception __e) { throw rethrow(__e); } } static public Map nuObjectWithoutArguments_cache = newDangerousWeakHashMap(); static public Object nuObjectWithoutArguments(String className) { try { return nuObjectWithoutArguments(classForName(className)); } catch (Exception __e) { throw rethrow(__e); } } static public A nuObjectWithoutArguments(Class c) { try { if (nuObjectWithoutArguments_cache == null) return (A) nuObjectWithoutArguments_findConstructor(c).newInstance(); Constructor m = nuObjectWithoutArguments_cache.get(c); if (m == null) nuObjectWithoutArguments_cache.put(c, m = nuObjectWithoutArguments_findConstructor(c)); return (A) m.newInstance(); } catch (Exception __e) { throw rethrow(__e); } } static public Constructor nuObjectWithoutArguments_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (empty(m.getParameterTypes())) { makeAccessible(m); return m; } throw fail("No default constructor found in " + c.getName()); } static public List getClasses(Object[] array) { List l = emptyList(l(array)); for (Object o : array) l.add(_getClass(o)); return l; } static public List javaTokForStructure(String s) { return javaTok_noMLS(s); } static public int clampToInt(long l) { return (int) clamp(l, Integer.MIN_VALUE, Integer.MAX_VALUE); } static public boolean isOpeningBracket(String s) { return eqOneOf(s, "(", "{", "["); } static public boolean containsClosingBracket(List l) { return any(__95 -> isClosingBracket(__95), l); } static public String joinSubList(List l, int i, int j) { return join(subList(l, i, j)); } static public String joinSubList(List l, int i) { return join(subList(l, i)); } static public String joinSubList(List l, IntRange r) { return r == null ? null : joinSubList(l, r.start, r.end); } static public boolean isClosingBracket(String s) { return eqOneOf(s, ")", "}", "]"); } static public List firstOfPairs(Collection> l) { List out = new ArrayList(); for (Pair p : unnull(l)) out.add(firstOfPair(p)); return out; } static public Class primitiveToBoxedTypeOpt(Class type) { return or(primitiveToBoxedType(type), type); } static public Object dm_callOS(String functionName, Object... args) { return call(dm_os(), functionName, args); } static public DynModule dm_currentModuleMandatory() { return dm_current_mandatory(); } static public Set syncIdentityHashSet() { return (Set) synchronizedSet(identityHashSet()); } static public A third(List l) { return _get(l, 2); } static public A third(Iterable l) { if (l == null) return null; Iterator it = iterator(l); for (int _repeat_0 = 0; _repeat_0 < 2; _repeat_0++) { if (!it.hasNext()) return null; it.next(); } return it.hasNext() ? it.next() : null; } static public A third(Producer p) { if (p == null) return null; for (int _repeat_1 = 0; _repeat_1 < 2; _repeat_1++) { if (p.next() == null) return null; } return p.next(); } static public A third(A[] bla) { return bla == null || bla.length <= 2 ? null : bla[2]; } static public VF1 runnableToVF1(final Runnable r) { return r == null ? null : new VF1() { public void get(A a) { try { r.run(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "r.run()"; } }; } static public com.sun.management.OperatingSystemMXBean advancedOSMXBean() { return optCast(com.sun.management.OperatingSystemMXBean.class, osMXBean()); } static public Map synchroMap() { return synchroHashMap(); } static public Map synchroMap(Map map) { return Collections.synchronizedMap(map); } static public A singleObjectMethodProxy(Class intrface, Object object, String methodName) { return proxyFromInvocationHandler(intrface, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { String mname = method.getName(); if (mname.equals(methodName)) return call(object, methodName, unnull(args)); if (mname.equals("toString")) return "proxy for " + methodName; return null; } }); } static public String getStackTrace2(Throwable e) { return hideCredentials(getStackTrace(unwrapTrivialExceptionWraps(e)) + replacePrefix("java.lang.RuntimeException: ", "FAIL: ", hideCredentials(str(innerException2(e)))) + "\n"); } static public Throwable getInnerException(Throwable e) { if (e == null) return null; while (e.getCause() != null) e = e.getCause(); return e; } static public Throwable getInnerException(Runnable r) { return getInnerException(getException(r)); } static public Class run_overBot(String progID) { Class main = hotwire_overBot(progID); callMain(main); return main; } static public Map paramsToMap_withNulls(Object... params) { int n = l(params); if (l(params) == 1 && params[0] instanceof Map) return (Map) params[0]; LinkedHashMap map = new LinkedHashMap(); for (int i = 0; i + 1 < n; i += 2) map.put(params[i], params[i + 1]); return map; } static public String jsonEncode_extended(Object o) { StringBuilder buf = new StringBuilder(); jsonEncode_extended(o, buf); return str(buf); } static public void jsonEncode_extended(Object o, StringBuilder buf) { if (o == null) buf.append("null"); else if (o instanceof JS) buf.append(((JS) o).get()); 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_extended(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_extended(element, buf); } buf.append("]"); } else throw fail("Unknown object for JSON encoding: " + className(o)); } static public boolean isString(Object o) { return o instanceof String; } static public Object dm_getService(String serviceName) { return empty(serviceName) ? null : dm_getModule(vmBus_query(assertIdentifier(serviceName))); } static public boolean isStringOrIntOrLong(Object o) { return o instanceof String || o instanceof Integer || o instanceof Long; } static public Object dm_resolveModule(Object moduleOrStem) { return dm_callOS("resolveModule", moduleOrStem); } static public List methodsStartingWith(Object o, final String prefix) { return filter(allMethodNames(o), new F1() { public Object get(String s) { try { return startsWith(s, prefix); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "startsWith(s, prefix)"; } }); } static public boolean interruptThread_verbose = false; static public void interruptThread(Thread t) { if (t == null) return; if (interruptThread_verbose) print("Interrupting thread " + t); vm_threadInterruptionReasonsMap().put(t, getStackTrace()); t.interrupt(); URLConnection c = (URLConnection) (vm_generalSubMap("URLConnection per thread").get(t)); if (c != null) { try { print("Closing URLConnection of interrupted thread."); call(c, "disconnect"); } catch (Throwable __e) { _handleException(__e); } } } static public boolean isJavaXClassLoader(ClassLoader cl) { return startsWithOneOf(className(cl), "main$JavaXClassLoader", "x30$JavaXClassLoader"); } static public void setOptAll(Object o, Map fields) { if (fields == null) return; for (String field : keys(fields)) setOpt(o, field, fields.get(field)); } static public void setOptAll(Object o, Object... values) { warnIfOddCount(values); for (int i = 0; i + 1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i + 1]; setOpt(o, field, value); } } static public void close(AutoCloseable c) { _close(c); } static public boolean isTrueOrYes(Object o) { return isTrueOpt(o) || o instanceof String && (eqicOneOf(((String) o), "1", "t", "true") || isYes(((String) o))); } static public LinkedHashMap asLinkedHashMap(Map map) { if (map instanceof LinkedHashMap) return (LinkedHashMap) map; LinkedHashMap m = new LinkedHashMap(); if (map != null) synchronized (collectionMutex(map)) { m.putAll(map); } return m; } static public boolean endsWithLetterOrDigit(String s) { return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length() - 1)); } static public void rotateStringBuffer(StringBuffer buf, int max) { try { if (buf == null) return; synchronized (buf) { if (buf.length() <= max) return; try { int newLength = max / 2; int ofs = buf.length() - newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static public void rotateStringBuilder(StringBuilder buf, int max) { try { if (buf == null) return; synchronized (buf) { if (buf.length() <= max) return; try { int newLength = max / 2; int ofs = buf.length() - newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static public A setThreadLocal(ThreadLocal tl, A value) { if (tl == null) return null; A old = tl.get(); tl.set(value); return old; } static public List jsonTok(String s) { List tok = new ArrayList(); int l = l(s); int i = 0; while (i < l) { int j = i; char c; String cc; while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j + 2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isLetter(c)) do ++j; while (j < l && Character.isLetter(s.charAt(j))); else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static public Class main() { return getMainClass(); } static public Number boxedIntOrLong(long l) { return l != (int) l ? boxed(l) : boxed((int) l); } static public String getQueryFromURL(String url) { return dropAfterSubstring(substring(url, smartIndexOf(url, "?") + 1), "#"); } static public Object pcallF_minimalExceptionHandling(Object f, Object... args) { try { return callFunction(f, args); } catch (Throwable e) { System.out.println(getStackTrace(e)); _storeException(e); } return null; } static public 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 public boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) { return a != null && a.regionMatches(true, offsetA, b, offsetB, len); } static public Object subBot_serveByteArray(byte[] data, String mimeType) { return call(mainBot(), "serveByteArray", data, mimeType); } static public Charset utf8charset_cache; static public Charset utf8charset() { if (utf8charset_cache == null) utf8charset_cache = utf8charset_load(); return utf8charset_cache; } static public Charset utf8charset_load() { return Charset.forName("UTF-8"); } static public String jsonEncode_shallowLineBreaks(Object o) { return jsonEncode_breakAtLevel1(o); } static public void jsonEncode_shallowLineBreaks(Object o, StringBuilder buf, int level) { jsonEncode_breakAtLevel1(o, buf, level); } static public boolean containsNulls(Collection c) { return contains(c, null); } static public Map similarEmptyMap(Map m) { if (m instanceof TreeMap) return new TreeMap(((TreeMap) m).comparator()); if (m instanceof LinkedHashMap) return new LinkedHashMap(); return new HashMap(); } static public Map similarEmptyMap(Iterable m) { if (m instanceof TreeSet) return new TreeMap(((TreeSet) m).comparator()); if (m instanceof LinkedHashSet) return new LinkedHashMap(); return new HashMap(); } static public String charToString(char c) { return String.valueOf(c); } static public String charToString(int c) { return String.valueOf((char) c); } static public String reverseString(String s) { return empty(s) ? s : new StringBuilder(s).reverse().toString(); } static public CloseableIterableIterator linesFromFile(File f) { return linesFromFile(f, null); } static public CloseableIterableIterator linesFromFile(File f, IResourceHolder resourceHolder) { try { if (!f.exists()) return emptyCloseableIterableIterator(); if (ewic(f.getName(), ".gz")) return linesFromReader(utf8bufferedReader(newGZIPInputStream(f)), resourceHolder); return linesFromReader(utf8bufferedReader(f), resourceHolder); } catch (Exception __e) { throw rethrow(__e); } } static public CloseableIterableIterator linesFromFile(String path) { return linesFromFile(path, null); } static public CloseableIterableIterator linesFromFile(String path, IResourceHolder resourceHolder) { return linesFromFile(newFile(path), resourceHolder); } static public ArrayList cloneListSynchronizingOn(Collection l, Object mutex) { if (l == null) return new ArrayList(); synchronized (mutex) { return new ArrayList(l); } } static public boolean isOpeningTag(String token, String tag) { return isTag(token, tag) && !token.endsWith("/>"); } static public boolean isOpeningTag(String token) { return token.startsWith("<") && token.endsWith(">") && !token.endsWith("/>") && isLetter(token.charAt(1)); } static public boolean isTag(String token, String tag) { return token.regionMatches(true, 0, "<" + tag + " ", 0, tag.length() + 2) || token.regionMatches(true, 0, "<" + tag + ">", 0, tag.length() + 2); } static public String javaTokDropTrailingN(String s) { List tok = javaTok(s); return empty(last(tok)) ? unnull(s) : join(dropLast(tok)); } static public List findBackRefs(Collection concepts, Class type) { IdentityHashMap l = new IdentityHashMap(); for (Concept c : concepts) if (c.backRefs != null) for (Concept.Ref r : c.backRefs) if (instanceOf(r.concept(), type)) l.put((A) r.concept(), true); return asList(keys(l)); } static public List findBackRefs(Concept c, Class type) { IdentityHashMap l = new IdentityHashMap(); if (c != null && c.backRefs != null) for (Concept.Ref r : c.backRefs) if (instanceOf(r.concept(), type)) l.put((A) r.concept(), true); return asList(keys(l)); } static public List findBackRefs(Class type, Concept c) { return findBackRefs(c, type); } static public Collection findBackRefs(Concept c) { return findBackRefs(c, Concept.class); } static public boolean checkConceptFieldsIC(Concept x, Object... data) { for (int i = 0; i < l(data); i += 2) if (!eqicOrEq(cget(x, (String) data[i]), deref(data[i + 1]))) return false; return true; } static public boolean possibleMD5(String s) { return isMD5(s); } static public List map_ping(Iterable l, Object f) { return map_ping(f, l); } static public List map_ping(Object f, Iterable l) { List x = emptyList(l); if (l != null) for (Object o : l) x.add(callF(f, o)); return x; } static public List map_ping(Iterable l, F1 f) { return map_ping(f, l); } static public List map_ping(F1 f, Iterable l) { List x = emptyList(l); if (l != null) for (A o : l) x.add(callF(f, o)); return x; } static public List map_ping(IF1 f, Iterable l) { return map_ping(l, f); } static public List map_ping(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static public List map_ping(IF1 f, A[] l) { return map_ping(l, f); } static public List map_ping(A[] l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static public List map_ping(Object f, Object[] l) { return map_ping(f, asList(l)); } static public List map_ping(Object[] l, Object f) { return map_ping(f, l); } static public List map_ping(Object f, Map map) { return map_ping(map, f); } static public List map_ping(Map map, Object f) { List x = new ArrayList(); if (map != null) for (Object _e : map.entrySet()) { ping(); Map.Entry e = (Map.Entry) _e; x.add(callF(f, e.getKey(), e.getValue())); } return x; } static public List map_ping(Map map, IF2 f) { return map_ping(map, (Object) f); } static public boolean endsWithLetter(String s) { return nempty(s) && isLetter(last(s)); } static public File getProgramDir() { return programDir(); } static public File getProgramDir(String snippetID) { return programDir(snippetID); } static public Collection concatCollections_conservative(Collection a, Collection b) { if (empty(a)) return b; if (empty(b)) return a; return concatLists(a, b); } static public Object[] dropEntryFromParams(Object[] params, int i) { int n = l(params); if (i < 0 || i >= n) return params; if (n == 2) return null; Object[] p = new Object[n - 2]; System.arraycopy(params, 0, p, 0, i); System.arraycopy(params, i + 2, p, i, n - i - 2); return p; } static public List filterConceptsIC(Collection list, Object... params) { List l = new ArrayList(); if (list != null) for (A x : list) if (checkConceptFieldsIC(x, params)) l.add(x); return l; } static public Map javaTokForJFind_array_cache = synchronizedMRUCache(1000); static public String[] javaTokForJFind_array(String s) { String[] tok = javaTokForJFind_array_cache.get(s); if (tok == null) javaTokForJFind_array_cache.put(s, tok = codeTokensAsStringArray(jfind_preprocess(javaTok(s)))); return tok; } static public String jreplaceExpandRefs(String s, List tokref) { if (!contains(s, '$')) return s; List tok = javaTok(s); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("$") && isInteger(t.substring(1))) { String x = tokref.get(-1 + parseInt(t.substring(1)) * 2); tok.set(i, x); } else if (t.equals("\\")) { tok.set(i, ""); i += 2; } } return join(tok); } static public void clearAllTokens(List tok) { for (int i = 0; i < tok.size(); i++) tok.set(i, ""); } static public void clearAllTokens(List tok, int i, int j) { for (; i < j; i++) tok.set(i, ""); } static public List reTok(List tok) { replaceCollection(tok, javaTok(tok)); return tok; } static public List reTok(List tok, int i) { return reTok(tok, i, i + 1); } static public List reTok(List tok, int i, int j) { i = max(i & ~1, 0); j = min(l(tok), j | 1); if (i >= j) return tok; List t = javaTok(joinSubList(tok, i, j)); replaceListPart(tok, i, j, t); return tok; } static public List reTok(List tok, IntRange r) { if (r != null) reTok(tok, r.start, r.end); return tok; } static public String stringOptPar(Object[] params, String name) { return (String) optPar(params, name); } static public Object[] paramsWithout(Object[] a1, Object... keys) { if (l(a1) == 1 && a1[0] instanceof Map) return new Object[] { mapMinus((Map) a1[0], keys) }; Set set = lithashset(keys); List l = new ArrayList(); int n = l(a1); for (int i = 0; i < n; i += 2) if (i == n - 1) l.add(a1[i]); else if (!set.contains(a1[i])) { l.add(a1[i]); l.add(a1[i + 1]); } return toObjectArray(l); } static public double doubleRatio(double x, double y) { return y == 0 ? 0 : x / y; } static public boolean boolOptParam(ThreadLocal tl) { return isTrue(optPar(tl)); } static public boolean boolOptParam(Object[] __, String name) { return isTrue(optParam(__, name)); } static public boolean boolOptParam(String name, Object[] __) { return boolOptParam(__, name); } static public boolean boolOptParam(String name, Map __) { return isTrue(optPar(name, __)); } static public String[] asStringArray(Collection c) { return toStringArray(c); } static public String[] asStringArray(Object o) { return toStringArray(o); } static public Map compileRegexpIC_cache = syncMRUCache(10); static public java.util.regex.Pattern compileRegexpIC(String pat) { java.util.regex.Pattern p = compileRegexpIC_cache.get(pat); if (p == null) { try { compileRegexpIC_cache.put(pat, p = java.util.regex.Pattern.compile(pat, Pattern.CASE_INSENSITIVE)); } catch (PatternSyntaxException e) { throw rethrow(wrapPatternSyntaxException(e)); } } return p; } static public HashSet mapToSet(Object f, Iterable l) { return mapToHashSet(f, l); } static public HashSet mapToSet(IF1 f, Iterable l) { return mapToSet((Object) f, l); } static public HashSet mapToSet(IF1 f, A[] l) { return mapToSet(f, asList(l)); } static public HashSet mapToSet(Iterable l, IF1 f) { return mapToSet((Object) f, l); } static public Object unstructure(String text) { return unstructure(text, false); } static public Object unstructure(String text, boolean allDynamic) { return unstructure(text, allDynamic, null); } static public Object unstructure(String text, IF1 classFinder) { return unstructure(text, false, classFinder); } static public int structure_internStringsLongerThan = 50; static public int unstructure_unquoteBufSize = 100; static public int unstructure_tokrefs; abstract static public class unstructure_Receiver { abstract public void set(Object o); } static public Object unstructure(String text, boolean allDynamic, Object classFinder) { if (text == null) return null; return unstructure_tok(javaTokC_noMLS_iterator(text), allDynamic, classFinder); } static public Object unstructure_reader(BufferedReader reader) { return unstructure_tok(javaTokC_noMLS_onReader(reader), false, null); } static public Object unstructure_tok(final Producer tok, final boolean allDynamic, final Object _classFinder) { final boolean debug = unstructure_debug; final class X { public int i = -1; final public Object classFinder = _classFinder != null ? _classFinder : _defaultClassFinder(); public String mcDollar = actualMCDollar(); public HashMap refs = new HashMap(); public HashMap tokrefs = new HashMap(); public HashSet concepts = new HashSet(); public HashMap classesMap = new HashMap(); public List stack = new ArrayList(); public Map baseClassMap = new HashMap(); public HashMap innerClassConstructors = new HashMap(); public String curT; public char[] unquoteBuf = new char[unstructure_unquoteBufSize]; public X() { try { Class mc = (Class) (callF(_classFinder, "
")); if (mc != null) mcDollar = mc.getName() + "$"; } catch (Throwable __e) { _handleException(__e); } } public Class findAClass(String fullClassName) { try { return classFinder != null ? (Class) callF(classFinder, fullClassName) : findClass_fullName(fullClassName); } catch (Throwable __e) { return null; } } public String unquote(String s) { return unquoteUsingCharArray(s, unquoteBuf); } public String t() { return curT; } public String tpp() { String t = curT; consume(); return t; } public void parse(final unstructure_Receiver out) { String t = t(); int refID; if (structure_isMarker(t, 0, l(t))) { refID = parseInt(t.substring(1)); consume(); } else refID = -1; final int tokIndex = i; parse_inner(refID, tokIndex, new unstructure_Receiver() { public void set(Object o) { if (refID >= 0) refs.put(refID, o); if (o != null) tokrefs.put(tokIndex, o); out.set(o); } }); } public void parse_inner(int refID, int tokIndex, unstructure_Receiver out) { String t = t(); String cname = t; Class c = classesMap.get(cname); if (c == null) { if (t.startsWith("\"")) { String s = internIfLongerThan(unquote(tpp()), structure_internStringsLongerThan); out.set(s); return; } if (t.startsWith("'")) { out.set(unquoteCharacter(tpp())); return; } if (t.equals("bigint")) { out.set(parseBigInt()); return; } if (t.equals("d")) { out.set(parseDouble()); return; } if (t.equals("fl")) { out.set(parseFloat()); return; } if (t.equals("sh")) { consume(); t = tpp(); if (t.equals("-")) { t = tpp(); out.set((short) (-parseInt(t))); return; } out.set((short) parseInt(t)); return; } if (t.equals("-")) { consume(); t = tpp(); out.set(isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t))); return; } if (isInteger(t) || isLongConstant(t)) { consume(); if (isLongConstant(t)) { out.set(parseLong(t)); return; } long l = parseLong(t); boolean isInt = l == (int) l; out.set(isInt ? (Object) Integer.valueOf((int) l) : (Object) Long.valueOf(l)); return; } if (t.equals("false") || t.equals("f")) { consume(); out.set(false); return; } if (t.equals("true") || t.equals("t")) { consume(); out.set(true); return; } if (t.equals("-")) { consume(); t = tpp(); out.set(isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t))); return; } if (isInteger(t) || isLongConstant(t)) { consume(); if (isLongConstant(t)) { out.set(parseLong(t)); return; } long l = parseLong(t); boolean isInt = l == (int) l; out.set(isInt ? (Object) Integer.valueOf((int) l) : (Object) Long.valueOf(l)); return; } if (t.equals("File")) { consume(); File f = new File(unquote(tpp())); out.set(f); return; } if (t.startsWith("r") && isInteger(t.substring(1))) { consume(); int ref = Integer.parseInt(t.substring(1)); Object o = refs.get(ref); if (o == null) warn("unsatisfied back reference " + ref); out.set(o); return; } if (t.startsWith("t") && isInteger(t.substring(1))) { consume(); int ref = Integer.parseInt(t.substring(1)); Object o = tokrefs.get(ref); if (o == null) warn("unsatisfied token reference " + ref + " at " + tokIndex); out.set(o); return; } if (t.equals("hashset")) { parseHashSet(out); return; } if (t.equals("lhs")) { parseLinkedHashSet(out); return; } if (t.equals("treeset")) { parseTreeSet(out); return; } if (t.equals("ciset")) { parseCISet(out); return; } if (eqOneOf(t, "hashmap", "hm")) { consume(); parseMap(new HashMap(), out); return; } if (t.equals("lhm")) { consume(); parseMap(new LinkedHashMap(), out); return; } if (t.equals("tm")) { consume(); parseMap(new TreeMap(), out); return; } if (t.equals("cimap")) { consume(); parseMap(ciMap(), out); return; } if (t.equals("ll")) { consume(); LinkedList l = new LinkedList(); if (refID >= 0) refs.put(refID, l); { parseList(l, out); return; } } if (t.equals("syncLL")) { consume(); { parseList(synchroLinkedList(), out); return; } } if (t.equals("sync")) { consume(); { parse(new unstructure_Receiver() { public void set(Object value) { if (value instanceof Map) { if (value instanceof NavigableMap) { out.set(synchroNavigableMap((NavigableMap) value)); return; } if (value instanceof SortedMap) { out.set(synchroSortedMap((SortedMap) value)); return; } { out.set(synchroMap((Map) value)); return; } } else { out.set(synchroList((List) value)); return; } } }); return; } } if (t.equals("{")) { parseMap(out); return; } if (t.equals("[")) { ArrayList l = new ArrayList(); if (refID >= 0) refs.put(refID, l); this.parseList(l, out); return; } if (t.equals("bitset")) { parseBitSet(out); return; } if (t.equals("array") || t.equals("intarray") || t.equals("dblarray")) { parseArray(out); return; } if (t.equals("ba")) { consume(); String hex = unquote(tpp()); out.set(hexToBytes(hex)); return; } if (t.equals("boolarray")) { consume(); int n = parseInt(tpp()); String hex = unquote(tpp()); out.set(boolArrayFromBytes(hexToBytes(hex), n)); return; } if (t.equals("class")) { out.set(parseClass()); return; } if (t.equals("l")) { parseLisp(out); return; } if (t.equals("null")) { consume(); out.set(null); return; } if (eq(t, "c")) { consume(); t = t(); assertTrue(isJavaIdentifier(t)); concepts.add(t); } if (eq(t, "cu")) { consume(); t = tpp(); assertTrue(isJavaIdentifier(t)); String fullClassName = mcDollar + t; Class _c = findAClass(fullClassName); if (_c == null) throw fail("Class not found: " + fullClassName); parse(new unstructure_Receiver() { public void set(Object value) { out.set(call(_c, "_deserialize", value)); } }); return; } } if (eq(t, "j")) { consume(); out.set(parseJava()); return; } if (eq(t, "bc")) { consume(); String c1 = tpp(); String c2 = tpp(); baseClassMap.put(c1, c2); { parse_inner(refID, i, out); return; } } if (c == null && !isJavaIdentifier(t)) throw new RuntimeException("Unknown token " + (i + 1) + ": " + quote(t)); consume(); String className, fullClassName; if (eq(t(), ".")) { consume(); className = fullClassName = t + "." + assertIdentifier(tpp()); } else { className = t; fullClassName = mcDollar + t; } if (c == null && !allDynamic) { c = findAClass(fullClassName); classesMap.put(className, c); } if (c == null && !allDynamic) { Set seen = new HashSet(); String parent = className; while (true) { String baseName = baseClassMap.get(parent); if (baseName == null) break; if (!seen.add(baseName)) throw fail("Cyclic superclass info: " + baseName); c = findAClass(mcDollar + baseName); if (c == null) print("Base class " + baseName + " of " + parent + " doesn't exist either"); else if (isAbstract(c)) print("Can't instantiate abstract base class: " + c); else { printVars_str("Reverting to base class", "className", className, "baseName", baseName, "c", c); classesMap.put(className, c); break; } parent = baseName; } } boolean hasBracket = eq(t(), "("); if (hasBracket) consume(); boolean hasOuter = hasBracket && startsWith(t(), "this$"); DynamicObject dO = null; Object o = null; final String thingName = t; if (c != null) { if (hasOuter) try { Constructor ctor = innerClassConstructors.get(c); if (ctor == null) innerClassConstructors.put(c, ctor = nuStubInnerObject_findConstructor(c, classFinder)); o = ctor.newInstance(new Object[] { null }); } catch (Exception e) { print("Error deserializing " + c + ": " + e); o = nuEmptyObject(c); } else o = nuEmptyObject(c); if (o instanceof DynamicObject) dO = (DynamicObject) o; } else { if (concepts.contains(t) && (c = findAClass(mcDollar + "Concept")) != null) o = dO = (DynamicObject) nuEmptyObject(c); else dO = new DynamicObject(); dO.className = className; } if (refID >= 0) refs.put(refID, o != null ? o : dO); tokrefs.put(tokIndex, o != null ? o : dO); HashMap fields = new HashMap(); Object _o = o; DynamicObject _dO = dO; if (hasBracket) { stack.add(new Runnable() { public void run() { try { if (eq(t(), ",")) consume(); if (eq(t(), ")")) { consume(")"); objRead(_o, _dO, fields, hasOuter); out.set(_o != null ? _o : _dO); } else { final String key = unquote(tpp()); String t = tpp(); if (!eq(t, "=")) throw fail("= expected, got " + t + " after " + quote(key) + " in object " + thingName); stack.add(this); parse(new unstructure_Receiver() { public void set(Object value) { fields.put(key, value); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef unstructure_debug\r\n print(\"in object values, token: \" + t())..."; } }); } else { objRead(o, dO, fields, hasOuter); out.set(o != null ? o : dO); } } public void objRead(Object o, DynamicObject dO, Map fields, boolean hasOuter) { Object outer = fields.get("this$0"); if (outer != null) fields.put("this$1", outer); else { outer = fields.get("this$1"); if (outer != null) fields.put("this$0", outer); } if (o != null) { if (dO != null) { setOptAllDyn_pcall(dO, fields); } else { setOptAll_pcall(o, fields); } if (hasOuter) fixOuterRefs(o); } else for (Map.Entry e : fields.entrySet()) setDynObjectValue(dO, intern(e.getKey()), e.getValue()); if (o != null) pcallOpt_noArgs(o, "_doneLoading"); } public void parseSet(final Set set, final unstructure_Receiver out) { this.parseList(new ArrayList(), new unstructure_Receiver() { public void set(Object o) { set.addAll((List) o); out.set(set); } }); } public void parseLisp(final unstructure_Receiver out) { throw fail("class Lisp not included"); } public void parseBitSet(final unstructure_Receiver out) { consume("bitset"); consume("{"); final BitSet bs = new BitSet(); stack.add(new Runnable() { public void run() { try { if (eq(t(), "}")) { consume("}"); out.set(bs); } else { stack.add(this); parse(new unstructure_Receiver() { public void set(Object o) { bs.set((Integer) o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"}\")) {\r\n consume(\"}\");\r\n out.set(bs);\r\n ..."; } }); } public void parseList(final List list, final unstructure_Receiver out) { tokrefs.put(i, list); consume("["); stack.add(new Runnable() { public void run() { try { if (eq(t(), "]")) { consume(); out.set(list); } else { stack.add(this); parse(new unstructure_Receiver() { public void set(Object o) { list.add(o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"]\")) {\r\n consume();\r\n ifdef unstructure_debug\r..."; } }); } public void parseArray(unstructure_Receiver out) { String _type = tpp(); int dims; if (eq(t(), "S")) { _type = "S"; consume(); } if (eq(t(), "/")) { consume(); dims = parseInt(tpp()); } else dims = 1; consume("{"); List list = new ArrayList(); String type = _type; stack.add(new Runnable() { public void run() { try { if (eq(t(), "}")) { consume("}"); if (dims > 1) { Class atype; if (type.equals("intarray")) atype = int.class; else if (type.equals("S")) atype = String.class; else throw todo("multi-dimensional arrays of other types"); out.set(list.toArray((Object[]) newMultiDimensionalOuterArray(atype, dims, l(list)))); } else out.set(type.equals("intarray") ? toIntArray(list) : type.equals("dblarray") ? toDoubleArray(list) : type.equals("S") ? toStringArray(list) : list.toArray()); } else { stack.add(this); parse(new unstructure_Receiver() { public void set(Object o) { list.add(o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"}\")) {\r\n consume(\"}\");\r\n if (dims > 1) {\r\n ..."; } }); } public Object parseClass() { consume("class"); consume("("); String name = unquote(tpp()); consume(")"); Class c = allDynamic ? null : findAClass(name); if (c != null) return c; DynamicObject dO = new DynamicObject(); dO.className = "java.lang.Class"; name = dropPrefix(mcDollar, name); dO.fieldValues.put("name", name); return dO; } public Object parseBigInt() { consume("bigint"); consume("("); String val = tpp(); if (eq(val, "-")) val = "-" + tpp(); consume(")"); return new BigInteger(val); } public Object parseDouble() { consume("d"); consume("("); String val = unquote(tpp()); consume(")"); return Double.parseDouble(val); } public Object parseFloat() { consume("fl"); String val; if (eq(t(), "(")) { consume("("); val = unquote(tpp()); consume(")"); } else { val = unquote(tpp()); } return Float.parseFloat(val); } public void parseHashSet(unstructure_Receiver out) { consume("hashset"); parseSet(new HashSet(), out); } public void parseLinkedHashSet(unstructure_Receiver out) { consume("lhs"); parseSet(new LinkedHashSet(), out); } public void parseTreeSet(unstructure_Receiver out) { consume("treeset"); parseSet(new TreeSet(), out); } public void parseCISet(unstructure_Receiver out) { consume("ciset"); parseSet(ciSet(), out); } public void parseMap(unstructure_Receiver out) { parseMap(new TreeMap(), out); } public Object parseJava() { String j = unquote(tpp()); Matches m = new Matches(); if (jmatch("java.awt.Color[r=*,g=*,b=*]", j, m)) return nuObject("java.awt.Color", parseInt(m.unq(0)), parseInt(m.unq(1)), parseInt(m.unq(2))); else { warn("Unknown Java object: " + j); return null; } } public void parseMap(final Map map, final unstructure_Receiver out) { consume("{"); stack.add(new Runnable() { public boolean v = false; public Object key; public void run() { if (v) { v = false; stack.add(this); if (!eq(tpp(), "=")) throw fail("= expected, got " + t() + " in map of size " + l(map)); parse(new unstructure_Receiver() { public void set(Object value) { map.put(key, value); if (eq(t(), ",")) consume(); } }); } else { if (eq(t(), "}")) { consume("}"); out.set(map); } else { v = true; stack.add(this); parse(new unstructure_Receiver() { public void set(Object o) { key = o; } }); } } } }); } public void consume() { curT = tok.next(); ++i; } public void consume(String s) { if (!eq(t(), s)) { throw fail(quote(s) + " expected, got " + quote(t())); } consume(); } public void parse_initial(unstructure_Receiver out) { consume(); parse(out); while (nempty(stack)) popLast(stack).run(); } } ThreadLocal tlLoading = dynamicObjectIsLoading_threadLocal(); Boolean b = tlLoading.get(); tlLoading.set(true); try { final Var v = new Var(); X x = new X(); x.parse_initial(new unstructure_Receiver() { public void set(Object o) { v.set(o); } }); unstructure_tokrefs = x.tokrefs.size(); return v.get(); } finally { tlLoading.set(b); } } static public boolean unstructure_debug = false; static public List uniquifyList(Collection l) { if (l == null) return null; if (l(l) < 2) return asList(l); HashSet set = new HashSet(); List out = new ArrayList(); for (A a : l) if (set.add(a)) out.add(a); return out; } static public String formatWithThousandsSeparator(long l) { return NumberFormat.getInstance(new Locale("en_US")).format(l); } static public double toM_double(long l) { return l / (1024 * 1024.0); } static public AutoCloseable tempLock(Lock lock) { return tempLock("", lock); } static public AutoCloseable tempLock(String purpose, Lock lock) { if (lock == null) return null; lock(lock); return new AutoCloseable() { public String toString() { return "unlock(lock);"; } public void close() throws Exception { unlock(lock); } }; } static public String singleFieldName(Class c) { Set l = listFields(c); if (l(l) != 1) throw fail("No single field found in " + c + " (have " + n(l(l), "fields") + ")"); return first(l); } static public void warnIfOddCount(Object... list) { if (odd(l(list))) printStackTrace("Odd list size: " + list); } static public String getComputerID_quick() { return computerID(); } static public byte[] utf8(String s) { return toUtf8(s); } static public boolean isAGIBlueDomain(String domain) { return domainIsUnder(domain, theAGIBlueDomain()); } static public String hostNameFromURL(String url) { try { return new URL(url).getHost(); } catch (Exception __e) { throw rethrow(__e); } } static public Map compileRegexp_cache = syncMRUCache(10); static public java.util.regex.Pattern compileRegexp(String pat) { java.util.regex.Pattern p = compileRegexp_cache.get(pat); if (p == null) { compileRegexp_cache.put(pat, p = java.util.regex.Pattern.compile(pat)); } return p; } static public String trimSubstring(String s, int x) { return trim(substring(s, x)); } static public String trimSubstring(String s, int x, int y) { return trim(substring(s, x, y)); } static public String trimSubstring(String s, IntRange r) { return trim(substring(s, r)); } static public String trimSubstring(int x, String s) { return trimSubstring(s, x); } static public IResourceLoader vm_getResourceLoader() { return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader")); } static public boolean isImageServerSnippet(long id) { return id >= 1100000 && id < 1200000; } static public File loadImageAsFile(String snippetIDOrURL) { try { if (isURL(snippetIDOrURL)) throw fail("not implemented"); if (!isSnippetID(snippetIDOrURL)) throw fail("Not a URL or snippet ID: " + snippetIDOrURL); String snippetID = "" + parseSnippetID(snippetIDOrURL); File file = imageSnippetCacheFile(snippetID); if (fileSize(file) > 0) return file; String imageURL = snippetImageURL_noHttps(snippetID); System.err.println("Loading image: " + imageURL); byte[] data = loadBinaryPage(imageURL); saveBinaryFile(file, data); return file; } catch (Exception __e) { throw rethrow(__e); } } static public File DiskSnippetCache_file(long snippetID) { return new File(getGlobalCache(), "data_" + snippetID + ".jar"); } public static File DiskSnippetCache_getLibrary(long snippetID) throws IOException { File file = DiskSnippetCache_file(snippetID); return file.exists() ? file : null; } public static void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException { saveBinaryFile(DiskSnippetCache_file(snippetID), data); } static public byte[] loadDataSnippetImpl(String snippetID) throws IOException { byte[] data; try { URL url = new URL(dataSnippetLink(snippetID)); print("Loading library: " + hideCredentials(url)); try { data = loadBinaryPage(url.openConnection()); } catch (RuntimeException e) { data = null; } if (data == null || data.length == 0) { url = new URL(tb_mainServer() + "/blobs/" + parseSnippetID(snippetID)); print("Loading library: " + hideCredentials(url)); data = loadBinaryPage(url.openConnection()); } print("Bytes loaded: " + data.length); } catch (FileNotFoundException e) { throw new IOException("Binary snippet #" + snippetID + " not found or not public"); } return data; } static public File loadDataSnippetToFile(String snippetID) { try { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadDataSnippetToFile_noResourceLoader(snippetID); } catch (Exception __e) { throw rethrow(__e); } } static public File loadDataSnippetToFile_noResourceLoader(String snippetID) { try { snippetID = fsI(snippetID); File f = DiskSnippetCache_file(parseSnippetID(snippetID)); List urlsTried = new ArrayList(); List errors = new ArrayList(); try { URL url = addAndReturn(urlsTried, new URL(dataSnippetLink(snippetID))); print("Loading library: " + hideCredentials(url)); try { loadBinaryPageToFile(openConnection(url), f); if (fileSize(f) == 0) throw fail(); } catch (Throwable e) { errors.add(e); url = addAndReturn(urlsTried, new URL(tb_mainServer() + "/blobs/" + psI(snippetID))); print(e); print("Trying other server: " + hideCredentials(url)); loadBinaryPageToFile(openConnection(url), f); print("Got bytes: " + fileSize(f)); } if (fileSize(f) == 0) throw fail(); System.err.println("Bytes loaded: " + fileSize(f)); } catch (Throwable e) { errors.add(e); throw fail("Binary snippet " + snippetID + " not found or not public. URLs tried: " + allToString(urlsTried) + ", errors: " + allToString(errors)); } return f; } catch (Exception __e) { throw rethrow(__e); } } static public void logQuotedWithTime(String s) { logQuotedWithTime(standardLogFile(), s); } static public void logQuotedWithTime(File logFile, String s) { logQuoted(logFile, logQuotedWithTime_format(s)); } static public void logQuotedWithTime(String logFile, String s) { logQuoted(logFile, logQuotedWithTime_format(s)); } static public String logQuotedWithTime_format(String s) { return (now()) + " " + s; } static public JComponent wrap(Object swingable) { return _recordNewSwingComponent(wrap_2(swingable)); } static public JComponent wrap_2(Object swingable) { if (swingable == null) return null; JComponent c; if (swingable instanceof Component) c = componentToJComponent((Component) swingable); else c = componentToJComponent((Component) callOpt(swingable, "swing")); if (c instanceof JTable || c instanceof JList || c instanceof JTextArea || c instanceof JEditorPane || c instanceof JTextPane || c instanceof JTree) return jscroll(c); return c == null ? jlabel(str(swingable)) : c; } static public JTextArea wrappedTextArea(final JTextArea ta) { enableWordWrapForTextArea(ta); return ta; } static public JTextArea wrappedTextArea() { return wrappedTextArea(jtextarea()); } static public JTextArea wrappedTextArea(String text) { JTextArea ta = wrappedTextArea(); setText(ta, text); return ta; } static public A onClick(final A c, final Object runnable) { if (c != null) { swing(new Runnable() { public void run() { try { c.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { callF(runnable, e); } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.addMouseListener(new MouseAdapter {\r\n public void mouseClicked(MouseEv..."; } }); } return c; } static public void onClick(JButton btn, final Object runnable) { onEnter(btn, runnable); } static public void disposeWindow(final Window window) { if (window != null) { swing(new Runnable() { public void run() { try { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); myFrames_list.remove(window); window.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); //..."; } }); } } static public void disposeWindow(final Component c) { disposeWindow(getWindow(c)); } static public void disposeWindow(Object o) { if (o != null) disposeWindow(((Component) o)); } static public void disposeWindow() { disposeWindow(heldInstance(Component.class)); } static public Font typeWriterFont() { return typeWriterFont(iround(14 * getSwingFontScale())); } static public Font typeWriterFont(int size) { return new Font("Courier", Font.PLAIN, size); } static public JScrollPane jscroll(final Component c) { return swing(new F0() { public JScrollPane get() { try { return new JScrollPane(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret new JScrollPane(c);"; } }); } static public int withMargin_defaultWidth = 6; static public JPanel withMargin(Component c) { return withMargin(withMargin_defaultWidth, c); } static public JPanel withMargin(int w, Component c) { return withMargin(w, w, c); } static public JPanel withMargin(int w, int h, Component c) { return withMargin(w, h, w, h, c); } static public JPanel withMargin(final int top, final int left, final int bottom, final int right, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static public Window getWindow(Object o) { if (!(o instanceof Component)) return null; return swing(() -> { Component c = (Component) o; while (c != null) { if (c instanceof Window) return ((Window) c); c = c.getParent(); } return null; }); } static public Dimension getScreenSize() { return Toolkit.getDefaultToolkit().getScreenSize(); } static public boolean vmBus_anyFalse(String msg, Object... args) { return contains(vmBus_queryAll(msg, args), false); } static public int toMS_int(double seconds) { return toInt_checked((long) (seconds * 1000)); } static public String baseClassName(String className) { return substring(className, className.lastIndexOf('.') + 1); } static public String baseClassName(Object o) { return baseClassName(getClassName(o)); } static public String prependIfNempty(String prefix, String s) { return empty(s) ? unnull(s) : prefix + s; } static public Runnable _topLevelErrorHandling(Runnable r) { if (r == null) return null; Object info = _threadInfo(); Object mod = dm_current_generic(); if (info == null && mod == null) return r; return new Runnable() { public void run() { try { AutoCloseable __1 = (AutoCloseable) (rcall("enter", mod)); try { _threadInheritInfo(info); r.run(); } finally { _close(__1); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp (AutoCloseable) rcall enter(mod);\r\n _threadInheritInfo(info);\r\n r...."; } }; } static public int indexOfNonDigit(String s) { int n = l(s); for (int i = 0; i < n; i++) if (!isDigit(s.charAt(i))) return i; return -1; } static public boolean isLetter(char c) { return Character.isLetter(c); } static public void printNumberedLines(Map map) { printNumberedLines(mapToLines(map)); } static public void printNumberedLines(String prefix, Map map) { printNumberedLines(prefix, mapToLines(map)); } static public A printNumberedLines(A l) { int i = 0; if (l != null) for (Object a : cloneList(l)) print((++i) + ". " + str(a)); return l; } static public A printNumberedLines(String prefix, A l) { int i = 0; if (l != null) for (Object a : cloneList(l)) print(prefix + (++i) + ". " + str(a)); return l; } static public void printNumberedLines(Object[] l) { printNumberedLines("", l); } static public void printNumberedLines(String prefix, Object[] l) { printNumberedLines(prefix, wrapAsList(l)); } static public void printNumberedLines(Object o) { printNumberedLines(lines(str(o))); } static public List> pairsSortedByA(Collection> l) { return sortedByComparator(l, (a, b) -> cmp(a.a, b.a)); } static public String[][] htmldecode_escapes() { return htmldecode_ESCAPES; } static final public String[][] htmldecode_ESCAPES = { { "\"", "quot" }, { "&", "amp" }, { "<", "lt" }, { ">", "gt" }, { "\u00A0", "nbsp" }, { "\u00A1", "iexcl" }, { "\u00A2", "cent" }, { "\u00A3", "pound" }, { "\u00A4", "curren" }, { "\u00A5", "yen" }, { "\u00A6", "brvbar" }, { "\u00A7", "sect" }, { "\u00A8", "uml" }, { "\u00A9", "copy" }, { "\u00AA", "ordf" }, { "\u00AB", "laquo" }, { "\u00AC", "not" }, { "\u00AD", "shy" }, { "\u00AE", "reg" }, { "\u00AF", "macr" }, { "\u00B0", "deg" }, { "\u00B1", "plusmn" }, { "\u00B2", "sup2" }, { "\u00B3", "sup3" }, { "\u00B4", "acute" }, { "\u00B5", "micro" }, { "\u00B6", "para" }, { "\u00B7", "middot" }, { "\u00B8", "cedil" }, { "\u00B9", "sup1" }, { "\u00BA", "ordm" }, { "\u00BB", "raquo" }, { "\u00BC", "frac14" }, { "\u00BD", "frac12" }, { "\u00BE", "frac34" }, { "\u00BF", "iquest" }, { "\u00C0", "Agrave" }, { "\u00C1", "Aacute" }, { "\u00C2", "Acirc" }, { "\u00C3", "Atilde" }, { "\u00C4", "Auml" }, { "\u00C5", "Aring" }, { "\u00C6", "AElig" }, { "\u00C7", "Ccedil" }, { "\u00C8", "Egrave" }, { "\u00C9", "Eacute" }, { "\u00CA", "Ecirc" }, { "\u00CB", "Euml" }, { "\u00CC", "Igrave" }, { "\u00CD", "Iacute" }, { "\u00CE", "Icirc" }, { "\u00CF", "Iuml" }, { "\u00D0", "ETH" }, { "\u00D1", "Ntilde" }, { "\u00D2", "Ograve" }, { "\u00D3", "Oacute" }, { "\u00D4", "Ocirc" }, { "\u00D5", "Otilde" }, { "\u00D6", "Ouml" }, { "\u00D7", "times" }, { "\u00D8", "Oslash" }, { "\u00D9", "Ugrave" }, { "\u00DA", "Uacute" }, { "\u00DB", "Ucirc" }, { "\u00DC", "Uuml" }, { "\u00DD", "Yacute" }, { "\u00DE", "THORN" }, { "\u00DF", "szlig" }, { "\u00E0", "agrave" }, { "\u00E1", "aacute" }, { "\u00E2", "acirc" }, { "\u00E3", "atilde" }, { "\u00E4", "auml" }, { "\u00E5", "aring" }, { "\u00E6", "aelig" }, { "\u00E7", "ccedil" }, { "\u00E8", "egrave" }, { "\u00E9", "eacute" }, { "\u00EA", "ecirc" }, { "\u00EB", "euml" }, { "\u00EC", "igrave" }, { "\u00ED", "iacute" }, { "\u00EE", "icirc" }, { "\u00EF", "iuml" }, { "\u00F0", "eth" }, { "\u00F1", "ntilde" }, { "\u00F2", "ograve" }, { "\u00F3", "oacute" }, { "\u00F4", "ocirc" }, { "\u00F5", "otilde" }, { "\u00F6", "ouml" }, { "\u00F7", "divide" }, { "\u00F8", "oslash" }, { "\u00F9", "ugrave" }, { "\u00FA", "uacute" }, { "\u00FB", "ucirc" }, { "\u00FC", "uuml" }, { "\u00FD", "yacute" }, { "\u00FE", "thorn" }, { "\u00FF", "yuml" }, { "\u2013", "ndash" }, { "\u2018", "lsquo" }, { "\u2019", "rsquo" }, { "\u201D", "rdquo" }, { "\u201C", "ldquo" }, { "\u2014", "mdash" }, { "'", "apos" } }; static public List dropHTMLComments(List tok) { List l = new ArrayList(); for (int idx = 0; idx < l(tok); idx++) { String t = tok.get(idx); if (even(idx)) { int i; while ((i = t.indexOf("", i + 4); t = substring(t, 0, i) + substring(t, j + 3); } } l.add(t); } return l; } static public String dropTags(String html) { return dropAllTags(html); } static public List dropTags(List tok) { return dropAllTags(tok); } static public List filterNempty(Collection c) { List l = new ArrayList(); for (String x : unnull(c)) if (nempty(x)) l.add(x); return l; } static public Frame getAWTFrame(final Object _o) { return swing(new F0() { public Frame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof Frame) return (Frame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n /*\r\n ifdef HaveProcessing\r\n if (o instanceof PApplet) ..."; } }); } static public String[] codeTokensAsStringArray(List tok) { int n = max(0, (l(tok) - 1) / 2); String[] out = new String[n]; for (int i = 0; i < n; i++) out[i] = tok.get(i * 2 + 1); return out; } static public List replaceSublist(List l, List x, List y) { if (x == null) return l; int i = 0; while (true) { i = indexOfSubList(l, x, i); if (i < 0) break; replaceSublist(l, i, i + l(x), y); i += l(y); } return l; } static public List replaceSublist(List l, int fromIndex, int toIndex, List y) { int n = y.size(), toIndex_new = fromIndex + n; if (toIndex_new < toIndex) { removeSubList(l, toIndex_new, toIndex); copyListPart(y, 0, l, fromIndex, n); } else { copyListPart(y, 0, l, fromIndex, toIndex - fromIndex); if (toIndex_new > toIndex) l.addAll(toIndex, subList(y, toIndex - fromIndex)); } return l; } static public List replaceSublist(List l, IntRange r, List y) { return replaceSublist(l, r.start, r.end, y); } static public boolean checkTokCondition(Object condition, List tok, int i) { if (condition instanceof TokCondition) return ((TokCondition) condition).get(tok, i); return checkCondition(condition, tok, i); } static public List splitByJavaToken(String s, String splitToken) { List tok = javaTok(s); List l = new ArrayList(); int i = 1; while (i < l(tok)) { int j = smartIndexOf(tok, splitToken, i); l.add(join(subList(tok, i, j - 1))); i = j + 2; } return l; } static public String dollarVarsToStars(String s) { return dollarVarsToStars(s, null); } static public String dollarVarsToStars(String s, List varNames_out) { List tok = javaTok(s); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (isDollarVar(t)) { listAdd(varNames_out, t); tok.set(i, "*"); } else if (eq(t, "*")) listAdd(varNames_out, "*"); } return join(tok); } static public void tok_statementToBlock(List tok, int i) { if (neqGet(tok, i, "{")) { int iEnd = tok_findEndOfStatement(tok, i) - 1; tokAppend_reTok(tok, iEnd, " }"); tokPrepend_reTok(tok, i, "{ "); } } static public void tokAppend_reTok(List tok, int i, String s) { tok.set(i, tok.get(i) + s); reTok(tok, i, i + 1); } static public List mapWithIndexStartingAt1(Collection l, IF2 f) { int n = l(l), i = 0; List out = emptyList(n); for (A a : unnullForIteration(l)) out.add(f.get(++i, a)); return out; } static public boolean containsDollarVars(String s) { for (String t : javaTokC(s)) if (isDollarVar(t)) return true; return false; } static public String standardCredentialsUser() { return trim(loadTextFile(oneOfTheFiles(javaxSecretDir("tinybrain-username"), userDir(".tinybrain/username")))); } static public String standardCredentialsPass() { return trim(loadTextFile(oneOfTheFiles(javaxSecretDir("tinybrain-userpass"), userDir(".tinybrain/userpass")))); } static public Map parseStdFunctionsList(String snippetSrc) { return parseStdFunctionsList(snippetSrc, new LinkedHashMap()); } static public Map parseStdFunctionsList(String snippetSrc, Map map) { List tok = javaTok(snippetSrc); int i = findCodeTokens(tok, "standardFunctions", "=", "litlist", "("); int opening = i + 6; int closing = indexOf(tok, ")", opening) - 1; for (i = opening + 2; i < closing; i += 4) { String[] f = unquote(tok.get(i)).split("/"); map.put(f[1], f[0]); } return map; } static public String loadSnippetSilently(Snippet s) { return loadSnippetQuietly(s); } static public String loadSnippetSilently(String snippetID) { return loadSnippetQuietly(snippetID); } static public List toLinesFullTrim_java(String text) { return tlft(joinLines(map(__96 -> javaDropComments(__96), tlft(text)))); } static public Map weakHashMap() { return newWeakHashMap(); } static public Set emptySet() { return new HashSet(); } static public TreeSet asTreeSet(Collection set) { return set == null ? null : set instanceof TreeSet ? (TreeSet) set : new TreeSet(set); } static public class getOpt_Map extends WeakHashMap { public getOpt_Map() { if (getOpt_special == null) getOpt_special = new HashMap(); clear(); } public void clear() { super.clear(); put(Class.class, getOpt_special); put(String.class, getOpt_special); } } static final public Map> getOpt_cache = _registerDangerousWeakMap(synchroMap(new getOpt_Map())); static public HashMap getOpt_special; static public Map getOpt_getFieldMap(Object o) { Class c = _getClass(o); HashMap map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); return map; } static public Object getOpt_cached(Object o, String field) { try { if (o == null) return null; Map map = getOpt_getFieldMap(o); if (map == getOpt_special) { if (o instanceof Class) return getOpt((Class) o, field); if (o instanceof Map) return ((Map) o).get(field); } Field f = map.get(field); if (f != null) return f.get(o); if (o instanceof DynamicObject) return syncMapGet2(((DynamicObject) o).fieldValues, field); return null; } catch (Exception __e) { throw rethrow(__e); } } static public HashMap getOpt_makeCache(Class c) { HashMap map; if (isSubtypeOf(c, Map.class)) map = getOpt_special; else { map = new HashMap(); if (!reflection_classesNotToScan().contains(c.getName())) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) { makeAccessible(f); String name = f.getName(); if (!map.containsKey(name)) map.put(name, f); } _c = _c.getSuperclass(); } while (_c != null); } } if (getOpt_cache != null) getOpt_cache.put(c, map); return map; } static public int hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static public DynModule dm_current() { return dm_currentModule(); } static public List dm_modulesWithLibID(final String moduleLibID) { return filter(dm_moduleIDs(), new F1() { public Boolean get(String m) { try { return eq(dm_moduleLibID(m), moduleLibID); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "eq(dm_moduleLibID(m), moduleLibID)"; } }); } static public String dm_moduleID(Object module) { return strOrNull(getOpt(dm_getStem(module), "id")); } static public String dm_moduleID() { return dm_moduleID(dm_current_mandatory_generic()); } static public String lowestByAlphaNum(Collection c) { String best = null; for (String s : unnullForIteration(c)) if (best == null || alphaNumComparator().compare(s, best) < 0) best = s; return best; } static public boolean hasSuperclassShortNamed(Object o, String name) { Class c = _getClass(o); while (c != null) if (shortClassNameIs(c, name)) return true; else c = c.getSuperclass(); return false; } static public TimerTask smartTimerTask(Object r, java.util.Timer timer, long delay) { return new SmartTimerTask(r, timer, delay, _threadInfo()); } static public class SmartTimerTask extends TimerTask implements IFieldsToList { public Object r; public java.util.Timer timer; public long delay; public Object threadInfo; public SmartTimerTask() { } public SmartTimerTask(Object r, java.util.Timer timer, long delay, Object threadInfo) { this.threadInfo = threadInfo; this.delay = delay; this.timer = timer; this.r = r; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + r + ", " + timer + ", " + delay + ", " + threadInfo + ")"; } public Object[] _fieldsToList() { return new Object[] { r, timer, delay, threadInfo }; } public long lastRun; public void run() { if (!licensed()) timer.cancel(); else { _threadInheritInfo(threadInfo); AutoCloseable __1 = tempActivity(r); try { lastRun = fixTimestamp(lastRun); long now = now(); if (now >= lastRun + delay * 0.9) { lastRun = now; if (eq(false, pcallF(r))) timer.cancel(); } } finally { _close(__1); } } } } static public A vmBus_timerStarted(A timer) { vmBus_send("timerStarted", timer, costCenter()); return timer; } static public boolean isConceptClassIndexed(Class c) { return isConceptClassIndexed(db_mainConcepts(), c); } static public boolean isConceptClassIndexed(Concepts concepts, Class c) { return concepts.conceptCounterForClass(c) != null; } static public void indexRandomConceptField(Class c) { indexRandomConceptField(db_mainConcepts(), c); } static public void indexRandomConceptField(Concepts cc, Class c) { String field = or(first(conceptFields(c)), "_dummy"); print("Indexing " + c + "." + field); indexConceptField(cc, c, field); assertTrue("Concept class indexed", isConceptClassIndexed(cc, c)); { long _startTime_0 = sysNow(); try { print("Got " + nConcepts(countConcepts(cc, c))); } finally { _startTime_0 = sysNow() - _startTime_0; saveTiming(_startTime_0); } } } static public A setToolTipText(final A c, final Object toolTip) { if (c == null) return null; { swing(new Runnable() { public void run() { try { String s = nullIfEmpty(str(toolTip)); if (neq(s, c.getToolTipText())) c.setToolTipText(s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String s = nullIfEmpty(str(toolTip));\r\n if (neq(s, c.getToolTipText()))\r\n ..."; } }); } return c; } static public A setToolTipText(Object toolTip, A c) { return setToolTipText(c, toolTip); } static public JButton jbutton(String text, Object action) { return newButton(text, action); } static public JButton jbutton(String text) { return newButton(text, null); } static public JButton jbutton(Action action) { return swingNu(JButton.class, action); } static public String unicode_downPointingTriangle() { return charToString(0x25BC); } static public A optPar_ignoreOddLength(Object[] opt, String name, A defaultValue) { int n = l(opt); if (n == 1 && opt[0] instanceof Map) { Map map = (Map) (opt[0]); return map.containsKey(name) ? (A) map.get(name) : defaultValue; } for (int i = 0; i + 1 < l(opt); i += 2) if (eq(opt[i], name)) return (A) opt[i + 1]; return defaultValue; } static public Object optPar_ignoreOddLength(Object[] opt, String name) { return optPar_ignoreOddLength(opt, name, null); } static public Object optPar_ignoreOddLength(String name, Object[] params) { return optPar_ignoreOddLength(params, name); } static public void fillJPopupMenu(JPopupMenu m, Object... x) { if (x == null) return; for (int i = 0; i < l(x); i++) { Object o = x[i], y = get(x, i + 1); if (o instanceof IVF1) callF(o, m); else if (o instanceof List) fillJPopupMenu(m, asArray((List) o)); else if (isMenuSeparatorIndicator(o)) m.addSeparator(); else if (o instanceof LiveValue && ((LiveValue) o).getType() == String.class && isRunnableX(y)) { final LiveValue lv = (LiveValue) o; final JMenuItem mi = jmenuItem("", y); bindLiveValueListenerToComponent(mi, lv, new Runnable() { public void run() { try { String s = lv.get(); if (isCurlyBracketed(s)) { setEnabled(mi, false); s = unCurlyBracket(s); } else setEnabled(mi, true); setText(mi, s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String s = lv.get();\r\n if (isCurlyBracketed(s)) {\r\n setEnable..."; } }); m.add(mi); } else if (o instanceof String && isRunnableX(y)) { m.add(jmenuItem((String) o, y)); ++i; } else if (o instanceof JMenuItem) m.add((JMenuItem) o); else if (o instanceof String || o instanceof Action || o instanceof Component) call(m, "add", o); else if (o != null) print("Unknown menu item: " + o); } } static public A heldInstance(Class c) { List l = holdInstance_l.get(); for (int i = l(l) - 1; i >= 0; i--) { Object o = l.get(i); if (isInstanceOf(o, c)) return (A) o; } throw fail("No instance of " + className(c) + " held"); } static public int getPreferredWidth(Component c) { return preferredWidth(c); } static public String stackTraceToString(StackTraceElement[] st) { return lines(st); } static public String stackTraceToString(Throwable e) { return getStackTrace_noRecord(e); } static public Object interceptPrintInThisThread(Object f) { Object old = print_byThread().get(); print_byThread().set(f); return old; } static public Object mainBot() { return getMainBot(); } static public FileInputStream newFileInputStream(File path) throws IOException { return newFileInputStream(path.getPath()); } static public FileInputStream newFileInputStream(String path) throws IOException { FileInputStream f = new FileInputStream(path); _registerIO(f, path, true); return f; } static public List sortByCalculatedFieldDesc_inPlace(List l, final Object f) { sort(l, new Comparator() { public int compare(A b, A a) { return stdcompare((Object) callF(f, a), (Object) callF(f, b)); } }); return l; } static public List sortByCalculatedFieldDesc_inPlace(Object f, List c) { return sortByCalculatedFieldDesc_inPlace(c, f); } static public long collectMinLong(Collection c, String field) { long x = Long.MAX_VALUE; for (Object o : unnull(c)) { Long l = (Long) (getOpt(o, field)); if (l != null) x = min(x, l); } return x; } static public long collectMaxLong(Collection c, String field) { long x = Long.MIN_VALUE; for (Object o : unnull(c)) { Long l = (Long) (getOpt(o, field)); if (l != null) x = max(x, l); } return x; } static public String i(String s, Object... params) { return tag("i", s, params); } static public String formatDateAndTime(long timestamp) { return formatDate(timestamp); } static public String formatDateAndTime() { return formatDate(); } static public String shortenEndTime(String endTime, String startTime) { int i = endTime.lastIndexOf(' ') + 1; if (i > 0 && eq(substring(startTime, 0, i), substring(endTime, 0, i))) return trim(substring(endTime, i)); return endTime; } static public String unicode_leftPointingTriangle() { return unicodeFromCodePoint(0x25C2); } static public String unicode_rightPointingTriangle() { return charToString(0x25B8); } static public float abs(float f) { return Math.abs(f); } static public int abs(int i) { return Math.abs(i); } static public double abs(double d) { return Math.abs(d); } static public String f2s(File f) { return f == null ? null : f.getAbsolutePath(); } static public String f2s(String s) { return f2s(newFile(s)); } static public String f2s(java.nio.file.Path p) { return p == null ? null : f2s(p.toFile()); } static public File parentFile(File f) { return dirOfFile(f); } static public String hms() { return hms(now()); } static public String hms(long time) { return new SimpleDateFormat("HHmmss").format(time); } static public void assertFalse(Object o) { if (!(eq(o, false))) throw fail(str(o)); } static public boolean assertFalse(boolean b) { if (b) throw fail("oops"); return b; } static public boolean assertFalse(String msg, boolean b) { if (b) throw fail(msg); return b; } static public boolean isAbsoluteURL(String s) { return isURL(s); } static public boolean isRelativeURL(String s) { return startsWithOneOf(s, "/", "./", "../"); } static public List replaceSubList(List l, List x, List y) { return replaceSublist(l, x, y); } static public List replaceSubList(List l, int fromIndex, int toIndex, List y) { return replaceSublist(l, fromIndex, toIndex, y); } static public boolean checkConceptFields(Concept x, Object... data) { for (int i = 0; i < l(data); i += 2) if (neq(cget(x, (String) data[i]), deref(data[i + 1]))) return false; return true; } static public int smartLastIndexOf(String s, char c) { if (s == null) return 0; int i = s.lastIndexOf(c); return i >= 0 ? i : l(s); } static public int smartLastIndexOf(List l, A sub) { int i = lastIndexOf(l, sub); return i < 0 ? l(l) : i; } static public List filterConcepts(List list, Object... params) { if (empty(params)) return list; List l = new ArrayList(); for (A x : list) if (checkConceptFields(x, params)) l.add(x); return l; } static public int year() { return localYear(); } static public int year(long now) { return localYear(now); } static public int year(long now, TimeZone tz) { return parseInt(simpleDateFormat("y", tz).format(now)); } static public String formatInt(int i, int digits) { return padLeft(str(i), '0', digits); } static public String formatInt(long l, int digits) { return padLeft(str(l), '0', digits); } static public int month() { return localMonth(); } static public int month(long now) { return localMonth(now); } static public int month(long now, TimeZone tz) { return parseInt(simpleDateFormat("M", tz).format(now)); } static public int dayOfMonth() { return localDayOfMonth(); } static public int dayOfMonth(long now) { return localDayOfMonth(now); } static public int dayOfMonth(long now, TimeZone tz) { return parseInt(simpleDateFormat("d", tz).format(now)); } static public ThreadLocal threadLocalWithDefault(A defaultValue) { return new ThreadLocal() { public A initialValue() { return defaultValue; } }; } static public boolean instanceOf(Object o, String className) { if (o == null) return false; String c = o.getClass().getName(); return eq(c, className) || eq(c, "main$" + className); } static public boolean instanceOf(Object o, Class c) { if (c == null) return false; return c.isInstance(o); } static public boolean instanceOf(Class c, Object o) { return instanceOf(o, c); } static public List keysWithoutHidden(Map map) { return filter(keys(map), new F1() { public Boolean get(Object o) { try { return !eq(o, "[hidden]") && !isStringStartingWith(o, "[hidden] "); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "!eq(o, \"[hidden]\") && !isStringStartingWith(o, \"[hidden] \")"; } }); } static public String structureOrTextForUser(Object o) { return o == null ? "" : o instanceof String ? (String) o : structureForUser(o); } static public void consoleFont(Font font) { callOpt(getConsoleTextArea_gen(), "setFont", font); } static public void consoleInputFont(final Font f) { { swing(new Runnable() { public void run() { try { JTextField input = consoleInputField(); if (input != null) { input.setFont(f); revalidateFrame(input); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JTextField input = consoleInputField();\r\n if (input != null) {\r\n inpu..."; } }); } } static public List listZipFile(File inZip) { try { ZipFile zipFile = new ZipFile(inZip); try { return listZipFile(zipFile); } finally { zipFile.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public List listZipFile(ZipFile zipFile) { try { List list = new ArrayList(); Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry) entries.nextElement(); if (!entry.isDirectory()) list.add(entry.getName()); } return list; } catch (Exception __e) { throw rethrow(__e); } } static public List listZipFile(String name) { if (isSnippetID(name)) return listZipFile(loadLibrary(name)); return listZipFile(getProgramFile(name)); } static public void _registerIO(Object object, String path, boolean opened) { } static public String snippetRawURL_maxCache(String snippetID) { return snippetRawURL_maxCache(snippetID, null); } static public String snippetRawURL_maxCache(String snippetID, String contentType) { return "https://botcompany.de/serve/" + psI(snippetID) + htmlQuery("ct", contentType, "maxCache", 1); } static public List dropFirstAndLast(int n, List l) { return cloneSubList(l, n, l(l) - n); } static public List dropFirstAndLast(int m, int n, List l) { return cloneSubList(l, m, l(l) - n); } static public List dropFirstAndLast(List l) { return dropFirstAndLast(1, l); } static public String dropFirstAndLast(String s) { return substring(s, 1, l(s) - 1); } static public String[] drop(int n, String[] a) { n = Math.min(n, a.length); String[] b = new String[a.length - n]; System.arraycopy(a, n, b, 0, b.length); return b; } static public Object[] drop(int n, Object[] a) { n = Math.min(n, a.length); Object[] b = new Object[a.length - n]; System.arraycopy(a, n, b, 0, b.length); return b; } static public ArrayList toList(A[] a) { return asList(a); } static public ArrayList toList(int[] a) { return asList(a); } static public ArrayList toList(Set s) { return asList(s); } static public ArrayList toList(Iterable s) { return asList(s); } static public void mapPut_noOverwrite(Map map, A key, B value) { if (map != null && key != null && value != null && !map.containsKey(key)) map.put(key, value); } static public int[] subIntArray(int[] b, int start) { return subIntArray(b, start, l(b)); } static public int[] subIntArray(int[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new int[0]; int[] x = new int[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public int[] subIntArray(int[] a, IntRange r) { return r == null ? null : subIntArray(a, r.start, r.end); } static public int lastIndexOf(String a, String b) { return a == null || b == null ? -1 : a.lastIndexOf(b); } static public int lastIndexOf(String a, char b) { return a == null ? -1 : a.lastIndexOf(b); } static public int lastIndexOf(List l, int i, A a) { if (l == null) return -1; for (i = min(l(l), i) - 1; i >= 0; i--) if (eq(l.get(i), a)) return i; return -1; } static public int lastIndexOf(List l, A a) { if (l == null) return -1; for (int i = l(l) - 1; i >= 0; i--) if (eq(l.get(i), a)) return i; return -1; } static public SimpleDateFormat simpleDateFormat_local(String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(localTimeZone()); return sdf; } static public String pnlToString(String prefix, Iterable l) { return hijackPrint(new Runnable() { public void run() { try { pnl(prefix, l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pnl(prefix, l)"; } }); } static public String pnlToString(final Iterable l) { return hijackPrint(new Runnable() { public void run() { try { pnl(l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pnl(l)"; } }); } static public String pnlToString(final A[] l) { return hijackPrint(new Runnable() { public void run() { try { pnl(l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pnl(l)"; } }); } static public String pnlToString(final Map map) { return hijackPrint(new Runnable() { public void run() { try { pnl(map); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pnl(map)"; } }); } static public String pnlToString(MultiMap map) { return pnlToString(multiMapToMap(map)); } static public String base64(byte[] a) { return base64encode(a); } static public BufferedImage dropAlphaChannelFromBufferedImage(BufferedImage img) { if (img == null || img.getType() == BufferedImage.TYPE_INT_RGB) return img; int w = img.getWidth(), h = img.getHeight(); BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); int[] rgb = img.getRGB(0, 0, w, h, null, 0, w); newImage.setRGB(0, 0, w, h, rgb, 0, w); return newImage; } static public long toK(long l) { return (l + 1023) / 1024; } static public TreeSet caseInsensitiveSet_treeSet() { return new TreeSet(caseInsensitiveComparator()); } static public TreeSet caseInsensitiveSet_treeSet(Collection c) { return toCaseInsensitiveSet_treeSet(c); } static public String actualProgramID() { return programID(); } static public MultiMap treeMultiMap() { return new MultiMap(true); } static public MultiMap treeMultiMap(Comparator comparator) { return new MultiMap(new TreeMap>(comparator)); } static public List sortedByField(Collection c, final String field) { List l = new ArrayList(c); sort(l, new Comparator() { public int compare(A a, A b) { return cmp(getOpt(a, field), getOpt(b, field)); } }); return l; } static public List sortedByField(String field, Collection c) { return sortedByField(c, field); } static public Object loadJSONFile(File f) { return jsonDecode(loadTextFile(f)); } static public A objectWhere(Collection c, Object... data) { return findWhere(c, data); } static public Comparator makeComparator(final Object f) { if (f instanceof Comparator) return (Comparator) f; return new Comparator() { public int compare(Object a, Object b) { return (Integer) callF(f, a, b); } }; } static public List collectField(Iterable c, String field) { List l = new ArrayList(); if (c != null) for (Object a : c) l.add(getOpt(a, field)); return l; } static public List collectField(String field, Iterable c) { return collectField(c, field); } static public String imageServerLink(String md5OrID) { if (possibleMD5(md5OrID)) return "https://botcompany.de/images/md5/" + md5OrID; return imageServerLink(parseSnippetID(md5OrID)); } static public String imageServerLink(long id) { return "https://botcompany.de/images/" + id; } static public Comparator descFieldComparator(final String field) { return new Comparator() { public int compare(A a, A b) { return cmp(getOpt(b, field), getOpt(a, field)); } }; } static public TimerTask timerTask(final Object r, final java.util.Timer timer) { return new TimerTask() { public void run() { if (!licensed()) timer.cancel(); else pcallF(r); } }; } static public void ensureDBNotRunning(String name) { if (hasBot(name)) { try { String framesBot = dropSuffix(".", name) + " Frames"; print("Trying to activate frames of running DB: " + framesBot); if (isOK(sendOpt(framesBot, "activate frames")) && isMainProgram()) cleanKill(); } catch (Throwable __e) { _handleException(__e); } throw fail("Already running: " + name); } } static public void ensureDBNotRunning() { ensureDBNotRunning(dbBotStandardName()); } static public String dbBotStandardName() { String home = userHome(); String name = dbBotName(getDBProgramID()); if (neq(home, actualUserHome())) name += " " + quote(home); return name + "."; } static volatile public Android3 dbBot_instance; static public Android3 dbBot() { return dbBot(true); } static public Android3 dbBot(boolean ensureNotRunning) { return dbBot(dbBotStandardName(), ensureNotRunning); } static public Android3 dbBot(String name) { return dbBot(name, true); } static public Android3 dbBot(String name, boolean ensureNotRunning) { if (ensureNotRunning) ensureDBNotRunning(name); return dbBot_instance = methodsBot2(name, assertNotNull(db_mainConcepts()), db_standardExposedMethods(), db_mainConcepts().lock); } static public void thinAProgramsBackups(String progID, boolean doIt) { List files = new ArrayList(); Map ageMap = new HashMap(); java.util.regex.Pattern pat = regexp("^(.*)\\.backup(20\\d\\d)(\\d\\d)(\\d\\d)-(\\d\\d)(\\d*)$"); File dir = programDir(progID); for (File f : listFilesNotDirs(dir, newFile(dir, "backups"))) { String s = f.getName(); java.util.regex.Matcher matcher = pat.matcher(s); { if (!(matcher.find())) continue; } String originalName = matcher.group(1); { if (!(eq(originalName, "concepts.structure.gz"))) continue; } int year = matcherInt(matcher, 2); int month = matcherInt(matcher, 3); int day = matcherInt(matcher, 4); int hour = matcherInt(matcher, 5); int minute = matcherInt(matcher, 6); long time = timestampFromYMDHM(year, month, day, hour, minute); double age = ((now() - time) / 1000.0 / 60 / 60 / 24); ageMap.put(f, age); files.add(f); } int numDeleted = 0; sortByMap_inPlace(files, ageMap); double lastAge = -1; for (File f : files) { double age = ageMap.get(f); if (!thinAProgramsBackups_shouldKeep(age, lastAge)) { ++numDeleted; if (doIt) { print("Deleting: " + f); f.delete(); } } else { lastAge = age; } } if (numDeleted != 0) print((doIt ? "Deleted: " : "Would delete: ") + n(numDeleted, "file")); } static public boolean thinAProgramsBackups_shouldKeep(double age, double lastAge) { return defaultAgeBasedBackupRetentionStrategy_shouldKeep(age, lastAge); } static public A lookupOrKeep(Map map, A key) { return map != null && map.containsKey(key) ? map.get(key) : key; } static public Random defaultRandomGenerator() { return ThreadLocalRandom.current(); } static public Object subBot_httpd() { Object httpd = getThreadLocal((ThreadLocal) getOpt(mainBot(), "MyHTTPD_current")); if (httpd == null) httpd = getThreadLocal((ThreadLocal) getOpt(mainBot(), "WebSocketHTTPD_current")); return httpd; } static public String domainName() { Object session = call(getMainBot(), "getSession"); Map headers = (Map) (call(session, "getHeaders")); String host = (String) (headers.get("host")); if (host == null) return null; return dropFrom(host, ":"); } static public String codePointToString(int codePoint) { return new String(Character.toChars(codePoint)); } static public boolean isCISet(Iterable l) { return l instanceof TreeSet && ((TreeSet) l).comparator() == caseInsensitiveComparator(); } static public String hlabelFor(String id, Object contents) { String s = strOrEmpty(contents); return empty(s) ? "" : htag("label", s, "for", id); } static public SimpleDateFormat simpleDateFormat_timeZone(String format, String timeZone) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(timeZone(timeZone)); return sdf; } static public Map mruCache(int maxSize) { return synchronizedMRUCache(maxSize); } static public File javaxCachesDir_dir; static public File javaxCachesDir() { return javaxCachesDir_dir != null ? javaxCachesDir_dir : new File(userHome(), "JavaX-Caches"); } static public File javaxCachesDir(String sub) { return newFile(javaxCachesDir(), sub); } static public long ipToInt(String ip) { Matches m = new Matches(); assertTrue(jmatch("*.*.*.*", ip, m)); return parseLong(m.unq(3)) | parseLong(m.unq(2)) << 8 | parseLong(m.unq(1)) << 16 | parseLong(m.unq(0)) << 24; } static public B mapGetOrCreate(Map map, A key, Class c) { return getOrCreate(map, key, c); } static public B mapGetOrCreate(Map map, A key, Object f) { return getOrCreate(map, key, f); } static public B mapGetOrCreate(Map map, A key, IF0 f) { return getOrCreate(map, key, (Object) f); } static public B mapGetOrCreate(Class c, Map map, A key) { return getOrCreate(c, map, key); } static public boolean directoryEmpty(File f) { return directoryIsEmpty(f); } static public void unzipSnippet(String snippetID, File toDir) { print("Unzipping snippet " + snippetID + " to " + toDir); zip2dir(loadLibrary(snippetID), toDir); } static public Pair binarySearchForLineInTextFile(File file, IF1 nav) { long length = l(file); int bufSize = 1024; RandomAccessFile raf = randomAccessFileForReading(file); try { long min = 0, max = length; int direction = 0; Pair possibleResult = null; while (min < max) { ping(); long middle = (min + max) / 2; long lineStart = raf_findBeginningOfLine(raf, middle, bufSize); long lineEnd = raf_findEndOfLine(raf, middle, bufSize); String line = fromUtf8(raf_readFilePart(raf, lineStart, (int) (lineEnd - 1 - lineStart))); direction = nav.get(line); possibleResult = pair(new LongRange(lineStart, lineEnd), line); if (direction == 0) return possibleResult; if (direction < 0) max = assertLessThan(max, lineStart); else min = assertBiggerThan(min, lineEnd); } if (direction >= 0) return possibleResult; long lineStart = raf_findBeginningOfLine(raf, min - 1, bufSize); String line = fromUtf8(raf_readFilePart(raf, lineStart, (int) (min - 1 - lineStart))); return pair(new LongRange(lineStart, min), line); } finally { _close(raf); } } static public List tok_splitAtComma_unquote(String s) { List tok = javaTok(s); List out = new ArrayList(); for (int i = 0; i < l(tok); i++) { int j = smartIndexOf(tok, ",", i); out.add(unquote(trimJoinSubList(tok, i, j))); i = j; } return out; } static public long parseLongOpt(String s) { return isInteger(s) ? parseLong(s) : 0; } static public String regexReplaceIC(String s, String pat, Object f) { return regexReplace(regexpMatcherIC(pat, s), f); } static public String regexReplaceIC(String s, String pat, String replacement) { return regexpReplaceIC_direct(s, pat, replacement); } static public JTextField standardTextFieldPopupMenu(final JTextField tf) { final WeakReference ref = weakRef(tf); componentPopupMenuItem(tf, "Copy text to clipboard", new Runnable() { public void run() { try { copyTextToClipboard(ref.get().getText()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyTextToClipboard(ref.get().getText())"; } }); componentPopupMenuItem(tf, "Paste", new Runnable() { public void run() { try { ref.get().paste(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ref.get().paste()"; } }); return tf; } static public A jenableUndoRedo(final A textcomp) { { swing(new Runnable() { public void run() { try { final UndoManager undo = new UndoManager(); vm_generalWeakSet("Undo Managers").add(undo); textcomp.getDocument().addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); textcomp.getActionMap().put("Undo", abstractAction("Undo", new Runnable() { public void run() { try { if (undo.canUndo()) undo.undo(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canUndo()) undo.undo()"; } })); textcomp.getActionMap().put("Redo", abstractAction("Redo", new Runnable() { public void run() { try { if (undo.canRedo()) undo.redo(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canRedo()) undo.redo()"; } })); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo"); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final new UndoManager undo;\r\n vm_generalWeakSet(\"Undo Managers\").add(undo)..."; } }); } return textcomp; } static public JPanel showFormTitled_customArrangement(final boolean internalFrame, final F1, JPanel> arrange, final String title, final Object... _parts) { return swing(new F0() { public JPanel get() { try { List out = showForm_arrange1(showForm_makeComponents(internalFrame, _parts)); JPanel panel = callF(arrange, out); showForm_makeFrame(title, panel); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "L out = showForm_arrange1(showForm_makeComponents(internalFrame, ..."; } }); } static public JPanel customLayoutPanel(final Object layouter) { return jpanel(layoutManagerFromFunction(layouter)); } static public JPanel customLayoutPanel(final Object layouter, final List components) { return addAllComponents(customLayoutPanel(layouter), components); } static public List getComponents(final Component c) { return !(c instanceof Container) ? emptyList() : asList(swing(new F0() { public Component[] get() { try { return ((Container) c).getComponents(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret ((Container) c).getComponents();"; } })); } static public boolean containsATextArea(Component c) { return childOfType(c, JTextArea.class) != null; } static public int totalPreferredHeight(List l) { int h = 0; for (Component c : unnull(l)) h += c.getPreferredSize().height; return h; } static public List listWithoutIndicesInBitSet(List l, BitSet bs) { List out = new ArrayList(); for (int i = 0; i < l(l); i++) if (!bs.get(i)) out.add(l.get(i)); return out; } static public Dimension componentsBoundingSize(Container container, int insetBottomRight) { Rectangle r = new Rectangle(0, 0, 0, 0); for (Component c : container.getComponents()) r = rectangleUnion(r, c.getBounds()); return new Dimension(r.x + r.width + insetBottomRight, r.y + r.height + insetBottomRight); } static public void sleepInCleanUp(long ms) { try { if (ms < 0) return; Thread.sleep(ms); } catch (Exception __e) { throw rethrow(__e); } } static public ActionListener actionListener(final Object runnable) { return actionListener(runnable, null); } static public ActionListener actionListener(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; final Object info = _threadInfo(); return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { _threadInheritInfo(info); AutoCloseable __1 = holdInstance(instanceToHold); try { callF(runnable); } finally { _close(__1); } } catch (Throwable __e) { messageBox(__e); } } }; } static public String getProgramName_cache; static public String getProgramName() { Lock __0 = downloadLock(); lock(__0); try { if (getProgramName_cache == null) getProgramName_cache = getSnippetTitleOpt(programID()); return getProgramName_cache; } finally { unlock(__0); } } static public void _onLoad_getProgramName() { { startThread(new Runnable() { public void run() { try { getProgramName(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getProgramName();"; } }); } } static public JButton renameButton(JComponent c, String name) { JButton b = first(childrenOfType(c, JButton.class)); if (b != null) b.setText(name); return b; } static public JButton renameButton(JComponent c, String oldName, String newName) { JButton b = findButton(c, oldName); if (b != null) b.setText(newName); return b; } static public String showFormSubmitButtonName() { return "Submit"; } static public int indexOfSpaceEtc(String s) { int n = l(s); for (int i = 0; i < n; i++) if (isSpace(s.charAt(i))) return i; return -1; } static public IterableIterator iff(Object f) { return iteratorFromFunction_withEndMarker(f); } static public IterableIterator iff(F0 f) { return iteratorFromFunction_withEndMarker(f); } static public IterableIterator iff(IF0 f) { return iteratorFromFunction_withEndMarker(f); } static public Object endMarker() { return iteratorFromFunction_endMarker; } static public List wrapArrayAsList(A[] a) { return a == null ? null : Arrays.asList(a); } static public String joinWithSemicolon(Iterable l) { return join("; ", l); } static public void litmap_impl_noOverwrite(Map map, Object... x) { if (x != null) for (int i = 0; i < x.length - 1; i += 2) putIfNotThere(map, x[i], x[i + 1]); } static public List splitAtColon(String s) { return empty(s) ? emptyList() : asList(s.split(":")); } static public List words2(String s) { List l = new ArrayList(); int n = l(s); for (int i = 0; i < n; ) { int j = i; while (j < n && isLetterOrDigit(s.charAt(j))) ++j; if (j > i) l.add(substring(s, i, j)); while (j < n && !isLetterOrDigit(s.charAt(j))) ++j; i = j; } return l; } static public String indentx(String s) { return indentx(indent_default, s); } static public String indentx(int n, String s) { return dropSuffix(repeat(' ', n), indent(n, s)); } static public String indentx(String indent, String s) { return dropSuffix(indent, indent(indent, s)); } static public String hcomment_unescaped(String text) { return ""; } static public Set setMinus(Set set, Object... stuff) { Set s2 = cloneSet(set); for (Object o : stuff) s2.remove(o); return s2; } static public Set mergeSets(Collection... l) { return joinSets(l); } static public Set allNonStaticNonTransientFields(Object o) { TreeSet fields = new TreeSet(); Class _c = _getClass(o); do { for (Field f : _c.getDeclaredFields()) if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) fields.add(f.getName()); _c = _c.getSuperclass(); } while (_c != null); return fields; } static public String snippetRawURL(String snippetID) { return snippetRawURL(snippetID, null); } static public String snippetRawURL(String snippetID, String contentType) { return "https://botcompany.de/serve/" + psI(snippetID) + htmlQuery("ct", contentType); } static public A listGet(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static public Pair mapEntryToPair(Map.Entry e) { return e == null ? null : pair(e.getKey(), e.getValue()); } static public BufferedImage imageIO_readURL(String url) { try { return ImageIO.read(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static public boolean isAbsolutePath(String s) { return s != null && new File(s).isAbsolute(); } static public boolean isAbsolutePath(File f) { return f != null && f.isAbsolute(); } static public File imageSnippetsCacheDir() { return javaxCachesDir("Image-Snippets"); } static public String snippetImageURL_http(String snippetID) { return snippetImageURL_http(snippetID, "png"); } static public String snippetImageURL_http(String snippetID, String contentType) { return replacePrefix("https://", "http://", snippetImageURL(snippetID, contentType)).replace(":8443", ":8080"); } static public BufferedImage loadBufferedImageFile(File file) { try { return isFile(file) ? ImageIO.read(file) : null; } catch (Exception __e) { throw rethrow(__e); } } static public String repeat(char c, int n) { n = Math.max(n, 0); char[] chars = new char[n]; for (int i = 0; i < n; i++) chars[i] = c; return new String(chars); } static public List repeat(A a, int n) { n = Math.max(n, 0); List l = new ArrayList(n); for (int i = 0; i < n; i++) l.add(a); return l; } static public List repeat(int n, A a) { return repeat(a, n); } static public int indexOfIgnoreCase_manual(String a, String b) { return indexOfIgnoreCase_manual(a, b, 0); } static public int indexOfIgnoreCase_manual(String a, String b, int i) { int la = strL(a), lb = strL(b); if (la < lb) return -1; int n = la - lb; loop: for (; i <= n; i++) { for (int j = 0; j < lb; j++) { char c1 = a.charAt(i + j), c2 = b.charAt(j); if (!eqic(c1, c2)) continue loop; } return i; } return -1; } static public String beautifyStructure(String s) { List tok = javaTokForStructure(s); structure_addTokenMarkers(tok); jreplace(tok, "lhm", ""); return join(tok); } static public boolean tok_isRoundBracketed(String s) { List tok = tok_combineRoundBrackets_keep(javaTok(s)); return l(tok) == 3 && startsWithAndEndsWith(tok.get(1), "(", ")"); } static public List dropFirstThreeAndLastThree(List l) { return dropFirstAndLast(3, l); } static public List javaTokPlusBrackets(String s) { return tok_combineRoundOrCurlyBrackets_keep(javaTok(s)); } static public Map> javaTokWithAllBrackets_cached_cache = synchronizedMRUCache(defaultTokenizerCacheSize()); static public List javaTokWithAllBrackets_cached(String s) { List tok = javaTokWithAllBrackets_cached_cache.get(s); if (tok == null) javaTokWithAllBrackets_cached_cache.put(s, tok = javaTokWithAllBrackets(s)); return tok; } static public List splitAtTokens(String s, List tokens) { return splitAtTokens(javaTok(s), tokens); } static public List splitAtTokens(List tok, List tokens) { List l = new ArrayList(); int i = 0; while (i < l(tok)) { int j = indexOfSubList(tok, tokens, i); if (i >= l(tok)) break; if (j < 0) j = l(tok); l.add(trimJoin(tok.subList(i, j))); i = j + l(tokens); } return l; } static public List splitAtTokens(List tok, String... tokens) { List l = new ArrayList(); int i = 0; while (i < l(tok)) { int j = indexOfSubList(tok, tokens, i); if (i >= l(tok)) break; if (j < 0) j = l(tok); l.add(trimJoin(tok.subList(i, j))); i = j + l(tokens); } return l; } static public boolean cicWithSmartWordBoundary(String a, String b) { return containsRegexpIC(a, phraseToRegExp(b)); } static public boolean match3_startOrEndOfLine(String pat, String s, boolean startOfLine, boolean endOfLine) { if (startOfLine) return endOfLine ? match3(pat, s) : matchStart(pat, s); else return endOfLine ? matchEnd(pat, s) : find3(pat, s); } static public boolean all(Object pred, Iterable l) { if (l != null) for (Object o : l) if (!isTrue(callF(pred, o))) return false; return true; } static public boolean all(Iterable l, IF1 f) { if (l != null) for (A a : l) if (!f.get(a)) return false; return true; } static public boolean all(IF1 f, Iterable l) { return all(l, f); } static public boolean find3(String pat, String s) { return find3(pat, s, null); } static public boolean find3(String pat, String s, Matches matches) { return find3(pat, parse3_cachedInput(s), matches); } static public boolean find3(String pat, List toks, Matches matches) { List tokpat = parse3_cachedPattern(pat); String[] m = find2(tokpat, toks); if (m == null) return false; if (matches != null) matches.m = m; return true; } static public Integer find3_levenWithSwapsDistance(String pat, String input) { List tokPat = parse3_cachedPattern(pat); List tok = parse3_cachedInput(input); int end = tok.size() - tokPat.size() + 1; Integer min = null; for (int idx = 0; idx < end; idx += 2) { int score = 0; for (int i = 1; i < tokPat.size(); i += 2) { String p = tokPat.get(i), t = tok.get(idx + i); score += levenWithSwapsIC(p, t); } min = min_withNull(min, score); } return min; } static public Integer min_withNull(Integer a, Integer b) { return a == null ? b : b == null ? a : (Integer) min(a, b); } static public List splitAtMinus(String s) { return trimAll(asList(s.split("\\-"))); } static public Integer parseHourAndOptionalMinutesToMinutes(String s) { List l = trimAll(splitAtColon(s)); if (empty(l)) return null; int minute = parseInt(first(l)) * 60; if (l(l) > 1) minute += parseInt(second(l)); return minute; } static public Collection asCollection(Iterable l) { return l == null ? null : l instanceof Collection ? ((Collection) l) : asList(l); } static public A liftLast(List l) { if (empty(l)) return null; int i = l(l) - 1; A a = l.get(i); l.remove(i); return a; } static public List liftLast(int n, List l) { int i = l(l) - n; List part = cloneSubList(l, i); removeSubList(l, i); return part; } static public A copyFields(Object x, A y, String... fields) { if (empty(fields)) { Map map = objectToMap(x); for (String field : map.keySet()) setOpt(y, field, map.get(field)); } else for (String field : fields) { Object o = getOpt(x, field); if (o != null) setOpt(y, field, o); } return y; } static public A copyFields(Object x, A y, Collection fields) { return copyFields(x, y, asStringArray(fields)); } static public Map nuEmptyObject_cache = newDangerousWeakHashMap(); static public A nuEmptyObject(Class c) { try { Constructor ctr; synchronized (nuEmptyObject_cache) { ctr = nuEmptyObject_cache.get(c); if (ctr == null) { nuEmptyObject_cache.put(c, ctr = nuEmptyObject_findConstructor(c)); makeAccessible(ctr); } } try { return (A) ctr.newInstance(); } catch (InstantiationException e) { if (empty(e.getMessage())) if ((c.getModifiers() & Modifier.ABSTRACT) != 0) throw fail("Can't instantiate abstract class " + className(c), e); else throw fail("Can't instantiate " + className(c), e); else throw rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static public Constructor nuEmptyObject_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (m.getParameterTypes().length == 0) return m; throw fail("No default constructor declared in " + c.getName()); } static public boolean _inCore() { return false; } static public List hotwire_copyOver_after = synchroList(); static public void hotwire_copyOver(Class c) { for (String field : ll("print_log", "print_silent", "androidContext", "_userHome")) setOptIfNotNull(c, field, getOpt(mc(), field)); setOptIfNotNull(c, "mainBot", getMainBot()); setOpt(c, "creator_class", new WeakReference(mc())); pcallFAll(hotwire_copyOver_after, c); } static public JComboBox selectItem(A item, JComboBox cb) { if (cb != null) { swing(new Runnable() { public void run() { try { cb.setSelectedItem(item); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.setSelectedItem(item);"; } }); } return cb; } static public JComboBox selectItem(JComboBox cb, A item) { return selectItem(item, cb); } static public JList selectItem(JList list, A item) { { swing(new Runnable() { public void run() { try { selectRow(list, jlist_indexOf(list, item)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "selectRow(list, jlist_indexOf(list, item));"; } }); } return list; } static public JInternalFrame showForm_makeInternalFrame(JDesktopPane desktop, String title, JPanel panel) { JInternalFrame f = addInternalFrame(desktop, title, withMargin(panel)); minInternalFrameWidth(f, 400); packInternalFrameVertically(f); centerInternalFrame(f); return f; } static public JFrame handleEscapeKey(final JFrame frame) { KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); frame.getRootPane().registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { frame.dispose(); } }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); return frame; } static public JFrame minFrameWidth(JFrame frame, int w) { if (frame != null && frame.getWidth() < w) frame.setSize(w, frame.getHeight()); return frame; } static public JFrame minFrameWidth(int w, JFrame frame) { return minFrameWidth(frame, w); } static public JFrame showPackedFrame(String title, Component contents) { return packFrame(showFrame(title, contents)); } static public JFrame showPackedFrame(Component contents) { return packFrame(showFrame(contents)); } static public int showForm_leftWidth_safetyMargin = 10; static public int showForm_leftWidth(List> l) { forEachLevel2(l, x -> vmBus_send("updateLayoutNow", x)); int minW = 0; for (List row : l) minW = max(minW, getMinimumSize(first(row)).width); return minW + or((Integer) vmBus_query("formSafetyMargin"), showForm_leftWidth_safetyMargin); } static public JPanel westAndCenter(final Component w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.WEST, wrap(w)); panel.add(BorderLayout.CENTER, wrap(c)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.WEST..."; } }); } static public int withRightMargin_defaultWidth = 6; static public JPanel withRightMargin(Component c) { return withRightMargin(withRightMargin_defaultWidth, c); } static public JPanel withRightMargin(final int w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, w)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static public A jMinWidthAtLeast(int w, final A c) { if (c == null) return null; return swing(new F0() { public A get() { try { Dimension size = c.getMinimumSize(); Dimension d = new Dimension(max(w, size.width), size.height); c.setMinimumSize(d); return jPreferWidth(d.width, c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Dimension size = c.getMinimumSize();\r\n Dimension d = new Dimension(max(w, ..."; } }); } static public void setComponentID(Component c, String id) { if (c != null) componentID_map.put(c, id); } static public List mapLL(Object f, Object... data) { return map(f, ll(data)); } static public List mapLL(IF1 f, A... data) { return map(f, ll(data)); } static public JComponent wrapForSmartAdd_jComponent(Object o) { return componentToJComponent(wrapForSmartAdd(o)); } static public Map humanizeFormLabel_replacements = litmap("id", "ID", "md5", "MD5"); static public String humanizeFormLabel(String s) { if (containsSpace(s)) return s; return firstToUpper(joinWithSpace(replaceElementsUsingMap(splitCamelCase(s), humanizeFormLabel_replacements)).replace("I D", "ID")); } static public boolean isRunnable(Object o) { return o instanceof Runnable || hasMethod(o, "get"); } static public void disposeInternalFrame(Component c) { final JInternalFrame f = getInternalFrame(c); if (f != null) { swing(new Runnable() { public void run() { try { vmBus_send("disposingInternalFrame", f); f.dispose(); setOpt(f, "lastFocusOwner", null); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "vmBus_send disposingInternalFrame(f);\r\n f.dispose();\r\n setOpt(f, lastFo..."; } }); } } static public void disposeFrame(final Component c) { disposeWindow(c); } static public void onEnterInAllTextFields(JComponent c, Object action) { if (action == null) return; for (Component tf : allChildren(c)) onEnterIfTextField(tf, action); } static public void onEnterInAllTextFields(List c, Object action) { for (Object o : unnull(c)) if (o instanceof JComponent) onEnterInAllTextFields((JComponent) o, action); } static public void clickButton(final JButton b) { if (b != null) { swing(new Runnable() { public void run() { try { if (b.isEnabled()) b.doClick(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (b.isEnabled())\r\n b.doClick();"; } }); } } static public A makeBold(final A c) { if (c != null) { swing(new Runnable() { public void run() { try { c.setFont(c.getFont().deriveFont(java.awt.Font.BOLD)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setFont(c.getFont().deriveFont(java.awt.Font.BOLD));"; } }); } return c; } static public JPanel smartAddWithLayout(JPanel panel, Object layout, List parts) { for (Object o : parts) panel.add(wrapForSmartAdd(o), layout); return panel; } static public JPanel smartAddWithLayout(JPanel panel, Object layout, Object... parts) { return smartAddWithLayout(panel, layout, asList(flattenArray2(parts))); } static public Component jrigid() { return javax.swing.Box.createRigidArea(new Dimension(0, 0)); } static public Object callFunction(Object f, Object... args) { return callF(f, args); } static public int indexOfIC_underscore(String a, String b) { int la = l(a), lb = l(b); if (la < lb) return -1; int n = la - lb; elsewhere: for (int i = 0; i <= n; i++) { for (int j = 0; j < lb; j++) { char c2 = b.charAt(j); if (c2 == '_' || eqic(c2, a.charAt(i + j))) { } else continue elsewhere; } return i; } return -1; } static public Map myFrames_list = weakHashMap(); static public List myFrames() { return swing(new F0>() { public List get() { try { return keysList(myFrames_list); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret keysList(myFrames_list);"; } }); } static public ThreadLocal> holdInstance_l = new ThreadLocal(); static public AutoCloseable holdInstance(Object o) { if (o == null) return null; listThreadLocalAdd(holdInstance_l, o); return new AutoCloseable() { public void close() { listThreadLocalPopLast(holdInstance_l); } }; } static public Object iteratorFromFunction_endMarker = new Object(); static public IterableIterator iteratorFromFunction_withEndMarker(final Object f) { class IFF extends IterableIterator { public A a; public boolean have, done; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; have = false; return _a; } public void getNext() { if (done || have) return; Object o = callF(f); if (o == iteratorFromFunction_endMarker) { done = true; return; } a = (A) o; have = true; } } ; return new IFF(); } static public IterableIterator iteratorFromFunction_withEndMarker(final F0 f) { return iteratorFromFunction_withEndMarker_f0(f); } static public Map componentID_map = weakHashMap(); static public String componentID(Component c) { return c == null ? null : componentID_map.get(c); } static public List javaTok_noMLS(String s) { ArrayList tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { int c2 = s.charAt(j); if (c2 == opener || c2 == '\n' && opener == '\'') { ++j; break; } else if (c2 == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else ++j; tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static public A firstOfPair(Pair p) { return p == null ? null : p.a; } static public Class primitiveToBoxedType(Class type) { if (type == boolean.class) return Boolean.class; if (type == int.class) return Integer.class; if (type == long.class) return Long.class; if (type == float.class) return Float.class; if (type == short.class) return Short.class; if (type == char.class) return Character.class; if (type == byte.class) return Byte.class; if (type == double.class) return Double.class; return null; } static public Object dm_os() { { Object __1 = vm_generalMap_get("stefansOS"); if (__1 != null) return __1; } return creator(); } static public Set synchronizedSet() { return synchroHashSet(); } static public Set synchronizedSet(Set set) { return Collections.synchronizedSet(set); } static public Set identityHashSet() { return Collections.newSetFromMap(new IdentityHashMap()); } static public A proxyFromInvocationHandler(Class intrface, InvocationHandler handler) { return (A) java.lang.reflect.Proxy.newProxyInstance(intrface.getClassLoader(), new Class[] { intrface }, handler); } static public Throwable unwrapTrivialExceptionWraps(Throwable e) { if (e == null) return e; while (e.getClass() == RuntimeException.class && e.getCause() != null && eq(e.getMessage(), str(e.getCause()))) e = e.getCause(); return e; } static public String replacePrefix(String prefix, String replacement, String s) { if (!startsWith(s, prefix)) return s; return replacement + substring(s, l(prefix)); } static public Throwable innerException2(Throwable e) { if (e == null) return null; while (empty(e.getMessage()) && e.getCause() != null) e = e.getCause(); return e; } static public Throwable getException(Runnable r) { try { callF(r); return null; } catch (Throwable e) { return e; } } static public Class hotwire_overBot(String src) { return hotwire(src); } static public Object vmBus_query(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); { Object __1 = pcallFAll_returnFirstNotNull(vm_busListeners_live(), msg, arg); if (__1 != null) return __1; } return pcallFAll_returnFirstNotNull(vm_busListenersByMessage_live().get(msg), msg, arg); } static public Object vmBus_query(String msg) { return vmBus_query(msg, (Object) null); } static public String assertIdentifier(String s) { return assertIsIdentifier(s); } static public String assertIdentifier(String msg, String s) { return assertIsIdentifier(msg, s); } static public List allMethodNames(Object o) { Class c = _getClass(o); TreeSet names = new TreeSet(); while (c != null) { for (Method m : c.getDeclaredMethods()) names.add(m.getName()); c = c.getSuperclass(); } return asList(names); } static public Map vm_generalSubMap(Object name) { synchronized (get(javax(), "generalMap")) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = synchroMap()); return map; } } static public boolean isTrueOpt(Object o) { if (o instanceof Boolean) return ((Boolean) o).booleanValue(); return false; } static public boolean isTrueOpt(String field, Object o) { return isTrueOpt(getOpt(field, o)); } static public List isYes_yesses = litlist("y", "yes", "yeah", "y", "yup", "yo", "corect", "sure", "ok", "afirmative"); static public boolean isYes(String s) { return isYes_yesses.contains(collapseWord(toLowerCase(firstWord2(s)))); } static public Integer boxed(int i) { return i; } static public Long boxed(long l) { return l; } static public String dropAfterSubstring(String s, String b) { return substring(s, 0, smartIndexOf(s, b)); } static public Throwable _storeException_value; static public void _storeException(Throwable e) { _storeException_value = e; } static public Object[] changeParam(Object[] params, String name, Object value) { if (eq(optPar(params, name), value)) return params; Map map = paramsToOrderedMap(params); map.put(name, value); return mapToParams(map); } static public String jsonEncode_breakAtLevel1(Object o) { StringBuilder buf = new StringBuilder(); jsonEncode_breakAtLevel1(o, buf, 1); return str(buf); } static public void jsonEncode_breakAtLevel1(Object o, StringBuilder buf, int level) { if (o == null) buf.append("null"); else if (o instanceof String) buf.append(quote((String) o)); else if (o instanceof Number || o instanceof Boolean) buf.append(o); else if (o instanceof Map) { Map map = (Map) o; buf.append("{"); boolean first = true; for (Object key : keys(map)) { if (first) first = false; else buf.append(","); if (level == 1) buf.append("\n "); buf.append(quote((String) key)); buf.append(":"); jsonEncode_breakAtLevel1(map.get(key), buf, level + 1); } if (level == 1) buf.append("\n"); buf.append("}"); } else if (o instanceof Collection) { Collection l = (Collection) o; buf.append("["); boolean first = true; for (Object element : l) { if (first) first = false; else buf.append(","); if (level == 1) buf.append("\n "); jsonEncode_breakAtLevel1(element, buf, level + 1); } if (level == 1) buf.append("\n"); buf.append("]"); } else throw fail("Unknown object for JSON encoding: " + className(o)); } static public CloseableIterableIterator emptyCloseableIterableIterator_instance = new CloseableIterableIterator() { public Object next() { throw fail(); } public boolean hasNext() { return false; } }; static public CloseableIterableIterator emptyCloseableIterableIterator() { return emptyCloseableIterableIterator_instance; } static public boolean ewic(String a, String b) { return endsWithIgnoreCase(a, b); } static public boolean ewic(String a, String b, Matches m) { return endsWithIgnoreCase(a, b, m); } static public CloseableIterableIterator linesFromReader(Reader r) { return linesFromReader(r, null); } static public CloseableIterableIterator linesFromReader(Reader r, IResourceHolder resourceHolder) { final BufferedReader br = bufferedReader(r); return holdResource(resourceHolder, iteratorFromFunction_f0_autoCloseable(new F0() { public String get() { try { return readLineFromReaderWithClose(br); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret readLineFromReaderWithClose(br);"; } }, _wrapIOCloseable(r))); } static public BufferedReader utf8bufferedReader(InputStream in) { try { return in == null ? null : bufferedReader(_registerIOWrap(new InputStreamReader(in, "UTF-8"), in)); } catch (Exception __e) { throw rethrow(__e); } } static public BufferedReader utf8bufferedReader(File f) { try { return utf8bufferedReader(newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static public GZIPInputStream newGZIPInputStream(File f) { return gzInputStream(f); } static public GZIPInputStream newGZIPInputStream(InputStream in) { return gzInputStream(in); } static public boolean eqicOrEq(Object a, Object b) { return a instanceof String && b instanceof String ? eqic((String) a, (String) b) : eq(a, b); } static public Object deref(Object o) { if (o instanceof IRef) return ((IRef) o).get(); return o; } static public boolean isMD5(String s) { return l(s) == 32 && isLowerHexString(s); } static public Map synchronizedMRUCache(int maxSize) { return synchroMap(new MRUCache(maxSize)); } static public void replaceCollection(Collection dest, Collection src) { if (dest == src) return; dest.clear(); if (src != null) dest.addAll(src); } static public void replaceListPart(List l, int i, int j, List l2) { replaceSublist(l, i, j, l2); } static public Map syncMRUCache(int size) { return synchroMap(new MRUCache(size)); } static public RuntimeException wrapPatternSyntaxException(PatternSyntaxException e) { if (e == null) return null; String pat = e.getPattern(); int i = e.getIndex(); return new RuntimeException("Regular expression error between " + multiLineQuoteWithSpaces(substring(pat, 0, i)) + " and " + multiLineQuoteWithSpaces(substring(pat, i)) + " - " + e.getMessage()); } static public HashSet mapToHashSet(Object f, Iterable l) { HashSet x = new HashSet(l(l)); if (l != null) for (Object o : l) x.add(callF(f, o)); return x; } static public HashSet mapToHashSet(IF1 f, Iterable l) { return mapToHashSet((Object) f, l); } static public Producer javaTokC_noMLS_iterator(final String s) { return javaTokC_noMLS_iterator(s, 0); } static public Producer javaTokC_noMLS_iterator(final String s, final int startIndex) { return new Producer() { final public int l = s.length(); public int i = startIndex; public String next() { if (i >= l) return null; int j = i; char c, d; while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) return null; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; } else ++j; String t = quickSubstring(s, i, j); i = j; return t; } }; } static public Producer javaTokC_noMLS_onReader(final BufferedReader r) { final class X implements Producer { public StringBuilder buf = new StringBuilder(); public char c, d, e = 'x'; public X() { nc(); nc(); nc(); } public void nc() { try { c = d; d = e; if (e == '\0') return; int i = r.read(); e = i < 0 ? '\0' : i == '\0' ? '_' : (char) i; } catch (Exception __e) { throw rethrow(__e); } } public void ncSave() { if (c != '\0') { buf.append(c); nc(); } } public String next() { while (c != '\0') { if (c == ' ' || c == '\t' || c == '\r' || c == '\n') nc(); else if (c == '/' && d == '*') { do nc(); while (c != '\0' && !(c == '*' && d == '/')); nc(); nc(); } else if (c == '/' && d == '/') { do nc(); while (c != '\0' && "\r\n".indexOf(c) < 0); } else break; } if (c == '\0') return null; if (c == '\'' || c == '"') { char opener = c; ncSave(); while (c != '\0') { if (c == opener || c == '\n') { ncSave(); break; } else if (c == '\\') { ncSave(); ncSave(); } else ncSave(); } } else if (Character.isJavaIdentifierStart(c)) do ncSave(); while (Character.isJavaIdentifierPart(c) || c == '\''); else if (Character.isDigit(c)) { do ncSave(); while (Character.isDigit(c)); if (c == 'L') ncSave(); } else ncSave(); String t = buf.toString(); buf.setLength(0); return t; } } return new X(); } static public String actualMCDollar() { return actualMC().getName() + "$"; } static public String unquoteUsingCharArray(String s, char[] buf) { if (s == null) return null; if (startsWith(s, '[')) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i + 1, s.length() - i - 1); } } if (s.length() > 1) { char c = s.charAt(0); if (c == '\"' || c == '\'') { int l = endsWith(s, c) ? s.length() - 1 : s.length(); if (l > buf.length) return unquote(s); int n = 0; for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } buf[n++] = (char) Integer.parseInt(code, 8); continue; } switch(nextChar) { case '\"': ch = '\"'; break; case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\'': ch = '\''; break; case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt("" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); char[] x = Character.toChars(code); int lx = x.length; for (int j = 0; j < lx; j++) buf[n++] = x[j]; i += 5; continue; default: ch = nextChar; } i++; } buf[n++] = ch; } return new String(buf, 0, n); } } return s; } static public boolean structure_isMarker(String s, int i, int j) { if (i >= j) return false; if (s.charAt(i) != 'm') return false; ++i; while (i < j) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static public String internIfLongerThan(String s, int l) { return s == null ? null : l(s) >= l ? intern(s) : s; } static public char unquoteCharacter(String s) { assertTrue(s.startsWith("'") && s.length() > 1); return unquote("\"" + s.substring(1, s.endsWith("'") ? s.length() - 1 : s.length()) + "\"").charAt(0); } static public BigInteger parseBigInt(String s) { return new BigInteger(s); } static public float parseFloat(String s) { return Float.parseFloat(s); } static public boolean isLongConstant(String s) { if (!s.endsWith("L")) return false; s = s.substring(0, l(s) - 1); return isInteger(s); } static public List parseList(String s) { return (List) safeUnstructure(s); } static public List synchroLinkedList() { return Collections.synchronizedList(new LinkedList()); } static public NavigableMap synchroNavigableMap(NavigableMap map) { return (NavigableMap) call(Collections.class, "synchronizedNavigableMap", map); } static public SortedMap synchroSortedMap(SortedMap map) { return Collections.synchronizedSortedMap(map); } static public byte[] hexToBytes(String s) { if (odd(l(s))) throw fail("Hex string has odd length: " + quote(shorten(10, s))); int n = l(s) / 2; byte[] bytes = new byte[n]; for (int i = 0; i < n; i++) { int a = parseHexChar(s.charAt(i * 2)); int b = parseHexChar(s.charAt(i * 2 + 1)); if (a < 0 || b < 0) throw fail("Bad hex byte: " + quote(substring(s, i * 2, i * 2 + 2)) + " at " + i * 2 + "/" + l(s)); bytes[i] = (byte) ((a << 4) | b); } return bytes; } static public boolean[] boolArrayFromBytes(byte[] a, int n) { boolean[] b = new boolean[n]; int m = min(n, l(a) * 8); for (int i = 0; i < m; i++) b[i] = (a[i / 8] & 1 << (i & 7)) != 0; return b; } static public Constructor nuStubInnerObject_findConstructor(Class c) { return nuStubInnerObject_findConstructor(c, null); } static public Constructor nuStubInnerObject_findConstructor(Class c, Object classFinder) { try { Class outerType = getOuterClass(c, classFinder); Constructor m = c.getDeclaredConstructor(outerType); makeAccessible(m); return m; } catch (Exception __e) { throw rethrow(__e); } } static public void setOptAllDyn_pcall(DynamicObject o, Map fields) { if (fields == null || o == null) return; HashMap fieldMap = instanceFieldsMap(o); for (Map.Entry e : fields.entrySet()) { try { String field = e.getKey(); Object val = e.getValue(); Field f = fieldMap.get(field); if (f != null) smartSet(f, o, val); else { dynamicObject_setRawFieldValue(o, intern(field), val); } } catch (Throwable __e) { _handleException(__e); } } } static public void setOptAll_pcall(Object o, Map fields) { if (fields == null) return; for (String field : keys(fields)) try { setOpt(o, field, fields.get(field)); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } static public void setOptAll_pcall(Object o, Object... values) { warnIfOddCount(values); for (int i = 0; i + 1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i + 1]; try { setOpt(o, field, value); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } } static public void fixOuterRefs(Object o) { try { if (o == null) return; Field[] l = thisDollarOneFields(o.getClass()); if (l.length <= 1) return; Object father = null; for (Field f : l) { father = f.get(o); if (father != null) break; } if (father == null) return; for (Field f : l) f.set(o, father); } catch (Exception __e) { throw rethrow(__e); } } static public void setDynObjectValue(DynamicObject o, String field, Object value) { dynamicObject_setRawFieldValue(o, field, value); } static public String intern(String s) { return fastIntern(s); } static public void pcallOpt_noArgs(Object o, String method) { try { callOpt_noArgs(o, method); } catch (Throwable __e) { _handleException(__e); } } static public RuntimeException todo() { throw new RuntimeException("TODO"); } static public RuntimeException todo(Object msg) { throw new RuntimeException("TODO: " + msg); } static public Object newMultiDimensionalOuterArray(Class elementType, int dimensions, int length) { int[] dims = new int[dimensions]; dims[0] = length; return Array.newInstance(elementType, dims); } static public int[] toIntArray(Collection l) { int[] a = new int[l(l)]; int i = 0; if (a.length != 0) for (int x : l) a[i++] = x; return a; } static public double[] toDoubleArray(Collection l) { double[] a = new double[l(l)]; int i = 0; if (a.length != 0) for (double x : l) a[i++] = x; return a; } static public TreeSet ciSet() { return caseInsensitiveSet(); } static public boolean jmatch(String pat, String s) { return jmatch(pat, s, null); } static public boolean jmatch(String pat, String s, Matches matches) { if (s == null) return false; return jmatch(pat, javaTok(s), matches); } static public boolean jmatch(String pat, List toks) { return jmatch(pat, toks, null); } static public boolean jmatch(String pat, List toks, Matches matches) { List tokpat = javaTok(pat); String[] m = match2(tokpat, toks); if (m == null) return false; else { if (matches != null) matches.m = m; return true; } } static public Set listFields(Object c) { TreeSet fields = new TreeSet(); for (Field f : _getClass(c).getDeclaredFields()) fields.add(f.getName()); return fields; } static public String n(long l, String name) { return l + " " + trim(l == 1 ? singular(name) : getPlural(name)); } static public String n(Collection l, String name) { return n(l(l), name); } static public String n(Map m, String name) { return n(l(m), name); } static public String n(Object[] a, String name) { return n(l(a), name); } static public String n(MultiSet ms, String name) { return n(l(ms), name); } static public String _computerID; static public Lock computerID_lock = lock(); public static String computerID() { if (_computerID == null) { Lock __0 = computerID_lock; lock(__0); try { if (_computerID != null) return _computerID; File file = computerIDFile(); _computerID = loadTextFile(file.getPath()); if (_computerID == null) { _computerID = loadTextFile(userDir(".tinybrain/computer-id")); if (_computerID == null) _computerID = makeRandomID(12, new SecureRandom()); saveTextFile(file, _computerID); } } finally { unlock(__0); } } return _computerID; } static public boolean domainIsUnder(String domain, String mainDomain) { return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain); } static public String theAGIBlueDomain() { return "agi.blue"; } static public File imageSnippetCacheFile(String snippetID) { File dir = imageSnippetsCacheDir(); if (!loadBufferedImage_useImageCache) return null; return new File(dir, parseSnippetID(snippetID) + ".png"); } static public String snippetImageURL_noHttps(String snippetID) { return snippetImageURL_noHttps(snippetID, "png"); } static public String snippetImageURL_noHttps(String snippetID, String contentType) { return snippetImageURL(snippetID, contentType).replace("https://www.botcompany.de:8443/", "http://www.botcompany.de:8080/").replace("https://botcompany.de/", "http://botcompany.de/"); } static public ThreadLocal>> loadBinaryPage_responseHeaders = new ThreadLocal(); static public ThreadLocal> loadBinaryPage_extraHeaders = new ThreadLocal(); static public byte[] loadBinaryPage(String url) { try { print("Loading " + url); return loadBinaryPage(loadPage_openConnection(new URL(url))); } catch (Exception __e) { throw rethrow(__e); } } static public byte[] loadBinaryPage(URLConnection con) { try { Map extraHeaders = getAndClearThreadLocal(loadBinaryPage_extraHeaders); setHeaders(con); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); return loadBinaryPage_noHeaders(con); } catch (Exception __e) { throw rethrow(__e); } } static public byte[] loadBinaryPage_noHeaders(URLConnection con) { try { ByteArrayOutputStream buf = new ByteArrayOutputStream(); InputStream inputStream = con.getInputStream(); loadBinaryPage_responseHeaders.set(con.getHeaderFields()); long len = 0; try { len = con.getContentLength(); } catch (Throwable e) { printStackTrace(e); } int n = 0; while (true) { int ch = inputStream.read(); if (ch < 0) break; buf.write(ch); if (++n % 100000 == 0) println(" " + n + (len != 0 ? "/" + len : "") + " bytes loaded."); } inputStream.close(); return buf.toByteArray(); } catch (Exception __e) { throw rethrow(__e); } } static public File getGlobalCache() { File file = new File(javaxCachesDir(), "Binary Snippets"); file.mkdirs(); return file; } static public String dataSnippetLink(String snippetID) { long id = parseSnippetID(snippetID); if (id >= 1100000 && id < 1200000) return imageServerURL() + id; if (id >= 1200000 && id < 1300000) { String pw = muricaPassword(); if (empty(pw)) throw fail("Please set 'murica password by running #1008829"); return "https://botcompany.de/files/" + id + "?_pass=" + pw; } return fileServerURL() + "/" + id; } static public A addAndReturn(Collection c, A a) { if (c != null) c.add(a); return a; } static public void loadBinaryPageToFile(String url, File file) { try { print("Loading " + url); loadBinaryPageToFile(openConnection(new URL(url)), file); } catch (Exception __e) { throw rethrow(__e); } } static public void loadBinaryPageToFile(URLConnection con, File file) { try { setHeaders(con); loadBinaryPageToFile_noHeaders(con, file); } catch (Exception __e) { throw rethrow(__e); } } static public void loadBinaryPageToFile_noHeaders(URLConnection con, File file) { try { File ftemp = new File(f2s(file) + "_temp"); FileOutputStream buf = newFileOutputStream(mkdirsFor(ftemp)); try { InputStream inputStream = con.getInputStream(); long len = 0; try { len = con.getContentLength(); } catch (Throwable e) { printStackTrace(e); } String pat = " {*}" + (len != 0 ? "/" + len : "") + " bytes loaded."; copyStreamWithPrints(inputStream, buf, pat); inputStream.close(); buf.close(); file.delete(); renameFile_assertTrue(ftemp, file); } finally { if (buf != null) buf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public URLConnection openConnection(String url) { try { return openConnection(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static public URLConnection openConnection(URL url) { try { ping(); callOpt(javax(), "recordOpenURLConnection", str(url)); return url.openConnection(); } catch (Exception __e) { throw rethrow(__e); } } static public File standardLogFile() { return getProgramFile("log"); } static public A _recordNewSwingComponent(A c) { if (c != null) callF((Object) vm_generalMap_get("newSwingComponentRegistry"), (Object) c); return c; } static public JComponent componentToJComponent(Component c) { if (c instanceof JComponent) return (JComponent) c; if (c instanceof JFrame) return ((JFrame) c).getRootPane(); if (c == null) return null; throw fail("boohoo " + getClassName(c)); } static public JTextArea enableWordWrapForTextArea(JTextArea ta) { return enableWordWrapForTextArea(ta, true); } static public JTextArea enableWordWrapForTextArea(JTextArea ta, boolean enabled) { if (ta != null) { swing(new Runnable() { public void run() { try { ta.setLineWrap(enabled); ta.setWrapStyleWord(true); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ta.setLineWrap(enabled);\r\n ta.setWrapStyleWord(true);\r\n // Haven't foun..."; } }); } return ta; } static public JTextArea jtextarea() { return jTextArea(); } static public JTextArea jtextarea(String text) { return jTextArea(text); } static public boolean setText_opt = true; static public A setText(A c, Object text) { setText((JComponent) c, text); return c; } static public A setText(final A c, Object text) { final String s = strUnnull(text); { swing(new Runnable() { public void run() { try { c.getEditor().setItem(s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.getEditor().setItem(s);"; } }); } return c; } static public void setText(JLabel c, Object text) { setText((JComponent) c, text); } static public JButton setText(JButton c, Object text) { setText((JComponent) c, jlabel_textAsHTML_center_ifNeeded(strUnnull(text))); return c; } static public A setText(final A c, Object text) { if (c == null) return null; final String s = strUnnull(text); { swing(new Runnable() { public void run() { try { if (!setText_opt || neq(callOpt(c, "getText"), s)) call(c, "setText", s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!setText_opt || neq(callOpt(c, \"getText\"), s))\r\n call(c, \"setText\", s);"; } }); } return c; } static public JTextField onEnter(final JTextField tf, final Object action) { if (action == null || tf == null) return tf; tf.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { tf.selectAll(); callF(action); } catch (Throwable __e) { messageBox(__e); } } }); return tf; } static public JButton onEnter(JButton btn, final Object action) { if (action == null || btn == null) return btn; btn.addActionListener(actionListener(action)); return btn; } static public JList onEnter(JList list, Object action) { list.addKeyListener(enterKeyListener(rCallOnSelectedListItem(list, action))); return list; } static public JComboBox onEnter(final JComboBox cb, final Object action) { { swing(new Runnable() { public void run() { try { if (cb.isEditable()) { JTextField text = (JTextField) cb.getEditor().getEditorComponent(); onEnter(text, action); } else { cb.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); cb.getActionMap().put("enter", abstractAction("", new Runnable() { public void run() { try { cb.hidePopup(); callF(action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.hidePopup(); callF(action);"; } })); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (cb.isEditable()) {\r\n JTextField text = (JTextField) cb.getEditor().g..."; } }); } return cb; } static public JTable onEnter(final JTable table, final Object action) { table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter"); table.getActionMap().put("Enter", new AbstractAction() { public void actionPerformed(ActionEvent e) { callF(action, table.getSelectedRow()); } }); return table; } static public JTextField onEnter(Object action, JTextField tf) { return onEnter(tf, action); } static public float getSwingFontScale() { return or((Float) vm_generalMap_get("swingFontScale_value"), 1f); } static public List vmBus_queryAll(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); List out = new ArrayList(); for (Object o : unnullForIteration(vm_busListeners_live())) addIfNotNull(out, pcallF(o, msg, arg)); for (Object o : unnullForIteration(vm_busListenersByMessage_live().get(msg))) addIfNotNull(out, pcallF(o, msg, arg)); return out; } static public int toInt_checked(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static public boolean isDigit(char c) { return Character.isDigit(c); } static public List wrapAsList(A[] a) { return wrapArrayAsList(a); } static public List sortedByComparator(Collection l, Comparator c) { List l2 = cloneList(l); sort(l2, c); return l2; } static public List sortedByComparator(Comparator c, Collection l) { return sortedByComparator(l, c); } static public List buttonsInGroup(ButtonGroup g) { if (g == null) return ll(); return asList(g.getElements()); } static public int indexOfSubList(List x, List y) { return indexOfSubList(x, y, 0); } static public int indexOfSubList(List x, List y, int i) { outer: for (; i + l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i + j), y.get(j))) continue outer; return i; } return -1; } static public int indexOfSubList(List x, A[] y, int i) { outer: for (; i + l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i + j), y[j])) continue outer; return i; } return -1; } static public void copyListPart(List a, int i1, List b, int i2, int n) { if (a == null || b == null) return; for (int i = 0; i < n; i++) b.set(i2 + i, a.get(i1 + i)); } static public boolean isDollarVar(String s) { return startsWith(s, '$') && l(s) > 1; } static public void listAdd(Collection c, A a) { if (c != null) c.add(a); } static public boolean neqGet(List l, int i, Object o) { return neq(get(l, i), o); } static public int tok_findEndOfStatement(List tok, int i) { if (eq(get(tok, i), "{")) return findEndOfBlock(tok, i); int j = i; boolean special = false; while (j < l(tok) && neq(tok.get(j), ";")) { String t = get(tok, j); if (eqOneOf(t, "for", "if")) special = true; if (eqOneOf(t, "{", "(")) { j = findEndOfBracketPart(tok, j) + 1; if (special && eq(t, "{")) return j - 1; } else j += 2; } return j + 1; } static public void tokPrepend_reTok(List tok, int i, String s) { tokPrepend(tok, i, s); reTok(tok, i, i + 1); } static public File oneOfTheFiles(String... paths) { if (paths != null) for (String path : paths) if (fileExists(path)) return newFile(path); return null; } static public File oneOfTheFiles(File... files) { return oneOfTheFiles(asList(files)); } static public File oneOfTheFiles(Iterable files) { if (files != null) for (File f : files) if (fileExists(f)) return f; return null; } static public String joinLines(List lines) { return fromLines(lines); } static public String joinLines(String glue, String text) { return join(glue, toLines(text)); } static public String javaDropComments(String s) { return javaDropAllComments(s); } static public void clear(Collection c) { if (c != null) c.clear(); } static public void clear(Map map) { if (map != null) map.clear(); } static public List _registerDangerousWeakMap_preList; static public A _registerDangerousWeakMap(A map) { return _registerDangerousWeakMap(map, null); } static public A _registerDangerousWeakMap(A map, Object init) { callF(init, map); if (init instanceof String) { final String f = (String) init; init = new VF1() { public void get(Map map) { try { callMC(f, map); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callMC(f, map)"; } }; } if (javax() == null) { if (_registerDangerousWeakMap_preList == null) _registerDangerousWeakMap_preList = synchroList(); _registerDangerousWeakMap_preList.add(pair(map, init)); return map; } call(javax(), "_registerDangerousWeakMap", map, init); return map; } static public void _onLoad_registerDangerousWeakMap() { assertNotNull(javax()); if (_registerDangerousWeakMap_preList == null) return; for (Pair p : _registerDangerousWeakMap_preList) _registerDangerousWeakMap(p.a, p.b); _registerDangerousWeakMap_preList = null; } static public B syncMapGet2(Map map, A a) { if (map == null) return null; synchronized (collectionMutex(map)) { return map.get(a); } } static public B syncMapGet2(A a, Map map) { return syncMapGet2(map, a); } static public boolean isSubtypeOf(Class a, Class b) { return b.isAssignableFrom(a); } static public Set reflection_classesNotToScan_value = litset("jdk.internal.loader.URLClassPath"); static public Set reflection_classesNotToScan() { return reflection_classesNotToScan_value; } static public List dm_moduleIDs() { return dm_listModuleIDs(); } static public Object dm_getStem(Object moduleOrID) { if (isString(moduleOrID) && isIdentifier(((String) moduleOrID))) moduleOrID = dm_getService(((String) moduleOrID)); if (isStringOrIntOrLong(moduleOrID)) return dm_getStemByID(moduleOrID); return or(getOpt(dm_getModule(moduleOrID), "_host"), moduleOrID); } static public AlphanumComparator alphaNumComparator_instance; static public Comparator alphaNumComparator() { if (alphaNumComparator_instance == null) alphaNumComparator_instance = new AlphanumComparator(); return alphaNumComparator_instance; } static public boolean shortClassNameIs(Object o, String name) { return eq(shortClassName(o), name); } static public boolean shortClassNameIs(String name, Object o) { return shortClassNameIs(o, name); } static public AutoCloseable tempActivity(Object r) { return null; } static public long fixTimestamp(long timestamp) { return timestamp > now() ? 0 : timestamp; } static public Object costCenter() { return mc(); } static public ThreadLocal saveTiming_last = new ThreadLocal(); static public void saveTiming(long ms) { print(ms + " ms"); saveTiming_noPrint(ms); } static public void saveTiming_noPrint(long ms) { saveTiming_last.set(ms); } static public ThreadLocal saveTiming_tl() { return saveTiming_last; } static public String nullIfEmpty(String s) { return isEmpty(s) ? null : s; } static public Map nullIfEmpty(Map map) { return isEmpty(map) ? null : map; } static public List nullIfEmpty(List l) { return isEmpty(l) ? null : l; } static public boolean newButton_autoToolTip = true; static public JButton newButton(final String text, final Object action) { return swing(new F0() { public JButton get() { try { String text2 = dropPrefix("[disabled] ", text); final JButton btn = new JButton(text2); if (l(text2) < l(text)) btn.setEnabled(false); if (newButton_autoToolTip) { btn.setToolTipText(btn.getText()); } if (action != null) btn.addActionListener(actionListener(action, btn)); return btn; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S text2 = dropPrefix(\"[disabled] \", text);\r\n final JButton btn = new JButt..."; } }); } static public A swingNu(final Class c, final Object... args) { return swingConstruct(c, args); } static public Object[] asArray(List l) { return toObjectArray(l); } static public A[] asArray(Class type, List l) { return (A[]) l.toArray((Object[]) Array.newInstance(type, l.size())); } static public boolean isMenuSeparatorIndicator(Object o) { return eqOneOf(o, "***", "---", "===", ""); } static public boolean isRunnableX(Object o) { if (o == null) return false; if (o instanceof String) return hasMethod(mc(), (String) o); return o instanceof Runnable || hasMethod(o, "get"); } static public boolean jmenuItem_newThreads = false; static public JMenuItem jmenuItem(final String text) { return jMenuItem(text, null); } static public JMenuItem jmenuItem(final String text, final Object r) { return swing(new F0() { public JMenuItem get() { try { Pair p = jmenu_autoMnemonic(dropPrefix("[disabled] ", text)); JMenuItem mi = new JMenuItem(p.a); if (startsWith(text, "[disabled] ")) disableMenuItem(mi); if (p.b != 0) mi.setMnemonic(p.b); mi.addActionListener(jmenuItem_newThreads ? actionListenerInNewThread(r) : actionListener(r)); return mi; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Pair p = jmenu_autoMnemonic(dropPrefix(\"[disabled] \", text));\r\n JM..."; } }); } static public A bindLiveValueListenerToComponent(A component, final LiveValue lv, final Runnable listener) { if (lv != null) bindToComponent(component, new Runnable() { public void run() { try { lv.onChangeAndNow(listener); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef bindLiveValueListenerToComponent_debug\r\n print(\"bindLiveValueL..."; } }, new Runnable() { public void run() { try { lv.removeOnChangeListener(listener); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "lv.removeOnChangeListener(listener)"; } }); return component; } static public boolean isCurlyBracketed(String s) { return isCurlyBraced(s); } static public A setEnabled(A c, boolean enable) { if (c != null) { swing(new Runnable() { public void run() { try { c.setEnabled(enable); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setEnabled(enable);"; } }); } return c; } static public A setEnabled(boolean enable, A c) { return setEnabled(c, enable); } static public String unCurlyBracket(String s) { return tok_unCurlyBracket(s); } static public int preferredWidth(Component c) { return c == null ? 0 : getPreferredSize(c).width; } static public String formatDate() { return formatDate(now()); } static public String formatDate(long timestamp) { return timestamp == 0 ? "-" : str(new Date(timestamp)); } static public String formatDate(long timestamp, String format, TimeZone tz) { return simpleDateFormat(format, tz).format(timestamp); } static public File dirOfFile(File f) { return f == null ? null : f.getParentFile(); } static public int localYear() { return localYear(now()); } static public int localYear(long time) { return parseInt(simpleDateFormat_local("yyyy").format(time)); } static public String padLeft(String s, char c, int n) { return rep(c, n - l(s)) + s; } static public String padLeft(String s, int n) { return padLeft(s, ' ', n); } static public int localMonth(long time) { return parseInt(simpleDateFormat_local("MM").format(time)); } static public int localMonth() { return localMonth(now()); } static public int localDayOfMonth(long time) { return parseInt(simpleDateFormat_local("dd").format(time)); } static public int localDayOfMonth() { return localDayOfMonth(now()); } static public boolean isStringStartingWith(Object o, String prefix) { return o instanceof String && ((String) o).startsWith(prefix); } static public Object getConsoleTextArea_gen() { return getOpt(get(getJavaX(), "console"), "textArea"); } static public JTextField consoleInputField() { Object console = get(getJavaX(), "console"); return (JTextField) getOpt(console, "tfInput"); } static public void revalidateFrame(Component c) { revalidate(getFrame(c)); } static public TimeZone localTimeZone() { return getTimeZone(standardTimeZone()); } static public String hijackPrint(Runnable r) { return hijackPrint((Object) r); } static public String hijackPrint(Object r) { final StringBuilder buf = new StringBuilder(); Object old = interceptPrintInThisThread(new F1() { public Boolean get(String s) { buf.append(s); return false; } }); try { callF(r); return str(buf); } finally { interceptPrintInThisThread(old); } } static public Map> multiMapToMap(MultiMap m) { return m == null ? null : m.data; } static public String base64encode(byte[] a) { int aLen = a.length; int numFullGroups = aLen / 3; int numBytesInPartialGroup = aLen - 3 * numFullGroups; int resultLen = 4 * ((aLen + 2) / 3); StringBuffer result = new StringBuffer(resultLen); char[] intToAlpha = intToBase64; int inCursor = 0; for (int i = 0; i < numFullGroups; i++) { int byte0 = a[inCursor++] & 0xff; int byte1 = a[inCursor++] & 0xff; int byte2 = a[inCursor++] & 0xff; result.append(intToAlpha[byte0 >> 2]); result.append(intToAlpha[(byte0 << 4) & 0x3f | (byte1 >> 4)]); result.append(intToAlpha[(byte1 << 2) & 0x3f | (byte2 >> 6)]); result.append(intToAlpha[byte2 & 0x3f]); } if (numBytesInPartialGroup != 0) { int byte0 = a[inCursor++] & 0xff; result.append(intToAlpha[byte0 >> 2]); if (numBytesInPartialGroup == 1) { result.append(intToAlpha[(byte0 << 4) & 0x3f]); result.append("=="); } else { int byte1 = a[inCursor++] & 0xff; result.append(intToAlpha[(byte0 << 4) & 0x3f | (byte1 >> 4)]); result.append(intToAlpha[(byte1 << 2) & 0x3f]); result.append('='); } } return result.toString(); } static final public char[] intToBase64 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; static public TreeSet toCaseInsensitiveSet_treeSet(Iterable c) { if (isCISet(c)) return (TreeSet) c; TreeSet set = caseInsensitiveSet_treeSet(); addAll(set, c); return set; } static public TreeSet toCaseInsensitiveSet_treeSet(String... x) { TreeSet set = caseInsensitiveSet_treeSet(); addAll(set, x); return set; } static public A findWhere(Collection c, Object... data) { if (c != null) for (A x : c) if (checkFields(x, data)) return x; return null; } static public boolean isOK(String s) { s = trim(s); return swic(s, "ok ") || eqic(s, "ok") || matchStart("ok", s); } static public String sendOpt(String bot, String text, Object... args) { return sendToLocalBotOpt(bot, text, args); } static public boolean isMainProgram() { return creator() == null; } static public void cleanKill() { cleanKillVM(); } static public String dbBotName(String progIDWithCase) { return fsI_flex(progIDWithCase) + " Concepts"; } static public Android3 methodsBot2(String name, final Object receiver, final List exposedMethods) { return methodsBot2(name, receiver, exposedMethods, null); } static public Android3 methodsBot2(String name, final Object receiver, final List exposedMethods, final Lock lock) { Android3 android = new Android3(); android.greeting = name; android.console = false; android.responder = new Responder() { public String answer(String s, List history) { return exposeMethods2(receiver, s, exposedMethods, lock); } }; return makeBot(android); } static public List db_standardExposedMethods_list = ll("xlist", "xnew", "xset", "xdelete", "xget", "xclass", "xfullgrab", "xshutdown", "xchangeCount", "xcount"); static public List db_standardExposedMethods() { return db_standardExposedMethods_list; } static public List listFilesNotDirs(String dir) { return listFilesOnly(dir); } static public List listFilesNotDirs(File... dirs) { return listFilesOnly(dirs); } static public int matcherInt(Matcher m, int i) { return parseInt(m.group(i)); } static public long timestampFromYMDHM(int y, int m, int d, int h, int minutes) { return new GregorianCalendar(y, m - 1, d, h, minutes).getTimeInMillis(); } static public List sortByMap_inPlace(List l, Map map) { sort(l, mapComparator(map)); return l; } static public boolean defaultAgeBasedBackupRetentionStrategy_shouldKeep(double age, double lastAge) { if (age <= 1 / 12.0) return true; if (age <= 0.5 && age >= lastAge + 1 / 12.0) return true; if (age <= 7 && age >= lastAge + 1) return true; if (age <= 28 && age >= lastAge + 7) return true; if (age >= lastAge + 365.0 / 12) return true; return false; } static public String dropFrom(String s, String x) { if (s == null) return null; int i = s.indexOf(x); if (i < 0) return s; return substring(s, 0, i); } static public B getOrCreate(Map map, A key, Class c) { try { B b = map.get(key); if (b == null) map.put(key, b = c.newInstance()); return b; } catch (Exception __e) { throw rethrow(__e); } } static public B getOrCreate(Map map, A key, Object f) { try { B b = map.get(key); if (b == null) map.put(key, b = (B) callF(f)); return b; } catch (Exception __e) { throw rethrow(__e); } } static public B getOrCreate(IF0 f, Map map, A key) { return getOrCreate(map, key, f); } static public B getOrCreate(Map map, A key, IF0 f) { B b = map.get(key); if (b == null) map.put(key, b = f.get()); return b; } static public B getOrCreate(Class c, Map map, A key) { return getOrCreate(map, key, c); } static public boolean directoryIsEmpty(File f) { return !fileExists(f) || isDirectory(f) && empty(listFiles(f)); } static public void zip2dir(File inZip, String outDir) { zip2dir(inZip, newFile(outDir)); } static public void zip2dir(File inZip, File outDir) { zip2dir(inZip, outDir, ""); } static public void zip2dir(File inZip, String outDir, String prefix) { zip2dir(inZip, newFile(outDir), prefix); } static public void zip2dir(File inZip, File outDir, String prefix) { try { if (prefix.length() != 0 && !prefix.endsWith("/")) prefix += "/"; ZipFile zipFile = new ZipFile(inZip); try { Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry) entries.nextElement(); if (entry.isDirectory()) continue; if (!entry.getName().startsWith(prefix)) continue; File outFile = new File(outDir, entry.getName()); print("Unzipping " + entry.getName() + " to " + outFile.getAbsolutePath()); stream2file(zipFile.getInputStream(entry), outFile); } } finally { _close(zipFile); } } catch (Exception __e) { throw rethrow(__e); } } static public RandomAccessFile randomAccessFileForReading(File path) { try { return newRandomAccessFile(path, "r"); } catch (Exception __e) { throw rethrow(__e); } } static public long raf_findBeginningOfLine(RandomAccessFile raf, long pos, int bufSize) { try { byte[] buf = new byte[bufSize]; while (pos > 0) { long start = Math.max(pos - bufSize, 0); raf.seek(start); raf.readFully(buf, 0, (int) Math.min(pos - start, bufSize)); int idx = lastIndexOf_byteArray(buf, (byte) '\n'); if (idx >= 0) return start + idx + 1; pos = start; } return 0; } catch (Exception __e) { throw rethrow(__e); } } static public long raf_findEndOfLine(RandomAccessFile raf, long pos, int bufSize) { try { byte[] buf = new byte[bufSize]; long length = raf.length(); while (pos < length) { raf.seek(pos); raf.readFully(buf, 0, (int) Math.min(length - pos, bufSize)); int idx = indexOf_byteArray(buf, (byte) '\n'); if (idx >= 0) return pos + idx + 1; pos += bufSize; } return length; } catch (Exception __e) { throw rethrow(__e); } } static public String fromUtf8(byte[] bytes) { try { return bytes == null ? null : new String(bytes, utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } static public byte[] raf_readFilePart(RandomAccessFile raf, long start, int l) { try { byte[] buf = new byte[l]; raf.seek(start); raf.readFully(buf); return buf; } catch (Exception __e) { throw rethrow(__e); } } static public A assertLessThan(A a, A b) { assertTrue(cmp(b, a) < 0); return b; } static public A assertBiggerThan(A a, A b) { assertTrue(cmp(b, a) > 0); return b; } static public String trimJoinSubList(List l, int i, int j) { return trim(join(subList(l, i, j))); } static public String trimJoinSubList(List l, int i) { return trim(join(subList(l, i))); } static public Matcher regexpMatcherIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static public String regexpReplaceIC_direct(String s, String pat, String replacement) { Matcher m = regexpIC(pat, s); StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, replacement); m.appendTail(buf); return str(buf); } static public A componentPopupMenuItem(A c, final String name, final Object action) { componentPopupMenu(c, new VF1() { public void get(JPopupMenu menu) { try { addMenuItem(menu, name, action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, name, action);"; } }); return c; } static public void componentPopupMenuItem(JComponent c, final JMenuItem menuItem) { componentPopupMenu(c, new VF1() { public void get(JPopupMenu menu) { try { addMenuItem(menu, menuItem); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, menuItem);"; } }); } static public String copyTextToClipboard(Object _text) { String text = str(_text); StringSelection selection = new StringSelection(text); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); vmBus_send("newClipboardContents", text); return text; } static public Set vm_generalWeakSet(Object name) { synchronized (get(javax(), "generalMap")) { Set set = (Set) (vm_generalMap_get(name)); if (set == null) vm_generalMap_put(name, set = newWeakHashSet()); return set; } } static public AbstractAction abstractAction(String name, final Object runnable) { return new AbstractAction(name) { public void actionPerformed(ActionEvent evt) { pcallF(runnable); } }; } static public JPanel jpanel(LayoutManager layout) { return swingNu(JPanel.class, layout); } static public JPanel jpanel() { return swingNu(JPanel.class); } static public LayoutManager layoutManagerFromFunction(final Object layouter) { return new AbstractLayoutManager() { public void layoutContainer(Container parent) { Object size = pcallF(layouter, parent); if (size instanceof Dimension) preferredSize = (Dimension) size; else if (size instanceof Pair) { preferredSize = (Dimension) ((Pair) size).a; minimumSize = (Dimension) ((Pair) size).b; } } }; } static public A addAllComponents(final A c, final List components) { if (nempty(components)) { swing(new Runnable() { public void run() { try { for (Component x : components) c.add(x); revalidate(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (Component x : components)\r\n c.add(x);\r\n revalidate(c);"; } }); } return c; } static public A childOfType(Component c, Class theClass) { return first(childrenOfType(c, theClass)); } static public A childOfType(Class theClass, Component c) { return childOfType(c, theClass); } static public Rectangle rectangleUnion(Rectangle a, Rectangle b) { return a == null ? b : b == null ? a : a.union(b); } static public void messageBox(final String msg) { if (headless()) print(msg); else { swing(new Runnable() { public void run() { try { JOptionPane.showMessageDialog(null, msg, "JavaX", JOptionPane.INFORMATION_MESSAGE); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JOptionPane.showMessageDialog(null, msg, \"JavaX\", JOptionPane.INFORMATION_MES..."; } }); } } static public void messageBox(Throwable e) { printStackTrace(e); messageBox(hideCredentials(innerException2(e))); } static public Lock downloadLock_lock = fairLock(); static public Lock downloadLock() { return downloadLock_lock; } static public String getSnippetTitleOpt(String s) { return isSnippetID(s) ? getSnippetTitle(s) : s; } static public List childrenOfType(Component c, Class theClass) { List l = new ArrayList(); scanForComponents(c, theClass, l); return l; } static public List childrenOfType(Class theClass, Component c) { return childrenOfType(c, theClass); } static public JButton findButton(Component c, String name) { for (JButton b : childrenOfType(c, JButton.class)) if (eq(b.getText(), name)) return b; for (JButton b : childrenOfType(getFrame(c), JButton.class)) if (eq(b.getText(), name)) return b; return null; } static public JButton findButton(Component c) { return childOfType(c, JButton.class); } static public boolean isSpace(char c) { return " \t\r\n".indexOf(c) >= 0; } static public void putIfNotThere(Map map, A key, B value) { if (map != null && key != null && value != null && !map.containsKey(key)) map.put(key, value); } static public boolean isLetterOrDigit(char c) { return Character.isLetterOrDigit(c); } static public int indent_default = 2; static public String indent(int indent) { return repeat(' ', indent); } static public String indent(int indent, String s) { return indent(repeat(' ', indent), s); } static public String indent(String indent, String s) { return indent + s.replace("\n", "\n" + indent); } static public String indent(String s) { return indent(indent_default, s); } static public List indent(String indent, List lines) { List l = new ArrayList(); if (lines != null) for (String s : lines) l.add(indent + s); return l; } static public Set cloneSet(Collection set) { if (set == null) return new HashSet(); synchronized (collectionMutex(set)) { Set s = similarEmptySet(set); s.addAll(set); return s; } } static public String structure_addTokenMarkers(String s) { return join(structure_addTokenMarkers(javaTokForStructure(s))); } static public List structure_addTokenMarkers(List tok) { TreeSet refs = new TreeSet(); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("t") && isInteger(t.substring(1))) refs.add(parseInt(t.substring(1))); } if (empty(refs)) return tok; for (int i : refs) { int idx = i * 2 + 1; if (idx >= l(tok)) continue; String t = ""; if (endsWithLetterOrDigit(tok.get(idx - 1))) t = " "; tok.set(idx, t + "m" + i + " " + tok.get(idx)); } return tok; } static public List tok_combineRoundBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eq(t, "(")) { int j = findEndOfBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public boolean startsWithAndEndsWith(String s, String prefix, String suffix) { return startsWith(s, prefix) && endsWith(s, suffix); } static public List tok_combineRoundOrCurlyBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eqOneOf(t, "{", "(")) { int j = findEndOfBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public int defaultTokenizerCacheSize() { return 1000; } static public List javaTokWithAllBrackets(String s) { return javaTokPlusBrackets2(s); } static public String trimJoin(List s) { return trim(join(s)); } static public boolean containsRegexpIC(String s, String pat) { return compileRegexpIC(pat).matcher(s).find(); } static public String phraseToRegExp(String b) { return (startsWithLetterOrDigit(b) ? "\\b" : "") + regexpQuote(b) + (endsWithLetterOrDigit(b) ? "\\b" : ""); } static public boolean match3(String pat, String s) { return match3(pat, s, null); } static public boolean match3(String pat, String s, Matches matches) { if (pat == null || s == null) return false; return match3(pat, parse3_cachedInput(s), matches); } static public boolean match3(String pat, List toks, Matches matches) { List tokpat = parse3_cachedPattern(pat); return match3(tokpat, toks, matches); } static public boolean match3(List tokpat, List toks, Matches matches) { String[] m = match2(tokpat, toks); if (m == null) return false; if (matches != null) matches.m = m; return true; } static public boolean matchStart(String pat, String s) { return matchStart(pat, s, null); } static public boolean matchStart(String pat, String s, Matches matches) { if (s == null) return false; return matchStart(pat, parse3_cachedInput(s), matches); } static public boolean matchStart(String pat, List toks, Matches matches) { if (toks == null) return false; List tokpat = parse3_cachedPattern(pat); if (toks.size() < tokpat.size()) return false; String[] m = match2(tokpat, toks.subList(0, tokpat.size())); if (m == null) return false; if (matches != null) { matches.m = new String[m.length + 1]; arraycopy(m, matches.m); matches.m[m.length] = joinSubList(toks, tokpat.size(), toks.size()); } return true; } static public boolean matchEnd(String pat, String s) { return matchEnd(pat, s, null); } static public boolean matchEnd(String pat, String s, Matches matches) { if (s == null) return false; List tokpat = parse3(pat), toks = parse3(s); if (toks.size() < tokpat.size()) return false; String[] m = match2(tokpat, takeLast(l(tokpat), toks)); if (m == null) return false; if (matches != null) { matches.m = new String[m.length + 1]; arraycopy(m, matches.m); matches.m[m.length] = join(dropLast(l(tokpat), toks)); } return true; } static public Map> parse3_cachedInput_cache = synchronizedMRUCache(1000); static public List parse3_cachedInput(String s) { List tok = parse3_cachedInput_cache.get(s); if (tok == null) parse3_cachedInput_cache.put(s, tok = parse3(s)); return tok; } static public Map> parse3_cachedPattern_cache = synchronizedMRUCache(1000); static synchronized public List parse3_cachedPattern(String s) { List tok = parse3_cachedPattern_cache.get(s); if (tok == null) parse3_cachedPattern_cache.put(s, tok = parse3(s)); return tok; } static public String[] find2(List pat, List tok) { for (int idx = 0; idx < tok.size(); idx += 2) { String[] result = find2(pat, tok, idx); if (result != null) return result; } return null; } static public String[] find2(List pat, List tok, int idx) { if (idx + pat.size() > tok.size()) return null; List result = new ArrayList(); for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(idx + i); if (eq(p, "*")) result.add(t); else if (!p.equalsIgnoreCase(t)) return null; } return toStringArray(result); } static public int levenWithSwapsIC(String s, String t) { if (s.equals(t)) return 0; int ls = s.length(), lt = t.length(); if (ls == 0) return lt; if (lt == 0) return ls; int[] vx = new int[lt + 1]; int[] v0 = new int[lt + 1]; int[] v1 = new int[lt + 1]; for (int i = 0; i < v0.length; i++) v0[i] = i; for (int i = 0; i < ls; i++) { v1[0] = i + 1; for (int j = 0; j < lt; j++) { int cost = equalsIgnoreCase(s.charAt(i), t.charAt(j)) ? 0 : 1; int d = min3(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost); if (i > 0 && j > 0 && equalsIgnoreCase(s.charAt(i), t.charAt(j - 1)) && equalsIgnoreCase(s.charAt(i - 1), t.charAt(j))) d = min(d, vx[j - 1] + 1); v1[j + 1] = d; } int[] v = vx; vx = v0; v0 = v1; v1 = v; } return v0[lt]; } static public void setOptIfNotNull(Object o, String field, Object value) { if (value != null) setOpt(o, field, value); } static public void selectRow(final JTable table, final int i) { if (table != null) { swing(new Runnable() { public void run() { try { if (i >= 0 && i < table.getRowCount()) { table.setRowSelectionInterval(i, i); scrollRowToVisible(table, i); } else table.clearSelection(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (i >= 0 && i < table.getRowCount()) {\r\n table.setRowSelectionInterval..."; } }); } } static public void selectRow(final JList list, final int i) { if (list != null) { swing(new Runnable() { public void run() { try { if (i >= 0 && i < listRowCount(list)) list.setSelectedIndex(i); else list.clearSelection(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (i >= 0 && i < listRowCount(list))\r\n list.setSelectedIndex(i);\r\n e..."; } }); } } static public int jlist_indexOf(JList list, A item) { return swing(new F0() { public Integer get() { try { ListModel model = list.getModel(); int n = model.getSize(); for (int i = 0; i < n; i++) if (eq(model.getElementAt(i), item)) return i; return -1; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ListModel model = list.getModel();\r\n int n = model.getSize();\r\n for ..."; } }); } static public ThreadLocal addInternalFrame_dontSelect = new ThreadLocal(); static public ThreadLocal addInternalFrame_layer = new ThreadLocal(); static public ThreadLocal addInternalFrame_toBack = new ThreadLocal(); static public JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final int x, final int y, final int w, final int h) { return addInternalFrame(desktop, title, x, y, w, h, null); } static public JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final int x, final int y, final int w, final int h, final Component contents) { return addInternalFrame(desktop, title, rect(x, y, w, h), contents); } static public JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final Component contents) { return addInternalFrame(desktop, title, null, contents); } static public JInternalFrame addInternalFrame(final JDesktopPane desktop, final String title, final Rect r, final Component contents) { final boolean dontSelect = isTrue(optParam(addInternalFrame_dontSelect)); final boolean toBack = isTrue(optParam(addInternalFrame_toBack)); final Integer layer = optParam(addInternalFrame_layer); return swing(new F0() { public JInternalFrame get() { try { JInternalFrame frame; if (contents instanceof JInternalFrame) frame = (JInternalFrame) contents; else { frame = jInternalFrame(title); setInternalFrameContents(frame, contents); } frame.setVisible(true); desktop.add(frame, layer); if (r != null) setBounds(frame, r); else internalFrameDefaultPosition(frame); if (dontSelect) if (toBack) frame.toBack(); else frame.toFront(); else frame.setSelected(true); return fixInternalFrame(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JInternalFrame frame;\r\n if (contents instanceof JInternalFrame)\r\n fra..."; } }); } static public JInternalFrame addInternalFrame(JDesktopPane desktop, String title) { return addInternalFrame(desktop, title, jpanel()); } static public JInternalFrame minInternalFrameWidth(final JInternalFrame frame, final int w) { { swing(new Runnable() { public void run() { try { if (frame != null && frame.getWidth() < w) frame.setSize(w, frame.getHeight()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (frame != null && frame.getWidth() < w)\r\n frame.setSize(w, frame.getH..."; } }); } return frame; } static public JInternalFrame minInternalFrameWidth(int w, JInternalFrame frame) { return minInternalFrameWidth(frame, w); } static public A packInternalFrameVertically(A c) { return packInternalFrameVertically(-1, c); } static public A packInternalFrameVertically(int width, A c) { final JInternalFrame win = getInternalFrame(c); if (win == null) return c; final int w = width < 0 ? win.getWidth() : width; { swing(new Runnable() { public void run() { try { win.pack(); win.setSize(w, win.getHeight()); fixInternalFrame(win); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "win.pack();\r\n win.setSize(w, win.getHeight());\r\n fixInternalFrame(win);"; } }); } return c; } static public JInternalFrame centerInternalFrame(final JInternalFrame f) { { swing(new Runnable() { public void run() { try { Container c = f.getParent(); if (c != null) { f.setLocation((c.getWidth() - f.getWidth()) / 2, (c.getHeight() - f.getHeight()) / 2); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Container c = f.getParent();\r\n if (c != null) {\r\n //print(\"Container ..."; } }); } return f; } static public JInternalFrame centerInternalFrame(final int w, final int h, final JInternalFrame f) { { swing(new Runnable() { public void run() { try { f.setSize(w, h); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.setSize(w, h);"; } }); } return centerInternalFrame(f); } static public int packFrame_minw = 150, packFrame_minh = 50; static public A packFrame(final A c) { { swing(new Runnable() { public void run() { try { Window w = getWindow(c); if (w != null) { w.pack(); int maxW = getScreenWidth() - 50, maxH = getScreenHeight() - 50; w.setSize(min(maxW, max(w.getWidth(), packFrame_minw)), min(maxH, max(w.getHeight(), packFrame_minh))); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Window w = getWindow(c);\r\n if (w != null) {\r\n w.pack();\r\n int ma..."; } }); } return c; } static public JFrame packFrame(ButtonGroup g) { return packFrame(getFrame(g)); } static public JFrame showFrame() { return makeFrame(); } static public JFrame showFrame(Object content) { return makeFrame(content); } static public JFrame showFrame(String title) { return makeFrame(title); } static public JFrame showFrame(String title, Object content) { return makeFrame(title, content); } static public JFrame showFrame(final JFrame f) { if (f != null) { swing(new Runnable() { public void run() { try { if (frameTooSmall(f)) frameStandardSize(f); if (!f.isVisible()) f.setVisible(true); if (f.getState() == Frame.ICONIFIED) f.setState(Frame.NORMAL); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (frameTooSmall(f)) frameStandardSize(f);\r\n if (!f.isVisible()) f.setVis..."; } }); } return f; } static public JFrame showFrame(String title, Object content, JFrame frame) { if (frame == null) return showFrame(title, content); else { frame.setTitle(title); setFrameContents(frame, content); return frame; } } static public > void forEachLevel2(Iterable l, IVF1 f) { if (l != null) for (B b : l) forEach(b, f); } static public > void forEachLevel2(IVF1 f, Iterable l) { forEachLevel2(f, l); } static public Dimension getMinimumSize(final Component c) { return c == null ? null : swing(new F0() { public Dimension get() { try { return c.getMinimumSize(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getMinimumSize();"; } }); } static public A jPreferWidth(int w, A c) { Dimension size = c.getPreferredSize(); c.setPreferredSize(new Dimension(w, size.height)); return c; } static public Component wrapForSmartAdd(Object o) { if (o == null) return jpanel(); if (o instanceof String) return jlabel((String) o); return wrap(o); } static public boolean containsSpace(String s) { return containsSpaces(s); } static public String firstToUpper(String s) { if (empty(s)) return s; return Character.toUpperCase(s.charAt(0)) + s.substring(1); } static public List replaceElementsUsingMap(Iterable l, final Map map) { return map(l, new F1() { public A get(A a) { try { return getOrKeep(map, a); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getOrKeep(map, a)"; } }); } static public List splitCamelCase(String s) { return ai_splitCamelCase(s); } static public boolean hasMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args) != null; } static public JInternalFrame getInternalFrame(final Object _o) { return _o == null ? null : swing(new F0() { public JInternalFrame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof JInternalFrame) return (JInternalFrame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n if (o instanceof ButtonGroup) o = first(buttonsInGroup((Button..."; } }); } static public List allChildren(Component c) { return childrenOfType(c, Component.class); } static public void onEnterIfTextField(Component c, Object action) { if (action == null) return; if (c instanceof JTextField) onEnter((JTextField) c, action); else if (c instanceof JComboBox) onEnter((JComboBox) c, action); } static public Object[] flattenArray2(Object... a) { List l = new ArrayList(); if (a != null) for (Object x : a) if (x instanceof Object[]) l.addAll(asList((Object[]) x)); else if (x instanceof Collection) l.addAll((Collection) x); else l.add(x); return asObjectArray(l); } static public void listThreadLocalAdd(ThreadLocal> tl, A a) { List l = tl.get(); if (l == null) tl.set(l = new ArrayList()); l.add(a); } static public A listThreadLocalPopLast(ThreadLocal> tl) { List l = tl.get(); if (l == null) return null; A a = popLast(l); if (empty(l)) tl.set(null); return a; } static public IterableIterator iteratorFromFunction_withEndMarker_f0(final F0 f) { class IFF2 extends IterableIterator { public A a; public boolean have, done; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; have = false; return _a; } public void getNext() { if (done || have) return; Object o = f.get(); if (o == iteratorFromFunction_endMarker) { done = true; return; } a = (A) o; have = true; } } ; return new IFF2(); } static public WeakReference creator_class; static public Object creator() { return creator_class == null ? null : creator_class.get(); } static public Object pcallFAll_returnFirstNotNull(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) { Object __1 = pcallF(f, args); if (__1 != null) return __1; } return null; } static public Object pcallFAll_returnFirstNotNull(Iterator it, Object... args) { while (it.hasNext()) { Object __2 = pcallF(it.next(), args); if (__2 != null) return __2; } return null; } static public String assertIsIdentifier(String s) { if (!isIdentifier(s)) throw fail("Not an identifier: " + quote(s)); return s; } static public String assertIsIdentifier(String msg, String s) { if (!isIdentifier(s)) throw fail(msg + " - Not an identifier: " + quote(s)); return s; } static public String collapseWord(String s) { if (s == null) return ""; StringBuilder buf = new StringBuilder(); for (int i = 0; i < l(s); i++) if (i == 0 || !charactersEqualIC(s.charAt(i), s.charAt(i - 1))) buf.append(s.charAt(i)); return buf.toString(); } static public List toLowerCase(List strings) { List x = new ArrayList(); for (String s : strings) x.add(s.toLowerCase()); return x; } static public String[] toLowerCase(String[] strings) { String[] x = new String[l(strings)]; for (int i = 0; i < l(strings); i++) x[i] = strings[i].toLowerCase(); return x; } static public String toLowerCase(String s) { return s == null ? "" : s.toLowerCase(); } static public String firstWord2(String s) { s = xltrim(s); if (empty(s)) return ""; if (isLetterOrDigit(first(s))) return takeCharsWhile(__97 -> isLetterOrDigit(__97), s); else return "" + first(s); } static public boolean endsWithIgnoreCase(String a, String b) { int la = l(a), lb = l(b); return la >= lb && regionMatchesIC(a, la - lb, b, 0, lb); } static public boolean endsWithIgnoreCase(String a, String b, Matches m) { if (!endsWithIgnoreCase(a, b)) return false; if (m != null) m.m = new String[] { substring(a, 0, l(a) - l(b)) }; return true; } static public BufferedReader bufferedReader(Reader r) { return bufferedReader(r, 8192); } static public BufferedReader bufferedReader(Reader r, int bufSize) { if (r == null) return null; return r instanceof BufferedReader ? (BufferedReader) r : _registerIOWrap(new BufferedReader(r, bufSize), r); } static public A holdResource(IResourceHolder holder, A a) { { if (holder != null) holder.add(a); } return a; } static public CloseableIterableIterator iteratorFromFunction_f0_autoCloseable(final F0 f, final AutoCloseable closeable) { class IFF2 extends CloseableIterableIterator { public A a; public boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } public void getNext() { if (done || a != null) return; a = f.get(); done = a == null; } public void close() throws Exception { if (closeable != null) closeable.close(); } } ; return new IFF2(); } static public String readLineFromReaderWithClose(BufferedReader r) { try { String s = r.readLine(); if (s == null) r.close(); return s; } catch (Exception __e) { throw rethrow(__e); } } static public AutoCloseable _wrapIOCloseable(final AutoCloseable c) { return c == null ? null : new AutoCloseable() { public String toString() { return "c.close();\r\n _registerIO(c, null, false);"; } public void close() throws Exception { c.close(); _registerIO(c, null, false); } }; } static public A _registerIOWrap(A wrapper, Object wrapped) { return wrapper; } static public int gzInputStream_defaultBufferSize = 65536; static public GZIPInputStream gzInputStream(File f) { try { return gzInputStream(new FileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static public GZIPInputStream gzInputStream(File f, int bufferSize) { try { return gzInputStream(new FileInputStream(f), bufferSize); } catch (Exception __e) { throw rethrow(__e); } } static public GZIPInputStream gzInputStream(InputStream in) { return gzInputStream(in, gzInputStream_defaultBufferSize); } static public GZIPInputStream gzInputStream(InputStream in, int bufferSize) { try { return _registerIOWrap(new GZIPInputStream(in, gzInputStream_defaultBufferSize), in); } catch (Exception __e) { throw rethrow(__e); } } static public boolean isLowerHexString(String s) { for (int i = 0; i < l(s); i++) { char c = s.charAt(i); if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f') { } else return false; } return true; } static public String multiLineQuoteWithSpaces(String s) { return multiLineQuote(" " + s + " "); } static public String quickSubstring(String s, int i, int j) { if (i == j) return ""; return s.substring(i, j); } static public Class actualMC() { return or((Class) realMC(), mc()); } static public Object safeUnstructure(String s) { return unstructure(s, true); } static public Object safeUnstructure(File f) { return safeUnstructureGZFile(f); } static public int parseHexChar(char c) { if (c >= '0' && c <= '9') return charDiff(c, '0'); if (c >= 'a' && c <= 'f') return charDiff(c, 'a') + 10; if (c >= 'A' && c <= 'F') return charDiff(c, 'A') + 10; return -1; } static public Class getOuterClass(Class c) { return getOuterClass(c, null); } static public Class getOuterClass(Class c, Object classFinder) { try { String s = c.getName(); int i = s.lastIndexOf('$'); String name = substring(s, 0, i); return classForName(name, classFinder); } catch (Exception __e) { throw rethrow(__e); } } static public Class getOuterClass(Object o) { return getOuterClass(o, null); } static public Class getOuterClass(Object o, Object classFinder) { return getOuterClass(_getClass(o), classFinder); } static public HashMap instanceFieldsMap(Object o) { return (HashMap) getOpt_getFieldMap(o); } static public void dynamicObject_setRawFieldValue(DynamicObject o, Object key, Object value) { if (o == null) return; synchronized (o) { o.fieldValues = syncMapPut2_createLinkedHashMap((LinkedHashMap) o.fieldValues, key, value); } } static public Map thisDollarOneFields_cache = newDangerousWeakHashMap(); static public Field[] thisDollarOneFields(Class c) { synchronized (thisDollarOneFields_cache) { Field[] l = thisDollarOneFields_cache.get(c); if (l == null) thisDollarOneFields_cache.put(c, l = thisDollarOneFields_uncached(c)); return l; } } static public Field[] thisDollarOneFields_uncached(Class c) { List fields = new ArrayList(); do { for (Field f : c.getDeclaredFields()) if (f.getName().startsWith("this$")) fields.add(makeAccessible(f)); c = c.getSuperclass(); } while (c != null); return toArray(new Field[l(fields)], fields); } static public Method fastIntern_method; static public String fastIntern(String s) { try { if (s == null) return null; if (fastIntern_method == null) { fastIntern_method = findMethodNamed(javax(), "internPerProgram"); if (fastIntern_method == null) upgradeJavaXAndRestart(); } return (String) fastIntern_method.invoke(null, s); } catch (Exception __e) { throw rethrow(__e); } } static public Map> callOpt_noArgs_cache = newDangerousWeakHashMap(); static public Object callOpt_noArgs(Object o, String method) { try { if (o == null) return null; if (o instanceof Class) return callOpt(o, method); Class c = o.getClass(); HashMap map; synchronized (callOpt_noArgs_cache) { map = callOpt_noArgs_cache.get(c); if (map == null) map = callOpt_noArgs_makeCache(c); } Method m = map.get(method); return m != null ? m.invoke(o) : null; } catch (Exception __e) { throw rethrow(__e); } } static public HashMap callOpt_noArgs_makeCache(Class c) { HashMap map = new HashMap(); Class _c = c; do { for (Method m : c.getDeclaredMethods()) if (m.getParameterTypes().length == 0 && !reflection_isForbiddenMethod(m)) { makeAccessible(m); String name = m.getName(); if (!map.containsKey(name)) map.put(name, m); } _c = _c.getSuperclass(); } while (_c != null); callOpt_noArgs_cache.put(c, map); return map; } static public String[] match2(List pat, List tok) { int i = pat.indexOf("..."); if (i < 0) return match2_match(pat, tok); pat = new ArrayList(pat); pat.set(i, "*"); while (pat.size() < tok.size()) { pat.add(i, "*"); pat.add(i + 1, ""); } return match2_match(pat, tok); } static public String[] match2_match(List pat, List tok) { List result = new ArrayList(); if (pat.size() != tok.size()) { return null; } for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(i); if (eq(p, "*")) result.add(t); else if (!equalsIgnoreCase(unquote(p), unquote(t))) return null; } return result.toArray(new String[result.size()]); } static public Map singular_specials = litmap("children", "child", "images", "image", "chess", "chess"); static public Set singular_specials2 = litciset("time", "machine", "line", "rule"); static public String singular(String s) { if (s == null) return null; { String __1 = singular_specials.get(s); if (!empty(__1)) return __1; } if (singular_specials2.contains(dropSuffix("s", afterLastSpace(s)))) return dropSuffix("s", s); if (s.endsWith("ness")) return s; if (s.endsWith("ges")) return dropSuffix("s", s); if (endsWith(s, "bases")) return dropLast(s); s = dropSuffix("es", s); s = dropSuffix("s", s); return s; } static public List getPlural_specials = ll("sheep", "fish"); static public String getPlural(String s) { if (containsIgnoreCase(getPlural_specials, s)) return s; if (ewic(s, "y")) return dropSuffixIgnoreCase("y", s) + "ies"; if (ewicOneOf(s, "ss", "ch")) return s + "es"; if (ewic(s, "s")) return s; return s + "s"; } static public File computerIDFile() { return javaxDataDir("Basic Info/computer-id.txt"); } static public int loadPage_defaultTimeout = 60000; static public ThreadLocal loadPage_charset = new ThreadLocal(); static public boolean loadPage_allowGzip = true, loadPage_debug; static public boolean loadPage_anonymous = false; static public int loadPage_verboseness = 100000; static public int loadPage_retries = 1; static public ThreadLocal loadPage_silent = new ThreadLocal(); static volatile public int loadPage_forcedTimeout; static public ThreadLocal loadPage_forcedTimeout_byThread = new ThreadLocal(); static public ThreadLocal>> loadPage_responseHeaders = new ThreadLocal(); static public ThreadLocal> loadPage_extraHeaders = new ThreadLocal(); static public ThreadLocal loadPage_sizeLimit = new ThreadLocal(); public static String loadPageSilently(String url) { try { return loadPageSilently(new URL(loadPage_preprocess(url))); } catch (Exception __e) { throw rethrow(__e); } } public static String loadPageSilently(URL url) { try { if (!networkAllowanceTest(str(url))) throw fail("Not allowed: " + url); IOException e = null; for (int tries = 0; tries < loadPage_retries; tries++) try { URLConnection con = loadPage_openConnection(url); return loadPage(con, url); } catch (IOException _e) { e = _e; if (loadPage_debug) print(exceptionToStringShort(e)); if (tries < loadPage_retries - 1) sleepSeconds(1); } throw e; } catch (Exception __e) { throw rethrow(__e); } } static public String loadPage_preprocess(String url) { if (url.startsWith("tb/")) url = tb_mainServer() + "/" + url; if (url.indexOf("://") < 0) url = "http://" + url; return url; } static public String loadPage(String url) { try { url = loadPage_preprocess(url); if (!isTrue(loadPage_silent.get())) printWithTime("Loading: " + hideCredentials(url)); return loadPageSilently(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static public String loadPage(URL url) { return loadPage(url.toExternalForm()); } static public String loadPage(URLConnection con, URL url) throws IOException { return loadPage(con, url, true); } static public String loadPage(URLConnection con, URL url, boolean addHeaders) throws IOException { Map extraHeaders = getAndClearThreadLocal(loadPage_extraHeaders); Long limit = optPar(loadPage_sizeLimit); if (addHeaders) try { if (!loadPage_anonymous) setHeaders(con); if (loadPage_allowGzip) con.setRequestProperty("Accept-Encoding", "gzip"); con.setRequestProperty("X-No-Cookies", "1"); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); } catch (Throwable e) { } vm_generalSubMap("URLConnection per thread").put(currentThread(), con); loadPage_responseHeaders.set(con.getHeaderFields()); InputStream in = null; try { in = urlConnection_getInputStream(con); if (loadPage_debug) print("Put stream in map: " + currentThread()); String contentType = con.getContentType(); if (contentType == null) { throw new IOException("Page could not be read: " + hideCredentials(url)); } String charset = loadPage_charset == null ? null : loadPage_charset.get(); if (charset == null) charset = loadPage_guessCharset(contentType); if ("gzip".equals(con.getContentEncoding())) { if (loadPage_debug) print("loadPage: Using gzip."); in = newGZIPInputStream(in); } Reader r; try { r = new InputStreamReader(in, unquote(charset)); } catch (UnsupportedEncodingException e) { print(toHex(utf8(charset))); throw e; } boolean silent = isTrue(loadPage_silent.get()); StringBuilder buf = new StringBuilder(); int n = 0; while (limit == null || n < limit) { ping(); int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; if (!silent && (n % loadPage_verboseness) == 0) print(" " + n + " chars read"); } return buf.toString(); } finally { if (loadPage_debug) print("loadPage done"); vm_generalSubMap("URLConnection per thread").remove(currentThread()); if (in != null) in.close(); } } static public String loadPage_guessCharset(String contentType) { Matcher m = regexpMatcher("text/[a-z]+;\\s*charset=([^\\s]+)\\s*", contentType); String match = m.matches() ? m.group(1) : null; if (loadPage_debug) print("loadPage: contentType=" + contentType + ", match: " + match); return or(match, "UTF-8"); } static public URLConnection loadPage_openConnection(URL url) { URLConnection con = openConnection(url); int timeout = toInt(loadPage_forcedTimeout_byThread.get()); if (timeout == 0) timeout = loadPage_forcedTimeout; if (timeout != 0) setURLConnectionTimeouts(con, loadPage_forcedTimeout); else setURLConnectionDefaultTimeouts(con, loadPage_defaultTimeout); return con; } static public A getAndClearThreadLocal(ThreadLocal tl) { A a = tl.get(); tl.set(null); return a; } static public A println(A a) { return print(a); } static public String imageServerURL() { return or2(trim(loadTextFile(javaxDataDir("image-server-url.txt"))), "http://botcompany.de/images/raw/"); } static volatile public boolean muricaPassword_pretendNotAuthed = false; static public String muricaPassword() { if (muricaPassword_pretendNotAuthed) return null; return trim(loadTextFile(muricaPasswordFile())); } static public String fileServerURL() { return "https://botcompany.de/files"; } public static File mkdirsFor(File file) { return mkdirsForFile(file); } static public void copyStreamWithPrints(InputStream in, OutputStream out, String pat) { try { byte[] buf = new byte[65536]; int total = 0; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); if ((total + n) / 100000 > total / 100000) print(pat.replace("{*}", str(roundDownTo(100000, total)))); total += n; } } catch (Exception __e) { throw rethrow(__e); } } static public File renameFile_assertTrue(File a, File b) { try { if (a.equals(b)) return b; if (!a.exists()) throw fail("Source file not found: " + f2s(a)); if (b.exists()) throw fail("Target file exists: " + f2s(b)); mkdirsForFile(b); if (!a.renameTo(b)) throw fail("Can't rename " + f2s(a) + " to " + f2s(b)); return b; } catch (Exception __e) { throw rethrow(__e); } } static public JTextArea jTextArea() { return jTextArea(""); } static public JTextArea jTextArea(final String text) { return jTextAreaWithUndo(text); } static public String strUnnull(Object o) { return o == null ? "" : str(o); } static public String jlabel_textAsHTML_center_ifNeeded(String text) { if (swic(text, "") && ewic(text, "")) return text; if (!containsNewLines(text)) return text; return jlabel_textAsHTML_center(text); } static public KeyListener enterKeyListener(final Object action) { return new KeyAdapter() { public void keyPressed(KeyEvent ke) { if (ke.getKeyCode() == KeyEvent.VK_ENTER) pcallF(action); } }; } static public Runnable rCallOnSelectedListItem(final JList list, final Object action) { return new Runnable() { public void run() { try { pcallF(action, getSelectedItem(list)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(action, getSelectedItem(list))"; } }; } static public boolean addIfNotNull(Collection l, A a) { return a != null && l != null & l.add(a); } static public void addIfNotNull(MultiSet ms, A a) { if (a != null && ms != null) ms.add(a); } static public int findEndOfBlock(List cnc, int i) { int j = i + 2, level = 1, n = cnc.size(); while (j < n) { String t = cnc.get(j); if ("{".equals(t)) ++level; else if ("}".equals(t)) --level; if (level == 0) return j + 1; j += 2; } return n; } static public int findEndOfBracketPart(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eqOneOf(cnc.get(j), "{", "(")) ++level; else if (eqOneOf(cnc.get(j), "}", ")")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static public void tokPrepend(List tok, String s) { tokPrepend(tok, 0, s); } static public void tokPrepend(List tok, int i, String s) { tok.set(i, s + tok.get(i)); } static public String javaDropAllComments(String s) { return join(javaDropAllComments(javaTok(s))); } static public List javaDropAllComments(List tok) { for (int i = 0; i < l(tok); i += 2) tok.set(i, tok_javaDropCommentsFromWhitespace(tok.get(i))); return tok; } static public List dm_listModuleIDs() { return map(__98 -> dm_moduleID(__98), dm_listStems()); } static public Object dm_getStemByID(Object id) { return dm_callOS("getModuleByID", str(id)); } static public boolean isEmpty(Collection c) { return c == null || c.isEmpty(); } static public boolean isEmpty(CharSequence s) { return s == null || s.length() == 0; } static public boolean isEmpty(Object[] a) { return a == null || a.length == 0; } static public boolean isEmpty(byte[] a) { return a == null || a.length == 0; } static public boolean isEmpty(Map map) { return map == null || map.isEmpty(); } static public JMenuItem jMenuItem(final String text) { return jmenuItem(text); } static public JMenuItem jMenuItem(String text, Object r) { return jmenuItem(text, r); } static public Pair jmenu_autoMnemonic(String s) { int i = indexOf(s, '&'); if (i >= 0 && i < l(s) && isLetterOrDigit(s.charAt(i + 1))) return pair(substring(s, 0, i) + substring(s, i + 1), (int) s.charAt(i + 1)); return pair(s, 0); } static public JMenuItem disableMenuItem(final JMenuItem mi) { if (mi != null) { swing(new Runnable() { public void run() { try { mi.setEnabled(false); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mi.setEnabled(false);"; } }); } return mi; } static public ActionListener actionListenerInNewThread(final Object runnable) { return actionListenerInNewThread(runnable, null); } static public ActionListener actionListenerInNewThread(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { startThread("Action Listener", new Runnable() { public void run() { try { AutoCloseable __1 = holdInstance(instanceToHold); try { callF(runnable); } finally { _close(__1); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "AutoCloseable __1 = holdInstance(instanceToHold); try {\r\n callF(runnable..."; } }); } catch (Throwable __e) { messageBox(__e); } } }; } static public boolean isCurlyBraced(String s) { List tok = tok_combineCurlyBrackets_keep(javaTok(s)); return l(tok) == 3 && startsWithAndEndsWith(tok.get(1), "{", "}"); } static public String tok_unCurlyBracket(String s) { return isCurlyBraced(s) ? join(dropFirstThreeAndLastThree(javaTok(s))) : s; } static public Dimension getPreferredSize(final Component c) { return c == null ? null : swing(new F0() { public Dimension get() { try { return c.getPreferredSize(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getPreferredSize();"; } }); } static public A revalidate(final A c) { if (c == null || !c.isShowing()) return c; { swing(new Runnable() { public void run() { try { c.revalidate(); c.repaint(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "// magic combo to actually relayout and repaint\r\n c.revalidate();\r\n c.r..."; } }); } return c; } static public void revalidate(JFrame f) { revalidate((Component) f); } static public void revalidate(JInternalFrame f) { revalidate((Component) f); } static public JFrame getFrame(final Object _o) { return swing(new F0() { public JFrame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof JFrame) return (JFrame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n if (o instanceof ButtonGroup) o = first(buttonsInGroup((Button..."; } }); } static public TimeZone getTimeZone(String name) { return TimeZone.getTimeZone(name); } static public boolean checkFields(Object x, Object... data) { for (int i = 0; i < l(data); i += 2) if (neq(getOpt(x, (String) data[i]), data[i + 1])) return false; return true; } static public void cleanKillVM() { try { ping(); assertNotOnAWTThread(); cleanKillVM_noSleep(); Object o = new Object(); synchronized (o) { o.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static public void cleanKillVM_noSleep() { call(getJavaX(), "cleanKill"); } static public String fsI_flex(String s) { return startsWithDigit(s) ? "#" + s : s; } static public boolean exposeMethods2_debug = false; static public String exposeMethods2(Object receiver, String s, List methodNames) { return exposeMethods2(receiver, s, methodNames, null); } static public String exposeMethods2(Object receiver, String s, List methodNames, Lock lock) { Matches m = new Matches(); if (exposeMethods2_debug) print("Received: " + s); if (match("call *", s, m)) { List l; if (isIdentifier(m.unq(0))) l = ll(m.unq(0)); else l = (List) unstructure(m.unq(0)); String method = getString(l, 0); if (!contains(methodNames, method)) throw fail("Method not allowed: " + method); if (lock != null) lock.lock(); try { if (exposeMethods2_debug) print("Calling: " + method); Object o = call(receiver, method, asObjectArray(subList(l, 1))); if (exposeMethods2_debug) print("Got: " + getClassName(o)); return ok2(structure(o)); } finally { if (lock != null) lock.unlock(); } } if (match("list methods", s)) return ok2(structure(methodNames)); return null; } static public int makeBot(String greeting) { return makeAndroid3(greeting).port; } static public Android3 makeBot(Android3 a) { makeAndroid3(a); return a; } static public Android3 makeBot(String greeting, Object responder) { Android3 a = new Android3(greeting); a.responder = makeResponder(responder); makeBot(a); return a; } static public Android3 makeBot() { return makeAndroid3(defaultBotName()); } static public List listFilesOnly(String dir) { return listFilesOnly(new File(dir)); } static public List listFilesOnly(File... dirs) { return concatMap(rcurry("listFilesWithSuffix", ""), dirs); } static public Comparator mapComparator(final Map map) { return new Comparator() { public int compare(A a, A b) { return cmp(map.get(a), map.get(b)); } }; } static public boolean isDirectory(File f) { return f != null && f.isDirectory(); } static public boolean isDirectory(String path) { return path != null && isDirectory(newFile(path)); } static public File[] listFiles(File dir) { File[] files = dir.listFiles(); return files == null ? new File[0] : files; } static public File[] listFiles(String dir) { return listFiles(new File(dir)); } static public void stream2file(InputStream in, File out) { try { mkdirsForFile(out); FileOutputStream fos = new FileOutputStream(out); copyStream(in, fos); in.close(); fos.close(); } catch (Exception __e) { throw rethrow(__e); } } static public RandomAccessFile newRandomAccessFile(File path, String mode) { try { boolean forWrite = mode.indexOf('w') >= 0; if (forWrite) mkdirsForFile(path); RandomAccessFile f = new RandomAccessFile(path, mode); callJavaX("registerIO", f, path, forWrite); return f; } catch (Exception __e) { throw rethrow(__e); } } static public int lastIndexOf_byteArray(byte[] a, byte b) { for (int i = l(a) - 1; i >= 0; i--) if (a[i] == b) return i; return -1; } static public int indexOf_byteArray(byte[] a, byte b) { int n = l(a); for (int i = 0; i < n; i++) if (a[i] == b) return i; return -1; } static public void addMenuItem(JPopupMenu menu, String text, Object action) { menu.add(jmenuItem(text, action)); } static public void addMenuItem(JPopupMenu menu, JMenuItem menuItem) { menu.add(menuItem); } static public void addMenuItem(JMenu menu, String text, Object action) { menu.add(jmenuItem(text, action)); } static public void addMenuItem(Menu menu, String text, Object action) { menu.add(menuItem(text, action)); } static public void addMenuItem(JMenu menu, JMenuItem menuItem) { menu.add(menuItem); } static public void addMenuItem(JMenuBar menuBar, String text, Runnable action) { addMenuItem(menuBar, jmenuItem(text, action)); } static public void addMenuItem(JMenuBar menuBar, JMenuItem menuItem) { addDirectMenuItem(menuBar, menuItem); } static public Set newWeakHashSet() { return synchroWeakHashSet(); } static public boolean headless() { return isHeadless(); } static public String getSnippetTitle(String id) { if (id == null) return null; if (!isSnippetID(id)) return "?"; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getSnippetTitle(id); return getSnippetTitle_noResourceLoader(id); } static public String getSnippetTitle_noResourceLoader(String id) { try { if (isLocalSnippetID(id)) return localSnippetTitle(id); long parsedID = parseSnippetID(id); String url; if (isImageServerSnippet(parsedID)) url = imageServerURL() + "title/" + parsedID + muricaCredentialsQuery(); else if (isGeneralFileServerSnippet(parsedID)) url = "http://butter.botcompany.de:8080/files/name/" + parsedID; else url = tb_mainServer() + "/tb-int/getfield.php?id=" + parsedID + "&field=title" + standardCredentials_noCookies(); String title = trim(loadPageSilently(url)); if (title != null) try { saveTextFileIfChanged(snippetTitle_cacheFile(id), title); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } return or(title, "?"); } catch (Exception __e) { throw rethrow(__e); } } static public String getSnippetTitle(long id) { return getSnippetTitle(fsI(id)); } static public void scanForComponents(final Component c, final Class theClass, final List l) { if (theClass.isInstance(c)) l.add((A) c); if (c instanceof Container) { swing(new Runnable() { public void run() { try { for (Component comp : ((Container) c).getComponents()) scanForComponents(comp, theClass, l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (Component comp : ((Container) c).getComponents())\r\n scanForComponen..."; } }); } } static public List javaTokPlusBrackets2(String s) { return tok_combineRoundCurlySquareBrackets_keep(javaTok(s)); } static public boolean startsWithLetterOrDigit(String s) { return nempty(s) && Character.isLetterOrDigit(s.charAt(0)); } static public String regexpQuote(String s) { return s.length() == 0 ? "" : Pattern.quote(s); } static public List parse3(String s) { return dropPunctuation(javaTokPlusPeriod(s)); } static public List takeLast(List l, int n) { return newSubList(l, l(l) - n); } static public List takeLast(int n, List l) { return takeLast(l, n); } static public String takeLast(int n, String s) { return substring(s, l(s) - n); } static public String takeLast(String s, int n) { return substring(s, l(s) - n); } static public boolean equalsIgnoreCase(String a, String b) { return eqic(a, b); } static public boolean equalsIgnoreCase(char a, char b) { return eqic(a, b); } static public int min3(int a, int b, int c) { return min(min(a, b), c); } static public double min3(double a, double b, double c) { return min(min(a, b), c); } static public void scrollRowToVisible(JTable t, int rowIndex) { int colIndex = 0; if (!(t.getParent() instanceof JViewport)) return; JViewport viewport = (JViewport) t.getParent(); Rectangle rect = t.getCellRect(rowIndex, colIndex, true); Rectangle viewRect = viewport.getViewRect(); int x = viewRect.x; int y = viewRect.y; if (rect.x >= viewRect.x && rect.x <= (viewRect.x + viewRect.width - rect.width)) { } else if (rect.x < viewRect.x) { x = rect.x; } else if (rect.x > (viewRect.x + viewRect.width - rect.width)) { x = rect.x - viewRect.width + rect.width; } if (rect.y >= viewRect.y && rect.y <= (viewRect.y + viewRect.height - rect.height)) { } else if (rect.y < viewRect.y) { y = rect.y; } else if (rect.y > (viewRect.y + viewRect.height - rect.height)) { y = rect.y - viewRect.height + rect.height; } viewport.setViewPosition(new Point(x, y)); } static public int listRowCount(JList list) { return list == null ? 0 : swing(new F0() { public Integer get() { try { return list.getModel().getSize(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret list.getModel().getSize();"; } }); } static public Rect rect(int x, int y, int w, int h) { return new Rect(x, y, w, h); } static public Rect rect(Pt p, int w, int h) { return new Rect(p.x, p.y, w, h); } static public Rect rect(int w, int h) { return new Rect(0, 0, w, h); } static public boolean jInternalFrame_iconifiable = true; static public JInternalFrame jInternalFrame() { return jInternalFrame(""); } static public JInternalFrame jInternalFrame(final String title) { return swing(new F0() { public JInternalFrame get() { try { JInternalFrame f = new JInternalFrame(title, true, true, true, jInternalFrame_iconifiable); f.setVisible(true); return f; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JInternalFrame f = new JInternalFrame(title, true, true, true, jInternalFrame..."; } }); } static public void setInternalFrameContents(final Component c, final Object contents) { { swing(new Runnable() { public void run() { try { JInternalFrame frame = getInternalFrame(c); if (frame == null) return; frame.getContentPane().removeAll(); frame.getContentPane().setLayout(new BorderLayout()); if (contents != null) frame.getContentPane().add(wrap(contents)); revalidate(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JInternalFrame frame = getInternalFrame(c);\r\n if (frame == null) return;\r\n..."; } }); } } static public A setBounds(final int x, final int y, final int w, final int h, final A a) { if (a != null) { swing(new Runnable() { public void run() { try { a.setBounds(x, y, w, h); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setBounds(x, y, w, h);"; } }); } return a; } static public A setBounds(A a, Rect r) { if (a != null && r != null) { swing(new Runnable() { public void run() { try { a.setBounds(toRectangle(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setBounds(toRectangle(r));"; } }); } return a; } static public A setBounds(Rect r, A a) { return setBounds(a, r); } static public A setBounds(A a, int x, int y, int w, int h) { return setBounds(x, y, w, h, a); } static public void internalFrameDefaultPosition(JInternalFrame f) { f.setSize(500, 300); centerInternalFrame(f); } static public int fixInternalFrame_borderTopLeft = 0; static public int fixInternalFrame_borderBottomRight = 40; static public JInternalFrame fixInternalFrame(final JInternalFrame f) { return swing(new F0() { public JInternalFrame get() { try { Container c = f.getParent(); if (c == null) return f; Rect r = toRect(f.getBounds()); int a = fixInternalFrame_borderTopLeft, b = fixInternalFrame_borderBottomRight; Rect outer = new Rect(a, a, c.getWidth() - b, c.getHeight() - b); if (!rectContains(outer, r)) f.setLocation(max(a, min(r.x, outer.x2())), max(a, min(r.y, outer.y2()))); if (r.w > c.getWidth() || r.h > c.getHeight()) f.setSize(c.getWidth() - a, c.getHeight() - a); return f; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Container c = f.getParent();\r\n if (c == null) ret f;\r\n Rect r = toRect(..."; } }); } static public int getScreenWidth() { return getScreenSize().width; } static public int getScreenHeight() { return getScreenSize().height; } static public String makeFrame_defaultIcon; static public boolean makeFrame_hideConsole = false; static public ThreadLocal> makeFrame_post = new ThreadLocal(); static public JFrame makeFrame() { return makeFrame((Component) null); } static public JFrame makeFrame(Object content) { return makeFrame(programTitle(), content); } static public JFrame makeFrame(String title) { return makeFrame(title, null); } static public JFrame makeFrame(String title, Object content) { return makeFrame(title, content, true); } static public JFrame makeFrame(final String title, final Object content, final boolean showIt) { final VF1 post = optParam(makeFrame_post); return swing(new F0() { public JFrame get() { try { if (getFrame(content) != null) return getFrame(setFrameTitle((Component) content, title)); final JFrame frame = new JFrame(title); if (makeFrame_defaultIcon != null) setFrameIconLater(frame, makeFrame_defaultIcon); _initFrame(frame); Component wrapped = wrap(content); if (wrapped != null) frame.getContentPane().add(wrapped); frame.setBounds(defaultNewFrameBounds()); callF(post, frame); if (showIt) frame.setVisible(true); if (showIt && makeFrame_hideConsole) { hideConsole(); makeFrame_hideConsole = false; } return frame; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (getFrame(content) != null)\r\n ret getFrame(setFrameTitle((Component) ..."; } }); } static public boolean frameTooSmall(JFrame frame) { return frame.getWidth() < 100 || frame.getHeight() < 50; } static public void frameStandardSize(JFrame frame) { frame.setBounds(300, 100, 500, 400); } static public void setFrameContents(final Component c, final Object contents) { swing(new Runnable() { public void run() { try { JFrame frame = getFrame(c); if (frame == null) return; frame.getContentPane().removeAll(); frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add(wrap(contents)); revalidate(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFrame frame = getFrame(c);\r\n if (frame == null) return;\r\n frame.getContent..."; } }); } static public boolean containsSpaces(String s) { return indexOf(s, ' ') >= 0; } static public List ai_splitCamelCase(String s) { int j = 0; List l = new ArrayList(); if (isAllUpperCase(s)) { l.add(s); return l; } for (int i = 0; i < l(s); i++) if (i > j && isUpperCaseLetter(s.charAt(i))) { l.add(substring(s, j, i)); j = i; } if (j < l(s)) l.add(substring(s, j)); return l; } static public List listFilesWithSuffix(File dir, String suffix) { List l = new ArrayList(); for (File f : listFiles(dir)) if (!f.isDirectory() && (empty(suffix) || endsWithIgnoreCase(f.getName(), suffix))) l.add(f); return l; } static public boolean charactersEqualIC(char c1, char c2) { if (c1 == c2) return true; char u1 = Character.toUpperCase(c1); char u2 = Character.toUpperCase(c2); if (u1 == u2) return true; return Character.toLowerCase(u1) == Character.toLowerCase(u2); } static public String xltrim(String s) { int i = 0, n = l(s); while (i < n && contains(" \t\r\n", s.charAt(i))) ++i; return substr(s, i); } static public String takeCharsWhile(String s, Object pred) { int i = 0; while (i < l(s) && isTrue(callF(pred, s.charAt(i)))) ++i; return substring(s, 0, i); } static public String takeCharsWhile(IF1 f, String s) { return takeCharsWhile(s, f); } static public String multiLineQuote(String s) { for (int i = 0; ; i++) { String closer = "]" + rep('=', i) + "]"; if (!contains(s, closer)) return "[" + rep('=', i) + "[" + s + closer; } } static public Object realMC() { return getThreadLocal(realMC_tl()); } static public Object safeUnstructureGZFile(File f) { try { if (!fileExists(f)) return null; BufferedReader reader = utf8BufferedReader(gzInputStream(f)); return unstructure_tok(javaTokC_noMLS_onReader(reader), true, null); } catch (Exception __e) { throw rethrow(__e); } } static public int charDiff(char a, char b) { return (int) a - (int) b; } static public int charDiff(String a, char b) { return charDiff(stringToChar(a), b); } static public LinkedHashMap syncMapPut2_createLinkedHashMap(LinkedHashMap map, A key, B value) { if (key != null) if (value != null) { if (map == null) map = new LinkedHashMap(); synchronized (collectionMutex(map)) { map.put(key, value); } } else if (map != null) synchronized (collectionMutex(map)) { map.remove(key); } return map; } static public Object[] toArray(Collection c) { return toObjectArray(c); } static public A[] toArray(Class type, Iterable c) { return toArray(c, type); } static public A[] toArray(Iterable c, Class type) { A[] a = arrayOfType(l(c), type); if (a.length == 0) return a; asList(c).toArray(a); return a; } static public A[] toArray(A[] array, Collection c) { if (array == null || c == null) return null; asList(c).toArray(array); return array; } static public void upgradeJavaXAndRestart() { run("#1001639"); restart(); sleep(); } static public String afterLastSpace(String s) { return s == null ? null : substring(s, s.lastIndexOf(' ') + 1); } static public String dropSuffixIgnoreCase(String suffix, String s) { return ewic(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static public boolean ewicOneOf(String s, String... l) { if (s != null) for (String x : l) if (ewic(s, x)) return true; return false; } static public boolean networkAllowanceTest(String url) { return isAllowed("networkAllowanceTest", url); } static public void sleepSeconds(double s) { if (s > 0) sleep(round(s * 1000)); } static public A printWithTime(A a) { return printWithTime("", a); } static public A printWithTime(String s, A a) { print(hmsWithColons() + ": " + s, a); return a; } static public InputStream urlConnection_getInputStream(URLConnection con) throws IOException { UnknownHostException lastException = null; for (int _repeat_0 = 0; _repeat_0 < 2; _repeat_0++) { try { if (con instanceof HttpURLConnection) if (((HttpURLConnection) con).getResponseCode() == 500) throw new IOException(joinNemptiesWithColonSpace("Server code 500", tryToReadErrorStreamFromURLConnection((HttpURLConnection) con))); return con.getInputStream(); } catch (UnknownHostException e) { lastException = e; print("Retrying because of: " + e); continue; } } throw lastException; } static public String toHex(byte[] bytes) { return bytesToHex(bytes); } static public String toHex(byte[] bytes, int ofs, int len) { return bytesToHex(bytes, ofs, len); } static public Matcher regexpMatcher(String pat, String s) { return compileRegexp(pat).matcher(unnull(s)); } static public URLConnection setURLConnectionDefaultTimeouts(URLConnection con, long timeout) { if (con.getConnectTimeout() == 0) { con.setConnectTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout) print("Warning: URL connect timeout not set by JDK."); } if (con.getReadTimeout() == 0) { con.setReadTimeout(toInt(timeout)); if (con.getReadTimeout() != timeout) print("Warning: URL read timeout not set by JDK."); } return con; } static public File muricaPasswordFile() { return new File(javaxSecretDir(), "murica/muricaPasswordFile"); } static public int roundDownTo(int n, int x) { return x / n * n; } static public long roundDownTo(long n, long x) { return x / n * n; } static public JTextArea jTextAreaWithUndo() { return jTextAreaWithUndo(""); } static public JTextArea jTextAreaWithUndo(final String text) { return jenableUndoRedo(swingNu(JTextArea.class, text)); } static public boolean containsNewLines(String s) { return containsNewLine(s); } static public String jlabel_textAsHTML_center(String text) { return "
" + replace(htmlencode2(text), "\n", "
") + "
"; } static public String tok_javaDropCommentsFromWhitespace(String s) { int l = l(s), j = 0; StringBuilder buf = new StringBuilder(); while (j < l) { char c = s.charAt(j); char d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else { buf.append(c); ++j; } } return str(buf); } static public List dm_listStems() { return (List) dm_callOS("onModules"); } static public List tok_combineCurlyBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eq(t, "{")) { int j = findEndOfCurlyBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public void assertNotOnAWTThread() { assertFalse("Can't do this in AWT thread", isAWTThread()); } static public boolean startsWithDigit(String s) { return nempty(s) && isDigit(s.charAt(0)); } static public String ok2(String s) { return "ok " + s; } static public boolean makeAndroid3_disable = false; static public class Android3 implements AutoCloseable { public String greeting; public boolean publicOverride = false; public int startPort = 5000; public Responder responder; public boolean console = true; public boolean quiet = false; public boolean daemon = false; public boolean incomingSilent = false; public int incomingPrintLimit = 200; public boolean useMultiPort = true; public boolean recordHistory = false; public boolean verbose = false; public int answerPrintLimit = 500; public boolean newLineAboveAnswer, newLineBelowAnswer; public int port; public long vport; public DialogHandler handler; public ServerSocket server; public Android3(String greeting) { this.greeting = greeting; } public Android3() { } public void close() { dispose(); } synchronized public void dispose() { if (server != null) { try { server.close(); } catch (IOException e) { print("[internal] " + e); } server = null; } if (vport != 0) { try { print("Disposing " + this); removeFromMultiPort(vport); vport = 0; } catch (Throwable __e) { _handleException(__e); } } } public String toString() { return "Bot: " + greeting + " [vport " + vport + "]"; } } static abstract public class Responder { abstract public String answer(String s, List history); } static public Android3 makeAndroid3(final String greeting) { return makeAndroid3(new Android3(greeting)); } static public Android3 makeAndroid3(final String greeting, Responder responder) { Android3 android = new Android3(greeting); android.responder = responder; return makeAndroid3(android); } static public Android3 makeAndroid3(final Android3 a) { if (makeAndroid3_disable) return a; if (a.responder == null) a.responder = new Responder() { public String answer(String s, List history) { return callStaticAnswerMethod(s, history); } }; if (!a.quiet) print("[bot] " + a.greeting); if (a.console && (readLine_noReadLine || makeAndroid3_consoleInUse())) a.console = false; record(a); if (a.useMultiPort) a.vport = addToMultiPort(a.greeting, makeAndroid3_verboseResponder(a)); if (a.console) makeAndroid3_handleConsole(a); if (a.useMultiPort) return a; a.handler = makeAndroid3_makeDialogHandler(a); if (a.quiet) startDialogServer_quiet.set(true); try { a.port = a.daemon ? startDialogServerOnPortAboveDaemon(a.startPort, a.handler) : startDialogServerOnPortAbove(a.startPort, a.handler); } finally { startDialogServer_quiet.set(null); } a.server = startDialogServer_serverSocket; return a; } static public void makeAndroid3_handleConsole(final Android3 a) { if (!a.quiet) print("You may also type on this console."); { startThread(new Runnable() { public void run() { try { List history = new ArrayList(); while (licensed()) { String line; try { line = readLine(); } catch (Throwable e) { print(getInnerMessage(e)); break; } if (line == null) break; { history.add(line); history.add(makeAndroid3_getAnswer(line, history, a)); } } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "List history = new ArrayList();\r\n while (licensed()) {\r\n Stri..."; } }); } } static public DialogHandler makeAndroid3_makeDialogHandler(final Android3 a) { return new DialogHandler() { public void run(final DialogIO io) { if (!a.publicOverride && !(publicCommOn() || io.isLocalConnection())) { io.sendLine("Sorry, not allowed"); return; } String dialogID = randomID(8); io.sendLine(a.greeting + " / Your ID: " + dialogID); List history = new ArrayList(); while (io.isStillConnected()) { if (io.waitForLine()) { final String line = io.readLineNoBlock(); String s = dialogID + " at " + now() + ": " + quote(line); if (!a.incomingSilent) print(shorten(s, a.incomingPrintLimit)); if (eq(line, "bye")) { io.sendLine("bye stranger"); return; } Matches m = new Matches(); if (a.recordHistory) history.add(line); String answer; if (match3("this is a continuation of talk *", s, m) || match3("hello bot! this is a continuation of talk *", s, m)) { dialogID = unquote(m.m[0]); answer = "ok"; } else try { makeAndroid3_io.set(io); answer = makeAndroid3_getAnswer(line, history, a); } finally { makeAndroid3_io.set(null); } if (a.recordHistory) history.add(answer); io.sendLine(answer); } } } }; } static public String makeAndroid3_getAnswer(String line, List history, Android3 a) { String answer, originalAnswer; try { originalAnswer = a.responder.answer(line, history); answer = makeAndroid3_fallback(line, history, originalAnswer); } catch (Throwable e) { e = getInnerException(e); printStackTrace(e); originalAnswer = answer = e.toString(); } if (!a.incomingSilent) { if (originalAnswer == null) originalAnswer = "?"; if (a.newLineAboveAnswer) print(); print(">" + dropFirst(indentx(2, shorten(rtrim(originalAnswer), a.answerPrintLimit)))); if (a.newLineBelowAnswer) print(); } return answer; } static public String makeAndroid3_fallback(String s, List history, String answer) { if (answer == null && match3("what is your pid", s)) return getPID(); if (answer == null && match3("what is your program id", s)) return getProgramID(); if (match3("get injection id", s)) return getInjectionID(); if (answer == null) answer = "?"; if (answer.indexOf('\n') >= 0 || answer.indexOf('\r') >= 0) answer = quote(answer); return answer; } static public boolean makeAndroid3_consoleInUse() { if (isTrue(vm_generalMap_get("consoleInUse"))) return true; for (Object o : record_list) if (o instanceof Android3 && ((Android3) o).console) return true; return false; } static public Responder makeAndroid3_verboseResponder(final Android3 a) { return new Responder() { public String answer(String s, List history) { if (a.verbose) print("> " + shorten(s, a.incomingPrintLimit)); String answer = a.responder.answer(s, history); if (a.verbose) print("< " + shorten(answer, a.incomingPrintLimit)); return answer; } }; } static public ThreadLocal makeAndroid3_io = new ThreadLocal(); static public Android3 makeAndroid3() { return makeAndroid3(getProgramTitle() + "."); } static public String makeResponder_callAnswerMethod(Object bot, String s, List history) { String answer = (String) callOpt(bot, "answer", s, history); if (answer == null) answer = (String) callOpt(bot, "answer", s); return answer; } static public Responder makeResponder(final Object bot) { if (bot instanceof Responder) return (Responder) bot; if (bot instanceof String) { String f = (String) bot; return new Responder() { public String answer(String s, List history) { String answer = (String) callOptMC((String) bot, s, history); if (answer == null) answer = (String) callOptMC((String) bot, s); return answer; } }; } return new Responder() { public String answer(String s, List history) { return makeResponder_callAnswerMethod(bot, s, history); } }; } static public String defaultBotName() { return getProgramTitle() + "."; } static public Object rcurry(final Object f, final Object arg) { int n = numberOfFunctionArguments(f); if (n == 0) throw fail("function takes no arguments"); if (n == 1) return new F0() { public Object get() { return callF(f, arg); } }; if (n == 2) return new F1() { public Object get(Object a) { return callF(f, a, arg); } }; throw todo("currying a function with " + n + "arguments"); } static public Object callJavaX(String method, Object... args) { return callOpt(getJavaX(), method, args); } static public MenuItem menuItem(String text, final Object r) { MenuItem mi = new MenuItem(text); mi.addActionListener(actionListener(r)); return mi; } static public void addDirectMenuItem(JMenuBar mb, String text, Object action) { if (mb != null) { swing(new Runnable() { public void run() { try { addDirectMenuItem(mb, directJMenuItem(text, action)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addDirectMenuItem(mb, directJMenuItem(text, action));"; } }); } } static public void addDirectMenuItem(Component c, String text, Object action) { addDirectMenuItem(addMenuBar(c), text, action); } static public void addDirectMenuItem(JMenuBar mb, JMenuItem menuItem) { if (mb != null) { swing(new Runnable() { public void run() { try { mb.add(menuItem); revalidate(mb); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mb.add(menuItem);\r\n revalidate(mb);"; } }); } } static public boolean isLocalSnippetID(String snippetID) { return isSnippetID(snippetID) && isLocalSnippetID(psI(snippetID)); } static public boolean isLocalSnippetID(long snippetID) { return snippetID >= 1000 && snippetID <= 9999; } static public String localSnippetTitle(String snippetID) { if (!isLocalSnippetID(snippetID)) return null; File f = localSnippetFile(snippetID); if (!f.exists()) return null; return or2(getFileInfoField(dropExtension(f), "Title"), "Unnamed"); } static public String muricaCredentialsQuery() { return htmlQuery(muricaCredentials()); } static public boolean isGeneralFileServerSnippet(long id) { return id >= 1400000 && id < 1500000; } static public String standardCredentials_noCookies() { return standardCredentials() + "&noCookies=1"; } static public boolean saveTextFileIfChanged(File f, String contents) { return saveTextFileIfDifferent(f, contents); } static public File snippetTitle_cacheFile(String snippetID) { return javaxCachesDir("Snippet Titles/" + psI(snippetID)); } static public List tok_combineRoundCurlySquareBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eqOneOf(t, "{", "(", "[")) { int j = findEndOfBracketPart2(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static public List dropPunctuation_keep = ll("*", "<", ">"); static public List dropPunctuation(List tok) { tok = new ArrayList(tok); for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (t.length() == 1 && !Character.isLetter(t.charAt(0)) && !Character.isDigit(t.charAt(0)) && !dropPunctuation_keep.contains(t)) { tok.set(i - 1, tok.get(i - 1) + tok.get(i + 1)); tok.remove(i); tok.remove(i); i -= 2; } } return tok; } static public String dropPunctuation(String s) { return join(dropPunctuation(nlTok(s))); } static public List javaTokPlusPeriod(String s) { List tok = new ArrayList(); if (s == null) return tok; int l = s.length(); int i = 0; while (i < l) { int j = i; char c; String cc; while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j + 2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); cc = s.substring(i, Math.min(i + 2, l)); if (c == (char) 0x201C || c == (char) 0x201D) c = '"'; if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { char _c = s.charAt(j); if (_c == (char) 0x201C || _c == (char) 0x201D) _c = '"'; if (_c == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } if (j - 1 >= i + 1) { tok.add(opener + s.substring(i + 1, j - 1) + opener); i = j; continue; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else if (cc.equals("[[")) { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (cc.equals("[=") && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else if (s.substring(j, Math.min(j + 3, l)).equals("...")) j += 3; else if (c == '$' || c == '#') do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static public Rectangle toRectangle(Rect r) { return r == null ? null : r.getRectangle(); } static public Rect toRect(Rectangle r) { return r == null ? null : new Rect(r); } static public Rect toRect(RectangularShape r) { return r == null ? null : toRect(r.getBounds()); } static public Rect toRect(Rect r) { return r; } static public boolean rectContains(int x1, int y1, int w, int h, Pt p) { return p.x >= x1 && p.y >= y1 && p.x < x1 + w && p.y < y1 + h; } static public boolean rectContains(Rect a, Rect b) { return b.x >= a.x && b.y >= a.y && b.x2() <= a.x2() && b.y2() <= a.y2(); } static public boolean rectContains(Rect a, int x, int y) { return a != null && a.contains(x, y); } static public String programTitle() { return getProgramName(); } static public JFrame setFrameIconLater(Component c, final String imageID) { final JFrame frame = getFrame(c); if (frame != null) startThread("Loading Icon", new Runnable() { public void run() { try { final Image i = imageIcon(or2(imageID, "#1005557")).getImage(); swingLater(new Runnable() { public void run() { try { frame.setIconImage(i); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setIconImage(i);"; } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final Image i = imageIcon(or2(imageID, \"#1005557\")).getImage();\r\n swingL..."; } }); return frame; } static public void _initFrame(JFrame f) { myFrames_list.put(f, Boolean.TRUE); standardTitlePopupMenu(f); } static public Rectangle defaultNewFrameBounds_r = new Rectangle(300, 100, 500, 400); static public Rectangle defaultNewFrameBounds() { return swing(new F0() { public Rectangle get() { try { defaultNewFrameBounds_r.translate(60, 20); if (!screenRectangle().contains(defaultNewFrameBounds_r)) defaultNewFrameBounds_r.setLocation(30 + random(30), 20 + random(20)); return new Rectangle(defaultNewFrameBounds_r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "defaultNewFrameBounds_r.translate(60, 20);\r\n if (!screenRectangle().contai..."; } }); } static public void hideConsole() { final JFrame frame = consoleFrame(); if (frame != null) { autoVMExit(); swingLater(new Runnable() { public void run() { try { frame.setVisible(false); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setVisible(false);"; } }); } } static public boolean isAllUpperCase(String s) { return hasLettersAllUpperCase(s); } static public boolean isUpperCaseLetter(char c) { return Character.isUpperCase(c); } static public String substr(String s, int x) { return substring(s, x); } static public String substr(String s, int x, int y) { return substring(s, x, y); } static public BufferedReader utf8BufferedReader(InputStream in) { return utf8bufferedReader(in); } static public BufferedReader utf8BufferedReader(File f) { return utf8bufferedReader(f); } static public char stringToChar(String s) { if (l(s) != 1) throw fail("bad stringToChar: " + s); return firstChar(s); } static public void restart() { Object j = getJavaX(); call(j, "cleanRestart", get(j, "fullArgs")); } static volatile public Object isAllowed_function; static volatile public boolean isAllowed_all = true; static public boolean isAllowed(String askingMethod, Object... args) { Object f = vm_generalMap_get("isAllowed_function"); if (f != null && !isTrue(callF(f, askingMethod, args))) return false; return isAllowed_all || isTrue(callF(isAllowed_function, askingMethod, args)); } static public long round(double d) { return Math.round(d); } static public String round(String s) { return roundBracket(s); } static public String hmsWithColons() { return hmsWithColons(now()); } static public String hmsWithColons(long time) { return new SimpleDateFormat("HH:mm:ss").format(time); } static public String joinNemptiesWithColonSpace(String... strings) { return joinNempties(": ", strings); } static public String joinNemptiesWithColonSpace(Collection strings) { return joinNempties(": ", strings); } static public String tryToReadErrorStreamFromURLConnection(URLConnection conn) { try { if (conn instanceof HttpURLConnection) return stream2string(((HttpURLConnection) conn).getErrorStream()); return null; } catch (Throwable __e) { return null; } } static public boolean containsNewLine(String s) { return contains(s, '\n'); } static public String htmlencode2(String s) { return htmlencode_noQuotes(s); } static public int findEndOfCurlyBracketPart(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eq(cnc.get(j), "{")) ++level; else if (eq(cnc.get(j), "}")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static public void removeFromMultiPort(long vport) { if (vport == 0) return; for (Object port : getMultiPorts()) call(port, "removePort", vport); } static public String callStaticAnswerMethod(List bots, String s) { for (Object c : bots) try { String answer = callStaticAnswerMethod(c, s); if (!empty(answer)) return answer; } catch (Throwable e) { print("Error calling " + getProgramID(c)); e.printStackTrace(); } return null; } static public String callStaticAnswerMethod(Object c, String s) { String answer = (String) callOpt(c, "answer", s, litlist(s)); if (answer == null) answer = (String) callOpt(c, "answer", s); return emptyToNull(answer); } static public String callStaticAnswerMethod(String s) { return callStaticAnswerMethod(mc(), s); } static public String callStaticAnswerMethod(String s, List history) { return callStaticAnswerMethod(mc(), s, history); } static public String callStaticAnswerMethod(Object c, String s, List history) { String answer = (String) callOpt(c, "answer", s, history); if (answer == null) answer = (String) callOpt(c, "answer", s); return emptyToNull(answer); } static public List record_list = synchroList(); static public void record(Object o) { record_list.add(o); } static public Object addToMultiPort_responder; static public long addToMultiPort(final String botName) { return addToMultiPort(botName, new Object() { public String answer(String s, List history) { String answer = (String) (callOpt(getMainClass(), "answer", s, history)); if (answer != null) return answer; answer = (String) callOpt(getMainClass(), "answer", s); if (answer != null) return answer; if (match3("get injection id", s)) return getInjectionID(); return null; } }); } static public long addToMultiPort(final String botName, final Object responder) { addToMultiPort_responder = responder; startMultiPort(); List ports = getMultiPorts(); if (ports == null) return 0; if (ports.isEmpty()) throw fail("No multiports!"); if (ports.size() > 1) print("Multiple multi-ports. Using last one."); Object port = last(ports); Object responder2 = new Object() { public String answer(String s, List history) { if (match3("get injection id", s)) return getInjectionID(); if (match3("your name", s)) return botName; return (String) call(responder, "answer", s, history); } }; record(responder2); return (Long) call(port, "addResponder", botName, responder2); } static public AtomicInteger dialogServer_clients = new AtomicInteger(); static public boolean dialogServer_printConnects = false; static public ThreadLocal startDialogServer_quiet = new ThreadLocal(); static public Set dialogServer_knownClients = synchroTreeSet(); static public int startDialogServerOnPortAbove(int port, DialogHandler handler) { while (!forbiddenPort(port) && !startDialogServerIfPortAvailable(port, handler)) ++port; return port; } static public int startDialogServerOnPortAboveDaemon(int port, DialogHandler handler) { while (!forbiddenPort(port) && !startDialogServerIfPortAvailable(port, handler, true)) ++port; return port; } static public void startDialogServer(int port, DialogHandler handler) { if (!startDialogServerIfPortAvailable(port, handler)) throw fail("Can't start dialog server on port " + port); } static public boolean startDialogServerIfPortAvailable(int port, final DialogHandler handler) { return startDialogServerIfPortAvailable(port, handler, false); } static public ServerSocket startDialogServer_serverSocket; static public boolean startDialogServerIfPortAvailable(int port, final DialogHandler handler, boolean daemon) { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); } catch (IOException e) { return false; } final ServerSocket _serverSocket = serverSocket; startDialogServer_serverSocket = serverSocket; Thread thread = new Thread("Socket accept port " + port) { public void run() { try { while (true) { try { final Socket s = _serverSocket.accept(); String client = s.getInetAddress().toString(); if (!dialogServer_knownClients.contains(client) && neq(client, "/127.0.0.1")) { print("connect from " + client + " - clients: " + dialogServer_clients.incrementAndGet()); dialogServer_knownClients.add(client); } String threadName = "Handling client " + s.getInetAddress(); Thread t2 = new Thread(threadName) { public void run() { try { final Writer w = new OutputStreamWriter(s.getOutputStream(), "UTF-8"); final BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8")); DialogIO io = new DialogIO() { public boolean isLocalConnection() { return s.getInetAddress().isLoopbackAddress(); } public boolean isStillConnected() { return !(eos || s.isClosed()); } public void sendLine(String line) { try { w.write(line + "\n"); w.flush(); } catch (Exception __e) { throw rethrow(__e); } } public String readLineImpl() { try { return in.readLine(); } catch (Exception __e) { throw rethrow(__e); } } public void close() { try { s.close(); } catch (IOException e) { } } public Socket getSocket() { return s; } }; try { handler.run(io); } finally { if (!io.noClose) s.close(); } } catch (IOException e) { print("[internal] " + e); } finally { } } }; t2.setDaemon(true); t2.start(); } catch (SocketTimeoutException e) { } } } catch (IOException e) { print("[internal] " + e); } } }; if (daemon) thread.setDaemon(true); thread.start(); if (!isTrue(getAndClearThreadLocal(startDialogServer_quiet))) print("Dialog server on port " + port + " started."); return true; } static volatile public boolean readLine_noReadLine = false; static public String readLine_lastInput; static public String readLine_prefix = "[] "; static public String readLine() { if (readLine_noReadLine) return null; String s = readLineHidden(); if (s != null) { readLine_lastInput = s; print(readLine_prefix + s); } return s; } static public String getInnerMessage(Throwable e) { if (e == null) return null; return getInnerException(e).getMessage(); } static public boolean publicCommOn() { return "1".equals(loadTextFile(new File(userHome(), ".javax/public-communication"))); } static public String processID_cached; static public String getPID() { if (processID_cached == null) { String name = ManagementFactory.getRuntimeMXBean().getName(); processID_cached = name.replaceAll("@.*", ""); } return processID_cached; } static public String getInjectionID() { return (String) call(getJavaX(), "getInjectionID", getMainClass()); } static public String getProgramTitle() { return getProgramName(); } static public Object callOptMC(String method, Object... args) { return callOpt(mc(), method, args); } static public int numberOfFunctionArguments(Object f) { if (f instanceof F0) return 0; if (f instanceof F1) return 1; if (f instanceof F2) return 2; if (f instanceof VF1) return 1; if (f instanceof VF2) return 2; if (f instanceof String) return numberOfMethodArguments(mc(), (String) f); return numberOfMethodArguments(f, "get"); } static public JMenuItem directJMenuItem(Action a) { return new JMenuItem(a) { public Dimension getMaximumSize() { return new Dimension(super.getPreferredSize().width, super.getMaximumSize().height); } }; } static public JMenuItem directJMenuItem(String text, Object action) { return directJMenuItem(abstractAction(text, action)); } static public JMenuBar addMenuBar(final Component c) { return swing(new F0() { public JMenuBar get() { try { RootPaneContainer f = getPossiblyInternalFrame(c); if (f == null) return null; JMenuBar bar = (JMenuBar) (call(f, "getJMenuBar")); if (bar == null) { setMenuBar(f, bar = new JMenuBar()); revalidate((Component) f); } return bar; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "RootPaneContainer f = getPossiblyInternalFrame(c);\r\n if (f == null) null;\r..."; } }); } static public File localSnippetFile(long snippetID) { return localSnippetsDir(snippetID + ".text"); } static public File localSnippetFile(String snippetID) { return localSnippetFile(parseSnippetID(snippetID)); } static public String getFileInfoField(File f, String field) { return getOneLineFileInfoField(f, field); } static public File dropExtension(File f) { return f == null ? null : fileInSameDir(f, dropExtension(f.getName())); } static public String dropExtension(String s) { return takeFirst(s, smartLastIndexOf(s, '.')); } static public Object[] muricaCredentials() { String pass = muricaPassword(); return nempty(pass) ? new Object[] { "_pass", pass } : new Object[0]; } static public String standardCredentials() { String user = standardCredentialsUser(); String pass = standardCredentialsPass(); if (nempty(user) && nempty(pass)) return "&_user=" + urlencode(user) + "&_pass=" + urlencode(pass); return ""; } static public boolean saveTextFileIfDifferent(File f, String contents) { if (eq(loadTextFile(f), contents)) return false; { saveTextFile(f, contents); return true; } } static public int findEndOfBracketPart2(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eqOneOf(cnc.get(j), "{", "(", "[")) ++level; else if (eqOneOf(cnc.get(j), "}", ")", "]")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static public List nlTok(String s) { return javaTokPlusPeriod(s); } static public int imageIcon_cacheSize = 10; static public boolean imageIcon_verbose = false; static public Map imageIcon_cache; static public Lock imageIcon_lock = lock(); static public ThreadLocal imageIcon_fixGIF = new ThreadLocal(); static public ImageIcon imageIcon(String imageID) { try { if (imageID == null) return null; Lock __0 = imageIcon_lock; lock(__0); try { if (imageIcon_cache == null) imageIcon_cache = new MRUCache(imageIcon_cacheSize); imageID = fsI(imageID); ImageIcon ii = imageIcon_cache.get(imageID); if (ii == null) { if (imageIcon_verbose) print("Loading image icon: " + imageID); File f = loadBinarySnippet(imageID); Boolean b = imageIcon_fixGIF.get(); if (!isFalse(b)) ii = new ImageIcon(loadBufferedImageFixingGIFs(f)); else ii = new ImageIcon(f.toURI().toURL()); } else imageIcon_cache.remove(imageID); imageIcon_cache.put(imageID, ii); return ii; } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } static public ImageIcon imageIcon(File f) { try { return new ImageIcon(f.toURI().toURL()); } catch (Exception __e) { throw rethrow(__e); } } static public ImageIcon imageIcon(Image img) { return new ImageIcon(img); } static public ImageIcon imageIcon(RGBImage img) { return imageIcon(img.getBufferedImage()); } static public void standardTitlePopupMenu(final JFrame frame) { if (!isSubstanceLAF()) return; titlePopupMenu(frame, new VF1() { public void get(JPopupMenu menu) { try { boolean alwaysOnTop = frame.isAlwaysOnTop(); menu.add(jmenuItem("Restart Program", "restart")); menu.add(jmenuItem("Duplicate Program", "duplicateThisProgram")); menu.add(jmenuItem("Show Console", "showConsole")); menu.add(jCheckBoxMenuItem("Always On Top", alwaysOnTop, new Runnable() { public void run() { try { toggleAlwaysOnTop(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "toggleAlwaysOnTop(frame)"; } })); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "bool alwaysOnTop = frame.isAlwaysOnTop();\r\n ifndef standardTitlePopupMenu_..."; } }); } static public Rectangle screenRectangle() { return new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); } static public Rectangle screenRectangle(GraphicsDevice device) { if (device == null) return null; DisplayMode mode = device.getDisplayMode(); return new Rectangle(0, 0, mode.getWidth(), mode.getHeight()); } static public JFrame consoleFrame() { return (JFrame) getOpt(get(getJavaX(), "console"), "frame"); } static public void autoVMExit() { call(getJavaX(), "autoVMExit"); } static public boolean hasLettersAllUpperCase(String s) { return hasLetters(s) && !containsLowerCase(s); } static public void duplicateThisProgram() { nohupJavax(trim(programID() + " " + smartJoin((String[]) get(getJavaX(), "fullArgs")))); } static public void showConsole() { callOpt(get(javax(), "console"), "showConsole"); } static public char firstChar(String s) { return s.charAt(0); } static public String stream2string(InputStream in) { return utf8streamToString(in); } static public List getMultiPorts() { return (List) callOpt(getJavaX(), "getMultiPorts"); } static public String emptyToNull(String s) { return eq(s, "") ? null : s; } static public Map emptyToNull(Map map) { return empty(map) ? null : map; } static public void startMultiPort() { List mp = getMultiPorts(); if (mp != null && mp.isEmpty()) { nohupJavax("#1001639"); throw fail("Upgrading JavaX, please restart this program afterwards."); } } static public Set synchroTreeSet() { return Collections.synchronizedSet(new TreeSet()); } static public Set synchroTreeSet(TreeSet set) { return Collections.synchronizedSet(set); } static public boolean forbiddenPort(int port) { return port == 5037; } static public String readLineHidden() { try { if (get(javax(), "readLine_reader") == null) set(javax(), "readLine_reader", new BufferedReader(new InputStreamReader(System.in, "UTF-8"))); try { return ((BufferedReader) get(javax(), "readLine_reader")).readLine(); } finally { consoleClearInput(); } } catch (Exception __e) { throw rethrow(__e); } } static public int numberOfMethodArguments(Object o, String method) { Class c; boolean mustBeStatic = false; if (o instanceof Class) { c = (Class) o; mustBeStatic = true; } else c = o.getClass(); Class _c = c; int n = -1; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (!m.getName().equals(method)) continue; if (mustBeStatic && !methodIsStatic(m)) continue; int nn = l(m.getParameterTypes()); if (n == -1) n = nn; else if (n != nn) throw fail("Variable number of method arguments: " + _c + "." + method); } c = c.getSuperclass(); } if (n == -1) throw fail("Method not found: " + _c + "." + method); return n; } static public RootPaneContainer getPossiblyInternalFrame(Component c) { JInternalFrame f = getInternalFrame(c); if (f != null) return f; return optCast(RootPaneContainer.class, getWindow(c)); } static public void setMenuBar(final JMenuBar mb, final RootPaneContainer f) { { swing(new Runnable() { public void run() { try { call(f, "setJMenuBar", mb); revalidate((Component) f); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(f, \"setJMenuBar\", mb);\r\n revalidate((Component) f);"; } }); } } static public void setMenuBar(RootPaneContainer f, JMenuBar mb) { setMenuBar(mb, f); } static public File localSnippetsDir() { return javaxDataDir("Personal Programs"); } static public File localSnippetsDir(String sub) { return newFile(localSnippetsDir(), sub); } static public String getOneLineFileInfoField(File f, String field) { File infoFile = associatedInfosFile(f); List lines = lines(loadTextFile(infoFile)); return firstStartingWithIC_drop(lines, field + ": "); } static public boolean loadBufferedImageFixingGIFs_debug = false; static public ThreadLocal> loadBufferedImageFixingGIFs_output = new ThreadLocal(); static public Image loadBufferedImageFixingGIFs(File file) { try { if (!file.exists()) return null; if (!isGIF(file)) return ImageIO.read(file); if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": checking gif"); ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next(); reader.setInput(ImageIO.createImageInputStream(file)); int numImages = reader.getNumImages(true); IIOMetadata imageMetaData = reader.getImageMetadata(0); String metaFormatName = imageMetaData.getNativeMetadataFormatName(); boolean foundBug = false; for (int i = 0; i < numImages && !foundBug; i++) { IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(i).getAsTree(metaFormatName); int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { String delay = ((IIOMetadataNode) node).getAttribute("delayTime"); if (Integer.parseInt(delay) == 0) { foundBug = true; } break; } } } if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": " + f2s(file) + " foundBug=" + foundBug); Image image; if (!foundBug) { image = Toolkit.getDefaultToolkit().createImage(f2s(file)); } else { ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); { ImageOutputStream ios = ImageIO.createImageOutputStream(baoStream); try { ImageWriter writer = ImageIO.getImageWriter(reader); writer.setOutput(ios); writer.prepareWriteSequence(null); for (int i = 0; i < numImages; i++) { BufferedImage frameIn = reader.read(i); IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(i).getAsTree(metaFormatName); int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { String delay = ((IIOMetadataNode) node).getAttribute("delayTime"); if (Integer.parseInt(delay) == 0) { ((IIOMetadataNode) node).setAttribute("delayTime", "10"); } break; } } IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(frameIn), null); metadata.setFromTree(metadata.getNativeMetadataFormatName(), root); IIOImage frameOut = new IIOImage(frameIn, null, metadata); writer.writeToSequence(frameOut, writer.getDefaultWriteParam()); } writer.endWriteSequence(); } finally { _close(ios); } } byte[] data = baoStream.toByteArray(); setVar(loadBufferedImageFixingGIFs_output.get(), data); if (loadBufferedImageFixingGIFs_debug) print("Data size: " + l(data)); image = Toolkit.getDefaultToolkit().createImage(data); } return image; } catch (Exception __e) { throw rethrow(__e); } } static public boolean isSubstanceLAF() { return substanceLookAndFeelEnabled(); } static public boolean titlePopupMenu(final Component c, final Object menuMaker) { JComponent titleBar = getTitlePaneComponent(getPossiblyInternalFrame(c)); if (titleBar == null) { print("Can't add title right click!"); return false; } else { componentPopupMenu(titleBar, menuMaker); return true; } } static public JCheckBoxMenuItem jCheckBoxMenuItem(String text, boolean checked, final Object r) { final JCheckBoxMenuItem mi = swing(() -> new JCheckBoxMenuItem(text, checked)); addActionListener(mi, new Runnable() { public void run() { try { callF(r, isChecked(mi)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r, isChecked(mi))"; } }); return mi; } static public JCheckBoxMenuItem jCheckBoxMenuItem(String text, boolean checked, IVF1 r) { return jCheckBoxMenuItem(text, checked, (Object) r); } static public void toggleAlwaysOnTop(JFrame frame) { frame.setAlwaysOnTop(!frame.isAlwaysOnTop()); } static public boolean hasLetters(String s) { for (int i = 0; i < s.length(); i++) if (Character.isLetter(s.charAt(i))) return true; return false; } static public boolean containsLowerCase(String s) { for (int i = 0; i < l(s); i++) if (isLowerCase(s.charAt(i))) return true; return false; } static public void nohupJavax(final String javaxargs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs);"; } }); } } static public void nohupJavax(final String javaxargs, final String vmArgs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs, vmArgs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs, vmArgs);"; } }); } } static public String smartJoin(String[] args) { if (empty(args)) return ""; if (args.length == 1) return args[0]; String[] a = new String[args.length]; for (int i = 0; i < a.length; i++) a[i] = !isJavaIdentifier(args[i]) && !isQuoted(args[i]) ? quote(args[i]) : args[i]; return join(" ", a); } static public String smartJoin(List args) { return smartJoin(toStringArray(args)); } static public String utf8streamToString(InputStream in) { return readerToString(utf8bufferedReader(in)); } static public void consoleClearInput() { consoleSetInput(""); } static public File associatedInfosFile(File f) { return replaceExtension(f, ".infos"); } static public String firstStartingWithIC_drop(Collection l, final String prefix) { for (String s : unnull(l)) if (swic(s, prefix)) return substring(s, l(prefix)); return null; } static public String firstStartingWithIC_drop(String prefix, Collection l) { return firstStartingWithIC_drop(l, prefix); } static public byte[] isGIF_magic = bytesFromHex("47494638"); static public boolean isGIF(byte[] data) { return byteArrayStartsWith(data, isGIF_magic); } static public boolean isGIF(File f) { return isGIF(loadBeginningOfBinaryFile(f, l(isGIF_magic))); } static public void setVar(IVar v, A value) { if (v != null) v.set(value); } static public IVF1 setVar(IVar v) { return a -> { if (v != null) v.set(a); }; } static public boolean substanceLookAndFeelEnabled() { return startsWith(getLookAndFeel(), "org.pushingpixels."); } static public JComponent getTitlePaneComponent(RootPaneContainer window) { if (window instanceof JInternalFrame) return getInternalFrameTitlePaneComponent((JInternalFrame) window); if (!substanceLookAndFeelEnabled() || window == null) return null; JRootPane rootPane = window.getRootPane(); if (rootPane != null) { Object ui = rootPane.getUI(); return (JComponent) call(ui, "getTitlePane"); } return null; } static public void addActionListener(JTextField tf, final Runnable action) { onEnter(tf, action); } static public void addActionListener(final JComboBox cb, final Runnable action) { if (cb != null) { swing(new Runnable() { public void run() { try { cb.addActionListener(actionListener(action)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.addActionListener(actionListener(action));"; } }); } } static public void addActionListener(final AbstractButton b, final Runnable action) { if (b != null) { swing(new Runnable() { public void run() { try { b.addActionListener(actionListener(action)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "b.addActionListener(actionListener(action));"; } }); } } static public boolean isChecked(JCheckBox checkBox) { return checkBox != null && (boolean) swing(new F0() { public Boolean get() { try { return checkBox.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret checkBox.isSelected();"; } }); } static public boolean isChecked(JCheckBoxMenuItem mi) { return mi != null && (boolean) swing(new F0() { public Boolean get() { try { return mi.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret mi.isSelected();"; } }); } static public boolean isChecked(JRadioButton rb) { return rb != null && (boolean) swing(() -> rb.isSelected()); } static public boolean isLowerCase(char c) { return Character.isLowerCase(c); } static public Class hotwireOnce(String programID) { return hotwireCached(programID, false); } static public String readerToString(Reader r) { try { if (r == null) return null; try { StringBuilder buf = new StringBuilder(); int n = 0; while (true) { int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; } return buf.toString(); } finally { r.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public void consoleSetInput(final String text) { if (headless()) return; setTextAndSelectAll(consoleInputField(), text); focusConsole(); } static public File replaceExtension(File f, String extOld, String extNew) { return newFile(replaceExtension(f2s(f), extOld, extNew)); } static public File replaceExtension(File f, String extNew) { return replaceExtension(f, fileExtension(f), extNew); } static public String replaceExtension(String s, String extOld, String extNew) { s = dropSuffixIC(addPrefixOptIfNempty(".", extOld), s); return s + addPrefixOptIfNempty(".", extNew); } static public String replaceExtension(String name, String extNew) { return replaceExtension(name, fileExtension(name), extNew); } static public byte[] bytesFromHex(String s) { return hexToBytes(s); } static public boolean byteArrayStartsWith(byte[] a, byte[] b) { if (a == null || b == null) return false; if (a.length < b.length) return false; for (int i = 0; i < b.length; i++) if (a[i] != b[i]) return false; return true; } static public byte[] loadBeginningOfBinaryFile(File file, int maxBytes) { return loadBinaryFilePart(file, 0, maxBytes); } static public String getLookAndFeel() { return getClassName(UIManager.getLookAndFeel()); } static public JComponent getInternalFrameTitlePaneComponent(JInternalFrame f) { return (JComponent) childWithClassNameEndingWith(f, "InternalFrameTitlePane"); } static public TreeMap hotwireCached_cache = new TreeMap(); static public Lock hotwireCached_lock = lock(); static public Class hotwireCached(String programID) { return hotwireCached(programID, true); } static public Class hotwireCached(String programID, boolean runMain) { return hotwireCached(programID, runMain, false); } static public Class hotwireCached(String programID, boolean runMain, boolean dependent) { Lock __0 = hotwireCached_lock; lock(__0); try { programID = formatSnippetID(programID); Class c = hotwireCached_cache.get(programID); if (c == null) { c = hotwire(programID); if (dependent) makeDependent(c); if (runMain) callMain(c); hotwireCached_cache.put(programID, c); } return c; } finally { unlock(__0); } } static public JTextField setTextAndSelectAll(final JTextField tf, final String text) { if (tf != null) { swing(new Runnable() { public void run() { try { tf.setText(text); tf.selectAll(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tf.setText(text);\r\n tf.selectAll();"; } }); } return tf; } static public void focusConsole(String s) { setConsoleInput(s); focusConsole(); } static public void focusConsole() { JComponent tf = consoleInputFieldOrComboBox(); if (tf != null) { tf.requestFocus(); } } static public String dropSuffixIC(String suffix, String s) { return s == null ? null : ewic(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static public String addPrefixOptIfNempty(String prefix, String s) { return addPrefixIfNotEmpty2(prefix, s); } static public byte[] loadBinaryFilePart(File file, long start, long end) { try { RandomAccessFile raf = new RandomAccessFile(file, "r"); int n = toInt(min(raf.length(), end - start)); byte[] buffer = new byte[n]; try { raf.seek(start); raf.readFully(buffer, 0, n); return buffer; } finally { raf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public Component childWithClassNameEndingWith(Component c, String suffix) { if (endsWith(className(c), suffix)) return c; Component x; for (Component comp : getComponents(c)) if ((x = childWithClassNameEndingWith(comp, suffix)) != null) return x; return null; } static public Object makeDependent_postProcess; static public void makeDependent(Object c) { if (c == null) return; assertTrue("Not a class", c instanceof Class); dependentClasses(); hotwire_classes.add(new WeakReference(c)); Object local_log = getOpt(mc(), "local_log"); if (local_log != null) setOpt(c, "local_log", local_log); Object print_byThread = getOpt(mc(), "print_byThread"); if (print_byThread != null) setOpt(c, "print_byThread", print_byThread); callF(makeDependent_postProcess, c); } static public void setConsoleInput(String text) { consoleSetInput(text); } static public JComponent consoleInputFieldOrComboBox() { Object console = get(getJavaX(), "console"); JComboBox cb = (JComboBox) (getOpt(console, "cbInput")); if (cb != null) return cb; return (JTextField) getOpt(console, "tfInput"); } static public String addPrefixIfNotEmpty2(String prefix, String s) { return empty(s) ? "" : addPrefix(prefix, s); } static public List dependentClasses() { return cleanUpAndGetWeakReferencesList(hotwire_classes); } static public List> hotwire_classes = synchroList(); static public Class hotwireDependent(String src) { Class c = hotwire(src); makeDependent(c); return c; } static public List cleanUpAndGetWeakReferencesList(List> l) { if (l == null) return null; synchronized (l) { List out = new ArrayList(); for (int i = 0; i < l(l); i++) { A a = l.get(i).get(); if (a == null) l.remove(i--); else out.add(a); } return out; } } static abstract public class VF2 { abstract public void get(A a, B b); } static public class DefunctClassLoader { } static public class JS implements IF0 { public JS() { } public String code; public Set requiredLibraries; public Set requiredLibraries() { return requiredLibraries; } public JS(String code, Object... dollarVars) { this.code = jsDollarVars(code, dollarVars); } public String get() { return code; } public String toString() { return unnull(code); } public void requireJQuery() { require("jquery"); } public void require(Object library) { requiredLibraries = addToSet_create(requiredLibraries, library); } } static public class BetterThread extends Thread { public Runnable target; public BetterThread(Runnable target) { this.target = target; _created(); } public BetterThread(Runnable target, String name) { super(name); this.target = target; _created(); } public void _created() { vmBus_send("threadCreated", this); } public void run() { try { vmBus_send("threadStarted", this); if (target != null) target.run(); } finally { vmBus_send("threadEnded", this); } } public Runnable getTarget() { return target; } } static public interface ITokCondition { public boolean get(List tok, int i); } static abstract public class TokCondition implements ITokCondition { public abstract boolean get(List tok, int i); } static abstract public class LiveValue { abstract public Class getType(); abstract public A get(); abstract public void onChange(Runnable l); abstract public void removeOnChangeListener(Runnable l); public void onChangeAndNow(Runnable l) { onChange(l); callF(l); } } static final public class ParameterizedTypeImpl implements ParameterizedType { final public Type ownerType; final public Type rawType; final public Type[] typeArguments; public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) { this.typeArguments = typeArguments; this.rawType = rawType; this.ownerType = ownerType; } public Type[] getActualTypeArguments() { return typeArguments; } public Type getRawType() { return rawType; } public Type getOwnerType() { return ownerType; } @Override public boolean equals(Object other) { if (other instanceof ParameterizedType) return eq(ownerType, ((ParameterizedType) other).getOwnerType()) && eq(rawType, ((ParameterizedType) other).getRawType()) && eq(asList(typeArguments), asList(((ParameterizedType) other).getActualTypeArguments())); return false; } @Override public int hashCode() { return Arrays.hashCode(typeArguments) ^ rawType.hashCode() ^ _hashCode(ownerType); } @Override public String toString() { int length = typeArguments.length; if (length == 0) return typeToString(rawType); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(typeToString(rawType)).append("<").append(typeToString(typeArguments[0])); for (int i = 1; i < length; i++) { stringBuilder.append(", ").append(typeToString(typeArguments[i])); } return stringBuilder.append(">").toString(); } static public String typeToString(Type type) { return type instanceof Class ? ((Class) type).getName() : type.toString(); } } final static public class LongRange { public long start, end; public LongRange() { } public LongRange(long start, long end) { this.end = end; this.start = start; } public boolean equals(Object o) { if (o instanceof LongRange) return start == ((LongRange) o).start && end == ((LongRange) o).end; return false; } public int hashCode() { return boostHashCombine(hashOfLong(start), hashOfLong(end)); } public long length() { return end - start; } static public String _fieldOrder = "start end"; public String toString() { return "[" + start + ";" + end + "]"; } } final static public class ConceptFieldIndexDesc extends ConceptFieldIndexBase { public ConceptFieldIndexDesc(Class cc, String field) { super(cc, field); } public ConceptFieldIndexDesc(Concepts concepts, Class cc, String field) { super(concepts, cc, field); } public void init() { valueToObject = treeMultiSetMap(reverseOrder()); } public void register() { concepts.addFieldIndex(cc, field, this); } public void close() { concepts.removeFieldIndex(cc, field, this); super.close(); } synchronized public List objectsWithValueGreaterThan(Object value) { SortedMap> subMap = ((SortedMap>) valueToObject.data).headMap(value); return concatLists(values(subMap)); } } static public class Lowest { public A best; public double score; transient public Object onChange; synchronized public boolean isNewBest(double score) { return best == null || score < this.score; } synchronized public double bestScore() { return best == null ? Double.NaN : score; } public double score() { return bestScore(); } synchronized public float floatScore() { return best == null ? Float.NaN : (float) score; } synchronized public float floatScoreOr(float defaultValue) { return best == null ? defaultValue : (float) score; } public boolean put(A a, double score) { boolean change = false; synchronized (this) { if (a != null && isNewBest(score)) { best = a; this.score = score; change = true; } } if (change) pcallF(onChange); return change; } synchronized public void clear() { best = null; score = 0; } synchronized public A get() { return best; } synchronized public boolean has() { return best != null; } synchronized public Pair pair() { return best == null ? null : new Pair(best, bestScore()); } public String toString() { return "Score " + formatDouble_significant2(score, 4) + ": " + best; } } static public class SnippetTitles { public Map titles = synchroHashMap(); public String get(String snippetID) { if (snippetID == null) return null; long id = parseSnippetID(snippetID); if (titles.containsKey(id)) return titles.get(id); else { String title = getSnippetTitle_safe(snippetID); titles.put(id, title); return title; } } public String probe(String id) { return titles.get(parseSnippetID(id)); } public void put(String id, String title) { titles.put(parseSnippetID(id), title); } public boolean has(String id) { return titles.containsKey(parseSnippetID(id)); } public void clear() { titles.clear(); } } static public class JavaScript extends Var { public JavaScript() { } public JavaScript(String src) { super(src); } public String javaScriptSource() { return get(); } public String toString() { return hjs(get()); } } static public class _PrintIndent extends F1 { public String prefix; public boolean beginningOfLine = true; public _PrintIndent() { } public _PrintIndent(String prefix) { this.prefix = prefix; } public Boolean get(String s) { if (empty(s)) return false; boolean nl = s.endsWith("\n"); if (nl) s = dropLast(s); s = s.replace("\n", "\n" + prefix); print_raw(beginningOfLine ? prefix + s : s); if (nl) print_raw("\n"); beginningOfLine = nl; return false; } } static public interface IResourceLoader { public String loadSnippet(String snippetID); public String getTranspiled(String snippetID); public int getSnippetType(String snippetID); public String getSnippetTitle(String snippetID); public File loadLibrary(String snippetID); default public File pathToJavaXJar() { return pathToJavaxJar_noResourceLoader(); } default public File getSnippetJar(String snippetID, String transpiledSrc) { return null; } } static public class Either { public byte which; public Object value; public Either() { } public Either(int which, Object value) { this.which = (byte) which; this.value = value; } public boolean isA() { return which == 1; } public boolean isB() { return which == 2; } public A a() { if (which != 1) _failMe(); return (A) value; } public B b() { if (which != 2) _failMe(); return (B) value; } public A aOpt() { return which != 1 ? null : (A) value; } public B bOpt() { return which != 2 ? null : (B) value; } public void _failMe() { throw fail("Either object is of wrong type: " + shortClassName(value)); } public String toString() { return "Either" + (isA() ? "A" : "B") + "(" + value + ")"; } } static public class CompactLinkedHashSet extends AbstractSet { public UnsynchronizedCompactHashSet> entries = new UnsynchronizedCompactHashSet(); public Entry head, tail; static public class Entry { public A value; public Entry prev, next; public int hashCode() { return _hashCode(value); } public boolean equals(Object o) { return o == this || eq(value, o); } } public boolean add(A a) { if (entries.contains(a)) return false; Entry n = new Entry(); n.value = a; n.prev = tail; if (tail != null) tail.next = n; tail = n; if (head == null) head = n; entries.add(n); return true; } public boolean remove(Object a) { return remove(entries.find(a)); } public boolean remove(Entry node) { if (node == null) return false; if (node.next != null) node.next.prev = node.prev; else tail = node.prev; if (node.prev != null) node.prev.next = node.next; else head = node.next; entries.remove(node); return true; } public int size() { return entries.size(); } public IterableIterator iterator() { return new IterableIterator() { public Entry entry = head, prev = null; public boolean hasNext() { return entry != null; } public A next() { A a = entry.value; prev = entry; entry = entry.next; return a; } public void remove() { if (prev == null) throw new IllegalStateException(); CompactLinkedHashSet.this.remove(prev); prev = null; } }; } public void clear() { entries.clear(); head = tail = null; } public boolean contains(Object a) { return entries.contains(a); } public A find(Object o) { Entry e = entries.find(o); return e == null ? null : e.value; } public A prevElement(A a) { Entry e = entries.find(a); if (e == null || e.prev == null) return null; return e.prev.value; } public A nextElement(A a) { Entry e = entries.find(a); if (e == null || e.next == null) return null; return e.next.value; } public A first() { return head == null ? null : head.value; } public A last() { return tail == null ? null : tail.value; } public boolean removeIfSame(Object o) { A value = find(o); if (value == o) { remove(value); return true; } return false; } } static public class proxy_InvocationHandler implements InvocationHandler { public Object target; public proxy_InvocationHandler() { } public proxy_InvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) { return call(target, method.getName(), unnull(args)); } } static public class FixedRateTimer extends java.util.Timer implements AutoCloseable { public FixedRateTimer() { this(false); } public FixedRateTimer(boolean daemon) { this(defaultTimerName(), daemon); } public FixedRateTimer(String name) { this(name, false); } public FixedRateTimer(String name, boolean daemon) { super(name, daemon); _registerTimer(this); } public List entries = synchroList(); static public class Entry implements IFieldsToList { public TimerTask task; public long firstTime; public long period; public Entry() { } public Entry(TimerTask task, long firstTime, long period) { this.period = period; this.firstTime = firstTime; this.task = task; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + task + ", " + firstTime + ", " + period + ")"; } public Object[] _fieldsToList() { return new Object[] { task, firstTime, period }; } } public void scheduleAtFixedRate(TimerTask task, long delay, long period) { entries.add(new Entry(task, now() + delay, period)); super.scheduleAtFixedRate(task, delay, period); } public void cancel() { entries.clear(); super.cancel(); } public int purge() { entries.clear(); return super.purge(); } public FixedRateTimer changeRate(int newPeriod) { Object r = ((SmartTimerTask) first(entries).task).r; cancel(); return doEvery(newPeriod, r); } public void close() { cancel(); } } static public class MetaTransformer { static public interface StructureHandler { default public Object transform(Object o, IF1 recurse) { return null; } public void visit(Object o, IVF1 recurse); } public List structureHandlers; public Set seen; public MetaTransformer() { } public MetaTransformer(StructureHandler... handlers) { structureHandlers = asList(handlers); } final public void add(StructureHandler sh) { addStructureHandler(sh); } public void addStructureHandler(StructureHandler sh) { structureHandlers.add(sh); } public Object transform(IF1 f, Object o) { ping(); Object x = f.get(o); if (x != null) return x; IF1 recurse = liftFunction(f); for (StructureHandler h : unnullForIteration(structureHandlers)) { ping(); { Object __2 = h.transform(o, recurse); if (__2 != null) return __2; } } return o; } public void visit(IVF1 f, Object o) { ping(); if (o == null) return; if (seen != null && !seen.add(o)) return; f.get(o); for (StructureHandler h : unnullForIteration(structureHandlers)) { ping(); IVF1 recurse = x -> { markPointer(o, x); visit(f, x); }; h.visit(o, recurse); } } public void visit_vstack(IVF1 f, Object o) { vstackCompute(new visit_vstackComputable(f, o)); } public class visit_vstackComputable extends VStackComputableWithStep implements IFieldsToList { public IVF1 f; public Object o; public visit_vstackComputable() { } public visit_vstackComputable(IVF1 f, Object o) { this.o = o; this.f = f; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + f + ", " + o + ")"; } public boolean equals(Object _o) { if (!(_o instanceof visit_vstackComputable)) return false; visit_vstackComputable __0 = (visit_vstackComputable) _o; return eq(f, __0.f) && eq(o, __0.o); } public int hashCode() { int h = 1091269166; h = boostHashCombine(h, _hashCode(f)); h = boostHashCombine(h, _hashCode(o)); return h; } public Object[] _fieldsToList() { return new Object[] { f, o }; } public void step(VStack stack) { if (step == 0) { ping(); if (o == null) { stack._return(); return; } step++; } if (step == 1) { if (seen != null && !seen.add(o)) { stack._return(); return; } ++step; } if (step == 2) { f.get(o); ++step; } stack.replace(new ForEach_vstack<>(structureHandlers, h -> { IVF1 recurse = x -> { markPointer(o, x); stack.call(new visit_vstackComputable(f, x)); }; h.visit(o, recurse); })); } } public IF1 liftFunction(IF1 f) { return o -> transform(f, o); } public boolean any(IF1 pred, Object o) { Flag flag = new Flag(); withCancelPoint(cp -> visit(x -> { if (pred.get(x)) { flag.raise(); cancelTo(cp); } }, o)); return flag.isUp(); } public void addVisitor(IVF1 visitor) { if (visitor == null) return; addStructureHandler(new StructureHandler() { public void visit(Object o, IVF1 recurse) { visitor.get(o); } }); } public void avoidCycles() { seen = identityHashSet(); } transient public IVF2 markPointer; public void markPointer(Object a, Object b) { if (markPointer != null) markPointer.get(a, b); else markPointer_base(a, b); } final public void markPointer_fallback(IVF2 _f, Object a, Object b) { if (_f != null) _f.get(a, b); else markPointer_base(a, b); } public void markPointer_base(Object a, Object b) { } } static public interface IResourceHolder { public A add(A a); } static abstract public class DialogIO implements AutoCloseable { public String line; public boolean eos, loud, noClose; public Lock lock = lock(); abstract public String readLineImpl(); abstract public boolean isStillConnected(); abstract public void sendLine(String line); abstract public boolean isLocalConnection(); abstract public Socket getSocket(); public int getPort() { Socket s = getSocket(); return s == null ? 0 : s.getPort(); } public boolean helloRead = false; public int shortenOutputTo = 500; public String readLineNoBlock() { String l = line; line = null; return l; } public boolean waitForLine() { try { ping(); if (line != null) return true; line = readLineImpl(); if (line == null) eos = true; return line != null; } catch (Exception __e) { throw rethrow(__e); } } public String readLine() { waitForLine(); helloRead = true; return readLineNoBlock(); } public String ask(String s, Object... args) { if (loud) return askLoudly(s, args); if (!helloRead) readLine(); if (args.length != 0) s = format3(s, args); sendLine(s); return readLine(); } public String askLoudly(String s, Object... args) { if (!helloRead) readLine(); if (args.length != 0) s = format3(s, args); print("> " + shorten(s, shortenOutputTo)); sendLine(s); String answer = readLine(); print("< " + shorten(answer, shortenOutputTo)); return answer; } public void pushback(String l) { if (line != null) throw fail(); line = l; helloRead = false; } } static abstract public class DialogHandler { abstract public void run(DialogIO io); } static public class ConceptFieldIndex extends ConceptFieldIndexBase { public ConceptFieldIndex(Class cc, String field) { super(cc, field); } public ConceptFieldIndex(Concepts concepts, Class cc, String field) { super(concepts, cc, field); } public void init() { valueToObject = new MultiSetMap(); } public void register() { concepts.addFieldIndex(cc, field, this); } } static public interface IRef extends IF0 { public default void replaceValue(A oldValue, A newValue) { } } abstract static public class AbstractLayoutManager implements LayoutManager { public Dimension preferredSize = new Dimension(100, 100); public Dimension minimumSize = new Dimension(10, 10); public void addLayoutComponent(String name, Component comp) { } public void removeLayoutComponent(Component comp) { } public Dimension preferredLayoutSize(Container parent) { layoutContainer(parent); return preferredSize; } public Dimension minimumLayoutSize(Container parent) { return minimumSize; } } static abstract public class F2 { abstract public C get(A a, B b); } final static public class ContentsIndexedList extends RandomAccessAbstractList implements IContentsIndexedList, IContentsIndexedList2 { public Map>> index = new HashMap(); final public ArrayList> list = new ArrayList(); final static public class Elem extends HasIndex { public A s; public String toString() { return "Elem " + quote(s) + "@" + idx; } } public ContentsIndexedList() { } public ContentsIndexedList(Map>> index) { this.index = index; } public ContentsIndexedList(Collection l) { addAll(l); } public A get(int i) { return list.get(i).s; } public int size() { return list.size(); } public A set(int i, A s) { Elem t = list.get(i); A old = t.s; if (eq(old, s)) return old; removeFromIdx(t); t.s = s; addToIdx(t); return old; } public boolean add(A s) { ++modCount; Elem t = new Elem(); t.s = s; t.idx = size(); list.add(t); addToIdx(t); return true; } public void add(int i, A s) { ++modCount; Elem t = new Elem(); t.s = s; t.idx = i; list.add(i, t); reorder(i + 1); addToIdx(t); } public boolean addAll(int i, Collection l) { int n = l.size(); if (n == 0) return false; ++modCount; List> l2 = emptyList(n); int j = i; for (A s : l) { Elem t = new Elem(); t.s = s; t.idx = j++; l2.add(t); } list.addAll(i, l2); reorder(i + n); for (Elem t : l2) addToIdx(t); return true; } public A remove(int i) { ++modCount; Elem t = list.get(i); removeFromIdx(t); list.remove(i); reorder(i); return t.s; } public void reorder(int fromIdx) { int n = size(); for (int i = fromIdx; i < n; i++) list.get(i).idx = i; } public void removeFromIdx(Elem t) { TreeSet> idx = index.get(t.s); idx.remove(t); if (idx.isEmpty()) index.remove(t.s); } public void addToIdx(Elem t) { TreeSet> idx = index.get(t.s); if (idx == null) index.put(t.s, idx = new TreeSet()); idx.add(t); } @Override public int indexOf(Object s) { TreeSet> l = index.get(s); return l == null ? -1 : first(l).idx; } @Override public int lastIndexOf(Object s) { TreeSet> l = index.get(s); return l == null ? -1 : last(l).idx; } @Override public boolean contains(Object s) { return index.containsKey(s); } public void clear() { ++modCount; index.clear(); list.clear(); } public void removeRange(int fromIndex, int toIndex) { if (fromIndex == toIndex) return; ++modCount; for (int i = fromIndex; i < toIndex; i++) removeFromIdx(list.get(i)); list.subList(fromIndex, toIndex).clear(); reorder(fromIndex); } public int[] indicesOf(Object o) { TreeSet> idx = index.get(o); if (idx == null) return emptyIntArray(); int[] a = new int[idx.size()]; int i = 0; for (Elem t : idx) a[i++] = t.idx; return a; } public TreeSet indicesOf_treeSetOfHasIndex(Object o) { return (TreeSet) index.get(o); } } static public class MRUCache extends LinkedHashMap { public int maxSize = 10; public MRUCache() { } public MRUCache(int maxSize) { this.maxSize = maxSize; } public boolean removeEldestEntry(Map.Entry eldest) { return size() > maxSize; } public Object _serialize() { return ll(maxSize, cloneLinkedHashMap(this)); } static public MRUCache _deserialize(List l) { MRUCache m = new MRUCache(); m.maxSize = (int) first(l); m.putAll((LinkedHashMap) second(l)); return m; } } static abstract public class CloseableIterableIterator extends IterableIterator implements AutoCloseable { public void close() throws Exception { } } static public class ExpiringMap2 extends AbstractMap { public Map> byKey = new HashMap(); public PriorityBlockingQueue> queue = new PriorityBlockingQueue(); public long standardExpiryTime; public boolean renewOnOverwrite = true, renewOnGet; public Object onChange; public boolean useCountdown = true; public RestartableCountdown countdown = new RestartableCountdown(); public long nextClean; public ExpiringMap2() { } public ExpiringMap2(long standardExpiryTime) { this.standardExpiryTime = standardExpiryTime; } public ExpiringMap2(long standardExpiryTime, Object onChange) { this.onChange = onChange; this.standardExpiryTime = standardExpiryTime; } public ExpiringMap2(double standardExpirySeconds) { standardExpiryTime = toMS(standardExpirySeconds); } synchronized public boolean clean() { boolean changes = false; Pair p; long time = sysTime(); while ((p = queue.peek()) != null && time >= p.a) { if (useCountdown) { countdown.stop(); nextClean = 0; } p = queue.poll(); Pair v = byKey.get(p.b); if (v != null) { byKey.remove(p.b); changes = true; change(); } } if (useCountdown) { long needClean = p != null ? p.a : 0; if (needClean != nextClean) { nextClean = p.a; countdown.start(nextClean - time, new Runnable() { public void run() { try { clean(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "clean();"; } }); } } return changes; } public void change() { callF(onChange); } synchronized public B put(A a, B b) { clean(); long timeout = sysTime() + standardExpiryTime; Pair p = byKey.get(a); if (p != null && renewOnOverwrite) queue.remove(new Pair(p.a, a)); byKey.put(a, pair(timeout, b)); change(); if (p == null || renewOnOverwrite) queue.add(new Pair(timeout, a)); return pairB(p); } synchronized public B remove(Object a) { clean(); Pair p = byKey.get(a); if (p == null) return null; queue.remove(new Pair(p.a, a)); byKey.remove(a); change(); return p.b; } synchronized public B get(Object a) { clean(); Pair p = byKey.get(a); if (renewOnGet && p != null) { queue.remove(new Pair(p.a, a)); long timeout = sysTime() + standardExpiryTime; byKey.put((A) a, pair(timeout, p.b)); queue.add(new Pair(timeout, a)); } return pairB(p); } synchronized public Set> entrySet() { clean(); return synchronizedSet(mapValues(__106 -> pairB(__106), byKey).entrySet()); } synchronized public Set keySet() { clean(); return synchronizedSet(byKey.keySet()); } synchronized public int size() { clean(); return byKey.size(); } public void setStandardExpiryTime(long ms) { standardExpiryTime = ms; } synchronized public ExpiringMap2 setMap(Map innerMap) { byKey = innerMap; return this; } } static public class ConceptFieldIndexCI extends ConceptFieldIndexBase { public ConceptFieldIndexCI(Class cc, String field) { super(cc, field); } public ConceptFieldIndexCI(Concepts concepts, Class cc, String field) { super(concepts, cc, field); } public void init() { valueToObject = generalizedCIMultiSetMap(); } public void register() { concepts.addCIFieldIndex(cc, field, this); } } static public interface Producer { public A next(); } static public class InternationalPhoneValidator { public String rawInput; public String filtered; public List dialCodes; public String countryPart, localPart; public boolean valid = false; public String error; public InternationalPhoneValidator() { } public InternationalPhoneValidator(String rawInput) { this.rawInput = rawInput; } public void run() { filtered = dropPrefix("+", dropSpecialChars(rawInput)); if (!isAllDigits(filtered)) { error = "Bad characters"; return; } splitLocal(); } public String dropSpecialChars(String s) { return replaceAll(s, "[\\s\\(\\)\\-]", ""); } public void splitLocal() { String countryPart = longestPrefixInNavigableSet(filtered, navigableKeys(countryDialCodes_rawNumbersTreeMultiMap())); if (countryPart == null) { error = "Invalid country code"; return; } dialCodes = countryDialCodes_rawNumbersTreeMultiMap().get(countryPart); localPart = dropPrefix(countryPart, filtered); if (l(filtered) < 7) { error = "Phone number too short"; return; } else if (l(filtered) > 15) { error = "Phone number too long"; return; } valid = true; } } static public class AlphanumComparator implements Comparator { public boolean ignoreCase = false; final public boolean isDigit(char ch) { return ((ch >= 48) && (ch <= 57)); } final public String getChunk(String s, int slength, int marker) { StringBuilder chunk = new StringBuilder(); char c = s.charAt(marker); chunk.append(c); marker++; if (isDigit(c)) while (marker < slength) { c = s.charAt(marker); if (!isDigit(c)) break; chunk.append(c); marker++; } else while (marker < slength) { c = s.charAt(marker); if (isDigit(c)) break; chunk.append(c); marker++; } return chunk.toString(); } public int compare(String s1, String s2) { if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return 1; int thisMarker = 0; int thatMarker = 0; int s1Length = s1.length(); int s2Length = s2.length(); while (thisMarker < s1Length && thatMarker < s2Length) { String thisChunk = getChunk(s1, s1Length, thisMarker); thisMarker += thisChunk.length(); String thatChunk = getChunk(s2, s2Length, thatMarker); thatMarker += thatChunk.length(); int result = 0; if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) { int thisChunkLength = thisChunk.length(); result = thisChunkLength - thatChunk.length(); if (result == 0) { for (int i = 0; i < thisChunkLength; i++) { result = thisChunk.charAt(i) - thatChunk.charAt(i); if (result != 0) { return result; } } } } else { result = thisChunk.compareTo(thatChunk); } if (result != 0) return result; } return s1Length - s2Length; } } static public class Cache { public Object maker; public A value; public long loaded; static public boolean debug = false; public long changeCount; public Lock lock = lock(); public Cache() { } public Cache(Object maker) { this.maker = maker; } public Cache(IF0 maker) { this.maker = maker; } public A get() { if (hasLock(lock)) return value; Lock __0 = lock; lock(__0); try { if (loaded == 0) { value = make(); changeCount++; loaded = sysNow(); } return value; } finally { unlock(__0); } } public void clear() { Lock __1 = lock; lock(__1); try { if (debug && loaded != 0) print("Clearing cache"); value = null; changeCount++; loaded = 0; } finally { unlock(__1); } } public void clear(double seconds) { Lock __2 = lock; lock(__2); try { if (seconds != 0 && loaded != 0 && sysNow() >= loaded + seconds * 1000) clear(); } finally { unlock(__2); } } public void set(A a) { Lock __3 = lock; lock(__3); try { value = a; ++changeCount; loaded = sysNow(); } finally { unlock(__3); } } public A make() { return (A) callF(maker); } } abstract static public class ConceptFieldIndexBase implements IConceptIndex, IFieldIndex, IConceptCounter, AutoCloseable { public Concepts concepts; public Class cc; public String field; public Map objectToValue = syncHashMap(); public MultiSetMap valueToObject; public ConceptFieldIndexBase() { init(); } public ConceptFieldIndexBase(Class cc, String field) { this(db_mainConcepts(), cc, field); } public ConceptFieldIndexBase(Concepts concepts, Class cc, String field) { this(); this.field = field; this.cc = cc; this.concepts = concepts; concepts.addConceptIndex(this); updateAll(); register(); updateAll(); } public void updateAll() { for (A c : setToIndex()) updateImpl(c); } public Collection setToIndex() { return list(concepts, cc); } abstract public void init(); abstract public void register(); public void update(Concept c) { if (!isInstance(cc, c)) return; updateImpl((A) c); } synchronized public void updateImpl(A c) { Val newValue = (Val) (cget(c, field)); Val oldValue = objectToValue.get(c); if (newValue == oldValue && (oldValue != null || objectToValue.containsKey(c))) return; valueToObject.remove(oldValue, c); valueToObject.put(newValue, c); put(objectToValue, c, newValue); } public synchronized void remove(Concept c) { if (!isInstance(cc, c)) return; if (!objectToValue.containsKey(c)) return; Val value = objectToValue.get(c); objectToValue.remove(c); valueToObject.remove(value, (A) c); } synchronized public A get(Val value) { return valueToObject.getFirst(value); } public synchronized Collection getAll(Val value) { return valueToObject.get(value); } public synchronized List allValues() { return cloneKeys_noSync(valueToObject.data); } public IterableIterator objectIterator() { return navigableMultiSetMapValuesIterator_concurrent(valueToObject, this); } public synchronized MultiSet allValues_multiSet() { return multiSetMapToMultiSet(valueToObject); } public Class conceptClass() { return cc; } public int countConcepts() { return l(objectToValue); } public Collection allConcepts() { return (Collection) keys(objectToValue); } public Object mutex() { return this; } public void close() { concepts.removeConceptIndex(this); } } abstract static public class VStackComputableWithStep implements VStack.Computable { public int step; public void step(VStack stack, Object subComputationResult) { step(stack); } public void step(VStack stack) { } } static public interface IContentsIndexedList2 extends List { public TreeSet indicesOf_treeSetOfHasIndex(Object o); } static public class MultiSetMap { public Map> data = new HashMap>(); public int size; public MultiSetMap() { } public MultiSetMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); } public MultiSetMap(MultiSetMap map) { putAll(map); } public MultiSetMap(Map> data) { this.data = data; } public boolean put(A key, B value) { synchronized (data) { Set set = data.get(key); if (set == null) data.put(key, set = _makeEmptySet()); if (!set.add(value)) return false; { ++size; return true; } } } public boolean add(A key, B value) { return put(key, value); } public void addAll(A key, Collection values) { synchronized (data) { putAll(key, values); } } public void addAllIfNotThere(A key, Collection values) { synchronized (data) { for (B value : values) setPut(key, value); } } public void setPut(A key, B value) { synchronized (data) { if (!containsPair(key, value)) put(key, value); } } final public boolean contains(A key, B value) { return containsPair(key, value); } public boolean containsPair(A key, B value) { synchronized (data) { return get(key).contains(value); } } public void putAll(A key, Collection values) { synchronized (data) { for (B value : values) put(key, value); } } public void removeAll(A key, Collection values) { synchronized (data) { for (B value : values) remove(key, value); } } public Set get(A key) { synchronized (data) { Set set = data.get(key); return set == null ? Collections.emptySet() : set; } } public Set getOpt(A key) { synchronized (data) { return data.get(key); } } public Set getActual(A key) { synchronized (data) { Set set = data.get(key); if (set == null) data.put(key, set = _makeEmptySet()); return set; } } public void clean(A key) { synchronized (data) { Set list = data.get(key); if (list != null && list.isEmpty()) data.remove(key); } } public Set keySet() { synchronized (data) { return data.keySet(); } } public Set keys() { synchronized (data) { return data.keySet(); } } public void remove(A key) { synchronized (data) { size -= l(data.get(key)); data.remove(key); } } public void remove(A key, B value) { synchronized (data) { Set set = data.get(key); if (set != null) { if (set.remove(value)) { --size; if (set.isEmpty()) data.remove(key); } } } } public void clear() { synchronized (data) { data.clear(); size = 0; } } public boolean containsKey(A key) { synchronized (data) { return data.containsKey(key); } } public B getFirst(A key) { synchronized (data) { return first(get(key)); } } public void addAll(MultiSetMap map) { putAll(map); } public void putAll(MultiSetMap map) { synchronized (data) { for (A key : map.keySet()) putAll(key, map.get(key)); } } public void putAll(Map map) { synchronized (data) { if (map != null) for (Map.Entry e : map.entrySet()) put(e.getKey(), e.getValue()); } } public int keysSize() { synchronized (data) { return l(data); } } public int size() { synchronized (data) { return size; } } public int getSize(A key) { return l(data.get(key)); } public int count(A key) { return getSize(key); } public Set reverseGet(B b) { synchronized (data) { Set l = new HashSet(); for (A key : data.keySet()) if (data.get(key).contains(b)) l.add(key); return l; } } public A keyForValue(B b) { synchronized (data) { for (A key : data.keySet()) if (data.get(key).contains(b)) return key; return null; } } public Map> asMap() { synchronized (data) { return cloneMap(data); } } public boolean isEmpty() { synchronized (data) { return data.isEmpty(); } } public Set _makeEmptySet() { return new HashSet(); } public Collection> allLists() { synchronized (data) { return new HashSet(data.values()); } } public List allValues() { return concatLists(values(data)); } public List> allEntries() { synchronized (data) { List> l = emptyList(size); for (Map.Entry> __0 : _entrySet(data)) { A a = __0.getKey(); Set set = __0.getValue(); for (B b : set) l.add(pair(a, b)); } return l; } } public Object mutex() { return data; } public String toString() { return "mm" + str(data); } public Pair firstEntry() { synchronized (data) { if (empty(data)) return null; Map.Entry> entry = data.entrySet().iterator().next(); return pair(entry.getKey(), first(entry.getValue())); } } public A firstKey() { synchronized (data) { return main.firstKey(data); } } public A lastKey() { synchronized (data) { return (A) ((NavigableMap) data).lastKey(); } } public A higherKey(Object a) { synchronized (data) { return (A) ((NavigableMap) data).higherKey(a); } } } static public class ForEach_vstack extends VStackComputableWithStep implements IFieldsToList { public Iterable l; public IVF1 body; public ForEach_vstack() { } public ForEach_vstack(Iterable l, IVF1 body) { this.body = body; this.l = l; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + l + ", " + body + ")"; } public Object[] _fieldsToList() { return new Object[] { l, body }; } public Iterator it; public void step(VStack stack) { if (step == 0) { if (l == null) { stack._return(); return; } it = iterator(l); ++step; } if (!it.hasNext()) { stack._return(); return; } body.get(it.next()); } } static public class RestartableCountdown implements AutoCloseable { public java.util.Timer timer; synchronized public void start(long delayMS, Object action) { stop(); timer = doLater_daemon(delayMS, action); } public void start(double delaySeconds, Object action) { start(toMS(delaySeconds), action); } synchronized public void stop() { cancelTimer(timer); timer = null; } public void close() { stop(); } } static public class VStack implements Steppable { public List stack = new ArrayList(); public Object latestResult; transient public Object newResult; static public class NullSentinel { } static public NullSentinel nullSentinel = new NullSentinel(); public VStack() { } public VStack(Computable computation) { push(computation); } public VStack(Iterable l) { pushAll(l); } public interface Computable { public void step(VStack stack, Object subComputationResult); } final public Object deSentinel(Object o) { return o instanceof NullSentinel ? null : o; } final public Object sentinel(Object o) { return o == null ? nullSentinel : o; } final public void call(Computable computation) { push(computation); } public void push(Computable computation) { stack.add(computation); } public boolean step() { if (empty(stack)) return false; newResult = null; last(stack).step(this, result()); latestResult = newResult; newResult = null; return true; } public void _return() { _return(null); } public void _return(Object value) { newResult = sentinel(value); removeLast(stack); } final public void replace(Computable computation) { tailCall(computation); } public void tailCall(Computable computation) { removeLast(stack); stack.add(computation); } public A compute(Computable computation) { if (computation == null) return null; push(computation); stepAll(this); return (A) latestResult; } final public Object subResult() { return result(); } public Object result() { return deSentinel(latestResult); } public boolean hasSubResult() { return latestResult != null; } public void pushAll(Iterable l) { for (Computable c : unnullForIteration(l)) push(c); } public void add(Runnable r) { if (r == null) return; push((stack, subComputationResult) -> r.run()); } } static public class UnsynchronizedCompactHashSet extends java.util.AbstractSet { final static public int INITIAL_SIZE = 3; public final static double LOAD_FACTOR = 0.75; final static public Object nullObject = new Object(); final static public Object deletedObject = new Object(); public int elements; public int freecells; public A[] objects; public int modCount; public UnsynchronizedCompactHashSet() { this(INITIAL_SIZE); } public UnsynchronizedCompactHashSet(int size) { objects = (A[]) new Object[(size == 0 ? 1 : size)]; elements = 0; freecells = objects.length; modCount = 0; } public UnsynchronizedCompactHashSet(Collection c) { this(c.size()); addAll(c); } @Override public Iterator iterator() { return new CompactHashIterator(); } @Override public int size() { return elements; } @Override public boolean isEmpty() { return elements == 0; } @Override public boolean contains(Object o) { return find(o) != null; } public A find(Object o) { if (o == null) o = nullObject; int hash = o.hashCode(); int index = (hash & 0x7FFFFFFF) % objects.length; int offset = 1; while (objects[index] != null && !(objects[index].hashCode() == hash && objects[index].equals(o))) { index = ((index + offset) & 0x7FFFFFFF) % objects.length; offset = offset * 2 + 1; if (offset == -1) offset = 2; } return objects[index]; } public boolean removeIfSame(Object o) { A value = find(o); if (value == o) { remove(value); return true; } return false; } @Override public boolean add(Object o) { if (o == null) o = nullObject; int hash = o.hashCode(); int index = (hash & 0x7FFFFFFF) % objects.length; int offset = 1; int deletedix = -1; while (objects[index] != null && !(objects[index].hashCode() == hash && objects[index].equals(o))) { if (objects[index] == deletedObject) deletedix = index; index = ((index + offset) & 0x7FFFFFFF) % objects.length; offset = offset * 2 + 1; if (offset == -1) offset = 2; } if (objects[index] == null) { if (deletedix != -1) index = deletedix; else freecells--; modCount++; elements++; objects[index] = (A) o; if (1 - (freecells / (double) objects.length) > LOAD_FACTOR) rehash(); return true; } else return false; } @Override public boolean remove(Object o) { if (o == null) o = nullObject; int hash = o.hashCode(); int index = (hash & 0x7FFFFFFF) % objects.length; int offset = 1; while (objects[index] != null && !(objects[index].hashCode() == hash && objects[index].equals(o))) { index = ((index + offset) & 0x7FFFFFFF) % objects.length; offset = offset * 2 + 1; if (offset == -1) offset = 2; } if (objects[index] != null) { objects[index] = (A) deletedObject; modCount++; elements--; return true; } else return false; } @Override public void clear() { elements = 0; for (int ix = 0; ix < objects.length; ix++) objects[ix] = null; freecells = objects.length; modCount++; } @Override public Object[] toArray() { Object[] result = new Object[elements]; Object[] objects = this.objects; int pos = 0; for (int i = 0; i < objects.length; i++) if (objects[i] != null && objects[i] != deletedObject) { if (objects[i] == nullObject) result[pos++] = null; else result[pos++] = objects[i]; } return result; } @Override public T[] toArray(T[] a) { int size = elements; if (a.length < size) a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); A[] objects = this.objects; int pos = 0; for (int i = 0; i < objects.length; i++) if (objects[i] != null && objects[i] != deletedObject) { if (objects[i] == nullObject) a[pos++] = null; else a[pos++] = (T) objects[i]; } return a; } public void rehash() { int garbagecells = objects.length - (elements + freecells); if (garbagecells / (double) objects.length > 0.05) rehash(objects.length); else rehash(objects.length * 2 + 1); } public void rehash(int newCapacity) { int oldCapacity = objects.length; @SuppressWarnings("unchecked") A[] newObjects = (A[]) new Object[newCapacity]; for (int ix = 0; ix < oldCapacity; ix++) { Object o = objects[ix]; if (o == null || o == deletedObject) continue; int hash = o.hashCode(); int index = (hash & 0x7FFFFFFF) % newCapacity; int offset = 1; while (newObjects[index] != null) { index = ((index + offset) & 0x7FFFFFFF) % newCapacity; offset = offset * 2 + 1; if (offset == -1) offset = 2; } newObjects[index] = (A) o; } objects = newObjects; freecells = objects.length - elements; } public class CompactHashIterator implements Iterator { public int index; public int lastReturned = -1; public int expectedModCount; @SuppressWarnings("empty-statement") public CompactHashIterator() { for (index = 0; index < objects.length && (objects[index] == null || objects[index] == deletedObject); index++) ; expectedModCount = modCount; } @Override public boolean hasNext() { return index < objects.length; } @SuppressWarnings("empty-statement") @Override public T next() { int length = objects.length; if (index >= length) { lastReturned = -2; throw new NoSuchElementException(); } lastReturned = index; for (index += 1; index < length && (objects[index] == null || objects[index] == deletedObject); index++) ; if (objects[lastReturned] == nullObject) return null; else return (T) objects[lastReturned]; } @Override public void remove() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (lastReturned == -1 || lastReturned == -2) throw new IllegalStateException(); if (objects[lastReturned] != null && objects[lastReturned] != deletedObject) { objects[lastReturned] = (A) deletedObject; elements--; modCount++; expectedModCount = modCount; } } } public int capacity() { return objects.length; } public boolean shrinkToFactor(double factor) { if (factor > LOAD_FACTOR) throw fail("Shrink factor must be equal to or smaller than load factor: " + factor + " / " + LOAD_FACTOR); int newCapacity = max(INITIAL_SIZE, iround(size() / factor)); if (newCapacity >= capacity()) return false; rehash(newCapacity); return true; } } static public interface IContentsIndexedList extends List { public int[] indicesOf(Object o); } abstract static public class RandomAccessAbstractList extends AbstractList implements RandomAccess { } static public class Flag implements Runnable { public boolean up = false; public synchronized boolean raise() { if (!up) { up = true; notifyAll(); return true; } else return false; } public synchronized void waitUntilUp() { while (!up) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public boolean waitUntilUp(double timeout) { return waitUntilUp(toMS(timeout)); } public synchronized boolean waitUntilUp(long timeout) { if (!up) { try { wait(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } return isUp(); } public synchronized boolean isUp() { return up; } public boolean get() { return isUp(); } public String toString() { return isUp() ? "up" : "down"; } public void waitForThisOr(Flag otherFlag) { try { while (!isUp() && !otherFlag.isUp()) Thread.sleep(50); } catch (Exception __e) { throw rethrow(__e); } } public void run() { raise(); } } static public class HasIndex implements Comparable { public int idx; public HasIndex() { } public HasIndex(int idx) { this.idx = idx; } public int compareTo(HasIndex h) { return idx - h.idx; } } static public interface Steppable { public boolean step(); } static public String dropTrailingSlashIfNemptyAfterwards(String s) { return l(s) > 1 ? dropSuffix("/", s) : s; } static public A highestConceptByField(Class c, String field) { return highestConceptByField(db_mainConcepts(), c, field); } static public A highestConceptByField(Concepts concepts, Class c, String field) { IFieldIndex index = concepts.getFieldIndex(c, field); if (index instanceof ConceptFieldIndexDesc) { Map.Entry e = ((NavigableMap) ((ConceptFieldIndexDesc) index).valueToObject.data).firstEntry(); return e == null ? null : (A) first((Collection) e.getValue()); } return highestByField(field, concepts.list(c)); } static public List sortedByConceptIDDesc(Collection c) { return sortedByCalculatedFieldDesc(__107 -> conceptID(__107), c); } static public Collection conceptsWhereCI(Class c, Object... params) { return findConceptsWhereCI(c, params); } static public Collection conceptsWhereCI(String c, Object... params) { return findConceptsWhereCI(c, params); } static public Collection conceptsWhereCI(Concepts concepts, Class c, Object... params) { return findConceptsWhereCI(concepts, c, params); } static public List conceptsWhereCI(Concepts concepts, String c, Object... params) { return findConceptsWhereCI(concepts, c, params); } static public String joinNemptiesWithColon(String... strings) { return joinNempties(": ", strings); } static public String joinNemptiesWithColon(Collection strings) { return joinNempties(": ", strings); } static public long parseLongOpt_pcall(String s) { try { return isInteger(s) ? parseLong(s) : 0; } catch (Throwable __e) { print(exceptionToStringShort(__e)); } return 0; } static public String addPlusToCount(long max, long n, String s) { if (n != max) return s; return insertString(s, smartIndexOfSpaceEtc(s), "+"); } static public Object serveFavIcon(String icoSnippet) { return serveFavIcon(loadLibrary(icoSnippet)); } static public Object serveFavIcon(File icoFile) { return favIconHeaders(subBot_serveFile(icoFile, faviconMimeType())); } static public Map withoutKey(Map map, A key) { return mapWithoutKey(map, key); } static public Map withoutKey(A key, Map map) { return withoutKey(map, key); } static public String beforeSlashOrAll(String s) { return beforeSlash_orAll(s); } static public List stringToStringListOpt(IF1> f, Object o) { if (o instanceof String) return f.get((String) o); return (List) o; } static public List tok_identifiersInOrder(String s) { return filter(__108 -> isIdentifier(__108), javaTokC(s)); } static public List tok_identifiersInOrder(List tok) { return filter(__109 -> isIdentifier(__109), codeTokens(tok)); } static public List objectsWhereFieldGreaterThan(Collection c, String field, Object value) { List l = new ArrayList(); for (A x : unnull(c)) if (cmp(getOpt(x, field), value) > 0) l.add(x); return l; } static public boolean conceptsWithFieldGreaterThan_sorted_verbose = false; static public Collection conceptsWithFieldGreaterThan_sorted(Class c, String field, Object value) { return conceptsWithFieldGreaterThan_sorted(db_mainConcepts(), c, field, value); } static public Collection conceptsWithFieldGreaterThan_sorted(Concepts concepts, Class c, String field, Object value) { IFieldIndex index = concepts.getFieldIndex(c, field); if (index instanceof ConceptFieldIndexDesc) return reverseInPlace(((ConceptFieldIndexDesc) index).objectsWithValueGreaterThan(value)); if (conceptsWithFieldGreaterThan_sorted_verbose) print("conceptsWithFieldGreaterThan: table scan of " + c + " for field " + field); return sortByFieldInPlace(field, objectsWhereFieldGreaterThan(concepts.list(c), field, value)); } static public double elapsedSeconds_sysNow(long time) { return elapsedSeconds(time); } static public Pair uniq2(Class c, Object... params) { return uniq2(db_mainConcepts(), c, params); } static public Pair uniq2(Concepts cc, Class c, Object... params) { AutoCloseable __1 = tempDBLock(cc); try { params = expandParams(c, params); A x = findConceptWhere(cc, c, params); if (x == null) { x = unlisted(c); csetAll(x, params); cc.register(x); return pair(x, true); } return pair(x, false); } finally { _close(__1); } } static public List allToLong(Collection l) { return lmap(__110 -> toLong(__110), l); } static public List tok_integersInOrder(String s) { return filter(__111 -> isInteger(__111), javaTokC(s)); } static public boolean isProperlyQuoted(String s) { return s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"") && (!s.endsWith("\\\"") || s.endsWith("\\\\\"")) && !containsNewLine(s); } static public Map safeUnstructureMap(String s) { return (Map) safeUnstructure(s); } static public Map safeUnstructureMap(File f) { return (Map) safeUnstructure(f); } static public Map onlyKeys(Map map, Collection keys) { Set keySet = asSet(keys); return filterKeys(map, a -> contains(keySet, a)); } static public Map onlyKeys(Map map, A... keys) { return onlyKeys(map, litset(keys)); } static public Object serve500() { return subBot_serve500(); } static public Object serve500(String msg) { return subBot_serve500(msg); } static public B getAndRemove(Map map, A a) { if (!containsKey(map, a)) return null; B b = map.get(a); map.remove(a); return b; } static public B getAndRemove(A a, Map map) { return getAndRemove(map, a); } static public String sortLinesAlphaNumIC(String s) { return lines_possiblyRTrim(s, sortedAlphanumIC(lines(s))); } static public A assertNempty(A a) { return assertNempty("empty", a); } static public A assertNempty(String msg, A a) { if (empty(a)) throw fail(msg + ": " + a); return a; } static public String localTimeWithSeconds(long time) { return simpleDateFormat_local("HH:mm:ss").format(time); } static public String localTimeWithSeconds() { return localTimeWithSeconds(now()); } static public String unquoteAllLines(String s) { return linesPreservingTrailingNewLine(s, unquoteAll(lines(s))); } static public Either eitherB(B b) { return new Either(2, b); } static public Either eitherA(A a) { return new Either(1, a); } static public Map prependEmptyOptionForHSelect(Map map) { Map map2 = litorderedmap("", ""); putAll(map2, map); return map2; } static public LinkedHashMap mapToOrderedMap(Object f, Iterable l) { LinkedHashMap map = new LinkedHashMap(); for (Object o : unnullForIteration(l)) { Pair p = (Pair) (callF(f, o)); map.put(p.a, p.b); } return map; } static public LinkedHashMap mapToOrderedMap(IF1> f, Iterable l) { LinkedHashMap map = new LinkedHashMap(); for (A o : unnullForIteration(l)) { Pair p = callF(f, o); map.put(p.a, p.b); } return map; } static public LinkedHashMap mapToOrderedMap(Iterable l, IF1> f) { return mapToOrderedMap(f, l); } static public boolean conceptsSortedByFieldCI_verbose = false; static public Collection conceptsSortedByFieldCI(Class c, String field) { return conceptsSortedByFieldCI(db_mainConcepts(), c, field); } static public Collection conceptsSortedByFieldCI(Concepts concepts, Class c, String field) { IFieldIndex index = concepts.getCIFieldIndex(c, field); if (index instanceof ConceptFieldIndexCI) return (Collection) asList(((ConceptFieldIndexCI) index).objectIterator()); if (conceptsSortedByFieldCI_verbose) print("conceptsSortedByFieldCI_verbose: Manual sort of " + c + " for " + field); return sortedByFieldIC(field, concepts.list(c)); } static public String hselect(String name, Map map, Object... params) { return hselect(map, paramsPlus_skipFirst(params, "name", name)); } static public String hselect(Map map, Object... params) { StringBuilder buf = new StringBuilder(); String selected = null; if (odd(l(params))) { selected = str(first(params)); params = dropFirst(params); } int i = indexOf(params, "allowEmpty"); if (even(i)) { buf.append("\n"); params[i] = params[i + 1] = null; } if (nempty(map)) for (Object key : keys(map)) { Object value = map.get(key); String k = str(key); buf.append(tag("option", htmlencode(str(or(value, ""))), "value", k, "selected", eq(selected, k) ? "selected" : null)).append("\n"); } return tag("select", buf, params) + "\n"; } static public String hquery(Map params) { return htmlQuery(params); } static public String hquery(Object... data) { return htmlQuery(data); } static public String loadJQuery() { return ""; } static public String hscriptsrc(String src) { return hjavascript_src(src); } static public boolean conceptsWithFieldGreaterThan_verbose = false; static public Collection conceptsWithFieldGreaterThan(Class c, String field, Object value) { return conceptsWithFieldGreaterThan(db_mainConcepts(), c, field, value); } static public Collection conceptsWithFieldGreaterThan(Concepts concepts, Class c, String field, Object value) { IFieldIndex index = concepts.getFieldIndex(c, field); if (index instanceof ConceptFieldIndexDesc) return ((ConceptFieldIndexDesc) index).objectsWithValueGreaterThan(value); if (conceptsWithFieldGreaterThan_verbose) print("conceptsWithFieldGreaterThan: table scan of " + c + " for field " + field); return objectsWhereFieldGreaterThan(concepts.list(c), field, value); } static public String hhiddenWithID(String id) { return hhiddenWithID(id, null); } static public String hhiddenWithID(String id, Object value, Object... params) { return tag("input", "", paramsPlus(params, "type", "hidden", "id", id, "value", value)); } static public String hsimpletableheader(String... cols) { return tag("tr", join(lambdaMap(__112 -> th(__112), cols))); } static public List lastTwo(List l) { return takeLast(2, l); } static public String hparagraphs(Collection l) { return lines(lambdaMap(__113 -> p(__113), l)); } static public String hscript_clickableRows() { return hscript("\r\n jQuery(document).ready(function($) {\r\n $(\".clickable-row\").click(function() {\r\n window.location = $(this).data(\"href\");\r\n });\r\n });\r\n "); } static public String hdivWithID(String id, Object contents, Object... params) { return hdiv(contents, paramsPlus(params, "id", id)); } static public String hdesktopNotifications() { return hscript("\r\n function sendDesktopNotification(text, options) {\r\n if (\"Notification\" in window && Notification.permission === \"granted\")\r\n new Notification(text, options);\r\n }\r\n window.sendDesktopNotification = sendDesktopNotification;\r\n \r\n function initDesktopNotifications() {\r\n if (!(\"Notification\" in window))\r\n $(\"#notiStatus\").html(\"Desktop notifications not supported in this browser\");\r\n else if (Notification.permission === \"granted\")\r\n $(\"#notiStatus\").html(\"Desktop notifications enabled\");\r\n else if (Notification.permission === \"denied\")\r\n $(\"#notiStatus\").html(\"Desktop notifications denied\");\r\n else {\r\n $(\"#notiStatus\").html(\"Requesting permission for desktop notifications\");\r\n Notification.requestPermission().then(function (permission) {\r\n initDesktopNotifications();\r\n sendDesktopNotification(\"Notifications will look like this!\");\r\n });\r\n }\r\n }\r\n \r\n $(document).ready(initDesktopNotifications);\r\n "); } static public String hframeset_cols(String cols, Object contents, Object... params) { return tag("frameset", contents, paramsPlus(params, "cols", cols)); } static public String hframeset_rows(String rows, Object contents, Object... params) { return tag("frameset", contents, paramsPlus(params, "rows", rows)); } static public String htmlEncode2If(boolean b, String s) { return b ? htmlEncode2(s) : s; } static public JPanel centerAndSouthWithMargins(Component c, Component s) { return applyDefaultMargin(centerAndSouth(c, withTopMargin(s))); } static public JPanel centerAndSouthWithMargins(int margin, Component c, Component s) { return applyMargin(margin, centerAndSouth(c, withTopMargin(margin, s))); } static public SingleComponentPanel singleComponentPanel() { return singleComponentPanel(null); } static public SingleComponentPanel singleComponentPanel(final Component c) { return swing(new F0() { public SingleComponentPanel get() { try { return new SingleComponentPanel(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret new SingleComponentPanel(c);"; } }); } static public JPanel jrightalignedline(Component... components) { return jrightAlignedLine(components); } static public JPanel jrightalignedline(List components) { return jrightAlignedLine(components); } static public JPanel centerAndEastWithMargin(Component c, Component e) { return centerAndEastWithMarginInbetween(c, e); } static public JCheckBox dm_fieldCheckBox(String field) { return dm_fieldCheckBox(humanizeFormLabel(field), field); } static public JCheckBox dm_fieldCheckBox(String text, String field) { if (isIdentifier(text) && !isIdentifier(field)) { String temp = field; field = text; text = temp; } return jLiveValueCheckBox(text, dm_fieldLiveValue(field)); } static public void addComponentsFirst(Container c, Component... l) { containerAddFirst(c, l); } static public void scpSet(SingleComponentPanel scp, Component c) { setSCPComponent(scp, c); } static public Set addToSet_create(Set set, A a) { return createOrAddToSet(set, a); } static public A onChange(A spinner, Object r) { { swing(new Runnable() { public void run() { try { spinner.addChangeListener(changeListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "spinner.addChangeListener(changeListener(r));"; } }); } return spinner; } static public A onChange(A b, Object r) { { swing(new Runnable() { public void run() { try { b.addItemListener(itemListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "b.addItemListener(itemListener(r));"; } }); } return b; } static public void onChange(JTextComponent tc, Object r) { onUpdate(tc, r); } static public A onChange(A slider, final Object r) { { swing(new Runnable() { public void run() { try { slider.addChangeListener(changeListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "slider.addChangeListener(changeListener(r));"; } }); } return slider; } static public JComboBox onChange(Object r, JComboBox cb) { return onChange(cb, r); } static public JComboBox onChange(JComboBox cb, final Object r) { if (isEditableComboBox(cb)) onChange(textFieldFromComboBox(cb), r); else onSelectedItem(cb, new VF1() { public void get(String s) { try { callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r)"; } }); return cb; } static public Type getRawType(Type t) { if (t instanceof ParameterizedType) return ((ParameterizedType) t).getRawType(); return t; } static public int hashOfLong(long l) { return Long.hashCode(l); } static public MultiSetMap treeMultiSetMap() { return new MultiSetMap(true); } static public MultiSetMap treeMultiSetMap(Comparator comparator) { return new MultiSetMap(new TreeMap>(comparator)); } static public Comparator reverseOrder() { return new Comparator() { public int compare(Object a, Object b) { return cmp(b, a); } }; } static public String formatDouble_significant2(double d, int digits) { try { digits -= max(0, Math.floor(Math.log10(abs(d)) + 1)); return formatDouble(d, digits); } catch (Throwable _e) { print("Had number: " + d + ", digits: " + digits); throw rethrow(_e); } } static public String getSnippetTitle_safe(String id) { if (isLocalSnippetID(id)) return localSnippetTitle(id); String title = or(loadTextFile(snippetTitle_cacheFile(id)), "?"); try { title = getSnippetTitle(id); } catch (Throwable __e) { _handleException(__e); } return title; } static public File pathToJavaxJar() { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.pathToJavaXJar(); return pathToJavaxJar_noResourceLoader(); } static public File pathToJavaxJar_noResourceLoader() { try { int x = latestInstalledJavaX(); File xfile = new File(userHome(), ".javax/x" + Math.max(x, 30) + ".jar"); if (!xfile.isFile()) { print("Saving " + f2s(xfile)); String url = x30JarServerURL(); byte[] data = loadBinaryPage(url); if (data.length < 1000000) throw fail("Could not load " + url); saveBinaryFile(xfile.getPath(), data); } return xfile; } catch (Exception __e) { throw rethrow(__e); } } static public boolean isA(Either e) { return eitherIsA(e); } static public String find(String pattern, String text) { Matcher matcher = Pattern.compile(pattern).matcher(text); if (matcher.find()) return matcher.group(1); return null; } static public A find(Collection c, Object... data) { for (A x : c) if (checkFields(x, data)) return x; return null; } static public String defaultTimerName_name; static public String defaultTimerName() { if (defaultTimerName_name == null) defaultTimerName_name = "A timer by " + programID(); return defaultTimerName_name; } static public Set _registerTimer_list = newWeakHashSet(); static public void _registerTimer(java.util.Timer timer) { _registerTimer_list.add(timer); } static public void cleanMeUp__registerTimer() { cancelTimers(getAndClearList(_registerTimer_list)); } static public A vstackCompute(VStack.Computable computation) { return vStackCompute(computation); } static public void withCancelPoint(VF1 r) { CancelPoint cp = newCancelPoint(); try { try { callF(r, cp); } catch (Throwable e) { e = innerException(e); if (!(e instanceof CancelToCancelPoint && ((CancelToCancelPoint) e).cp == cp)) rethrow(e); } } finally { _close(cp); } } static public void withCancelPoint(IVF1 r) { CancelPoint cp = newCancelPoint(); try { try { r.get(cp); } catch (Throwable e) { e = innerException(e); if (!(e instanceof CancelToCancelPoint && ((CancelToCancelPoint) e).cp == cp)) rethrow(e); } } finally { _close(cp); } } static public RuntimeException cancelTo(CancelPoint cp) { if (cp.closed) throw fail("cancel point closed"); throw new CancelToCancelPoint(cp); } static public long sysTime() { return sysNow(); } static public Map mapValues(Object func, Map map) { Map m = similarEmptyMap(map); for (Object key : keys(map)) m.put(key, callF(func, map.get(key))); return m; } static public Map mapValues(Map map, IF1 f) { return mapValues(f, map); } static public Map mapValues(IF1 f, Map map) { Map m = similarEmptyMap(map); for (Map.Entry __0 : _entrySet(map)) { A key = __0.getKey(); B val = __0.getValue(); m.put(key, f.get(val)); } return m; } static public Map mapValues(Map map, Object func) { return mapValues(func, map); } static public MultiSetMap generalizedCIMultiSetMap() { MultiSetMap mm = new MultiSetMap(); mm.data = generalizedCIMap(); return mm; } static public boolean isAllDigits(String s) { int n = l(s); for (int i = 0; i < n; i++) if (!isDigit(s.charAt(i))) return false; return true; } static public List replaceAll(List l, final A a, final A b) { return map(l, new F1() { public A get(A x) { try { return eq(x, a) ? b : x; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "eq(x, a) ? b : x"; } }); } static public String replaceAll(String s, String a, String b) { return s == null ? null : s.replaceAll(a, b); } static public String longestPrefixInNavigableSet(String s, NavigableSet set) { if (set == null || s == null) return null; while (licensed()) { String key = set.floor(s); if (key == null) break; int n = lCommonPrefix(key, s); if (n == l(key)) return key; s = takeFirst(s, n); } return null; } static public NavigableSet navigableKeys(NavigableMap map) { return map == null ? new TreeSet() : map.navigableKeySet(); } static public NavigableSet navigableKeys(MultiSet ms) { return ((NavigableMap) ms.map).navigableKeySet(); } static public NavigableSet navigableKeys(MultiMap mm) { return ((NavigableMap) mm.data).navigableKeySet(); } static public Cache> countryDialCodes_rawNumbersTreeMultiMap_cache = new Cache<>(() -> countryDialCodes_rawNumbersTreeMultiMap_load()); static public MultiMap countryDialCodes_rawNumbersTreeMultiMap() { return countryDialCodes_rawNumbersTreeMultiMap_cache.get(); } static public MultiMap countryDialCodes_rawNumbersTreeMultiMap_load() { return mapToMultiMap(mapKeys(__114 -> digitsOnly(__114), multiMapToMap(countryDialCodesMultiMap()))); } static public boolean hasLock(Lock lock) { return ((ReentrantLock) lock).isHeldByCurrentThread(); } static public Map syncHashMap() { return synchroHashMap(); } static public void register(Concept c) { registerConcept(c); } static public List getAll(Map map, Collection l) { return lookupAllOpt(map, l); } static public List getAll(Collection l, Map map) { return lookupAllOpt(map, l); } static public > List getAll(Iterable l) { return getVars(l); } static public List cloneKeys_noSync(Map map) { return cloneList_noSync(keys(map)); } static public IterableIterator navigableMultiSetMapValuesIterator_concurrent(final MultiSetMap mm) { return navigableMultiSetMapValuesIterator_concurrent(mm, mm.data); } static public IterableIterator navigableMultiSetMapValuesIterator_concurrent(final MultiSetMap mm, Object mutex) { return iteratorFromFunction(new F0() { public Iterator> it = concurrentlyIterateValues((NavigableMap) mm.data, mutex); public Iterator it2; public B get() { while (it2 == null || !it2.hasNext()) { if (!it.hasNext()) return null; it2 = iterator(asList(it.next())); } return it2.next(); } }); } static public MultiSet multiSetMapToMultiSet(MultiSetMap mm) { MultiSet ms = new MultiSet(); for (A a : keys(mm)) ms.add(a, l(mm.get(a))); return ms; } static public Collection allConcepts() { return db_mainConcepts().allConcepts(); } static public Collection allConcepts(Concepts concepts) { return concepts.allConcepts(); } static public boolean step(Steppable steppable) { return steppable == null ? null : steppable.step(); } static public Map.Entry firstEntry(Map map) { return empty(map) ? null : first(map.entrySet()); } static public A firstKey(Map map) { return first(keys(map)); } static public A firstKey(MultiSetMap map) { return map == null ? null : firstKey(map.data); } static public java.util.Timer doLater_daemon(long delay, final Object r) { final java.util.Timer timer = new java.util.Timer(true); timer.schedule(timerTask(r, timer), delay); return timer; } static public java.util.Timer doLater_daemon(double delaySeconds, final Object r) { return doLater_daemon(toMS(delaySeconds), r); } static public void cancelTimer(javax.swing.Timer timer) { if (timer != null) timer.stop(); } static public void cancelTimer(java.util.Timer timer) { if (timer != null) timer.cancel(); } static public void cancelTimer(Object o) { if (o instanceof java.util.Timer) cancelTimer((java.util.Timer) o); else if (o instanceof javax.swing.Timer) cancelTimer((javax.swing.Timer) o); else if (o instanceof AutoCloseable) { try { ((AutoCloseable) o).close(); } catch (Throwable __e) { _handleException(__e); } } } static public void stepAll(Steppable s) { if (s != null) while (s.step()) { ping(); } } static public class HyperCompactTreeSet extends AbstractSet { static final public boolean RED = true; static final public boolean BLACK = false; static final public Object nullSentinel = new Object(); public Node root; public int size; abstract static public class Node { public A val; public Node left() { return null; } abstract public Node setLeft(Node left); public Node right() { return null; } abstract public Node setRight(Node right); abstract public boolean color(); abstract public Node convertToBlack(); abstract public Node convertToRed(); abstract public Node invertColor(); public Node convertToColor(boolean color) { return color == RED ? convertToRed() : convertToBlack(); } abstract public boolean isLeaf(); } static public class SpecialNode extends Node { public A leftVal; public SpecialNode(A leftVal, A val) { this.val = val; this.leftVal = leftVal; } public boolean color() { return BLACK; } public Node convertToBlack() { return this; } public Node convertToRed() { return newNode(RED, val, left(), right()); } public Node invertColor() { return convertToRed(); } public Node left() { return newLeaf(RED, leftVal); } public Node setLeft(Node left) { if (left != null && left.isLeaf() && left.color() == RED) { leftVal = left.val; return this; } else return newNode(BLACK, val, left, right()); } public Node right() { return null; } public Node setRight(Node right) { if (right == null) return this; return newNode(color(), val, left(), right); } public boolean isLeaf() { return false; } } abstract static public class NonLeaf extends Node { public Object left, right; public boolean defaultLeftLeafColor() { return BLACK; } public boolean defaultRightLeafColor() { return BLACK; } public Node left() { return left == null ? null : left instanceof Node ? (Node) left : newLeaf(defaultLeftLeafColor(), (A) left); } public void setLeft_noMorph(Node left) { this.left = left != null && left.isLeaf() && left.color() == defaultLeftLeafColor() ? left.val : left; } public void setRight_noMorph(Node right) { this.right = right != null && right.isLeaf() && right.color() == defaultRightLeafColor() ? right.val : right; } public Node setLeft(Node left) { if (color() == BLACK && right == null && left != null && left.isLeaf() && left.color() == RED) return new SpecialNode(left.val, val); setLeft_noMorph(left); if (left == null && right() == null) return newLeaf(color(), val); return this; } public Node right() { return right == null ? null : right instanceof Node ? (Node) right : newLeaf(defaultRightLeafColor(), (A) right); } public Node setRight(Node right) { if (right == null && this.right != null) return newNode(color(), val, left(), null); setRight_noMorph(right); return this; } public boolean isLeaf() { return false; } } static public class BlackNode extends NonLeaf { public BlackNode(A val) { this.val = val; } public boolean color() { return BLACK; } public Node convertToBlack() { return this; } public Node convertToRed() { return newNode(RED, val, left(), right()); } public Node invertColor() { return convertToRed(); } } static public class RedNode extends NonLeaf { public RedNode(A val) { this.val = val; } public boolean color() { return RED; } public Node convertToBlack() { return newNode(BLACK, val, left(), right()); } public Node convertToRed() { return this; } public Node invertColor() { return convertToBlack(); } } abstract static public class Leaf extends Node { public boolean isLeaf() { return true; } public Node setLeft(Node left) { return left == null ? this : newNode(color(), val, left, null); } public Node setRight(Node right) { return right == null ? this : newNode(color(), val, null, right); } } static public class BlackLeaf extends Leaf { public BlackLeaf(A val) { this.val = val; } public boolean color() { return BLACK; } public Node convertToBlack() { return this; } public Node convertToRed() { return new RedLeaf(val); } public Node invertColor() { return convertToRed(); } } static public class RedLeaf extends Leaf { public RedLeaf(A val) { this.val = val; } public boolean color() { return RED; } public Node convertToBlack() { return new BlackLeaf(val); } public Node convertToRed() { return this; } public Node invertColor() { return convertToBlack(); } } public HyperCompactTreeSet() { } public HyperCompactTreeSet(Collection cl) { addAll(cl); } static public Object deSentinel(Object o) { return o == nullSentinel ? null : o; } static public Object sentinel(Object o) { return o == null ? nullSentinel : o; } static public boolean isRed(Node x) { return x != null && x.color() == RED; } static public Node newLeaf(boolean color, A val) { return color == RED ? new RedLeaf(val) : new BlackLeaf(val); } static public Node newNode(boolean color, A val, Node left, Node right) { if (left == null && right == null) return newLeaf(color, val); if (color == BLACK && right == null && left != null && left.isLeaf() && left.color() == RED) return new SpecialNode(left.val, val); NonLeaf node = color == RED ? new RedNode(val) : new BlackNode(val); node.setLeft_noMorph(left); node.setRight_noMorph(right); return node; } public int size() { return size; } public boolean isEmpty() { return root == null; } public boolean add(A val) { val = (A) sentinel(val); int oldSize = size; root = put(root, val); root = root.convertToBlack(); return size > oldSize; } final public Node put(Node h, A val) { if (h == null) { ++size; return new RedLeaf(val); } int cmp = compare_deSentinel(val, h.val); if (cmp < 0) h = h.setLeft(put(h.left(), val)); else if (cmp > 0) h = h.setRight(put(h.right(), val)); else { } if (isRed(h.right()) && !isRed(h.left())) h = rotateLeft(h); if (isRed(h.left()) && isRed(h.left().left())) h = rotateRight(h); if (isRed(h.left()) && isRed(h.right())) h = flipColors(h); return h; } final public int compare_deSentinel(A a, A b) { return compare((A) deSentinel(a), (A) deSentinel(b)); } public int compare(A a, A b) { return cmp(a, b); } public boolean remove(Object key) { if (!contains(key)) return false; key = sentinel(key); if (!isRed(root.left()) && !isRed(root.right())) root = root.convertToRed(); root = delete(root, (A) key); if (!isEmpty()) root = root.convertToBlack(); return true; } final public Node delete(Node h, A key) { if (compare_deSentinel(key, h.val) < 0) { if (!isRed(h.left()) && !isRed(h.left().left())) h = moveRedLeft(h); h = h.setLeft(delete(h.left(), key)); } else { if (isRed(h.left())) h = rotateRight(h); if (compare_deSentinel(key, h.val) == 0 && (h.right() == null)) { --size; return null; } if (!isRed(h.right()) && !isRed(h.right().left())) h = moveRedRight(h); if (compare_deSentinel(key, h.val) == 0) { --size; Node x = min(h.right()); h.val = x.val; h = h.setRight(deleteMin(h.right())); } else h = h.setRight(delete(h.right(), key)); } return balance(h); } final public Node rotateRight(Node h) { Node x = h.left(); h = h.setLeft(x.right()); x = x.setRight(h); x = x.convertToColor(x.right().color()); x = x.setRight(x.right().convertToRed()); return x; } final public Node rotateLeft(Node h) { Node x = h.right(); h = h.setRight(x.left()); x = x.setLeft(h); x = x.convertToColor(x.left().color()); x = x.setLeft(x.left().convertToRed()); return x; } final public Node flipColors(Node h) { h = h.setLeft(h.left().invertColor()); h = h.setRight(h.right().invertColor()); return h.invertColor(); } final public Node moveRedLeft(Node h) { h = flipColors(h); if (isRed(h.right().left())) { h = h.setRight(rotateRight(h.right())); h = rotateLeft(h); h = flipColors(h); } return h; } final public Node moveRedRight(Node h) { h = flipColors(h); if (isRed(h.left().left())) { h = rotateRight(h); h = flipColors(h); } return h; } final public Node balance(Node h) { if (isRed(h.right())) h = rotateLeft(h); if (isRed(h.left()) && isRed(h.left().left())) h = rotateRight(h); if (isRed(h.left()) && isRed(h.right())) h = flipColors(h); return h; } public int height() { return height(root); } final public int height(Node x) { if (x == null) return -1; return 1 + Math.max(height(x.left()), height(x.right())); } public boolean contains(Object val) { return find(root, (A) sentinel(val)) != null; } public A find(A probeVal) { probeVal = (A) sentinel(probeVal); Node n = find(root, probeVal); return n == null ? null : n.val; } final public A get(Node x, A key) { x = find(x, key); return x == null ? null : x.val; } public Node find(Node x, A key) { while (x != null) { int cmp = compare_deSentinel(key, x.val); if (cmp < 0) x = x.left(); else if (cmp > 0) x = x.right(); else return x; } return null; } final public boolean check() { if (!is23()) println("Not a 2-3 tree"); if (!isBalanced()) println("Not balanced"); return is23() && isBalanced(); } final public boolean is23() { return is23(root); } final public boolean is23(Node x) { if (x == null) return true; if (isRed(x.right())) return false; if (x != root && isRed(x) && isRed(x.left())) return false; return is23(x.left()) && is23(x.right()); } final public boolean isBalanced() { int black = 0; Node x = root; while (x != null) { if (!isRed(x)) black++; x = x.left(); } return isBalanced(root, black); } final public boolean isBalanced(Node x, int black) { if (x == null) return black == 0; if (!isRed(x)) black--; return isBalanced(x.left(), black) && isBalanced(x.right(), black); } public void clear() { root = null; size = 0; } final public Node min(Node x) { while (x.left() != null) x = x.left(); return x; } final public Node deleteMin(Node h) { if (h.left() == null) return null; if (!isRed(h.left()) && !isRed(h.left().left())) h = moveRedLeft(h); h = h.setLeft(deleteMin(h.left())); return balance(h); } public Iterator iterator() { return new MyIterator(); } public class MyIterator extends IterableIterator { public List> path = new ArrayList(); public MyIterator() { fetch(root); } public void fetch(Node node) { while (node != null) { path.add(node); node = node.left(); } } public boolean hasNext() { return !path.isEmpty(); } public A next() { if (path.isEmpty()) throw fail("no more elements"); Node node = popLast(path); fetch(node.right()); return (A) deSentinel(node.val); } } public A ceiling(A key) { key = (A) sentinel(key); Node x = ceiling(root, key); return x == null ? null : x.val; } public Node ceiling(Node x, A key) { if (x == null) return null; int cmp = compare_deSentinel(key, x.val); if (cmp == 0) return x; if (cmp > 0) return ceiling(x.right(), key); Node t = ceiling(x.left(), key); if (t != null) return t; else return x; } public A floor(A key) { key = (A) sentinel(key); Node x = floor(root, key); return x == null ? null : x.val; } public Node floor(Node x, A key) { if (x == null) return null; int cmp = compare_deSentinel(key, x.val); if (cmp == 0) return x; if (cmp < 0) return floor(x.left(), key); Node t = floor(x.right(), key); if (t != null) return t; else return x; } public void testInternalStructure() { assertTrue(countLeafObjects() <= 1); } public int countLeafObjects() { return countLeafObjects(root); } public int countLeafObjects(Node node) { if (node instanceof Leaf) return 1; if (node instanceof NonLeaf) return countLeafObjects(optCast(Node.class, ((NonLeaf) node).left)) + countLeafObjects(optCast(Node.class, ((NonLeaf) node).right)); return 0; } public Collection unoptimizedNodes() { List out = new ArrayList(); findUnoptimizedNodes(out); return out; } public void findUnoptimizedNodes(List out) { findUnoptimizedNodes(root, out); } public void findUnoptimizedNodes(Node node, List out) { if (node == null) return; if (node instanceof NonLeaf) { if (isUnoptimizedNode((NonLeaf) node)) out.add((NonLeaf) node); findUnoptimizedNodes(optCast(Node.class, ((NonLeaf) node).left), out); findUnoptimizedNodes(optCast(Node.class, ((NonLeaf) node).right), out); } } public boolean isUnoptimizedNode(Node node) { if (node instanceof NonLeaf) return ((NonLeaf) node).left instanceof Leaf || ((NonLeaf) node).right instanceof Leaf; return false; } public HyperCompactTreeSet compact() { return new HyperCompactTreeSet(this); } } static public A highestByField(String field, Collection l) { A best = null; Object bestValue = null; if (l != null) for (A a : l) { Object val = getOpt(a, field); if (val != null && (bestValue == null || cmp(val, bestValue) > 0)) { best = a; bestValue = val; } } return best; } static public A highestByField(Collection l, String field) { return highestByField(field, l); } static public List sortedByCalculatedFieldDesc(Collection c, final Object f) { return sortByCalculatedFieldDesc(c, f); } static public List sortedByCalculatedFieldDesc(Object f, Collection c) { return sortByCalculatedFieldDesc(f, c); } static public List sortedByCalculatedFieldDesc(Iterable c, IF1 f) { return sortByCalculatedFieldDesc(c, f); } static public List sortedByCalculatedFieldDesc(IF1 f, Iterable c) { return sortByCalculatedFieldDesc(f, c); } static public String insertString(String a, int idx, String b) { return spliceString(a, idx, idx, b); } static public int smartIndexOfSpaceEtc(String s) { int i = indexOfSpaceEtc(s); return i < 0 ? l(s) : i; } static public Map mapWithoutKey(Map map, A key) { if (map == null || !map.containsKey(key)) return map; Map m = cloneMap(map); m.remove(key); return m; } static public Map mapWithoutKey(A key, Map map) { return mapWithoutKey(map, key); } static public String beforeSlash_orAll(String s) { return takeFirst(smartIndexOf(s, '/'), s); } static public List reverseInPlace(List l) { return reverseList(l); } static public List sortByFieldInPlace(List l, String field) { sort(l, fieldComparator(field)); return l; } static public List sortByFieldInPlace(String field, List l) { return sortByFieldInPlace(l, field); } static public double elapsedSeconds(long time) { return toSeconds(sysNow() - time); } static public String lines_possiblyRTrim(String originalText, List lines) { return endsWithNewLine(originalText) ? lines(lines) : lines_rtrim(lines); } static public String lines_possiblyRTrim(List lines, String originalText) { return lines_possiblyRTrim(originalText, lines); } static public List sortedAlphanumIC(Collection c) { List l = cloneList(c); Collections.sort(l, alphaNumComparatorIC()); return l; } static public String linesPreservingTrailingNewLine(String original, List lines) { String s = lines(lines); return endsWith(original, "\n") ? s : dropSuffix("\n", s); } static public List unquoteAll(List l) { List t = cloneList(l); for (int i = 0; i < l(t); i++) if (isQuoted(t.get(i))) t.set(i, unquote(t.get(i))); return t; } static public List sortedByFieldIC(Collection c, final String field) { List l = new ArrayList(c); sort(l, new Comparator() { public int compare(A a, A b) { return compareIC((String) getOpt(a, field), (String) getOpt(b, field)); } }); return l; } static public List sortedByFieldIC(String field, Collection c) { return sortedByFieldIC(c, field); } static public Object[] paramsPlus_skipFirst(Object[] a1, Object... a2) { if (odd(l(a1))) return itemPlusArray(first(a1), paramsPlus(dropFirst(a1), a2)); return paramsPlus(a1, a2); } static public String th(Object contents, Object... params) { return tag("th", contents, params); } static public A applyDefaultMargin(final A c) { if (c != null) { swing(new Runnable() { public void run() { try { c.setBorder(BorderFactory.createEmptyBorder(withMargin_defaultWidth, withMargin_defaultWidth, withMargin_defaultWidth, withMargin_defaultWidth)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setBorder(BorderFactory.createEmptyBorder(withMargin_defaultWidth, withMarg..."; } }); } return c; } static public JPanel centerAndSouth(final Component c, final Component s) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.CENTER, wrap(c)); if (s != null) panel.add(BorderLayout.SOUTH, wrap(s)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.CENT..."; } }); } static public int withTopMargin_defaultWidth = 6; static public JPanel withTopMargin(Component c) { return withTopMargin(withTopMargin_defaultWidth, c); } static public JPanel withTopMargin(final int w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(w, 0, 0, 0)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static public A applyMargin(int top, int left, int bottom, int right, A c) { return addMargin(top, left, bottom, right, c); } static public A applyMargin(int w, A c) { return addMargin(w, c); } static public JPanel jrightAlignedLine(final Component... components) { return swing(new F0() { public RightAlignedLine get() { try { return new RightAlignedLine(components); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret RightAlignedLine(components);"; } }); } static public JPanel jrightAlignedLine(List components) { return jrightAlignedLine(asArray(Component.class, components)); } static public JPanel centerAndEastWithMarginInbetween(Component c, final Component e) { return centerAndEast(c, withLeftMargin(e)); } static public JCheckBox jLiveValueCheckBox(String text, final SimpleLiveValue lv) { final JCheckBox cb = jCheckBox(text); bindCheckBoxToLiveValue(cb, lv); return cb; } static public SimpleLiveValue dm_fieldLiveValue(String fieldName) { return dm_fieldLiveValue(dm_current_mandatory(), fieldName); } static public SimpleLiveValue dm_fieldLiveValue(final DynModule module, final String fieldName) { Lock __0 = module.lock; lock(__0); try { AutoCloseable __2 = module.enter(); try { Class type = getFieldType(module, fieldName); final SimpleLiveValue value = new SimpleLiveValue(type, get(module, fieldName)); dm_watchField(fieldName, new Runnable() { public void run() { try { Object o = get(module, fieldName); value.set(o); ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef dm_fieldLiveValue_debug\r\n print(\"dm_fieldLiveValue: setting \" + fi..."; } }); value.onChange(new Runnable() { public void run() { try { module.setField(fieldName, value.get()); ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef dm_fieldLiveValue_debug\r\n print(\"dm_fieldLiveValue: setting 2 \" + ..."; } }); return value; } finally { _close(__2); } } finally { unlock(__0); } } static public void containerAddFirst(final Container c, final Component... l) { if (c != null) { swing(new Runnable() { public void run() { try { for (int i = 0; i < l(l); i++) c.add(l[i], i); revalidate(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (int i = 0; i < l(l); i++)\r\n c.add(l[i], i);\r\n revalidate(c);"; } }); } } static public void setSCPComponent(SingleComponentPanel scp, Component c) { if (scp != null) scp.setComponent(c); } static public Set createOrAddToSet(Set set, A a) { if (set == null) set = new HashSet(); set.add(a); return set; } static public ChangeListener changeListener(final Object r) { return new ChangeListener() { public void stateChanged(ChangeEvent e) { pcallF(r); } }; } static public ItemListener itemListener(final Object r) { return new ItemListener() { public void itemStateChanged(ItemEvent e) { pcallF(r); } }; } static public void onUpdate(JComponent c, final Object r) { if (c instanceof JTextComponent) ((JTextComponent) c).getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { call(r); } public void removeUpdate(DocumentEvent e) { call(r); } public void changedUpdate(DocumentEvent e) { call(r); } }); else if (c instanceof ItemSelectable) ((ItemSelectable) c).addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { call(r); } }); else print("Warning: onUpdate doesn't know " + getClassName(c)); } static public void onUpdate(List l, Object r) { for (JComponent c : l) onUpdate(c, r); } static public JTextField textFieldFromComboBox(JComboBox cb) { return (JTextField) cb.getEditor().getEditorComponent(); } static public JComboBox onSelectedItem(final JComboBox cb, final VF1 f) { addActionListener(cb, new Runnable() { public void run() { try { pcallF(f, selectedItem(cb)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(f, selectedItem(cb))"; } }); return cb; } static public int latestInstalledJavaX() { File[] files = new File(userHome(), ".javax").listFiles(); int v = 0; if (files != null) for (File f : files) { Matcher m = regexpMatcher("x(\\d\\d\\d?)\\.jar", f.getName()); if (m.matches()) v = Math.max(v, Integer.parseInt(m.group(1))); } return v; } static public String x30JarServerURL() { return "http://botcompany.de:8081/x30.jar"; } static public boolean eitherIsA(Either e) { return e != null && e.isA(); } static public void cancelTimers(Collection timers) { for (Object timer : timers) cancelTimer(timer); } static public List getAndClearList(Collection l) { if (l == null) return emptyList(); synchronized (collectionMutex(l)) { List out = cloneList(l); l.clear(); return out; } } static public A vStackCompute(VStack.Computable computation) { if (computation == null) return null; VStack stack = new VStack(computation); stepAll(stack); return (A) stack.result(); } static public CancelPoint newCancelPoint() { return new CancelPoint(); } static public TreeMap generalizedCIMap() { return new TreeMap(generalizedCIComparator()); } static public > MultiMap mapToMultiMap(Map map) { if (map == null) return null; MultiMap mm = similarEmptyMultiMap(map); for (Map.Entry> __0 : _entrySet(map)) { A key = __0.getKey(); Collection values = __0.getValue(); mm.putAll(key, values); } return mm; } static public String digitsOnly(String s) { return filterChars(__115 -> isDigit(__115), s); } static public List lookupAllOpt(Map map, Collection l) { List out = new ArrayList(); if (l != null) for (A a : l) addIfNotNull(out, map.get(a)); return out; } static public List lookupAllOpt(Collection l, Map map) { return lookupAllOpt(map, l); } static public > List getVars(Iterable l) { return lambdaMap(__116 -> getVar(__116), l); } static public ArrayList cloneList_noSync(Iterable l) { return l instanceof Collection ? cloneList_noSync((Collection) l) : asList(l); } static public ArrayList cloneList_noSync(Collection l) { if (l == null) return new ArrayList(); return new ArrayList(l); } static public IterableIterator iteratorFromFunction(final Object f) { class IFF extends IterableIterator { public A a; public boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } public void getNext() { if (done || a != null) return; a = (A) callF(f); done = a == null; } } ; return new IFF(); } static public IterableIterator iteratorFromFunction(F0 f) { return iteratorFromFunction_f0(f); } static public IterableIterator iteratorFromFunction(IF0 f) { return iteratorFromFunction_if0(f); } static public IterableIterator concurrentlyIterateValues(NavigableMap map) { return concurrentlyIterateValues(map, map); } static public IterableIterator concurrentlyIterateValues(final NavigableMap map, Object mutex) { return iteratorFromFunction(new F0() { public Iterator it = keys(map).iterator(); public A key; public B get() { synchronized (mutex) { try { if (!it.hasNext()) return null; return map.get(key = it.next()); } catch (ConcurrentModificationException e) { print("Re-iterating"); it = map.tailMap(key, false).keySet().iterator(); if (!it.hasNext()) return null; return map.get(key = it.next()); } } } }); } static public double floor(double d) { return Math.floor(d); } static public String spliceString(String a, int from, int to, String b) { return substring(a, 0, from) + b + substring(a, Math.max(from, to)); } static public String spliceString(String a, int from, int to, char b) { return spliceString(a, from, to, str(b)); } static public List reverseList(List l) { Collections.reverse(l); return l; } static public Comparator fieldComparator(final String field) { return new Comparator() { public int compare(A a, A b) { return cmp(getOpt(a, field), getOpt(b, field)); } }; } static public boolean endsWithNewLine(String s) { return endsWith(s, "\n"); } static public AlphanumComparator alphaNumComparatorIC_instance; static public Comparator alphaNumComparatorIC() { if (alphaNumComparatorIC_instance == null) { AlphanumComparator ac = new AlphanumComparator(); ac.ignoreCase = true; alphaNumComparatorIC_instance = ac; } return alphaNumComparatorIC_instance; } static public int compareIC(String s1, String s2) { return compareIgnoreCase_jdk(s1, s2); } static public A[] itemPlusArray(A a, A[] l) { return singlePlusArray(a, l); } static public A addMargin(final int top, final int left, final int bottom, final int right, final A c) { if (c != null) { swing(new Runnable() { public void run() { try { Border margin = BorderFactory.createEmptyBorder(top, left, bottom, right); c.setBorder(jCompoundBorder(c.getBorder(), margin)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Border margin = BorderFactory.createEmptyBorder(top, left, bottom, right);\r\n ..."; } }); } return c; } static public A addMargin(int w, A c) { return addMargin(w, w, w, w, c); } static public JPanel centerAndEast(final Component c, final Component e) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.CENTER, wrap(c)); panel.add(BorderLayout.EAST, wrap(e)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.CENT..."; } }); } static public int withLeftMargin_defaultWidth = 6; static public JPanel withLeftMargin(Component c) { return withLeftMargin(withLeftMargin_defaultWidth, c); } static public JPanel withLeftMargin(final int margin, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(0, margin, 0, 0)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static public JCheckBox jCheckBox() { return swingNu(JCheckBox.class); } static public JCheckBox jCheckBox(boolean checked) { return swingNu(JCheckBox.class, "", checked); } static public JCheckBox jCheckBox(String text, boolean checked) { return swingNu(JCheckBox.class, text, checked); } static public JCheckBox jCheckBox(String text) { return swingNu(JCheckBox.class, text); } static public JCheckBox jCheckBox(String text, boolean checked, final Object onChange) { JCheckBox cb = jCheckBox(checked, onChange); cb.setText(text); return cb; } static public JCheckBox jCheckBox(boolean checked, final Object onChange) { final JCheckBox cb = jCheckBox(checked); cb.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { pcallF(onChange, cb.isSelected()); } }); return cb; } static public A bindCheckBoxToLiveValue(final A cb, final SimpleLiveValue lv) { bindLiveValueListenerToComponent(cb, lv, new Runnable() { public void run() { try { setChecked(cb, isTrue(lv.get())); ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef bindCheckBoxToLiveValue_debug\r\n print(\"bindCheckBoxToLiveValue: se..."; } }); onChange(cb, new Runnable() { public void run() { try { lv.set(isChecked(cb)); ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef bindCheckBoxToLiveValue_debug\r\n print(\"bindCheckBoxToLiveValue: se..."; } }); return cb; } static public Class getFieldType(Object o, String field) { return fieldType(o, field); } static public void dm_watchField(String field, Runnable onChange) { new Dyn_FieldWatcher(dm_current_mandatory(), field, onChange); } static public generalizedCIComparator_C generalizedCIComparator_cache; static public generalizedCIComparator_C generalizedCIComparator() { if (generalizedCIComparator_cache == null) generalizedCIComparator_cache = generalizedCIComparator_load(); return generalizedCIComparator_cache; } static public generalizedCIComparator_C generalizedCIComparator_load() { return new generalizedCIComparator_C(); } final static public class generalizedCIComparator_C implements Comparator { public int compare(Object o1, Object o2) { if (o1 instanceof String) if (o2 instanceof String) return betterCIComparator().compare(((String) o1), ((String) o2)); else return -1; else if (o2 instanceof String) return 1; else return cmp(o1, o2); } } static public MultiMap similarEmptyMultiMap(MultiMap m) { return similarEmptyMultiMap(m == null ? null : m.data); } static public MultiMap similarEmptyMultiMap(Map m) { MultiMap mm = new MultiMap(); if (m != null) mm.data = similarEmptyMap(m); return mm; } static public String filterChars(IF1 pred, String s) { if (s == null) return null; StringBuilder buf = new StringBuilder(); int n = l(s); char c; for (int i = 0; i < n; i++) if (isTrue(callF(pred, c = s.charAt(i)))) buf.append(c); return str(buf); } static public IterableIterator iteratorFromFunction_f0(final F0 f) { class IFF2 extends IterableIterator { public A a; public boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } public void getNext() { if (done || a != null) return; a = f.get(); done = a == null; } } ; return new IFF2(); } static public IterableIterator iteratorFromFunction_if0(final IF0 f) { class IFF2 extends IterableIterator { public A a; public boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } public void getNext() { if (done || a != null) return; a = f.get(); done = a == null; } } ; return new IFF2(); } static public int compareIgnoreCase_jdk(String s1, String s2) { if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return 1; int n1 = s1.length(); int n2 = s2.length(); int min = Math.min(n1, n2); for (int i = 0; i < min; i++) { char c1 = s1.charAt(i); char c2 = s2.charAt(i); if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); if (c1 != c2) return c1 - c2; } } } return n1 - n2; } static public A[] singlePlusArray(A a, A[] l) { A[] out = newObjectArrayOfSameType(l, l(l) + 1); out[0] = a; arraycopy(l, 0, out, 1, l(l)); return out; } static public Border jCompoundBorder(Border inner, Border outer) { if (inner == null) return outer; if (outer == null) return inner; return BorderFactory.createCompoundBorder(inner, outer); } static public void setChecked(JCheckBox checkBox, boolean b) { if (checkBox != null) { swing(new Runnable() { public void run() { try { if (isChecked(checkBox) != b) checkBox.setSelected(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (isChecked(checkBox) != b)\r\n checkBox.setSelected(b);"; } }); } } static public void setChecked(JCheckBoxMenuItem mi, boolean b) { if (mi != null) { swing(new Runnable() { public void run() { try { mi.setSelected(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mi.setSelected(b);"; } }); } } static public class CancelPoint implements AutoCloseable { volatile public boolean closed = false; public void close() { closed = true; } } static public class SimpleLiveValue extends LiveValue { public Class type; volatile public A value; transient public List onChange = synchroList(); public SimpleLiveValue(Class type) { this.type = type; } public SimpleLiveValue(Class type, A value) { this.value = value; this.type = type; } public Class getType() { return type; } public A get() { return value; } public void onChange(Runnable l) { onChange.add(l); } public void onChangeAndNow(Runnable l) { onChange(l); callF(l); } public void removeOnChangeListener(Runnable l) { onChange.remove(l); } public void fireChanged() { pcallFAll(onChange); } public void set(A a) { if (neq(value, a)) { value = a; fireChanged(); } } } static public class CancelToCancelPoint extends QuickException { public CancelPoint cp; public CancelToCancelPoint(CancelPoint cp) { this.cp = cp; } } static public class Dyn_FieldWatcher { public DynModule module; public String field; public Object value; public Runnable action; transient public IF1 cloneValue; public Object cloneValue(Object o) { return cloneValue != null ? cloneValue.get(o) : cloneValue_base(o); } final public Object cloneValue_fallback(IF1 _f, Object o) { return _f != null ? _f.get(o) : cloneValue_base(o); } public Object cloneValue_base(Object o) { return o; } public Dyn_FieldWatcher(DynModule module, String field, Runnable action) { this(module, field, action, null); } public Dyn_FieldWatcher(DynModule module, String field, Runnable action, IF1 cloneValue) { this.cloneValue = cloneValue; this.action = action; this.field = field; this.module = module; value = cloneValue(get(module, field)); module.onChange(new Runnable() { public void run() { try { check(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "check();"; } }); module.onFieldChange(new VF1() { public void get(String f) { try { if (eq(f, field)) check(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(f, field))\r\n check();"; } }); } public void check() { Object newValue = cloneValue(get(module, field)); if (eq(value, newValue)) return; value = newValue; dm_q(module, action); } } static public class RightAlignedLine extends JPanel { public RightAlignedLine(Component... components) { setLayout(LetterLayout.rightAlignedRow()); for (Component component : components) add(component); } public void add(String text) { add(new JLabel(text)); } } static public class QuickException extends RuntimeException { public Throwable fillInStackTrace() { return this; } public QuickException() { } public QuickException(Throwable e) { super(e); } public QuickException(String msg) { super(msg); } public QuickException(String msg, Throwable e) { super(msg, e); } } static public class LetterLayout implements LayoutManager { public String[] lines; public Map map = new TreeMap(); public Map constraints = new HashMap(); public RC[] rows; public RC[] cols; public Cell[][] cells; public int spacingX = 10, spacingY = 10; public int insetTop, insetBottom, insetLeft, insetRight; public int template; public boolean formWideLeftSide, formWideRightSide; static final public int STALACTITE = 1, LEFT_ALIGNED_ROW = 2, CENTERED_ROW = 3, FORM = 4, RIGHT_ALIGNED_ROW = 5; public boolean debug = false; public void setLeftBorder(int border) { insetLeft = border; } public void setRightBorder(int border) { insetRight = border; } public static JComponent withBorder(JComponent component, int border) { JPanel panel = new JPanel(new LetterLayout("C").setBorder(border)); panel.add("C", component); return panel; } public static JPanel panel(String... lines) { return new JPanel(new LetterLayout(lines)); } public static JPanel stalactitePanel() { return new JPanel(stalactite()); } static public class DummyComponent extends JComponent { } static public class Cell { public boolean aux = false; public int minWidth, minHeight; public Component component; public int colspan, rowspan; public double weightX, weightY; } static public class RC { public int min; public double weightSum; public int start; public int minEnd; } public LetterLayout(int template) { this.template = template; } public LetterLayout(String... lines) { this.lines = lines; } public void layoutContainer(Container container) { prepareLayout(container); if (debug) System.out.println("Container size: " + container.getSize()); Insets insets = getInsets(container); for (int r = 0; r < rows.length; r++) { for (int i = 0; i < cols.length; ) { Cell cell = cells[i][r]; if (cell.aux) ++i; else { if (cell.component != null) { int x1 = cols[i].start; int y1 = rows[r].start; int x2 = i + cell.colspan < cols.length ? cols[i + cell.colspan].start - spacingX : container.getWidth() - insets.right; int y2 = r + cell.rowspan < rows.length ? rows[r + cell.rowspan].start - spacingY : container.getHeight() - insets.bottom; if (debug) System.out.println("Layouting (" + i + ", " + r + ", " + cell.component.getClass().getName() + "): " + x1 + " " + y1 + " " + x2 + " " + y2); cell.component.setBounds(x1, y1, x2 - x1, y2 - y1); } i += cells[i][r].colspan; } } } } final public void prepareLayout(Container container) { applyTemplate(container); int numRows = lines.length, numCols = lines[0].length(); for (int i = 1; i < numRows; i++) if (lines[i].length() != numCols) throw new IllegalArgumentException("Lines have varying length"); cells = new Cell[numCols][numRows]; rows = new RC[numRows]; cols = new RC[numCols]; for (int r = 0; r < numRows; r++) rows[r] = new RC(); for (int i = 0; i < numCols; i++) cols[i] = new RC(); for (int r = 0; r < numRows; r++) for (int i = 0; i < numCols; i++) cells[i][r] = new Cell(); for (int r = 0; r < numRows; r++) { String line = lines[r]; for (int i = 0; i < numCols; ) { Cell cell = cells[i][r]; if (cell.aux) { ++i; continue; } char ch = line.charAt(i); int iNext = i; do ++iNext; while (iNext < numCols && ch == line.charAt(iNext)); int rNext = r; do ++rNext; while (rNext < numRows && ch == lines[rNext].charAt(i)); cell.weightX = numCols == 1 || iNext > i + 1 ? 1.0 : 0.0; cell.weightY = numRows == 1 || rNext > r + 1 ? 1.0 : 0.0; Component c = map.get(String.valueOf(ch)); cell.component = c; if (c != null) { cell.minWidth = c.getMinimumSize().width + spacingX; cell.minHeight = getMinimumHeight(c) + spacingY; } cell.colspan = iNext - i; cell.rowspan = rNext - r; if (cell.colspan == 1) cols[i].min = Math.max(cols[i].min, cell.minWidth); if (cell.rowspan == 1) rows[r].min = Math.max(rows[r].min, cell.minHeight); for (int r2 = r; r2 < rNext; r2++) for (int i2 = i; i2 < iNext; i2++) if (r2 != r || i2 != i) cells[i2][r2].aux = true; i = iNext; } } while (true) { for (int i = 0; i < numCols; i++) { int minStart = i == 0 ? 0 : cols[i - 1].minEnd; double weightStart = i == 0 ? 0.0 : cols[i - 1].weightSum; for (int r = 0; r < numRows; r++) { Cell cell = cells[i][r]; if (!cell.aux) { RC rc = cols[i + cell.colspan - 1]; rc.minEnd = Math.max(rc.minEnd, minStart + cell.minWidth); rc.weightSum = Math.max(rc.weightSum, weightStart + cell.weightX); } } } for (int r = 0; r < numRows; r++) { int minStart = r == 0 ? 0 : rows[r - 1].minEnd; double weightStart = r == 0 ? 0.0 : rows[r - 1].weightSum; for (int i = 0; i < numCols; i++) { Cell cell = cells[i][r]; if (!cell.aux) { RC rc = rows[r + cell.rowspan - 1]; rc.minEnd = Math.max(rc.minEnd, minStart + cell.minHeight); rc.weightSum = Math.max(rc.weightSum, weightStart + cell.weightY); } } } if (allWeightsZero(cols)) { for (int r = 0; r < numRows; r++) for (int i = 0; i < numCols; i++) cells[i][r].weightX = 1.0; continue; } if (allWeightsZero(rows)) { for (int r = 0; r < numRows; r++) for (int i = 0; i < numCols; i++) cells[i][r].weightY = 1.0; continue; } break; } Insets insets = getInsets(container); determineStarts(cols, insets.left, container.getWidth() - insets.left - insets.right + spacingX, spacingX); determineStarts(rows, insets.top, container.getHeight() - insets.top - insets.bottom + spacingY, spacingY); } final public boolean allWeightsZero(RC[] rcs) { for (int i = 0; i < rcs.length; i++) if (rcs[i].weightSum != 0.0) return false; return true; } static public int getMinimumHeight(Component c) { return c.getMinimumSize().height; } final public void applyTemplate(Container container) { if (template == STALACTITE) { Component[] components = container.getComponents(); lines = new String[components.length + 2]; map.clear(); for (int i = 0; i < components.length; i++) { String s = String.valueOf(makeIndexChar(i)); map.put(s, components[i]); lines[i] = s; } lines[components.length] = lines[components.length + 1] = " "; } else if (template == FORM) { Component[] components = container.getComponents(); int numRows = components.length / 2; lines = new String[numRows + 2]; map.clear(); for (int row = 0; row < numRows; row++) { String lower = String.valueOf(makeIndexChar(row)); String upper = String.valueOf(makeAlternateIndexChar(row)); Component rightComponent = components[row * 2 + 1]; if (rightComponent instanceof DummyComponent) upper = lower; lines[row] = (formWideLeftSide ? lower + lower : lower) + (formWideRightSide ? upper + upper : upper); map.put(lower, components[row * 2]); if (!(rightComponent instanceof DummyComponent)) map.put(upper, rightComponent); } lines[numRows] = lines[numRows + 1] = (formWideLeftSide ? " " : " ") + (formWideRightSide ? " " : " "); } else if (template == LEFT_ALIGNED_ROW) { lines = new String[] { makeSingleRow(container) + RIGHT_CHAR + RIGHT_CHAR }; } else if (template == CENTERED_ROW) { lines = new String[] { "" + LEFT_CHAR + LEFT_CHAR + makeSingleRow(container) + RIGHT_CHAR + RIGHT_CHAR }; } else if (template == RIGHT_ALIGNED_ROW) { lines = new String[] { "" + LEFT_CHAR + LEFT_CHAR + makeSingleRow(container) }; } } final public String makeSingleRow(Container container) { Component[] components = container.getComponents(); StringBuffer buf = new StringBuffer(); map.clear(); for (int i = 0; i < components.length; i++) { var c = components[i]; String s = constraints.get(c); if (isOneOfSingleChars(s, LEFT_CHAR, RIGHT_CHAR)) continue; s = str(makeAlternateIndexChar(i)); setConstraints(c, s); buf.append(s); } return buf.toString(); } static public void determineStarts(RC[] rcs, int start, int totalSize, int spacing) { int minTotal = rcs[rcs.length - 1].minEnd; double weightSum = rcs[rcs.length - 1].weightSum; int spare = (int) ((totalSize - minTotal) / (weightSum == 0.0 ? 1.0 : weightSum)); int x = start, minSum = 0; double prevWeightSum = 0.0; for (int i = 0; i < rcs.length; i++) { int width = rcs[i].minEnd - minSum + (int) ((rcs[i].weightSum - prevWeightSum) * spare) - spacing; rcs[i].start = x; x += width + spacing; prevWeightSum = rcs[i].weightSum; minSum = rcs[i].minEnd; } } public void addLayoutComponent(String s, Component component) { setConstraints(component, s); } public void setConstraints(Component component, String s) { mapPutOrRemove(map, s, component); mapPutOrRemove(constraints, component, s); } public void removeLayoutComponent(Component component) { map.values().remove(component); constraints.remove(component); } public Dimension minimumLayoutSize(Container container) { prepareLayout(container); Insets insets = getInsets(container); Dimension result = new Dimension(insets.left + cols[cols.length - 1].minEnd + insets.right - spacingX, insets.top + rows[rows.length - 1].minEnd + insets.bottom - spacingY); return result; } final public Insets getInsets(Container container) { Insets insets = container.getInsets(); return new Insets(insets.top + insetTop, insets.left + insetLeft, insets.bottom + insetBottom, insets.right + insetRight); } public Dimension preferredLayoutSize(Container container) { return minimumLayoutSize(container); } public LetterLayout setSpacing(int x, int y) { spacingX = x; spacingY = y; return this; } public LetterLayout setSpacing(int spacing) { return setSpacing(spacing, spacing); } public LetterLayout setBorder(int top, int left, int bottom, int right) { insetTop = top; insetLeft = left; insetBottom = bottom; insetRight = right; return this; } public LetterLayout setBorder(int inset) { return setBorder(inset, inset, inset, inset); } public LetterLayout setTopBorder(int inset) { insetTop = inset; return this; } public static LetterLayout stalactite() { return new LetterLayout(STALACTITE); } public static LetterLayout leftAlignedRow() { return new LetterLayout(LEFT_ALIGNED_ROW); } public static LetterLayout leftAlignedRow(int spacing) { return leftAlignedRow().setSpacing(spacing); } public static LetterLayout centeredRow() { return new LetterLayout(CENTERED_ROW); } public static LetterLayout rightAlignedRow() { return new LetterLayout(RIGHT_ALIGNED_ROW); } public static JPanel rightAlignedRowPanel(JComponent... components) { return makePanel(new LetterLayout(RIGHT_ALIGNED_ROW), components); } static public JPanel makePanel(LetterLayout letterLayout, JComponent[] components) { JPanel panel = new JPanel(letterLayout); for (JComponent component : components) { panel.add(component); } return panel; } public static LetterLayout form() { LetterLayout letterLayout = new LetterLayout(FORM); letterLayout.formWideLeftSide = true; letterLayout.formWideRightSide = true; return letterLayout; } public static LetterLayout formWideRightSide() { LetterLayout letterLayout = new LetterLayout(FORM); letterLayout.formWideRightSide = true; return letterLayout; } public static Component getDummyComponent() { return new DummyComponent(); } public static JPanel newPanel(String... lines) { return new JPanel(new LetterLayout(lines)); } public boolean isDebug() { return debug; } public void setDebug(boolean debug) { this.debug = debug; } public static char makeIndexChar(int idx) { return (char) ('a' + idx * 2); } public static char makeAlternateIndexChar(int idx) { return (char) ('b' + idx * 2); } public static char LEFT_CHAR = ',', RIGHT_CHAR = '.'; public static void main(String[] args) { System.out.println((int) makeIndexChar(0)); System.out.println((int) makeAlternateIndexChar(0)); System.out.println((int) makeIndexChar(32000)); System.out.println((int) makeAlternateIndexChar(32000)); System.out.println((int) LEFT_CHAR); System.out.println((int) RIGHT_CHAR); } } static public Q dm_q() { return dm_current_mandatory().q(); } static public void dm_q(Runnable r) { dm_inQ(r); } static public void dm_q(DynModule module, Runnable r) { module.q().add(r); } static public A dm_q(IF0 f) { return dm_evalInQ(if0ToF0(f)); } static public boolean isOneOfSingleChars(String s, char... chars) { if (l(s) != 1) return false; char real = s.charAt(0); for (char c : unnullForIteration(chars)) if (real == c) return true; return false; } static public void dm_inQ(Runnable r) { dm_q().add(r); } static public void dm_inQ(DynModule mod, Runnable r) { dm_q(mod, r); } static public A dm_evalInQ(F0 f) { return dm_evalInQ(dm_current_mandatory(), f); } static public A dm_evalInQ(IF0 f) { return dm_evalInQ(dm_current_mandatory(), if0ToF0(f)); } static public A dm_evalInQ(DynModule module, F0 f) { return evalInQ(module.q(), f); } static public F0 if0ToF0(IF0 f) { return f == null ? null : new F0() { public A get() { try { return f.get(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret f.get();"; } }; } static public A evalInQ(Q q, final F0 f) { if (isInQ(q)) return callF(f); final Var> var = new Var(); q.add(new Runnable() { public void run() { try { try { var.set(eitherA(callF(f))); } catch (Throwable e) { var.set(eitherB(e)); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "try {\r\n var.set(eitherA(callF(f)));\r\n } catch (Throwable e) {\r\n ..."; } }); return returnOrThrow_either(waitForVarToBeNotNull(var)); } static public boolean isInQ(Q q) { return q != null && isCurrentThread(q.rst.thread); } static public A returnOrThrow_either(Either e) { if (isEitherB(e)) throw rethrow(e.b()); return eitherAOpt(e); } static public A waitForVarToBeNotNull(Var v) { try { synchronized (v) { while (!v.has()) v.wait(); return v.get(); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean isCurrentThread(Thread t) { return t != null && t == currentThread(); } static public boolean isEitherB(Either e) { return eitherIsB(e); } static public A eitherAOpt(Either e) { return e != null && e.isA() ? e.a() : null; } static public boolean eitherIsB(Either e) { return e != null && e.isB(); } }