import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import java.util.function.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.table.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.awt.geom.*; import javax.imageio.*; import java.math.*; import java.time.Duration; import com.google.api.services.calendar.model.EventDateTime; import com.google.api.client.util.DateTime; import com.google.api.client.util.store.FileDataStoreFactory; import com.google.api.services.calendar.Calendar; import com.google.api.services.calendar.CalendarScopes; import com.google.api.services.calendar.model.Event; import com.google.api.services.calendar.model.Events; import java.text.*; import java.text.SimpleDateFormat; import java.util.TimeZone; import java.text.NumberFormat; import java.awt.geom.*; import java.nio.charset.Charset; import com.google.api.client.googleapis.auth.oauth2.*; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson2.JacksonFactory; import java.util.function.BiConsumer; import java.util.function.BiFunction; import static x30_pkg.x30_util.DynamicObject; import org.apache.bcel.classfile.ClassParser; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.Const; import org.apache.bcel.generic.*; import java.lang.reflect.Type; import java.nio.file.Path; import java.util.jar.*; public class main { static public String dbBotID = "#1028421"; static public boolean newDesign = true; static public boolean ariaLiveTrick = false; static public boolean ariaLiveTrick2 = true; static public String templateID = "#1028653"; static public String cssID = "#1028652"; static public String thoughtBotID = null; static public String botName = "BookBetter"; static public String heading = "Schedule"; static public String botImageID = "#1102935"; static public String userImageID = "#1102803"; static public String chatHeaderImageID = "#1102802"; static public String timeZone = californiaTimeZone_string(); static public String timeZoneForGoogleAPI = "America/Los_Angeles"; static public String baseLink; static public boolean botOnRight = true; static public class Worker extends Concept { public String loginName, displayName; public boolean available = false; public long lastOnline; static public String _fieldOrder = "loginName displayName"; public String renderAsHTML() { return htmlEncode2(loginName + " (display name: " + displayName + ")"); } } static public class WorkerChat { public int workerLongPollTick = 200; public int workerLongPollMaxWait = 1000 * 30; public long lastWorkerRequested; public Object html(String uri, Map params, Conversation conv, AuthedDialogID auth) { String uri2 = appendSlash(uri); boolean requestAuthed = auth != null; if (startsWith(uri2, "/workers-admin/")) { if (!requestAuthed) return serveAuthForm(params.get("uri")); return serveWorkersAdmin(uri, params); } if (startsWith(uri2, "/worker/")) { if (!subBot_isHttps()) return subBot_serveRedirect("https://" + domain() + fullSelfLink(params)); if (!requestAuthed) return serveAuthForm(params.get("uri")); if (nempty(params.get("turnBotOn"))) conv.turnBotOn(); return serveWorkerPage(auth, conv, uri, params); } return null; } public String serveWorkersAdmin(String uri, Map params) { String nav = p(ahref(rawBotLink(dbBotID), "Main admin") + " | " + ahref(baseLink + "/workers-admin", "Workers admin")); if (eq(uri, "/workers-admin/change-image")) { long id = parseLong(params.get("id")); Worker worker = getConcept(Worker.class, id); File f = workerImageFile(id); String content; String b64 = params.get("base64"); if (nempty(b64)) saveFile(f, decodeBASE64(b64)); if (worker == null) content = "Worker not found"; else content = nav + hscript("\r\n function submitIt() {\r\n var file = $('#myUpload')[0].files[0];\r\n var reader = new FileReader();\r\n \r\n reader.onloadend = function () {\r\n var b64 = reader.result.replace(/^data:.+;base64,/, '');\r\n $(\"#base64\").val(b64);\r\n console.log(\"Got base64 data: \" + b64.length);\r\n $(\"#submitForm\").submit();\r\n };\r\n \r\n reader.readAsDataURL(file);\r\n return false;\r\n }\r\n ") + h2("Worker image for: " + worker.renderAsHTML()) + p(!fileExists(f) ? "No image set" : himgsrc(rawLink("worker-image/" + id))) + hpostform(hhiddenWithIDAndName("base64") + "Choose image: " + hfileupload("accept", "image/png,image/jpeg,image/gif", "id", "myUpload") + "

" + "Note: Image should be square. Will be scaled to 40x40px in the chat" + hhidden("id", id), "action", rawLink("/workers-admin/change-image"), "id", "submitForm") + hbuttonOnClick_returnFalse("Upload", "submitIt()"); return hhtml(hhead_title("Change worker image") + hsansserif() + hbody(loadJQuery() + content)); } HCRUD_Concepts data = new HCRUD_Concepts(Worker.class); HCRUD crud = new HCRUD(rawLink("workers-admin"), data) { public String frame(String title, String contents) { return hhtml(hhead_title_htmldecode(title) + hbody(nav + h1(title) + contents)); } }; crud.unshownFields = litset("available", "lastOnline", "away"); crud.postProcessTableRow = (item, rendered) -> { printStruct("item", item); long id = parseLong(item.get("id")); File f = workerImageFile(id); return mapPlus(rendered, "Image", f == null ? "???" : !fileExists(f) ? "-" : himgsrc(rawLink("worker-image/" + id))); }; crud.renderCmds = item -> crud.renderCmds_base(item) + " | " + ahref(rawLink("workers-admin/change-image" + hquery("id", item.get("id"))), "Change image..."); crud.tableClass = "responstable"; return hsansserif() + hcss_responstable() + crud.renderPage(params); } public String serveWorkerPage(AuthedDialogID auth, Conversation conv, String uri, Map 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", rawLink("worker")); if (eq(uri2, "conversation")) { if (conv == null) return "Conversation not found"; String onOffURL = rawLink("worker/botOnOff" + hquery("cookie", cookie) + "&on="); return hsansserif() + loadJQuery() + hhidden("cookie", conv.cookie) + hpostform(hhidden("cookie", cookie) + p(renderBotStatus(conv)) + p(conv.botOn ? hsubmit("Accept conversation", "name", "acceptConversation") : hsubmit("Turn bot back on", "name", "turnBotOn")), "action", rawLink("worker/innerFrameSet"), "target", "innerFrameSet") + hscriptsrc(rawLink(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 = rawLink("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(__47 -> renderMsgForWorkerChat(__47), lastMsgs)), "target", "innerFrameSet", "style", "text-decoration: none")), "style", style); }), "class", "responstable"); if (poll) return content; String incrementalURL = rawLink("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", rawLink("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", rawLink("worker/conversations" + hquery("cookie", cookie))) + tag("frame", "", "name", "conversation", "src", conv == null ? null : rawLink("worker/conversation" + hquery("cookie", cookie))))); return hhtml(hhead_title("Worker Chat [" + auth.loggedIn.loginName + "]") + hframeset_rows("50,*", tag("frame", "", "name", "notificationArea", "src", rawLink("worker/notificationArea")) + tag("frame", "", "name", "innerFrameSet", "src", conv == null ? null : rawLink("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); } } static public WorkerChat workerChat = new WorkerChat(); static public List testModeEventRanges() { return ll(longRange(parseYMDHMS("2020/07/03 9:00:00", localTimeZone()), parseYMDHMS("2020/07/03 10:30:00", localTimeZone())), longRange(parseYMDHMS("2020/07/06 9:00:00", localTimeZone()), parseYMDHMS("2020/07/06 20:00:00", localTimeZone()))); } static public long testModeDate() { return parseYMDHMS("2020/07/02 17:00:00", localTimeZone()); } static public Map> testModeBusinessHours() { List r = parseBusinessHours("9-5"); return litmap(2, r, 3, r, 4, r, 5, r, 6, r); } static public class BookingConfig extends Concept { static final public String _fieldOrder = "bookingOpen googleCalendarAccessToken googleCalendarRefreshToken twilioAccountSID twilioAuthToken twilioPhoneNr ownerPhoneNr eventKeyword businessHoursSunday businessHoursMonday businessHoursTuesday businessHoursWednesday businessHoursThursday businessHoursFriday businessHoursSaturday businessName appointmentName appointmentDuration appointmentGranularity appointmentMaxLead dateSuggestionsInGreeting dateSuggestionsOnFail smsTemplate"; public boolean bookingOpen = true; public String googleCalendarAccessToken, googleCalendarRefreshToken; public String twilioAccountSID, twilioAuthToken, twilioPhoneNr; public String ownerPhoneNr; public String eventKeyword = "[SALES]"; public String businessHoursSunday, businessHoursMonday, businessHoursTuesday, businessHoursWednesday, businessHoursThursday, businessHoursFriday, businessHoursSaturday; public String businessName; public String appointmentName; public int appointmentDuration; public int appointmentGranularity; public int appointmentMaxLead; public int dateSuggestionsInGreeting, dateSuggestionsOnFail = 2; public String smsTemplate; public Map businessHourStrings() { return pairsToTreeMap(ll(pair(1, businessHoursSunday), pair(2, businessHoursMonday), pair(3, businessHoursTuesday), pair(4, businessHoursWednesday), pair(5, businessHoursThursday), pair(6, businessHoursFriday), pair(7, businessHoursSaturday))); } } static public Booking booking; static public class Booking { public GoogleAccess googleAccess = new GoogleAccess(); public Calendar googleCalendarService; public BookingConfig conf; public boolean anyTimeSlots = true; public Booking() { indexSingletonConcept(BookingConfig.class); conf = uniq(BookingConfig.class); initGoogleCalendar(); initTwilio(); print("Booking inited"); } public Object html(String uri, Map params, AuthedDialogID auth) { print("Booking: " + uri); String uri2 = appendSlash(uri); boolean requestAuthed = auth != null; if (startsWith(uri2, "/booking-admin/")) { if (!requestAuthed) return serveAuthForm(params.get("uri")); return serveBookingAdmin(uri, params); } return null; } public String serveBookingAdmin(String uri, Map params) { String nav = p(ahref(rawBotLink(dbBotID), botName + " Main admin") + " | " + ahref(baseLink + "/booking-admin", "Booking admin")); HCRUD_Concepts data = new HCRUD_Concepts(BookingConfig.class); data.fieldHelp = litmap("bookingOpen", "Whether booking is open at all", "eventKeyword", "keyword to recognize events in Google Calendar, e.g. [SALES]", "businessHoursMonday", "Regular hours available for appointments on Monday, e.g.: 9-12, 15-18", "businessName", "What's your business called?", "appointmentName", "Description of a typical appointment", "appointmentDuration", "Duration of an appointment in minutes", "appointmentGranularity", "Appointment grid size in minutes (e.g. 10)", "appointmentMaxLead", "How many days in advance can an appointment be made", "smsTemplate", "Template for appointment confirmation, e.g.: Hello [name], your [appointment] is scheduled for [time] on [date] at [business]", "dateSuggestionsInGreeting", "How many date suggestions are shown in bot greeting (0 for no suggestions)"); data.onCreateOrUpdate.add(c -> initGoogleCalendar()); HCRUD crud = new HCRUD(rawLink("booking-admin"), data) { public String frame(String title, String contents) { return hhtml(hhead_title_htmldecode(title) + hbody(hsansserif() + hcss_responstable() + nav + h1(title) + p(join(". ", calendarStatus(), twilioStatus())) + h3("Business hours") + p(businessHourStatus()) + contents)); } }; crud.singleton = true; crud.cmdsLeft = true; crud.tableClass = "responstable"; return crud.renderPage(params); } public Object twilio() { return vmBus_query("twilioHolder"); } public boolean twilioInited() { return isTrue(call(twilio(), "twilioInited")); } public void initTwilio() { if (twilioInited()) return; if (empty(conf.twilioAccountSID) || empty(conf.twilioAuthToken) || empty(conf.twilioPhoneNr)) return; try { print("initTwilio"); Object twilio = twilio(); if (twilio == null) { print("No twilio holder in VM"); return; } call(twilio, "twilioInit", conf.twilioAccountSID, conf.twilioAuthToken); print("initTwilio done"); } catch (Throwable __e) { printStackTrace(__e); } } public void initGoogleCalendar() { googleCalendarService = null; BookingConfig c = conf; if (empty(c.googleCalendarAccessToken) || empty(c.googleCalendarRefreshToken)) return; try { googleAccess.credentialFromTokens(c.googleCalendarAccessToken, c.googleCalendarRefreshToken); googleCalendarService = googleCalendarService(googleAccess, botName); print("googleCalendarService", googleCalendarService); } catch (Throwable __e) { printStackTrace(__e); } } public String calendarStatus() { return googleCalendarService == null ? "Calendar NOT initialized (auth problem?)" : "Calendar access OK"; } public String twilioStatus() { return twilioInited() ? "Twilio initialized" : "Twilio NOT initialized"; } public String businessHourStatus() { Map map = conf.businessHourStrings(); List l = new ArrayList(); double totalHours = 0; for (Map.Entry __2 : _entrySet(map)) { int day = __2.getKey(); String s = __2.getValue(); List ranges = parseBusinessHours_pcall(s); if (ranges == null) l.add(englishWeekday(day) + ": Error in business hour definition, please fix"); else { double hours = totalIntRangesLength(ranges) / 60.0; l.add(englishWeekday(day) + ": " + formatDouble(hours, 1) + (hours == 1 ? " hour" : " hours")); totalHours += hours; } } l.add("Total business hours per week: " + formatDouble(totalHours, 1)); return joinWithBR(l); } public LongRange maxLead(long now) { return longRange(now, dateStructureToTimestampRange(new DateStructures.TodayPlus(conf.appointmentMaxLead)).start); } public String answer(String s, Conversation conv) { DateInterpretationConfig config = new DateInterpretationConfig(); config.now = nowInConv(conv); LongRange range = parseEnglishDateRange(s, config); if (range == null) return null; LongRange extendedRange = new LongRange(beginningOfDay(range.start, localTimeZone()), endOfDay(range.end - 1, localTimeZone())); long now = nowInConv(conv); print("now=" + now + ", testMode: " + conv.testMode); range = intersectLongRanges(range, maxLead(now)); if (range == null) return template("#badTimeRange"); print("range: " + range); List eventRanges = getEventRanges(extendedRange, conv.testMode); TreeSet allPossibleDates = possibleDatesInTimeRange_unfiltered(extendedRange, conv.testMode); removeEventsFromPossibleDates(allPossibleDates, eventRanges); TreeSet possibleDates = possibleDatesInTimeRange_unfiltered(range, conv.testMode); removeEventsFromPossibleDates(possibleDates, eventRanges); print("Possible dates: " + l(possibleDates)); String formattedRange = formatDateRange(extendedRange, " and "); if (empty(possibleDates)) { if (empty(allPossibleDates)) { if (conf.dateSuggestionsOnFail != 0) { LongRange range2 = maxLead(nowInConv(conv)); TreeSet possibleDates2 = possibleDates(range2, conv.testMode); print("Possible dates: " + l(possibleDates2)); if (nempty(possibleDates2)) { proposeForm(new ProposeAppointmentsForm(possibleDates2, conf.dateSuggestionsOnFail)); return template("#noTimeSlots", "range", formattedRange); } return template("#bookedOut"); } return template("#noTimeSlots", "range", formattedRange); } long proposedDate = first(allPossibleDates); ProposeAppointmentForm form = new ProposeAppointmentForm(allPossibleDates, proposedDate); form.setTemplate("#suggestOtherTime"); proposeForm(form); return ""; } long proposedDate = first(possibleDates); ProposeAppointmentForm form = new ProposeAppointmentForm(allPossibleDates, proposedDate); form.setTemplate("#yesWeCanDoThatHowAboutDate"); if (range.length() <= hoursToMS(1)) form.setTemplate("#confirmDate"); proposeForm(form); return ""; } public List getEventRanges(LongRange range, boolean testMode) { long duration = minutesToMS(conf.appointmentDuration); int maxEvents = 10000; List eventRanges; if (testMode) eventRanges = testModeEventRanges(); else { long _startTime_3 = sysNow(); List events = googleCalendar_eventsInDateRange(booking.googleCalendarService, localTimeZone(), range, maxEvents); events = filterEventsByKeyword(events); eventRanges = map(events, evt -> longRange(evt.getStart().getDateTime().getValue() - duration + 1, evt.getEnd().getDateTime().getValue())); done2_always("Get events from calendar", _startTime_3); } return eventRanges; } public TreeSet possibleDatesInTimeRange_unfiltered(LongRange range, boolean testMode) { long granularity = granularity(); List ranges = sliceTimeRangeIntoBusinessHours(range, testMode); print("Sliced ranges: " + lambdaMap(__48 -> formatDateRange(__48), ranges)); ranges = map(r -> cutLongRangeToGranularity(r, granularity), ranges); ranges = filter(ranges, r -> r.length() >= 0); print("Final ranges: " + lambdaMap(__49 -> formatDateRange(__49), ranges) + ", granularity: " + granularity); TreeSet possibleDates = new TreeSet(); for (LongRange r : ranges) for (long x = r.start; x <= r.end; x += granularity) possibleDates.add(x); print("Possible dates: " + l(possibleDates)); return possibleDates; } public void removeEventsFromPossibleDates(TreeSet possibleDates, Collection eventRanges) { for (LongRange evt : eventRanges) { SortedSet subSet = possibleDates.subSet(evt.start, evt.end); if (nempty(subSet)) { subSet.clear(); } } } public TreeSet possibleDates(LongRange range, boolean testMode) { List eventRanges = getEventRanges(range, testMode); TreeSet possibleDates = possibleDatesInTimeRange_unfiltered(range, testMode); removeEventsFromPossibleDates(possibleDates, eventRanges); return possibleDates; } public List filterEventsByKeyword(List l) { return filter(l, e -> cic(e.getSummary(), conf.eventKeyword)); } public List sliceTimeRangeIntoBusinessHours(LongRange range, boolean testMode) { long firstDay = beginningOfDay(range.start, timeZone()); long lastDay = beginningOfDay(range.end, timeZone()); lastDay = min(firstDay + daysToMS(365), lastDay); List out = new ArrayList(); Map> businessHours = businessHours(testMode); long duration = minutesToMS(conf.appointmentDuration); for (long day = firstDay; day <= lastDay; day += daysToMS(1)) { int weekday = dayOfWeek_nr(day, timeZone()); List hours = businessHours.get(weekday); for (IntRange r : unnullForIteration(hours)) { LongRange r2 = longRange(day + r.start * 60 * 1000, day + r.end * 60 * 1000 - duration); r2 = intersectLongRanges(range, r2); if (r2 != null) out.add(r2); } } return out; } public String dateAndTimeFormat() { return dateFormat() + " " + timeFormat(); } public String dateFormat() { return "EEE M/dd/y"; } public String timeFormat() { return "hh:mm aa"; } public TimeZone timeZone() { return localTimeZone(); } public String formatDate(long date) { return main.formatDate(date, dateAndTimeFormat(), timeZone()); } public String formatDateRange(LongRange r) { return formatDateRange(r, " to "); } public String formatDateRange(LongRange r, String connector) { return r == null ? null : formatDate(r.start) + connector + formatDate(r.end); } public long granularity() { return minutesToMS(max(conf.appointmentGranularity, 5)); } public String acceptAppointment(Conversation conv, long date) { proposeForm(conv, new TakeUserInfoForm(date)); return ""; } public Object serveTwilioWebhook(String uri, Map params) { String twilioSig = subBot_getHeader("X-Twilio-Signature"); printAndProgramLog("twilioSig=" + twilioSig); print("params", params); String url = subBot_completeRequestURL(); printAndProgramLog("url", url); programLog("webhook: " + params); initTwilio(); boolean validated = isTrue(call(twilio(), "twilioValidateRequest", conf.twilioAuthToken, url, params, twilioSig)); printAndProgramLog("validated", validated); if (!validated) return "not validated"; String accountSID = params.get("AccountSid"); String body = params.get("Body"); String from = params.get("From"); String msgTo = conf.ownerPhoneNr; String msgText = from + " said: " + body; try { Object message = call(twilio(), "twilioSend", conf.twilioPhoneNr, msgTo, msgText); printAndProgramLog("Message sent: " + message); } catch (Throwable e) { printStackTrace(e); programLog(stackTraceToString(e)); } return hfulltag("Response", ""); } public Map> businessHours(boolean testMode) { return testMode ? testModeBusinessHours() : mapValues(__50 -> parseBusinessHours_pcall(__50), conf.businessHourStrings()); } public boolean anyBusinessHours() { return !allEmpty(values(businessHours(false))); } public void checkIfAnyTimeSlots() { int n = l(possibleDates(maxLead(now()), false)); print("Found " + n2(n, "possible date") + " in near future"); anyTimeSlots = n != 0; } public boolean anyBookingPossible() { return conf.bookingOpen && anyBusinessHours() && anyTimeSlots; } public List pickDates(int n, Collection possibleDates) { LinkedHashSet l = new LinkedHashSet(); if (nempty(possibleDates)) { long first = first(possibleDates); l.add(first); if (n >= 2) { boolean firstIsPM = hours(first, localTimeZone()) > 12; addIfNotNull(l, firstThat(dropFirst(possibleDates), d -> (hours(d, localTimeZone()) > 12) != firstIsPM)); } for (long date : possibleDates) { if (l(l) >= n) break; l.add(date); } } return asList(l); } } static public class ProposeAppointmentForm extends FormInFlight { public TreeSet possibleDates; public long date; public String template = "#howAboutDate"; public ProposeAppointmentForm() { } public ProposeAppointmentForm(TreeSet possibleDates, long date) { this.date = date; this.possibleDates = possibleDates; makeSteps(); } public void setTemplate(String template) { this.template = template; makeSteps(); } public void resetTemplate() { template = new ProposeAppointmentForm().template; } public void makeSteps() { steps = ll(nu(FormStep.class, "key", "start", "displayText", template(template, "date", booking.formatDate(date)), "buttons", ll_nonNulls(template("#illTakeIt"), possibleDates.lower(date) == null ? null : "Earlier please", possibleDates.higher(date) == null ? null : "Later please"))); change(); } public String handleInput(String s) { Matches m = new Matches(); if (find3plusRestsX("...earlier...", s, m)) { Long date2 = possibleDates.lower(date); if (date2 == null) return template("#noEarlierDate"); date = date2; resetTemplate(); makeSteps(); return ""; } if (find3plusRestsX("...later...", s, m)) { Long date2 = possibleDates.higher(date); if (date2 == null) return template("#noLaterDate"); date = date2; resetTemplate(); makeSteps(); return ""; } if (find3(template("#illTakeIt"), s)) return booking.acceptAppointment(cancelMe(), date); return null; } public boolean allowGeneralOverride() { return true; } } static public class ProposeAppointmentsForm extends FormInFlight { public int maxDatesToShow = 2; public List possibleDates; public List dateTexts; public ProposeAppointmentsForm() { } public ProposeAppointmentsForm(Collection possibleDates, int maxDatesToShow) { this.possibleDates = booking.pickDates(maxDatesToShow, possibleDates); this.maxDatesToShow = maxDatesToShow; dateTexts = map(d -> booking.formatDate(d), this.possibleDates); makeSteps(); } public void makeSteps() { steps = ll(nu(FormStep.class, "key", "select", "buttons", dateTexts)); change(); } public String handleInput(String s) { Matches m = new Matches(); for (int i = 0; i < l(dateTexts); i++) if (cic(s, dateTexts.get(i))) { long date = possibleDates.get(i); return booking.acceptAppointment(cancelMe(), date); } return null; } public boolean allowGeneralOverride() { return true; } } static public class TakeUserInfoForm extends FormInFlight { public long date; public TakeUserInfoForm() { } public TakeUserInfoForm(long date) { this.date = date; steps.add(nu(FormStep.class, "key", "name", "displayText", template("#bookingYouForPlusName", "date", booking.formatDate(date)), "placeholder", template("#yourName"))); steps.add(nu(USPhoneNrStep.class, "key", "phone", "displayText", template("#pleaseEnterAPhoneNr"), "placeholder", template("#yourPhoneNr"))); } public String complete() { try { BookingConfig conf = booking.conf; if (!conversation.testMode) { String name = shorten(getValue("name"), 50); String title = conf.eventKeyword + " " + conf.appointmentName + " with " + name; Event event = new Event().setSummary(title).setLocation(conf.businessName).setDescription("Booked through chat bot on " + ymdWithSlashes(nowInConv(conversation), localTimeZone()) + ". Phone contact: " + getValue("phone")); DateTime startDateTime = new DateTime(new java.util.Date(date), localTimeZone()); EventDateTime start = new EventDateTime().setDateTime(startDateTime).setTimeZone(timeZoneForGoogleAPI); event.setStart(start); long endDate = date + minutesToMS(conf.appointmentDuration); DateTime endDateTime = new DateTime(new java.util.Date(endDate), localTimeZone()); EventDateTime end = new EventDateTime().setDateTime(endDateTime).setTimeZone(timeZoneForGoogleAPI); event.setEnd(end); event = booking.googleCalendarService.events().insert("primary", event).execute(); print("Event created: " + event.getHtmlLink()); if (!isDummyPhoneNr(getValue("phone"))) startThread("Twilio", new Runnable() { public void run() { try { booking.initTwilio(); if (!booking.twilioInited()) { print("Twilio not available"); return; } print("Sending Twilio msg"); String text = conf.smsTemplate; text = replaceIC(text, "[date]", ymd(date, localTimeZone())); text = replaceIC(text, "[time]", timeInZone_24(date, localTimeZone())); text = replaceIC(text, "[business]", conf.businessName); text = replaceIC(text, "[appointment]", conf.appointmentName); text = replaceIC(text, "[name]", name); String cleanedPhoneNr = trim(getValue("phone")); if (!startsWithOneOf(cleanedPhoneNr, "+1", "1-", "1 ", "1(")) cleanedPhoneNr = "1" + cleanedPhoneNr; cleanedPhoneNr = "+" + digitsOnly(cleanedPhoneNr); print("Cleaned phone number: " + cleanedPhoneNr); print("SMS text: " + text); Object message = call(booking.twilio(), "twilioSend", conf.twilioPhoneNr, cleanedPhoneNr, text); print("Twilio msg sent: " + message); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "booking.initTwilio();\r\n if (!booking.twilioInited()) { print(\"Twilio n..."; } }); } return template("#youAreBooked", "name", getValue("name"), "date", booking.formatDate(date)); } catch (Exception __e) { throw rethrow(__e); } } } static public class USPhoneNrStep extends FormStep { public String verifyData(String s) { s = digitsOnly(s); if (contains(usAreaCodes(), takeFirst(s, 3)) || startsWith(s, "1") && contains(usAreaCodes(), substring(s, 1, 4))) { } else return template("#invalidAreaCode"); if (countDigitsInString(s) < 7) return template("#tooFewDigits"); return null; } } static public long nowInConv(Conversation conv) { return conv.testMode ? testModeDate() : now(); } static public class TestScript extends Concept { static final public String _fieldOrder = "scriptName comments active lastRun testedOK botLinePattern1 userLine1 botLinePattern2 userLine2 botLinePattern3 userLine3 botLinePattern4 userLine4 botLinePattern5 userLine5 botLinePattern6 userLine6 botLinePattern7 userLine7 botLinePattern8 userLine8"; public String scriptName, comments; public boolean active = false; public long lastRun; public boolean testedOK = false; public String botLinePattern1, userLine1; public String botLinePattern2, userLine2; public String botLinePattern3, userLine3; public String botLinePattern4, userLine4; public String botLinePattern5, userLine5; public String botLinePattern6, userLine6; public String botLinePattern7, userLine7; public String botLinePattern8, userLine8; public int highestIndex() { return 8; } public String botLinePattern(int i) { return trim(getString(this, "botLinePattern" + i)); } public String userLine(int i) { return trim(getString(this, "userLine" + i)); } } static public class TestScripting { static public Object html(String uri, Map params, AuthedDialogID auth) { String uri2 = appendSlash(uri); boolean requestAuthed = auth != null; if (startsWith(uri2, "/testscripts/")) { if (!requestAuthed) return serveAuthForm(params.get("uri")); return serveTestScriptingAdmin(uri, params); } return null; } static public Object serveTestScriptingAdmin(String uri, Map params) { String nav = p(ahref(rawBotLink(dbBotID), "Main admin") + " | " + ahref(baseLink + "/testscripts", "Test scripts admin")); if (ewic(uri, "/run-test")) { long id = parseLong(params.get("id")); TestScript script = getConcept(TestScript.class, id); if (script == null) return "Script " + id + " not found"; String output = hijackPrint_tee_pcall(() -> runTestScript(script)); String title = "Test results for script: " + script.scriptName; return hhtml(hhead_title(title) + hbody(hsansserif() + nav + h1(title) + hsourcecode(output))); } HCRUD_Concepts data = new HCRUD_Concepts<>(TestScript.class); HCRUD crud = new HCRUD(rawLink("testscripts"), data) { public String frame(String title, String contents) { return hhtml(hhead_title_htmldecode(title) + hbody(hsansserif() + hcss_responstable() + nav + h1(title) + contents)); } public String renderValue(String field, Object value) { if (eq(field, "lastRun")) return renderHowLongAgo(toLong(value)); return super.renderValue(field, value); } }; crud.renderCmds = item -> crud.renderCmds_base(item) + " | " + ahref(rawLink("testscripts/run-test" + hquery("id", item.get("id"))), "run test"); crud.cmdsLeft = true; crud.tableClass = "responstable"; crud.uneditableFields = litset("lastRun", "testedOK"); return subBot_serveHTMLNoCache(crud.renderPage(params)); } static public void runTestScript(TestScript script) { try { WebBotTester tester = new WebBotTester(programID()); try { tester.params.put("testMode", "1"); tester.start(); int i = 0; for (int idx = 1; idx <= script.highestIndex(); idx++) { String pat = script.botLinePattern(idx); if (nempty(pat)) { print("Bot line pattern: " + pat); tester.waitForMessages(i + 1); WebChatBotMsg msg = get(tester.msgs, i); try { assertTrueVerbose(i + ": " + pat + "/" + msg.msgText, mmo2_match(pat, msg.msgText)); assertTrue("fromBot", !msg.fromUser); } catch (Throwable _e) { print("msgs", tester.msgs); throw rethrow(_e); } ++i; } String userLine = script.userLine(idx); if (nempty(userLine)) { print("Sending line: " + userLine); tester.sendMsg(userLine); ++i; } } print("Script OK: " + script.scriptName); cset(script, "testedOK", true); } finally { _close(tester); } } catch (Throwable e) { printStackTrace(e); cset(script, "testedOK", false); } cset(script, "lastRun", now()); } } public static void main(final String[] args) throws Exception { standardTimeZone_name = timeZone; thoughtBot = mc(); baseLink = "https://botcompany.de/" + psI(programID()) + "/raw"; pWebChatBot(); booking = new Booking(); } static public void processParams(Map map) { } static public ThreadLocal out = new ThreadLocal(); static public ThreadLocal conv = new ThreadLocal(); static transient public long lastConversationChange = now(); static public boolean testFunctions = false; static public class FormStep { public String key; public String displayText, desc; public String defaultValue; public String placeholder; public List buttons; public boolean allowFreeText = false; public String value; public void update(Runnable onChange) { } public String verifyData(String s) { return null; } } static public class FormInFlight { public Conversation conversation; public String hashTag; public List steps = new ArrayList(); public int stepIndex; public String handleInput(String s) { return null; } public FormStep currentStep() { return get(steps, stepIndex); } public void update(Runnable onChange) { if (currentStep() != null) currentStep().update(onChange); } public String complete() { return "Form complete"; } public String cancel() { return "Request cancelled"; } public FormStep byKey(String key) { return objectWhere(steps, "key", key); } public String getValue(String key) { FormStep step = byKey(key); return step == null ? null : step.value; } public Map allValues() { Map map = litorderedmap(); for (FormStep step : steps) map.put(step.key, step.value); return map; } public boolean allowGeneralOverride() { return false; } public Conversation cancelMe() { Conversation conv = conversation; conversation.cancelForm(); return conv; } public void change() { if (conversation != null) conversation.change(); } } static public boolean debug = false; static public String answer(String s) { out.set(new Out()); if (creator() == null) if (match("debug", s)) debug = true; String a = rawAnswer(s); List tokHashtags = regexpICMatchesAsCNC(regexpNegativeLookbehind("\\w") + "#\\w+\\b", a); for (int i = 1; i < l(tokHashtags); i += 2) { print("Found hashtag " + tokHashtags.get(i)); } a = join(tokHashtags); return deliverAnswerAndFormStep(a); } static public String rawAnswer(String s) { FormInFlight form = conv.get().form; String a = null; Object bot = getDBBot(); out.get().proposeMode = true; String generalAnswer; { AutoCloseable __16 = tempSetTL((ThreadLocal) getOpt(bot, "opt_noDefault"), true); try { generalAnswer = (String) call(bot, "answer", s, conv.get().language()); } finally { _close(__16); } } if (generalAnswer == null) { try { generalAnswer = booking.answer(s, conv.get()); print("Booking answer to " + s + ": " + generalAnswer + " with form: " + out.get().proposedForm); } catch (Throwable __e) { printStackTrace(__e); } } out.get().proposeMode = false; if (form != null && generalAnswer != null && form.allowGeneralOverride()) conv.get().cancelForm(); else if (form != null) { if ((a = form.handleInput(s)) != null) return a; if (eqicOneOf(s, "cancel", "Abbrechen", unicode_crossProduct())) { String answer = form.cancel(); conv.get().cancelForm(); return answer; } else if (eqicOneOf(s, "back", "zurück", unicode_undoArrow()) && form.stepIndex > 0) { --form.stepIndex; conv.get().change(); return ""; } else if (form.currentStep() != null) { FormStep step = form.currentStep(); if (!step.allowFreeText && nempty(step.buttons) && !cic(step.buttons, s)) return de() ? "Bitte wählen Sie eine Option!" : "Please choose an option."; print("Verifying data " + quote(s) + " in step " + step); String error = step.verifyData(s); if (error != null) return error; step.value = s; ++form.stepIndex; conv.get().change(); if (form.currentStep() == null) { String answer = form.complete(); if (conv.get().form == form) conv.get().cancelForm(); return answer; } return ""; } } a = generalAnswer; if (a == null) a = (String) call(bot, "answer", "#default", conv.get().language()); if (out.get().proposedForm != null) conv.get().setForm(out.get().proposedForm); return a; } static public String deliverAnswerAndFormStep(String answer) { FormInFlight form = conv.get().form; if (form == null || form.currentStep() == null) return answer; FormStep step = form.currentStep(); printVars_str("answer", answer, "displayText", step.displayText); answer = joinNemptiesWithSpace(answer, step.displayText); out.get().placeholder = or(step.placeholder, step.displayText); print("Step " + form.stepIndex + ": " + sfu(step)); out.get().defaultInput = or2(step.value, step.defaultValue); out.get().buttons = cloneList(step.buttons); if (form.stepIndex > 0) out.get().buttons.add(de() ? "Zurück" : "Back"); out.get().buttons.add(de() ? "Abbrechen" : "Cancel"); return answer; } static public String initialMessage() { if (out.get() != null) out.get().placeholder = template("#typeADay"); if (booking.conf.dateSuggestionsInGreeting == 0) return getCannedAnswer("#greetingWithoutSuggestions", conv.get()); if (booking.anyBookingPossible()) { try { print("Booking possible"); LongRange range = booking.maxLead(nowInConv(conv.get())); TreeSet possibleDates = booking.possibleDates(range, conv.get().testMode); print("Possible dates: " + l(possibleDates)); if (nempty(possibleDates)) { proposeForm(new ProposeAppointmentsForm(possibleDates, booking.conf.dateSuggestionsInGreeting)); return getCannedAnswer("#greeting", conv.get()); } return template("#greetingBookedOut"); } catch (Throwable __e) { printStackTrace(__e); } } return getCannedAnswer("#bookingClosed", conv.get()); } static public Object getDBBot() { return getBot(dbBotID); } static public boolean de() { return eqic(conv.get().language(), "de"); } static public Object thoughtBot; static public int longPollTick = 200; static public int longPollMaxWait = 1000 * 30; static public int activeConversationSafetyMargin = 15000; static public Set specialButtons = litciset("Cancel", "Back", "Abbrechen", "Zurück"); static public class Out extends DynamicObject { public List buttons; public boolean multipleChoice = false; public String multipleChoiceSeparator; public String placeholder; public String defaultInput; public Integer progressBarValue; public boolean glow = false; transient public boolean proposeMode = false; transient public FormInFlight proposedForm; } static public class Msg extends DynamicObject { public long time; public boolean fromUser = false; public Worker fromWorker; public String text; public Out out; 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(); } } static public class AuthedDialogID extends Concept { public String dialogID; public Worker loggedIn; } static public class Conversation extends Concept { static final public String _fieldOrder = "cookie ip country oldDialogs msgs lastPing botOn worker userTyping botTyping testMode dryRun proposedForm form language lastProposedDate"; public String cookie, ip, country; public List> oldDialogs = new ArrayList(); public List msgs = new ArrayList(); public long lastPing; public boolean botOn = true; public Worker worker; transient public long userTyping, botTyping; public boolean testMode = false; transient public boolean dryRun = false; transient public FormInFlight proposedForm; public FormInFlight form; public String language; public Long lastProposedDate; public void add(Msg m) { m.text = trim(m.text); if (!m.fromUser && empty(m.text)) return; syncAdd(msgs, m); noteConversationChange(); change(); vmBus_send("chatBot_messageAdded", mc(), this, m); } public int allCount() { return lengthLevel2(oldDialogs) + l(msgs); } public int archiveSize() { return lengthLevel2(oldDialogs); } public long lastMsgTime() { Msg m = last(msgs); return m == null ? 0 : m.time; } public void cancelForm() { if (form != null) { print("Cancelling form " + form); form.conversation = null; cset(this, "form", null); } } public A setForm(A form) { form.conversation = this; cset(this, "form", form); return form; } public String language() { return or2(language, "en"); } public void updateForm() { if (form != null) form.update(new Runnable() { public void run() { try { change(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "change();"; } }); } public void turnBotOff() { cset(this, "botOn", false); noteConversationChange(); updateForm(); } public void turnBotOn() { cset(this, "botOn", true, "worker", null); String backMsg = getCannedAnswer("#botBack", this); if (empty(msgs) || lastMessageIsFromUser() || !eq(last(msgs).text, backMsg)) add(new Msg(backMsg, false)); noteConversationChange(); } public boolean lastMessageIsFromUser() { return nempty(msgs) && last(msgs).fromUser; } public void newDialog() { cancelForm(); lastProposedDate = null; oldDialogs.add(msgs); cset(this, "msgs", new ArrayList()); change(); vmBus_send("chatBot_clearedSession", mc(), this); } } static public class ProposedMsg extends Concept { static final public String _fieldOrder = "authoringObject text conversation said"; public Object authoringObject; public String text; public Conversation conversation; public Msg said; } static public void pWebChatBot() { dbIndexing(Conversation.class, "cookie", Conversation.class, "worker", Conversation.class, "lastPing", Worker.class, "loginName", AuthedDialogID.class, "dialogID"); Class envType = fieldType(thoughtBot, "env"); if (envType != null) setOpt(thoughtBot, "env", proxy(envType, (Object) mc())); } static public Object html(String uri, Map params) { AutoCloseable __17 = tempRegisterThread(); try { if (eqic(uri, "/twilioWebhook")) return booking.serveTwilioWebhook(uri, params); String cookie = params.get("cookie"); if (empty(cookie)) { registerVisitor(); cookie = cookieSent(); } boolean workerMode = nempty(params.get("workerMode")) || startsWith(uri, "/worker"); Conversation conv = nempty(cookie) ? getConv(cookie) : null; if (conv != null && !workerMode) cset(conv, "ip", subBot_clientIP()); print("URI: " + uri + ", cookie: " + cookie + ", msgs: " + l(conv.msgs)); String dialogID = getDialogID(); String pw = trim(params.get("pw")); if (nempty(pw)) { String realPW = loadSecretTextFileOrCreateWithRandomID("password.txt"); if (neq(pw, realPW)) return errorMsg("Bad password, please try again"); uniq(AuthedDialogID.class, "dialogID", dialogID); if (nempty(params.get("redirect"))) return hrefresh(params.get("redirect")); } Matches m = new Matches(); if (startsWith(uri, "/worker-image/", m)) { long id = parseLong(m.rest()); return subBot_serveFile(workerImageFile(id), "image/jpeg"); } AuthedDialogID auth = authObject(); boolean requestAuthed = auth != null; if (eq(uri, "/stats")) { if (!requestAuthed) return serveAuthForm(rawLink(uri)); return "Threads: " + ul_htmlEncode(getThreadNames(registeredThreads())); } if (eq(uri, "/logs")) { if (!requestAuthed) return serveAuthForm(rawLink(uri)); return webChatBotLogsHTML2(rawLink(uri), params); } if (eq(uri, "/auth-only")) { if (eq(params.get("logout"), "1")) cdelete(AuthedDialogID.class, "dialogID", getDialogID()); if (!requestAuthed) return serveAuthForm(params.get("uri")); return ""; } if (workerChat != null) { var __13 = workerChat.html(uri, params, conv, auth); if (__13 != null) return __13; } if (booking != null) { var __14 = booking.html(uri, params, auth); if (__14 != null) return __14; } { var __15 = TestScripting.html(uri, params, auth); if (__15 != null) return __15; } { Lock __10 = dbLock(); lock(__10); try { String message = trim(params.get("btn")); if (empty(message)) message = trim(params.get("message")); if (match("new dialog", message)) { conv.newDialog(); message = null; } main.conv.set(conv); if (!workerMode && empty(conv.msgs)) addReplyToConvo(conv, () -> deliverAnswerAndFormStep(initialMessage())); if (nempty(message) && !lastUserMessageWas(conv, message)) { print("Adding message: " + message); if (workerMode) { Msg msg = new Msg(false, message); msg.fromWorker = auth.loggedIn; conv.add(msg); } else conv.add(new Msg(true, message)); } String testMode = params.get("testMode"); if (nempty(testMode)) { print("Setting testMode", testMode); cset(conv, "testMode", eq("1", testMode)); } if (!workerMode && conv.botOn && nempty(conv.msgs) && last(conv.msgs).fromUser) addReplyToConvo(conv, () -> makeReply(last(conv.msgs).text)); } finally { unlock(__10); } } if (eq(uri, "/msg")) return withHeader("OK"); if (eq(uri, "/typing")) { if (workerMode) { conv.botTyping = sysNow(); print(conv.botTyping + " Bot typing in: " + conv.cookie); } else { conv.userTyping = sysNow(); print(conv.userTyping + " User typing in: " + conv.cookie); } return withHeader("OK"); } if (eq(uri, "/incremental")) { vmBus_send("chatBot_userPolling", mc(), conv); cset(conv, "lastPing", now()); int a = parseInt(params.get("a")); long start = sysNow(); List msgs; boolean first = true; while (licensed() && sysNow() < start + longPollMaxWait) { int as = conv.archiveSize(); msgs = cloneSubList(conv.msgs, a - as); boolean newDialog = a <= as; long typing = workerMode ? conv.userTyping : conv.botTyping; boolean otherPartyTyping = typing > start; if (empty(msgs) && !otherPartyTyping) { if (first) { print("Long poll starting on " + cookie + ", " + a + "/" + a); first = false; } sleep(longPollTick); } else { if (first) print("Long poll ended."); StringBuilder buf = new StringBuilder(); if (otherPartyTyping) { print("Noticed " + (workerMode ? "user" : "bot") + " typing in " + conv.cookie); buf.append(hscript("showTyping();")); } renderMessages(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("window.playChatNotification();\n" + "window.setTitleStatus(" + jsQuote((workerMode ? "User" : botName) + " says…") + ");")); return withHeader("\n" + buf); } } return withHeader(""); } { Lock __11 = dbLock(); lock(__11); try { processParams(params); String html = loadSnippet(templateID); String workerModeParam = workerMode ? "workerMode=1&" : ""; String langlinks = ""; if (html.contains(langlinks)) html = html.replace(langlinks, ahref(rawLink("eng"), "English") + " | " + ahref(rawLink("deu"), "German")); html = html.replace("#BOTIMG#", imageSnippetURLOrEmptyGIF(chatHeaderImageID)); html = html.replace("#N#", "0"); html = html.replace("#INCREMENTALURL#", baseLink + "/incremental?" + workerModeParam + "a="); html = html.replace("#MSGURL#", baseLink + "/msg?" + workerModeParam + "message="); html = html.replace("#TYPINGURL#", baseLink + "/typing?" + workerModeParam); 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 || botAutoOpen())); html = html.replace("#BOT_ON#", jsBool(botOn())); html = html.replace("$HEADING", heading); html = html.replace("#WORKERMODE", jsBool(workerMode)); html = html.replace("", ""); html = hreplaceTitle(html, heading); if (eqGet(params, "_botDemo", "1")) return hhtml(hhead(htitle(heading) + loadJQuery()) + hbody(hjavascript(html))); else return withHeader(subBot_serveJavaScript(html)); } finally { unlock(__11); } } } finally { _close(__17); } } static public void addReplyToConvo(Conversation conv, IF0 think) { out.set(new Out()); String reply = ""; try { reply = think.get(); } catch (Throwable __e) { printStackTrace(__e); } Msg msg = new Msg(false, reply); msg.out = out.get(); conv.add(msg); } static public Object withHeader(String html) { return withHeader(subBot_noCacheHeaders(subBot_serveHTML(html))); } static public Object withHeader(Object response) { call(response, "addHeader", "Access-Control-Allow-Origin", "*"); return response; } static public String renderMessageText(String text, boolean htmlEncode) { text = trim(text); if (htmlEncode) text = htmlEncode2(text); text = nlToBr(text); return replace(text, ":wave:", html_wavingHand()); } static public void renderMessages(StringBuilder buf, List msgs) { if (empty(msgs)) return; Set buttonsToSkip = new HashSet(); List buttonsHtml = new ArrayList(); for (Msg m : msgs) { if (!m.fromUser && eq(m.text, "-")) continue; String html = renderMessageText(m.text, shouldHtmlEncodeMsg(m)); if (m == last(msgs) && m.out != null) { for (String btn : unnullForIteration(m.out.buttons)) if (specialButtons.contains(btn)) { buttonsToSkip.add(btn); buttonsHtml.add(renderButtons(ll(btn))); } } if (nempty(buttonsHtml) && l(m.out.buttons) == l(buttonsToSkip)) html += " " + hspan("  ", "class", "chat-button-span") + lines(buttonsHtml); else buttonsToSkip.clear(); appendMsg(buf, m.fromUser ? defaultUserName() : botName, formatTime(m.time), html, !m.fromUser, m.fromWorker); } appendButtons(buf, last(msgs).out, buttonsToSkip); } static public void appendMsg(StringBuilder buf, String name, String time, String text, boolean bot, Worker fromWorker) { boolean useTrick = ariaLiveTrick; String tag = useTrick ? "div" : "span"; if (bot) { String id = randomID(); String author = fromWorker != null ? htmlEncode2(fromWorker.displayName) : botName; 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\"" : "") + ">"); String imgURL = snippetImgLink(botImageID); if (fromWorker != null && fileExists(workerImageFile(fromWorker.id))) imgURL = fullRawLink("worker-image/" + fromWorker.id); 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)); } static public String replaceButtonText(String s) { if (eqicOneOf(s, "back", "zurück")) return unicode_undoArrow(); if (eqicOneOf(s, "cancel", "Abbrechen")) return unicode_crossProduct(); return s; } static public String renderMultipleChoice(List buttons, Collection selections, String multipleChoiceSeparator) { print("selections", selections); 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()", "style", "float: right") + 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) + "));" + "});"); } static public String renderButtons(List buttons) { List out = new ArrayList(); for (int i = 0; i < l(buttons); i++) { String code = buttons.get(i); String text = replaceButtonText(code); out.add(hbuttonOnClick_returnFalse(text, "submitAMsg(" + jsQuote(text) + ")", "class", "chatbot-choice-button", "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); } static public void appendButtons(StringBuilder buf, Out out, Set buttonsToSkip) { String placeholder = out == null ? "" : unnull(out.placeholder); String defaultInput = out == null ? "" : unnull(out.defaultInput); buf.append(hscript("chatBot_setInput(" + jsQuote(defaultInput) + ", " + jsQuote(placeholder) + ");")); if (out == null) return; List buttons = listMinusSet(out.buttons, buttonsToSkip); if (empty(buttons)) return; printVars_str("buttons", buttons, "buttonsToSkip", buttonsToSkip); String buttonsHtml; if (out.multipleChoice) buttonsHtml = renderMultipleChoice(buttons, mcSplit(out.defaultInput, out.multipleChoiceSeparator), out.multipleChoiceSeparator); else buttonsHtml = renderButtons(buttons); buf.append(""); buf.append(buttonsHtml); buf.append(""); } static public void appendDate(StringBuilder buf, String date) { buf.append("\r\n
\r\n DATE\r\n
".replace("DATE", date)); } static public boolean lastUserMessageWas(Conversation conv, String message) { Msg m = last(conv.msgs); return m != null && m.fromUser && eq(m.text, message); } static public String makeReply(String message) { try { return answer(message); } catch (Throwable e) { printStackTrace(e); return "Internal error"; } } static public String formatTime(long time) { return timeInTimeZoneWithOptionalDate_24(timeZone, time); } static 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); } static public Conversation getConv(final String cookie) { return withDBLock(new F0() { public Conversation get() { try { return uniq(Conversation.class, "cookie", cookie); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return uniq(Conversation, +cookie);"; } }); } static public String serveAuthForm(String redirect) { return hhtml(hhead(htitle("Authorization required")) + hbody(hfullcenter(h3_htmlEncode(heading + " Admin") + hpostform(hhidden("redirect", redirect) + "Password: " + hpassword("pw") + "

" + hsubmit())))); } static public String errorMsg(String msg) { return hhtml(hhead_title("Error") + hbody(hfullcenter(msg + "

" + ahref(jsBackLink(), "Back")))); } static public String defaultUserName() { return de() ? "Sie" : "You"; } static public boolean botOn() { return isTrue(call(getDBBot(), "botOn")); } static public boolean botAutoOpen() { return isTrue(call(getDBBot(), "botAutoOpen")); } static public File workerImageFile(long id) { return id == 0 ? null : javaxDataDir("adaptive-bot/images/" + id + ".jpg"); } static public long activeConversationTimeout() { return longPollMaxWait + activeConversationSafetyMargin; } static public AuthedDialogID authObject() { return conceptWhere(AuthedDialogID.class, "dialogID", getDialogID()); } static public boolean anyInterestingMessages(List msgs, boolean workerMode) { return any(msgs, m -> m.fromUser == workerMode); } static public boolean shouldHtmlEncodeMsg(Msg msg) { return msg.fromUser; } static public String getCountry(Conversation c) { if (empty(c.country) && nempty(c.ip)) cset(c, "country", ipToCountry2020_safe(c.ip)); return or2(c.country, "?"); } static public void noteConversationChange() { lastConversationChange = now(); } static public void addTimeout(double seconds, Runnable action) { doAfter(seconds, action); print("Timeout added: " + seconds + " => " + action); } static public String template(String hashtag, Object... params) { return replaceSquareBracketVars(getCannedAnswer(hashtag), params); } static public String getCannedAnswer(String hashtag) { return getCannedAnswer(hashtag, null); } static public String getCannedAnswer(String hashtag, Conversation conv) { if (!startsWith(hashtag, "#")) return hashtag; String lang = conv == null ? "en" : conv.language(); AutoCloseable __18 = tempSetTL((ThreadLocal) getOpt(getDBBot(), "opt_noDefault"), true); try { return or2((String) call(getDBBot(), "answer", hashtag, lang), hashtag); } finally { _close(__18); } } static public List mcSplit(String input, String multipleChoiceSeparator) { return trimAll(splitAt(input, dropSpaces(multipleChoiceSeparator))); } static public Msg lastBotMsg(List l) { return lastThat(l, msg -> !msg.fromUser); } static public String dbStats() { Collection all = list(Conversation.class); int nTestConvos = countPred(all, c -> startsWith(c.cookie, "test_")); return n2(l(all) - nTestConvos, "real conversation") + ", " + n2(nTestConvos, "test conversation"); } static public void proposeForm(FormInFlight form) { proposeForm(conv.get(), form); } static public void proposeForm(Conversation conversation, FormInFlight form) { if (out.get() != null && out.get().proposeMode) out.get().proposedForm = form; else if (conversation != null) conversation.setForm(form); } static public String californiaTimeZone_string() { return "America/Los_Angeles"; } static public String htmlEncode2(String s) { return htmlencode_noQuotes(s); } static public String htmlEncode2(Object o) { return htmlEncode2(strOrEmpty(o)); } static public String appendSlash(String s) { return addSlash(s); } 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 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 Object subBot_serveRedirect(String url) { return call(getMainBot(), "serveRedirect", url); } static public String domain() { return domainName(); } static public String domain(String url) { return hostNameFromURL(url); } static public String fullSelfLink(Map params) { return getActualURI() + htmlQuery(params); } static public String fullSelfLink() { return getActualURI(); } 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(BitSet bs) { return !empty(bs); } static public boolean nempty(Map m) { return !empty(m); } static public boolean nempty(Iterator i) { return i != null && i.hasNext(); } static public boolean nempty(IMultiMap mm) { return mm != null && mm.size() != 0; } 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 nempty(MultiSet ms) { return ms != null && !ms.isEmpty(); } static public String p(Object contents, Object... params) { return hfulltag("p", contents, params) + "\n"; } static public String p() { return p(""); } static public String ahref(String link, Object contents, Object... params) { return link == null ? str(contents) : href(link, contents, params); } static public String rawBotLink() { return rawBotLink(programID()); } static public String rawBotLink(String botID) { return "https://" + myDomain() + "/" + parseSnippetID(botID) + "/raw"; } static public String rawBotLink(String botID, String uri) { return "https://" + myDomain() + "/" + parseSnippetID(botID) + "/raw" + addPrefix("/", uri); } 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 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 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 byte[] saveFile(String fileName, byte[] contents) { return saveBinaryFile(fileName, contents); } static public byte[] saveFile(File fileName, byte[] contents) { return saveBinaryFile(fileName, contents); } static public byte[] decodeBASE64(String s) { return base64decode(s); } static public String hscript(String script) { return hjavascript(script); } static public String h2(String s, Object... params) { return tag("h2", s, params); } 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 himgsrc(String src, Object... params) { return tag("img", "", arrayPlus(params, "src", src)); } 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 hpostform(Object contents, Object... params) { return tag("form", contents, concatArrays(new Object[] { "method", "POST" }, params)); } 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 hfileupload(Object... params) { return hinputtag("", paramsPlus_noOverwrite(params, "type", "file", "name", "thefile")); } 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 hbuttonOnClick_returnFalse(String text, String onClick, Object... params) { return hfulltag("button", text, paramsPlus(params, "onclick", addSuffix(trim(onClick), ";") + " return false;")); } static public String hhtml(Object contents) { return containerTag("html", contents); } static public String hhead_title(String title) { return hhead(htitle(title)); } static public String hsansserif() { return hcss("body { font-family: Sans-Serif; }"); } static public String hbody(Object contents, Object... params) { return tag("body", contents, params); } static public String loadJQuery() { return ""; } static public String hhead_title_htmldecode(String title) { return hhead_title_decode(title); } static public String h1(String s, Object... params) { return hfulltag("h1", s, params); } static public HashSet litset(A... items) { return lithashset(items); } 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 Map mapPlus(Map m, Object... data) { m = cloneMap(m); litmap_impl(m, data); return m; } static public String hquery(Map params) { return htmlQuery(params); } static public String hquery(Object... data) { return htmlQuery(data); } 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 afterLastSlash(String s) { if (s == null) return null; int i = s.lastIndexOf('/'); return i < 0 ? s : substring(s, i + 1); } 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 joinWithComma(Collection c) { return join(", ", c); } static public String joinWithComma(Object... 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 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(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(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(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(Map map, IF2 f) { List x = new ArrayList(); if (map != null) for (Map.Entry e : map.entrySet()) { ping(); x.add(f.get(e.getKey(), e.getValue())); } return x; } 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 int cset(Concept c, Object... values) { try { if (c == null) return 0; warnIfOddCount(values = expandParams(c.getClass(), values)); int changes = 0; for (int i = 0; i + 1 < l(values); i += 2) if (_csetField(c, (String) values[i], values[i + 1])) ++changes; return changes; } catch (Exception __e) { throw rethrow(__e); } } static public int cset(Iterable l, Object... values) { int changes = 0; for (Concept c : unnullForIteration(l)) changes += cset(c, values); return changes; } static public int cset(Concept.Ref c, Object... values) { return cset(getVar(c), values); } static public boolean cset_trueIfChanged(Concept c, Object... values) { try { return cset(c, values) != 0; } catch (Exception __e) { throw rethrow(__e); } } 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 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 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 long conceptID(Concept c) { return c == null ? 0 : c.id; } static public long conceptID(Concept.Ref ref) { return conceptID(cDeref(ref)); } static public String hsubmit(String text, Object... params) { return tag("input", "", concatArrays(new Object[] { "type", "submit", "value", text }, params)); } static public String hsubmit() { return hsubmit("Submit"); } static public String hscriptsrc(String src) { return hjavascript_src(src); } static public long now_virtualTime; static public long now() { return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis(); } 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 Class mc() { return main.class; } static public long sysNow() { ping(); return System.nanoTime() / 1000000; } 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 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 void printVars_str(Object... params) { print(renderVars_str(params)); } 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 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 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 hsimpletableheader(String... cols) { return tag("tr", join(lambdaMap(__51 -> th(__51), cols))); } 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 lastTwo(List l) { return takeLast(2, l); } 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 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 hparagraphs(Collection l) { return lines(lambdaMap(__52 -> p(__52), l)); } static public List lambdaMap(IF1 f, Iterable l) { return map(l, f); } static public List lambdaMap(IF1 f, A[] l) { return map(l, f); } static public String hhead(Object contents) { return tag("head", contents); } 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 h3(String s, Object... params) { return tag("h3", s, params) + "\n"; } static public String hcheckboxWithText(String name, String text, boolean checked, Object... params) { String id = randomID(); return hcheckbox(name, checked, paramsPlus(params, "id", id)) + " " + hlabelFor(id, htmlEncode2(text)); } static public String hcheckboxWithText(String name, String text) { return hcheckboxWithText(name, text, false); } static public String b(Object contents, Object... params) { return tag("b", contents, params); } 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 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 Complex div(Complex a, double b) { return new Complex(a.re / b, a.im / b); } static public double div(double a, double b) { return a / b; } static public double div(double a, int b) { return a / b; } static public int div(int a, int b) { return a / b; } static public String small(Object contents, Object... params) { return tag("small", contents, params); } static public String span(Object contents, Object... params) { return hfulltag("span", contents, params); } static public String span() { return span(""); } static public String hbutton(String text, Object... params) { return hfulltag("button", text, params); } 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 List filter(Iterable c, Object pred) { if (pred instanceof F1) return filter(c, (F1) pred); List x = new ArrayList(); if (c != null) for (Object o : c) if (isTrue(callF(pred, o))) x.add(o); return x; } static public List filter(Object pred, Iterable c) { return filter(c, pred); } static public List filter(Iterable c, F1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(F1 pred, Iterable c) { return filter(c, pred); } static public List filter(Iterable c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(B[] c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static public List filter(IF1 pred, Iterable c) { return filter(c, pred); } static public List list(Class type) { return list(type, db_mainConcepts()); } static public List list(Class type, Concepts cc) { return cc.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 List list(Concepts concepts) { return asList(concepts.allConcepts()); } 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 LongRange longRange(long start, long end) { return new LongRange(start, end); } static public long parseYMDHMS(String s) { return parseYMDHMS_slashesSpaceColons(s); } static public long parseYMDHMS(String s, TimeZone tz) { return parseYMDHMS_slashesSpaceColons(s, tz); } static public TimeZone localTimeZone() { return getTimeZone(standardTimeZone()); } 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 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 TreeMap pairsToTreeMap(Collection> l) { TreeMap map = new TreeMap(); if (l != null) for (Pair p : l) map.put(p.a, p.b); return map; } static public void indexSingletonConcept(Concepts cc, Class c) { indexConceptField(cc, c, "_dummy"); } static public void indexSingletonConcept(Class c) { indexSingletonConcept(db_mainConcepts(), c); } 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 volatile public StringBuffer local_log = new StringBuffer(); static public boolean printAlsoToSystemOut = true; 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); if (printAlsoToSystemOut) System.out.print(s); vmBus_send("printed", mc(), s); } static public void print_autoRotate() { } public static String join(String glue, Iterable strings) { if (strings == null) return ""; if (strings instanceof Collection) { if (((Collection) strings).size() == 1) return str(first((Collection) strings)); } StringBuilder buf = new StringBuilder(); Iterator i = strings.iterator(); if (i.hasNext()) { buf.append(i.next()); while (i.hasNext()) buf.append(glue).append(i.next()); } return buf.toString(); } public static String join(String glue, String... strings) { return join(glue, Arrays.asList(strings)); } public static String join(String glue, Object... strings) { return join(glue, Arrays.asList(strings)); } static 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 Object vmBus_query(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); { var __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 boolean isTrue(Object o) { if (o instanceof Boolean) return ((Boolean) o).booleanValue(); if (o == null) return false; if (o instanceof ThreadLocal) return isTrue(((ThreadLocal) o).get()); throw fail(getClassName(o)); } static public boolean isTrue(Boolean b) { return b != null && b.booleanValue(); } static public Object call(Object o) { return callF(o); } static public Object call(Object o, String method, String[] arg) { return call(o, method, new Object[] { arg }); } static public Object call(Object o, String method, Object... args) { return call_withVarargs(o, method, args); } 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(BitSet bs) { return bs == null || bs.isEmpty(); } 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(IMultiMap mm) { return mm == null || mm.size() == 0; } 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 boolean empty(Chain c) { return c == null; } static public boolean empty(AppendableChain c) { return c == null; } static public A printStackTrace(A e) { if (e != null) 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 Calendar googleCalendarService(GoogleAccess ga, String applicationName) { return new Calendar.Builder(ga.transport(), ga.jsonFactory(), ga.credential).setApplicationName(applicationName).build(); } static public Set> _entrySet(Map map) { return map == null ? Collections.EMPTY_SET : map.entrySet(); } static public List parseBusinessHours_pcall(String s) { try { return parseBusinessHours(s); } catch (Throwable __e) { printStackTrace(__e); } return null; } static public String englishWeekday(int i) { return get(englishWeekdays(), i - 1); } static public long totalIntRangesLength(Iterable l) { long total = 0; for (IntRange r : unnullForIteration(l)) total += r.length(); return total; } 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 joinWithBR(Iterable l) { return join("
\n", l); } static public String joinWithBR(String... l) { return joinWithBR(asList(l)); } static public LongRange dateStructureToTimestampRange(DateStructures.SomeDate d) { return dateStructureToTimestampRange(d, new DateInterpretationConfig()); } static public LongRange dateStructureToTimestampRange(DateStructures.SomeDate d, DateInterpretationConfig config) { return new DateStructureToTimestampRange(config).getRange(d); } static public class DateStructureToTimestampRange { public TimeZone tz; public long now; public boolean assumeFuture = false; public DateStructureToTimestampRange(DateInterpretationConfig config) { tz = config.timeZone; now = config.now; assumeFuture = config.assumeFuture; } public DateStructures.Year currentYear() { return new DateStructures.Year(year(now, tz)); } public DateStructures.Month currentMonth() { return new DateStructures.Month(month(now, tz), currentYear()); } public DateStructures.SomeDate concretizeDate(DateStructures.SomeDate d) { if (d instanceof DateStructures.CurrentMonthPlus) d = new DateStructures.Month(month(now, tz) + ((DateStructures.CurrentMonthPlus) d).nMonths, currentYear()); if (d instanceof DateStructures.TodayPlus) d = new DateStructures.Day(dayOfMonth(now, tz) + ((DateStructures.TodayPlus) d).nDays, currentMonth()); if (d instanceof DateStructures.CurrentYearPlus) d = new DateStructures.Year(year(now, tz) + ((DateStructures.CurrentYearPlus) d).nYears); if (d instanceof DateStructures.CurrentWeekPlus) d = new DateStructures.Week(weekInYear(now, tz) + ((DateStructures.CurrentWeekPlus) d).nWeeks, currentYear()); return d; } public LongRange getRange(DateStructures.SomeDate d) { d = concretizeDate(d); if (d instanceof DateStructures.Year) return longRange(yearToTimestamp(((DateStructures.Year) d).year, tz), yearToTimestamp(((DateStructures.Year) d).year + 1, tz)); if (d instanceof DateStructures.Month) { if (((DateStructures.Month) d).year == null) ((DateStructures.Month) d).year = (DateStructures.Year) concretizeDate(new DateStructures.CurrentYearPlus(((DateStructures.Month) d).month < currentMonth().month ? 1 : 0)); int year = ((DateStructures.Month) d).year.year; return longRange(yearAndMonthToTimestamp(year, ((DateStructures.Month) d).month, tz), yearAndMonthToTimestamp(year, ((DateStructures.Month) d).month + 1, tz)); } if (d instanceof DateStructures.Week) { int year = ((DateStructures.Week) d).year.year; return longRange(yearAndWeekToTimestamp(year, ((DateStructures.Week) d).week, tz), yearAndWeekToTimestamp(year, ((DateStructures.Week) d).week + 1, tz)); } if (d instanceof DateStructures.Weekday) { if (((DateStructures.Weekday) d).week == null) ((DateStructures.Weekday) d).week = (DateStructures.Week) concretizeDate(new DateStructures.CurrentWeekPlus(((DateStructures.Weekday) d).weekday < dayOfWeek_nr(now, tz) ? 1 : 0)); long start = getRange(((DateStructures.Weekday) d).week).start + (((DateStructures.Weekday) d).weekday - 1) * 24 * 60 * 60 * 1000; return new LongRange(start, start + 24 * 60 * 60 * 1000); } if (d instanceof DateStructures.Day) { int month = ((DateStructures.Day) d).month.month; int year = ((DateStructures.Day) d).month.year.year; return longRange(ymdToTimestamp(year, month, ((DateStructures.Day) d).day, tz), ymdToTimestamp(year, month, ((DateStructures.Day) d).day + 1, tz)); } if (d instanceof DateStructures.Hour) { if (((DateStructures.Hour) d).isPM == null) throw fail("AM/PM unknown: " + ((DateStructures.Hour) d)); long dayStart = getRange(assertNotNull("day of hour", ((DateStructures.Hour) d).day)).start; int actualHour = ((DateStructures.Hour) d).hour + (((DateStructures.Hour) d).isPM ? 12 : 0); return longRange(dayStart + hoursToMS(actualHour), dayStart + hoursToMS(actualHour + 1)); } if (d instanceof DateStructures.Between) { return longRange(getRange(((DateStructures.Between) d).from).start, getRange(((DateStructures.Between) d).to).start); } throw fail("dateStructureToTimestampRange: unknown type " + d); } } static public LongRange parseEnglishDateRange(String s, DateInterpretationConfig config) { EnglishDateParser parser = new EnglishDateParser(); List dates = getVars(parser.topDogs(s)); print("dates", dates); if (empty(dates)) return null; LongRange first = dateStructureToTimestampRange(first(dates), config); if (l(dates) == 2 && !DateStructures.containsDateDates(second(dates)) && DateStructures.containsTimes(second(dates))) { DateStructures.Day day = new DateStructures.Day(dayOfMonth(first.start), new DateStructures.Month(month(first.start), new DateStructures.Year(year(first.start)))); DateStructures.SomeDate combined = (DateStructures.SomeDate) (defaultMetaTransformer().transform(o -> { if (o instanceof DateStructures.Hour) return cloneSetAll(((DateStructures.Hour) o), "day", day); return null; }, second(dates))); print("combined", combined); return dateStructureToTimestampRange(combined, config); } return joinLongRanges(map(d -> dateStructureToTimestampRange(d, config), dates)); } static public long beginningOfDay(long timestamp, TimeZone tz) { return parseYYYYMMDD(ymd(timestamp, tz), tz); } static public long endOfDay(long timestamp, TimeZone tz) { return beginningOfDay(timestamp, tz) + daysToMS(1); } static public LongRange intersectLongRanges(LongRange a, LongRange b) { long start = max(a.start, b.start); long end = min(a.end, b.end); return start <= end ? new LongRange(start, end) : null; } static public int l(Object[] a) { return a == null ? 0 : a.length; } static public int l(boolean[] a) { return a == null ? 0 : a.length; } static public int l(byte[] a) { return a == null ? 0 : a.length; } static public int l(short[] a) { return a == null ? 0 : a.length; } static public int l(long[] a) { return a == null ? 0 : a.length; } static public int l(int[] a) { return a == null ? 0 : a.length; } static public int l(float[] a) { return a == null ? 0 : a.length; } static public int l(double[] a) { return a == null ? 0 : a.length; } static public int l(char[] a) { return a == null ? 0 : a.length; } static public int l(Collection c) { return c == null ? 0 : c.size(); } static public int l(Iterator i) { return iteratorCount_int_close(i); } static public int l(Map m) { return m == null ? 0 : m.size(); } static public int l(CharSequence s) { return s == null ? 0 : s.length(); } static public long l(File f) { return f == null ? 0 : f.length(); } static public int l(MultiSet ms) { return ms == null ? 0 : ms.size(); } static public int l(IMultiMap mm) { return mm == null ? 0 : mm.size(); } static public int l(IntRange r) { return r == null ? 0 : r.length(); } static public long l(LongRange r) { return r == null ? 0 : r.length(); } static public int l(AppendableChain a) { return a == null ? 0 : a.size; } 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 Pair first(Map map) { return mapEntryToPair(first(entrySet(map))); } static public Pair first(MultiMap mm) { if (mm == null) return null; var e = first(mm.data.entrySet()); if (e == null) return null; return pair(e.getKey(), first(e.getValue())); } static 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 A first(T3 t) { return t == null ? null : t.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 A first(AppendableChain a) { return a == null ? null : a.element; } static public long hoursToMS(double hours) { return round(hours * 60 * 60 * 1000); } static public long minutesToMS(double minutes) { return round(minutes * 60 * 1000); } static public List googleCalendar_eventsInDateRange(Calendar calendarService, TimeZone tz, long startDate, long endDate, int maxEvents) { return googleCalendar_eventsInDateRange(calendarService, tz, longRange(startDate, endDate), maxEvents); } static public List googleCalendar_eventsInDateRange(Calendar calendarService, TimeZone tz, LongRange dateRange, int maxEvents) { try { Events events = calendarService.events().list("primary").setMaxResults(maxEvents).setTimeMin(new DateTime(new java.util.Date(dateRange.start), tz)).setTimeMax(new DateTime(new java.util.Date(dateRange.end), tz)).setOrderBy("startTime").setSingleEvents(true).execute(); return events.getItems(); } catch (Exception __e) { throw rethrow(__e); } } static public long done2_always(long startTime, String desc) { long time = sysNow() - startTime; saveTiming_noPrint(time); print(desc + " [" + time + " ms]"); return time; } static public long done2_always(String desc, long startTime) { return done2_always(startTime, desc); } static public long done2_always(long startTime) { return done2_always(startTime, ""); } static public LongRange cutLongRangeToGranularity(LongRange r, long granularity) { if (r == null || granularity < 1) return r; return new LongRange(roundUpTo(granularity, r.start), roundDownTo(granularity, r.end)); } 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 TimeZone timeZone(String name) { return TimeZone.getTimeZone(name); } static public int min(int a, int b) { return Math.min(a, b); } static public long min(long a, long b) { return Math.min(a, b); } static public float min(float a, float b) { return Math.min(a, b); } static public float min(float a, float b, float c) { return min(min(a, b), c); } static public double min(double a, double b) { return Math.min(a, b); } static public double min(double[] c) { double x = Double.MAX_VALUE; for (double d : c) x = Math.min(x, d); return x; } static public float min(float[] c) { float x = Float.MAX_VALUE; for (float d : c) x = Math.min(x, d); return x; } static public byte min(byte[] c) { byte x = 127; for (byte d : c) if (d < x) x = d; return x; } static public short min(short[] c) { short x = 0x7FFF; for (short d : c) if (d < x) x = d; return x; } static public int min(int[] c) { int x = Integer.MAX_VALUE; for (int d : c) if (d < x) x = d; return x; } static public long daysToMS(double days) { return round(days * 24 * 60 * 60 * 1000); } static public int dayOfWeek_nr() { return dayOfWeek_nr(java.util.Calendar.getInstance()); } static public int dayOfWeek_nr(java.util.Calendar calendar) { return calendar.get(java.util.Calendar.DAY_OF_WEEK); } static public int dayOfWeek_nr(long time) { return dayOfWeek_nr(calendarFromTime(time)); } static public int dayOfWeek_nr(long time, TimeZone tz) { return dayOfWeek_nr(calendarFromTime(time, tz)); } 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 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 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 > A max(Iterable l) { A max = null; var it = iterator(l); if (it.hasNext()) { max = it.next(); while (it.hasNext()) { A a = it.next(); if (cmp(a, max) > 0) max = a; } } return max; } 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 > A max(A a, A b) { return cmp(a, b) >= 0 ? a : b; } static public String subBot_getHeader(String key) { return subBot_getHeaders().get(lower(key)); } static public A printAndProgramLog(String s, A o) { printAndProgramLog((endsWithLetterOrDigit(s) ? s + ": " : s) + o); return o; } static public A printAndProgramLog(A a) { String s = str(a); print("[" + localDateWithMilliseconds() + "] " + s); logQuotedWithDate(programLog(), s); return a; } static public String subBot_completeRequestURL() { int port = subBot_currentPort(); boolean https = subBot_isHttps(); boolean standardPort = port == (https ? 443 : 80); return "http" + (https ? "s" : "") + "://" + domain() + (standardPort ? "" : ":" + port) + getActualURI(); } static public File programLog() { return programLogFile(); } static public String programLog(String s) { logQuotedWithDate(programLog(), s); return s; } static public String stackTraceToString(StackTraceElement[] st) { return lines(st); } static public String stackTraceToString(Throwable e) { return getStackTrace_noRecord(e); } 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 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 MultiMap mapValues(IF1 func, MultiMap mm) { return mapMultiMapValues(func, mm); } static public MultiMap mapValues(MultiMap mm, IF1 func) { return mapValues(func, mm); } static public > boolean allEmpty(Iterable l) { return all(__53 -> empty(__53), l); } 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 n2(long l) { return formatWithThousands(l); } static public String n2(AtomicLong l) { return n2(l.get()); } 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) { return n2(ms, singular, singular + "s"); } static public String n2(MultiSet ms, String singular, String plural) { return n_fancy2(ms, singular, plural); } static public String n2(IMultiMap mm, String singular) { return n2(mm, singular, singular + "s"); } static public String n2(IMultiMap mm, String singular, String plural) { return n_fancy2(l(mm), singular, plural); } 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 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 A firstThat(Iterable l, IF1 pred) { for (A a : unnullForIteration(l)) if (pred.get(a)) return a; return null; } static public A firstThat(A[] l, IF1 pred) { for (A a : unnullForIteration(l)) if (pred.get(a)) return a; return null; } static public A firstThat(IF1 pred, Iterable l) { return firstThat(l, pred); } static public A firstThat(IF1 pred, A[] l) { return firstThat(l, pred); } static public String[] dropFirst(int n, String[] a) { return drop(n, a); } static public String[] dropFirst(String[] a) { return drop(1, a); } static public Object[] dropFirst(Object[] a) { return drop(1, a); } static public List dropFirst(List l) { return dropFirst(1, l); } static public List dropFirst(int n, Iterable i) { return dropFirst(n, toList(i)); } static public List dropFirst(Iterable i) { return dropFirst(toList(i)); } static public List dropFirst(int n, List l) { return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size())); } static public List dropFirst(List l, int n) { return dropFirst(n, l); } static public String dropFirst(int n, String s) { return substring(s, n); } static public String dropFirst(String s, int n) { return substring(s, n); } static public String dropFirst(String s) { return substring(s, 1); } static public Chain dropFirst(Chain c) { return c == null ? null : c.next; } static public 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(short[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (short 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 ArrayList asList(ReverseChain c) { return c == null ? emptyList() : c.toList(); } static public List asList(Pair p) { return p == null ? null : ll(p.a, p.b); } static public A nu(Class c, Object... values) { A a = nuObject(c); setAll(a, values); return a; } static public List ll_nonNulls(A... a) { return llNonNulls(a); } static public void change() { callOpt(getOptMC("mainConcepts"), "allChanged"); } static public boolean find3plusRestsX(String pat, String s) { return find3plusRestsX(pat, s, null); } static public boolean find3plusRestsX(String pat, String s, Matches matches) { pat = dropPrefix("...", dropSuffix("...", pat)); List tokpat = parse3(pat), toks = parse3(s); Pair p = find2plusIndex(tokpat, toks); if (p == null) return false; if (matches != null) matches.m = concatStringArrays(new String[] { joinSubList(toks, 0, p.b - 1) }, p.a, new String[] { joinSubList(toks, p.b + l(tokpat) - 1) }); return true; } static public boolean find3(String pat, String s) { return find3(pat, s, null); } static public boolean find3(String pat, String s, Matches matches) { return find3(pat, parse3_cachedInput(s), matches); } static public boolean find3(String pat, List toks, Matches matches) { List tokpat = parse3_cachedPattern(pat); String[] m = find2(tokpat, toks); if (m == null) return false; if (matches != null) matches.m = m; return true; } static public 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 ymdWithSlashes() { return ymdWithSlashes(now()); } static public String ymdWithSlashes(long time) { return simpleDateFormat_local("YYYY/MM/dd").format(time); } static public String ymdWithSlashes(long time, TimeZone tz) { return simpleDateFormat("YYYY/MM/dd", tz).format(time); } static public boolean isDummyPhoneNr(String s) { return startsWith(digitsOnly(s), "123456"); } static public Thread startThread(Object runnable) { return startThread(defaultThreadName(), runnable); } static public Thread startThread(String name, Runnable runnable) { runnable = wrapAsActivity(runnable); return startThread(newThread(runnable, name)); } 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 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 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 timeInZone_24(long time, String timeZone) { return timeInZone_24(time, getTimeZone(timeZone)); } static public String timeInZone_24(long time, TimeZone timeZone) { return simpleDateFormat("HH:mm", timeZone).format(time); } static public String timeInZone_24(String timeZone) { return timeInZone_24(now(), timeZone); } 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 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 String digitsOnly(String s) { return filterChars(__54 -> isDigit(__54), s); } static public RuntimeException rethrow(Throwable t) { if (t instanceof Error) _handleError((Error) t); throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static public RuntimeException rethrow(String msg, Throwable t) { throw new RuntimeException(msg, t); } 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 boolean contains(Rect r, Pt p) { return rectContains(r, p); } static public Set usAreaCodes_cache; static public Set usAreaCodes() { if (usAreaCodes_cache == null) usAreaCodes_cache = usAreaCodes_load(); return usAreaCodes_cache; } static public Set usAreaCodes_load() { return asTreeSet(values(usAreaCodesMap())); } 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 short[] takeFirst(int n, short[] a) { return takeFirstOfShortArray(n, a); } static public byte[] takeFirst(int n, byte[] a) { return takeFirstOfByteArray(n, a); } static public byte[] takeFirst(byte[] a, int n) { return takeFirstOfByteArray(n, a); } static public double[] takeFirst(int n, double[] a) { return takeFirstOfDoubleArray(n, a); } static public double[] takeFirst(double[] a, int n) { return takeFirstOfDoubleArray(n, a); } 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 countDigitsInString(String s) { int n = 0; for (int i = 0; i < l(s); i++) if (isDigit(s.charAt(i))) ++n; return n; } static public String getString(Map map, Object key) { return map == null ? null : (String) map.get(key); } static public String getString(List l, int idx) { return (String) get(l, idx); } static public String getString(Object o, Object key) { if (o instanceof Map) return getString((Map) o, key); if (key instanceof String) return (String) getOpt(o, (String) key); throw fail("Not a string key: " + getClassName(key)); } static public String getString(String key, Object o) { return getString(o, (Object) key); } static public boolean ewic(String a, String b) { return endsWithIgnoreCase(a, b); } static public boolean ewic(String a, String b, Matches m) { return endsWithIgnoreCase(a, b, m); } static public String hijackPrint_tee_pcall(Runnable r) { return hijackPrint_tee(new Runnable() { public void run() { try { try { callF(r); } catch (Throwable __e) { printStackTrace(__e); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcall { callF(r); }"; } }); } static public String hsourcecode(Object o) { return sourceCodeToHTML(o); } 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 Object subBot_serveHTMLNoCache(String html) { return subBot_noCacheHeaders(subBot_serveHTML(html)); } static public String programID() { return getProgramID(); } static public String programID(Object o) { return getProgramID(o); } static public A get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static public A get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } static public boolean get(boolean[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : false; } static public Object get(Object o, String field) { try { if (o == null) return null; if (o instanceof Class) return get((Class) o, field); if (o instanceof Map) return ((Map) o).get(field); Field f = getOpt_findField(o.getClass(), field); if (f != null) { makeAccessible(f); return f.get(o); } if (o instanceof DynamicObject) return getOptDynOnly(((DynamicObject) o), field); } catch (Exception e) { throw asRuntimeException(e); } throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName()); } static public Object get_raw(String field, Object o) { return get_raw(o, field); } static public Object get_raw(Object o, String field) { try { if (o == null) return null; Field f = get_findField(o.getClass(), field); makeAccessible(f); return f.get(o); } catch (Exception __e) { throw rethrow(__e); } } static public Object get(Class c, String field) { try { Field f = get_findStaticField(c, field); makeAccessible(f); return f.get(null); } catch (Exception e) { throw new RuntimeException(e); } } static public Field get_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static public Field get_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } static public Object get(String field, Object o) { return get(o, field); } static public boolean get(BitSet bs, int idx) { return bs != null && bs.get(idx); } static public void assertTrueVerbose(Object o) { assertEqualsVerbose(true, o); } static public void assertTrueVerbose(String msg, Object o) { assertEqualsVerbose(msg, true, o); } 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 void assertTrue(Object o) { if (!(eq(o, true))) throw fail(str(o)); } static public boolean assertTrue(String msg, boolean b) { if (!b) throw fail(msg); return b; } static public boolean assertTrue(boolean b) { if (!b) throw fail("oops"); return b; } 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 long psI(String snippetID) { return parseSnippetID(snippetID); } static public A objectWhere(Collection c, Object... data) { return findWhere(c, data); } static public > List allValues(Map map) { List out = new ArrayList(); for (var l : values(map)) addAll(out, l); return out; } static public LinkedHashMap litorderedmap(Object... x) { LinkedHashMap map = new LinkedHashMap(); litmap_impl(map, x); return map; } static public WeakReference creator_class; static public Object creator() { return creator_class == null ? null : creator_class.get(); } static public boolean match(String pat, String s) { return match3(pat, s); } static public boolean match(String pat, String s, Matches matches) { return match3(pat, s, matches); } static public boolean match(String pat, List toks, Matches matches) { return match3(pat, toks, matches); } static public List regexpICMatchesAsCNC(String pat, String s) { return intRangesToCNC(s, regexpFindRangesIC(pat, s)); } static public String regexpNegativeLookbehind(String re) { return "(? AutoCloseable tempSetTL(ThreadLocal tl, A a) { return tempSetThreadLocal(tl, a); } static public AutoCloseable tempSetTL(BetterThreadLocal tl, A a) { return tempSetThreadLocalIfNecessary(tl, a); } static public Object getOpt(Object o, String field) { return getOpt_cached(o, field); } static public Object getOpt(String field, Object o) { return getOpt_cached(o, field); } static public Object getOpt_raw(Object o, String field) { try { Field f = getOpt_findField(o.getClass(), field); if (f == null) return null; makeAccessible(f); return f.get(o); } catch (Exception __e) { throw rethrow(__e); } } static public Object getOpt(Class c, String field) { try { if (c == null) return null; Field f = getOpt_findStaticField(c, field); if (f == null) return null; makeAccessible(f); return f.get(null); } catch (Exception __e) { throw rethrow(__e); } } static public Field getOpt_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static public boolean eqicOneOf(String s, String... l) { for (String x : l) if (eqic(s, x)) return true; return false; } static public String unicode_crossProduct() { return unicodeFromCodePoint(0x2A2F); } static public String unicode_undoArrow() { return unicodeFromCodePoint(0x21B6); } static public String quote(Object o) { if (o == null) return "null"; return quote(str(o)); } static public String quote(String s) { if (s == null) return "null"; StringBuilder out = new StringBuilder((int) (l(s) * 1.5 + 2)); quote_impl(s, out); return out.toString(); } static public void quote_impl(String s, StringBuilder out) { out.append('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') out.append('\\').append(c); else if (c == '\r') out.append("\\r"); else if (c == '\n') out.append("\\n"); else if (c == '\t') out.append("\\t"); else if (c == '\0') out.append("\\0"); else out.append(c); } out.append('"'); } static public String joinNemptiesWithSpace(String... strings) { return joinNempties(" ", strings); } static public String joinNemptiesWithSpace(Collection strings) { return joinNempties(" ", strings); } static public A or(A a, A b) { return a != null ? a : b; } static public String sfu(Object o) { return structureForUser(o); } 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 Object getBot(String botID) { return callOpt(getMainBot(), "getBot", botID); } 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 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 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 int lengthLevel2(Collection l) { int sum = 0; for (Collection c : l) sum += l(c); return sum; } 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 byte last(byte[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static public int last(int[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static public double last(double[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static public A last(A[] a) { return l(a) != 0 ? a[l(a) - 1] : null; } static public A last(Iterator it) { A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static public A last(Collection l) { if (l == null) return null; if (l instanceof List) return (A) last((List) l); if (l instanceof SortedSet) return (A) last((SortedSet) l); Iterator it = iterator(l); A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static public A last(SortedSet l) { return l == null ? null : l.last(); } static public A last(ReverseChain l) { return l == null ? null : l.element; } static public A last(CompactLinkedHashSet set) { return set == null ? null : set.last(); } 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 long add(AtomicLong l, long b) { return l.addAndGet(b); } static public void dbIndexing(Object... params) { db(); indexConceptFields(params); } static public Class fieldType(Object o, String field) { Field f = getField(o, field); return f == null ? null : f.getType(); } static public Field setOpt_findField(Class c, String field) { HashMap map; synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } return map.get(field); } static public void setOpt(Object o, String field, Object value) { try { if (o == null) return; Class c = o.getClass(); HashMap map; if (getOpt_cache == null) map = getOpt_makeCache(c); else synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } if (map == getOpt_special) { if (o instanceof Class) { setOpt((Class) o, field, value); return; } setOpt_raw(o, field, value); return; } Field f = map.get(field); if (f != null) { smartSet(f, o, value); return; } if (o instanceof DynamicObject) { setDyn(((DynamicObject) o), field, value); return; } if (o instanceof IMeta) setDyn(((IMeta) o), field, value); } catch (Exception __e) { throw rethrow(__e); } } static public void setOpt(Class c, String field, Object value) { if (c == null) return; try { Field f = setOpt_findStaticField(c, field); if (f != null) smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static public Field setOpt_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) { makeAccessible(f); return f; } _c = _c.getSuperclass(); } while (_c != null); return null; } 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 tempRegisterThread() { _registerThread(); return new AutoCloseable() { public String toString() { return "_unregisterThread();"; } public void close() throws Exception { _unregisterThread(); } }; } static public String registerVisitor() { Object visitorsBot = getBot("#1002157"); String visitorStats = visitorsBot == null ? null : str(callHtmlMethod(visitorsBot, "/")); return visitorStats; } static public String cookieSent() { Object visitorsBot = getBot("#1002157"); return (String) callOpt(visitorsBot, "cookieSent"); } static public String subBot_clientIP() { return getClientIP_subBot(); } static public String getDialogID() { return (String) callOpt(getMainBot(), "getDialogID"); } static public String loadSecretTextFileOrCreateWithRandomID(String name) { String id = trim(loadSecretTextFile(name)); if (empty(id)) saveSecretTextFile(name, id = aGlobalID()); return id; } static public String loadSecretTextFileOrCreateWithRandomID(File f) { String id = trim(loadTextFile(f)); if (empty(id)) saveTextFile(f, id = aGlobalID()); return id; } static public boolean neq(Object a, Object b) { return !eq(a, b); } 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 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 ul_htmlEncode(String... list) { return ul_htmlEncode(asList(list)); } static public String ul_htmlEncode(Collection list, Object... params) { return ul(map(__55 -> htmlEncode2(__55), allToString(list)), params); } static public List getThreadNames(Collection threads) { return mapMethod(threads, "getName"); } 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 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 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 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 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 int parseInt(String s) { return emptyString(s) ? 0 : Integer.parseInt(s); } static public int parseInt(char c) { return Integer.parseInt(str(c)); } static public List cloneSubList(List l, int startIndex, int endIndex) { return newSubList(l, startIndex, endIndex); } static public List cloneSubList(List l, int startIndex) { return newSubList(l, startIndex); } static public String jsQuote(String s) { return javascriptQuote(s); } static public boolean preferCached = false; static public boolean loadSnippet_debug = false; static public ThreadLocal loadSnippet_silent = new ThreadLocal(); static public ThreadLocal loadSnippet_publicOnly = new ThreadLocal(); static public int loadSnippet_timeout = 30000; static public String loadSnippet(String snippetID) { try { if (snippetID == null) return null; return loadSnippet(parseSnippetID(snippetID), preferCached); } catch (Exception __e) { throw rethrow(__e); } } static public String loadSnippet(String snippetID, boolean preferCached) throws IOException { return loadSnippet(parseSnippetID(snippetID), preferCached); } static public IF1 loadSnippet; static public String loadSnippet(long snippetID) { return loadSnippet != null ? loadSnippet.get(snippetID) : loadSnippet_base(snippetID); } final static public String loadSnippet_fallback(IF1 _f, long snippetID) { return _f != null ? _f.get(snippetID) : loadSnippet_base(snippetID); } static public String loadSnippet_base(long snippetID) { try { return loadSnippet(snippetID, preferCached); } catch (Exception __e) { throw rethrow(__e); } } static public String loadSnippet(long snippetID, boolean preferCached) throws IOException { if (isLocalSnippetID(snippetID)) return loadLocalSnippet(snippetID); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadSnippet(fsI(snippetID)); return loadSnippet_noResourceLoader(snippetID, preferCached); } static public String loadSnippet_noResourceLoader(long snippetID, boolean preferCached) throws IOException { String text; initSnippetCache(); text = DiskSnippetCache_get(snippetID); if (preferCached && text != null) return text; try { if (loadSnippet_debug && text != null) System.err.println("md5: " + md5(text)); String url = tb_mainServer() + "/getraw.php?id=" + snippetID + "&utf8=1"; if (nempty(text)) url += "&md5=" + md5(text); if (!isTrue(loadSnippet_publicOnly.get())) url += standardCredentials(); String text2 = loadSnippet_loadFromServer(url); boolean same = eq(text2, "==*#*=="); if (loadSnippet_debug) print("loadSnippet: same=" + same); if (!same) text = text2; } catch (RuntimeException e) { e.printStackTrace(); throw new IOException("Snippet #" + snippetID + " not found or not public"); } try { initSnippetCache(); DiskSnippetCache_put(snippetID, text); } catch (IOException e) { System.err.println("Minor warning: Couldn't save snippet to cache (" + DiskSnippetCache_getDir() + ")"); } return text; } static public File DiskSnippetCache_dir; public static void initDiskSnippetCache(File dir) { DiskSnippetCache_dir = dir; dir.mkdirs(); } public static synchronized String DiskSnippetCache_get(long snippetID) throws IOException { return loadTextFile(DiskSnippetCache_getFile(snippetID).getPath(), null); } static public File DiskSnippetCache_getFile(long snippetID) { return new File(DiskSnippetCache_dir, "" + snippetID); } public static synchronized void DiskSnippetCache_put(long snippetID, String snippet) throws IOException { saveTextFile(DiskSnippetCache_getFile(snippetID).getPath(), snippet); } public static File DiskSnippetCache_getDir() { return DiskSnippetCache_dir; } public static void initSnippetCache() { if (DiskSnippetCache_dir == null) initDiskSnippetCache(getGlobalCache()); } static public String loadSnippet_loadFromServer(String url) { Integer oldTimeout = setThreadLocal(loadPage_forcedTimeout_byThread, loadSnippet_timeout); try { return isTrue(loadSnippet_silent.get()) ? loadPageSilently(url) : loadPage(url); } finally { loadPage_forcedTimeout_byThread.set(oldTimeout); } } static public String imageSnippetURLOrEmptyGIF(String snippetID) { return empty(snippetID) ? smallestTransparentGIFDataURI() : snippetImageURL(snippetID); } 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 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 String htitle(String title) { return hfulltag("title", htmlencode_noQuotes(title)); } 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 Object subBot_serveJavaScript(String html) { return subBot_serveWithContentType(html, "text/javascript"); } 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
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 html_wavingHand() { return himg(dataSnippetURL("#1400314"), "style", "width: 1.4em; height: 1.4em; margin-top: -0.15em", "align", "top"); } static public String hspan(Object contents, Object... params) { return tag("span", contents, params); } 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 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 snippetImgLink(String snippetID) { return snippetImageURL(snippetID); } static public String fullRawLink(String pageName) { return (subBot_isHttps() ? "https" : "http") + "://" + domain() + rawLink(pageName); } static public TreeSet asCISet(Iterable c) { return toCaseInsensitiveSet(c); } static public TreeSet asCISet(String... x) { return toCaseInsensitiveSet(x); } static public String hcheckbox(String name, boolean checked, Object... params) { return tag("input", "", 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 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 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 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 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 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 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 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 hpassword(String name, Object... params) { return hpasswordfield(name, params); } static public String hpassword(String name) { return hpasswordfield(name); } 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 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 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) { if (l != null) for (A a : l) if (pred.get(a)) return true; return false; } 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) { printStackTrace(__e); } return "?"; } static public java.util.Timer doAfter(long delay, Object r) { return doLater(delay, r); } static public java.util.Timer doAfter(long delay, Runnable r) { return doLater(delay, (Object) r); } static public java.util.Timer doAfter(double delaySeconds, Object r) { return doLater(delaySeconds, r); } static public java.util.Timer doAfter(double delaySeconds, Runnable r) { return doLater(delaySeconds, r); } static public String replaceSquareBracketVars(String s, Object... params) { if (empty(params)) return s; Map vars = mapKeys(__56 -> deSquareBracket(__56), (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(String... l) { return trimAll(asList(l)); } 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 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 AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) { return print_byThread().get() == null ? tempInterceptPrint(f) : null; } 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 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 String htmlencode_noQuotes(String s) { if (s == null) return ""; int n = s.length(); StringBuilder out = null; for (int i = 0; i < n; i++) { char c = s.charAt(i); if (c == '<') { if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s)); out.append("<"); } else if (c == '>') { if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s)); out.append(">"); } else if (c > 127 || c == '&') { int cp = s.codePointAt(i); if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s)); out.append("&#x"); out.append(intToHex_flexLength(cp)); out.append(';'); i += Character.charCount(cp) - 1; } else { if (out != null) out.append(c); } } return out == null ? s : out.toString(); } static public String strOrEmpty(Object o) { return o == null ? "" : str(o); } static public String addSlash(String s) { return empty(s) || s.endsWith("/") ? s : s + "/"; } 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 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 boolean eqOneOf(Object o, Object... l) { if (l != null) for (Object x : l) if (eq(o, x)) return true; return false; } static public Object mainBot() { return getMainBot(); } static public Object mainBot; static public Object getMainBot() { return mainBot; } 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 hostNameFromURL(String url) { try { return empty(url) ? null : new URL(url).getHost(); } catch (Exception __e) { throw rethrow(__e); } } static public String getActualURI() { return (String) call(getMainBot(), "getActualURI"); } 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 str(Object o) { return o == null ? "null" : o.toString(); } static public String str(char[] c) { return new String(c); } static public String str(char[] c, int offset, int count) { return new String(c, offset, count); } 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 myDomain() { return or2(trim(loadTextFile(javaxDataDir("my-domain.txt"))), "botcompany.de"); } 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 String addPrefix(String prefix, String s) { return s.startsWith(prefix) ? s : prefix + s; } static public String dropSuffix(String suffix, String s) { return nempty(suffix) && endsWith(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } 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 boolean isInstance(Class type, Object arg) { return type.isInstance(arg); } 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 getClassName(Object o) { return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName(); } 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 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 Object[] arrayPlus(Object[] a1, Object... a2) { return concatArrays(a1, a2); } static public String programID; 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 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 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 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 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 addSuffix(String s, String suffix) { return s == null || s.endsWith(suffix) ? s : s + suffix; } 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(Object contents) { if (contents instanceof String && isRelativeOrAbsoluteURL((String) contents)) return hstylesheetsrc((String) contents); else return htag("style", contents); } static public String hhead_title_decode(String title) { return hhead_title(htmldecode_dropAllTags(title)); } static public HashSet lithashset(A... items) { HashSet set = new HashSet(); for (A a : items) set.add(a); return set; } 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 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 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(PingSource pingSource) { return ping(); } 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 Map> callF_cache = newDangerousWeakHashMap(); static public A callF(F0 f) { return f == null ? null : f.get(); } static public B callF(F1 f, A a) { return f == null ? null : f.get(a); } static public A callF(IF0 f) { return f == null ? null : f.get(); } static public B callF(IF1 f, A a) { return f == null ? null : f.get(a); } static public B callF(A a, IF1 f) { return f == null ? null : f.get(a); } static public C callF(IF2 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 void callF(A a, IVF1 f) { if (f != null) f.get(a); } static public void callF(IVF1 f, A a) { if (f != null) f.get(a); } static public Object callF(Runnable r) { { if (r != null) r.run(); } return null; } static public Object callF(Object f, Object... args) { return safeCallF(f, args); } static public Object safeCallF(Object f, Object... args) { if (f instanceof Runnable) { ((Runnable) f).run(); return null; } if (f == null) return null; Class c = f.getClass(); ArrayList methods; synchronized (callF_cache) { methods = callF_cache.get(c); if (methods == null) methods = callF_makeCache(c); } int n = l(methods); if (n == 0) { if (f instanceof String) throw fail("Legacy call: " + f); throw fail("No get method in " + getClassName(c)); } if (n == 1) return invokeMethod(methods.get(0), f, args); for (int i = 0; i < n; i++) { Method m = methods.get(i); if (call_checkArgs(m, args, false)) return invokeMethod(m, f, args); } throw fail("No matching get method in " + getClassName(c)); } static public ArrayList callF_makeCache(Class c) { ArrayList l = new ArrayList(); Class _c = c; do { for (Method m : _c.getDeclaredMethods()) if (m.getName().equals("get")) { makeAccessible(m); l.add(m); } if (!l.isEmpty()) break; _c = _c.getSuperclass(); } while (_c != null); callF_cache.put(c, l); return l; } static public void warnIfOddCount(Object... list) { if (odd(l(list))) printStackTrace("Odd list size: " + list); } 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 boolean _csetField(Concept c, String field, Object value) { try { Field f = setOpt_findField(c.getClass(), field); if (value instanceof RC) value = c._concepts.getConcept((RC) value); value = deref(value); if (value instanceof String && l((String) value) >= concepts_internStringsLongerThan) value = intern((String) value); if (f == null) { assertIdentifier(field); Object oldVal = mapGet(c.fieldValues, field); if (value instanceof Concept) { if (oldVal instanceof Concept.Ref) return ((Concept.Ref) oldVal).set((Concept) value); else { dynamicObject_setRawFieldValue(c, field, c.new Ref((Concept) value)); c.change(); return true; } } else { if (oldVal instanceof Concept.Ref) ((Concept.Ref) oldVal).unindexAndDrop(); if (eq(oldVal, value)) return false; if (isConceptList(value) && nempty(((List) value))) { dynamicObject_setRawFieldValue(c, field, c.new RefL(((List) value))); c.change(); return true; } if (value == null) { dynamicObject_dropRawField(c, field); } else { if (!isPersistable(value)) throw fail("Can't persist: " + c + "." + field + " = " + value); dynamicObject_setRawFieldValue(c, field, value); } c.change(); return true; } } else if (isSubtypeOf(f.getType(), Concept.Ref.class)) { ((Concept.Ref) f.get(c)).set((Concept) derefRef(value)); c.change(); return true; } else if (isSubtypeOf(f.getType(), Concept.RefL.class)) { ((Concept.RefL) f.get(c)).replaceWithList(lmap(__57 -> derefRef(__57), (List) value)); c.change(); return true; } else { Object old = f.get(c); if (neq(value, old)) { boolean isTransient = isTransient(f); if (!isTransient && !isPersistable(value)) throw fail("Can't persist: " + c + "." + field + " = " + value); f.set(c, value); if (!isTransient) c.change(); return true; } } return false; } catch (Exception __e) { throw rethrow(__e); } } static public A getVar(IF0 v) { return v == null ? null : v.get(); } static public A getVar(Optional v) { return v == null ? null : v.orElse(null); } 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 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 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 int indexOf(List l, A a, int startIndex) { if (l == null) return -1; int n = l(l); for (int i = startIndex; i < n; i++) if (eq(l.get(i), a)) return i; return -1; } static public int indexOf(List l, int startIndex, A a) { return indexOf(l, a, startIndex); } static public int indexOf(List l, A a) { if (l == null) return -1; return l.indexOf(a); } static public int indexOf(String a, String b) { return a == null || b == null ? -1 : a.indexOf(b); } static public int indexOf(String a, String b, int i) { return a == null || b == null ? -1 : a.indexOf(b, i); } static public int indexOf(String a, char b) { return a == null ? -1 : a.indexOf(b); } static public int indexOf(String a, int i, char b) { return indexOf(a, b, i); } static public int indexOf(String a, char b, int i) { return a == null ? -1 : a.indexOf(b, i); } static public int indexOf(String a, int i, String b) { return a == null || b == null ? -1 : a.indexOf(b, i); } static public int indexOf(A[] x, A a) { int n = l(x); for (int i = 0; i < n; i++) if (eq(x[i], a)) return i; return -1; } static public int indexOf(Iterable l, A a) { if (l == null) return -1; int i = 0; for (A x : l) { if (eq(x, a)) return i; i++; } return -1; } 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 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(IMultiMap mm) { return mm.keySet(); } static public A cDeref(Concept.Ref ref) { return ref == null ? null : ref.get(); } static public String hjavascript_src(String src, Object... __) { return hfulltag("script", "", paramsPlus(__, "src", src)); } 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 void ping_okInCleanUp() { if (ping_pauseAll || ping_anyActions) ping_impl(true); } static public boolean isAWTThread() { if (isAndroid()) return false; if (isHeadless()) return false; return isAWTThread_awt(); } static public boolean isAWTThread_awt() { return SwingUtilities.isEventDispatchThread(); } static public Object sleepQuietly_monitor = new Object(); static public void sleepQuietly() { try { assertFalse(isAWTThread()); synchronized (sleepQuietly_monitor) { sleepQuietly_monitor.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static public 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 List sortByCalculatedFieldDesc_inPlace(List l, final Object f) { sort(l, new Comparator() { public int compare(A b, A a) { return stdcompare((Object) callF(f, a), (Object) callF(f, b)); } }); return l; } static public List sortByCalculatedFieldDesc_inPlace(Object f, List c) { return sortByCalculatedFieldDesc_inPlace(c, f); } static public void sort(T[] a, Comparator c) { if (a != null) Arrays.sort(a, c); } static public void sort(T[] a) { if (a != null) Arrays.sort(a); } static public void sort(int[] a) { if (a != null) Arrays.sort(a); } static public void sort(List a, Comparator c) { if (a != null) Collections.sort(a, c); } static public void sort(List a) { if (a != null) Collections.sort(a); } static public int stdcompare(Number a, Number b) { return cmp(a, b); } static public int stdcompare(String a, String b) { return cmp(a, b); } static public int stdcompare(long a, long b) { return a < b ? -1 : a > b ? 1 : 0; } static public int stdcompare(Object a, Object b) { return cmp(a, b); } static public List 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 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 th(Object contents, Object... params) { return tag("th", contents, params); } 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 long timestampToLong(Timestamp ts) { return ts == null ? 0 : ts.date; } static public int howManySecondsAgo(long timestamp) { return iround(toSeconds(now() - timestamp)); } static public int iround(double d) { return (int) Math.round(d); } static public int iround(Number n) { return iround(toDouble(n)); } static public String hlabelFor(String id, Object contents) { String s = strOrEmpty(contents); return empty(s) ? "" : htag("label", s, "for", id); } static public String hdiv(Object contents, Object... params) { return div(contents, params); } static public BigInteger bigint(String s) { return new BigInteger(s); } static public BigInteger bigint(long l) { return BigInteger.valueOf(l); } static public long parseYMDHMS_slashesSpaceColons(String s) { try { return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(s).getTime(); } catch (Exception __e) { throw rethrow(__e); } } static public long parseYMDHMS_slashesSpaceColons(String s, TimeZone tz) { try { return simpleDateFormat("yyyy/MM/dd HH:mm:ss", tz).parse(s).getTime(); } catch (Exception __e) { throw rethrow(__e); } } static public TimeZone getTimeZone(String name) { return TimeZone.getTimeZone(name); } static public String standardTimeZone_name = "Europe/Berlin"; static public String standardTimeZone() { return standardTimeZone_name; } static public List nempties(Collection c) { return filterNempty(c); } 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 splitAtMinus(String s) { return trimAll(asList(s.split("\\-"))); } static public IntRange intRange(int start, int end) { return new IntRange(start, end); } 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 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 B second(T3 t) { return t == null ? null : t.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 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 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 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 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 String fixNewLines(String s) { int i = indexOf(s, '\r'); if (i < 0) return s; int l = s.length(); StringBuilder out = new StringBuilder(l); out.append(s, 0, i); for (; i < l; i++) { char c = s.charAt(i); if (c != '\r') out.append(c); else { out.append('\n'); if (i + 1 < l && s.charAt(i + 1) == '\n') ++i; } } return out.toString(); } static public void print_append(Appendable buf, String s, int max) { try { synchronized (buf) { buf.append(s); if (buf instanceof StringBuffer) rotateStringBuffer(((StringBuffer) buf), max); else if (buf instanceof StringBuilder) rotateStringBuilder(((StringBuilder) buf), max); } } catch (Exception __e) { throw rethrow(__e); } } static public Object pcallFAll_returnFirstNotNull(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) { var __1 = pcallF(f, args); if (__1 != null) return __1; } return null; } static public Object pcallFAll_returnFirstNotNull(Iterator it, Object... args) { while (it.hasNext()) { var __2 = pcallF(it.next(), args); if (__2 != null) return __2; } return null; } static public Object call_withVarargs(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.findStaticMethod(methodName, args); if (me != null) return invokeMethod(me, null, args); List methods = cache.cache.get(methodName); 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() + "." + methodName + "(" + joinWithComma(classNames(args)) + ") not found"); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(methodName, args); if (me != null) return invokeMethod(me, o, args); List methods = cache.cache.get(methodName); 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() + "." + methodName + "(" + joinWithComma(classNames(args)) + ") not found"); } } catch (Exception __e) { throw rethrow(__e); } } static public String getType(Object o) { return getClassName(o); } static public long getFileSize(String path) { return path == null ? 0 : new File(path).length(); } static public long getFileSize(File f) { return f == null ? 0 : f.length(); } static public List englishWeekdays_list = ll("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"); static public List englishWeekdays() { return englishWeekdays_list; } 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 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 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 int weekInYear(long time, TimeZone tz) { return parseInt(simpleDateFormat("w", tz).format(time)); } static public long yearToTimestamp(int year, TimeZone tz) { try { return simpleDateFormat("y", tz).parse(str(year)).getTime(); } catch (Exception __e) { throw rethrow(__e); } } static public long yearAndMonthToTimestamp(int year, int month, TimeZone tz) { try { return simpleDateFormat("y/M", tz).parse(year + "/" + month).getTime(); } catch (Exception __e) { throw rethrow(__e); } } static public long yearAndWeekToTimestamp(int year, int week, TimeZone tz) { try { return simpleDateFormat("y/w", tz).parse(year + "/" + week).getTime(); } catch (Exception __e) { throw rethrow(__e); } } static public long ymdToTimestamp(int year, int month, int day) { return ymdToTimestamp(year, month, day, defaultTimeZone()); } static public long ymdToTimestamp(int year, int month, int day, TimeZone tz) { try { return simpleDateFormat("y/M/d", tz).parse(year + "/" + month + "/" + day).getTime(); } catch (Exception __e) { throw rethrow(__e); } } 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 > List getVars(Iterable l) { return lambdaMap(__58 -> getVar(__58), l); } static public MetaTransformer defaultMetaTransformer() { return metaTransformer_transformableAndList(); } static public A cloneSetAll(A a, Object... params) { return setAll(clone(a), params); } static public LongRange joinLongRanges(Iterable l) { LongRange r = null; for (LongRange x : unnullForIteration(l)) r = r == null ? x : new LongRange(min(r.start, x.start), max(r.end, x.end)); return r; } static public long parseYYYYMMDD(String s, TimeZone tz) { try { return simpleDateFormat("yyyyMMdd", tz).parse(s).getTime(); } catch (Exception __e) { throw rethrow(__e); } } static public int iteratorCount_int_close(Iterator i) { try { int n = 0; if (i != null) while (i.hasNext()) { i.next(); ++n; } if (i instanceof AutoCloseable) ((AutoCloseable) i).close(); return n; } catch (Exception __e) { throw rethrow(__e); } } static public Pair mapEntryToPair(Map.Entry e) { return e == null ? null : pair(e.getKey(), e.getValue()); } static public Set> entrySet(Map map) { return _entrySet(map); } static public long round(double d) { return Math.round(d); } static public String round(String s) { return roundBracket(s); } static public Complex round(Complex c) { return new Complex(round(c.re), round(c.im)); } 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 int roundUpTo(int n, int x) { return (x + n - 1) / n * n; } static public long roundUpTo(long n, long x) { return (x + n - 1) / n * n; } 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 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 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 List immutableEmptyList() { return Collections.emptyList(); } 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 short[] emptyShortArray = new short[0]; static public short[] emptyShortArray() { return emptyShortArray; } static public Map immutableEmptyMap() { return Collections.emptyMap(); } 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 java.text.SimpleDateFormat simpleDateFormat(String format, TimeZone timeZone) { java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(format); sdf.setTimeZone(timeZone); return sdf; } static public Iterator iterator(Iterable c) { return c == null ? emptyIterator() : c.iterator(); } 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 Map subBot_getHeaders() { Object session = call(getMainBot(), "getSession"); return (Map) call(session, "getHeaders"); } static public String lower(String s) { return s == null ? null : s.toLowerCase(); } static public char lower(char c) { return Character.toLowerCase(c); } static public boolean endsWithLetterOrDigit(String s) { return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length() - 1)); } static public String localDateWithMilliseconds(Date time) { return localDateWithMilliseconds(time.getTime()); } static public String localDateWithMilliseconds(long time) { SimpleDateFormat format = simpleDateFormat_local("yyyy/MM/dd HH:mm:ss''SSSS"); return format.format(time); } static public String localDateWithMilliseconds() { return localDateWithMilliseconds(now()); } 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 int subBot_currentPort() { return toInt(getOpt(subBot_httpd(), "myPort")); } static public File programLogFile() { return programFile(defaultProgramLogFileName()); } static public File programLogFile(String programID) { return programFile(programID, defaultProgramLogFileName()); } 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 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 MultiMap mapMultiMapValues(Object func, MultiMap mm) { MultiMap m = similarEmptyMultiMap(mm); for (Object key : keys(mm)) for (Object value : mm.get(key)) m.put(key, callF(func, value)); return m; } static public MultiMap mapMultiMapValues(MultiMap mm, Object func) { return mapMultiMapValues(func, mm); } static public MultiMap mapMultiMapValues(IF1 func, MultiMap mm) { return mapMultiMapValues((Object) func, mm); } 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 all(int[] l, IIntPred f) { if (l != null) for (int i : l) if (!f.get(i)) return false; return true; } 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 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[] 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 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 == null || 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 : getDeclaredConstructors_cached(c)) { 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 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 List llNonNulls(A... a) { List l = new ArrayList(); for (A x : a) if (x != null) l.add(x); return l; } static public Object callOpt(Object o) { return callF(o); } static public Object callOpt(Object o, String method, Object... args) { return callOpt_withVarargs(o, method, args); } static public Object getOptMC(String field) { return getOpt(mc(), field); } static public String dropPrefix(String prefix, String s) { return s == null ? null : s.startsWith(prefix) ? s.substring(l(prefix)) : s; } static public List parse3(String s) { return dropPunctuation(javaTokPlusPeriod(s)); } static public Pair find2plusIndex(List pat, List tok) { for (int idx = 0; idx < tok.size(); idx += 2) { String[] result = find2(pat, tok, idx); if (result != null) return pair(result, idx + 1); } return null; } static public String[] concatStringArrays(String[]... arrays) { int l = 0; for (String[] a : arrays) l += l(a); String[] x = new String[l]; int i = 0; for (String[] a : arrays) if (a != null) { System.arraycopy(a, 0, x, i, l(a)); i += l(a); } return x; } 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 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 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 SimpleDateFormat simpleDateFormat_local(String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(localTimeZone()); return sdf; } 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 Runnable toRunnable(final Object o) { if (o == null) return null; if (o instanceof Runnable) return (Runnable) o; if (o instanceof String) throw fail("callF_legacy"); return new Runnable() { public void run() { try { callF(o); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(o)"; } }; } static public String patternQuote(String s) { return s.length() == 0 ? "" : Pattern.quote(s); } static public String quoteReplacement(String s) { return Matcher.quoteReplacement(s); } 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 String filterChars(IF1 pred, String s) { if (empty(s)) return null; int n = l(s), i = 0; char c = s.charAt(i); boolean totality = pred.get(c); for (++i; i < n; i++) { c = s.charAt(i); boolean b = pred.get(c); if (b != totality) { StringBuilder buf = new StringBuilder(); if (totality) buf.append(substring(s, 0, i)); while (true) { ping(); if (b) buf.append(c); if (++i >= n) break; c = s.charAt(i); b = pred.get(c); } return buf.toString(); } } return totality ? s : ""; } static public boolean isDigit(char c) { return Character.isDigit(c); } static public void _handleError(Error e) { } 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, Rectangle b) { return rectContains(a, toRect(b)); } static public boolean rectContains(Rect a, int x, int y) { return a != null && a.contains(x, y); } static public boolean rectContains(Rect a, Pt p) { return a != null && p != null && a.contains(p); } static public TreeSet asTreeSet(Collection set) { return set == null ? null : set instanceof TreeSet ? (TreeSet) set : new TreeSet(set); } static public MultiMap usAreaCodesMap_cache; static public MultiMap usAreaCodesMap() { if (usAreaCodesMap_cache == null) usAreaCodesMap_cache = usAreaCodesMap_load(); return usAreaCodesMap_cache; } static public MultiMap usAreaCodesMap_load() { File f = javaxCachesDir("us-area-codes.json"); if (!fileExists(f)) saveTextFile(f, loadSnippet("#1028616")); return mapMultiMapValues(__59 -> str(__59), mapToMultiMap(jsonDecodeMap(loadTextFile(f)))); } static public List newSubListOrSame(List l, int startIndex) { return newSubListOrSame(l, startIndex, l(l)); } static public List newSubListOrSame(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = max(0, startIndex); endIndex = min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return cloneList(l.subList(startIndex, endIndex)); } static public List newSubListOrSame(List l, IntRange r) { return newSubListOrSame(l, r.start, r.end); } static public 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 short[] takeFirstOfShortArray(short[] b, int n) { return subShortArray(b, 0, n); } static public short[] takeFirstOfShortArray(int n, short[] b) { return takeFirstOfShortArray(b, n); } static public byte[] takeFirstOfByteArray(byte[] b, int n) { return subByteArray(b, 0, n); } static public byte[] takeFirstOfByteArray(int n, byte[] b) { return takeFirstOfByteArray(b, n); } static public double[] takeFirstOfDoubleArray(double[] b, int n) { return subDoubleArray(b, 0, n); } static public double[] takeFirstOfDoubleArray(int n, double[] b) { return takeFirstOfDoubleArray(b, n); } static public int lCharSequence(CharSequence s) { return s == null ? 0 : s.length(); } static public boolean endsWithIgnoreCase(String a, String b) { int la = l(a), lb = l(b); return la >= lb && regionMatchesIC(a, la - lb, b, 0, lb); } static public boolean endsWithIgnoreCase(String a, String b, Matches m) { if (!endsWithIgnoreCase(a, b)) return false; if (m != null) m.m = new String[] { substring(a, 0, l(a) - l(b)) }; return true; } static public String hijackPrint_tee(Runnable r) { final StringBuilder buf = new StringBuilder(); Object old = interceptPrintInThisThread(new F1() { public Boolean get(String s) { buf.append(s); return true; } }); try { callF(r); return str(buf); } finally { interceptPrintInThisThread(old); } } static public String sourceCodeToHTML(String src) { return sourceCodeToHTML_noEncode(htmlencode2(src)); } static public String sourceCodeToHTML(Object o) { return sourceCodeToHTML(str(o)); } static public Field getOpt_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static 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 Object getOptDynOnly(DynamicObject o, String field) { if (o == null || o.fieldValues == null) return null; return o.fieldValues.get(field); } static public RuntimeException asRuntimeException(Throwable t) { if (t instanceof Error) _handleError((Error) t); return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static public A assertEqualsVerbose(Object x, A y) { assertEqualsVerbose((String) null, x, y); return y; } static public A assertEqualsVerbose(String msg, Object x, A y) { if (!eq(x, y)) { throw fail((nempty(msg) ? msg + ": " : "") + "expected: " + x + ", got: " + y); } else print("OK" + (empty(msg) ? "" : " " + msg) + ": " + (x)); return y; } 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 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(__60 -> mmo2_parsePattern(__60), l)); l = tok_splitAtPlus(tok); if (l(l) > 1) return new MMOPattern.And(lambdaMap(__61 -> mmo2_parsePattern(__61), 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 A findWhere(Collection c, Object... data) { if (c != null) for (A x : c) if (checkFields(x, data)) return x; return null; } 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 A addAll(A c, Collection components) { return addComponents(c, components); } static public A addAll(A c, Component... components) { return addComponents(c, components); } static public boolean match3(String pat, String s) { return match3(pat, s, null); } static public boolean match3(String pat, String s, Matches matches) { if (pat == null || s == null) return false; return match3(pat, parse3_cachedInput(s), matches); } static public boolean match3(String pat, List toks, Matches matches) { List tokpat = parse3_cachedPattern(pat); return match3(tokpat, toks, matches); } static public boolean match3(List tokpat, List toks, Matches matches) { String[] m = match2(tokpat, toks); if (m == null) return false; if (matches != null) matches.m = m; return true; } static public List intRangesToCNC(String s, List l) { List tok = new ArrayList(); int idx = 0; for (int i = 0; i < l(l); i++) { IntRange r = l.get(i); tok.add(substring(s, idx, r.start)); tok.add(substring(s, r)); idx = r.end; } tok.add(substring(s, idx)); return tok; } static public List regexpFindRangesIC(String pat, String s) { Matcher m = regexpMatcherIC(pat, s); List l = new ArrayList(); while (m.find()) l.add(new IntRange(m.start(), m.end())); return l; } 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(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 String unicodeFromCodePoint(int codePoint) { return codePointToString(codePoint); } 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 String structureForUser(Object o) { return structureForUser(o, new structure_Data()); } static public String structureForUser(Object o, structure_Data d) { d.noStringSharing = true; d.warnIfUnpersistable(false); return beautifyStructure(structure(o, d)); } static public Object collectionMutex(List l) { return l; } static public Object collectionMutex(Object o) { if (o instanceof List) return o; String c = className(o); return o; } static public String asString(Object o) { return o == null ? null : o.toString(); } 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 void addToContainer(Container a, Component... b) { if (a == null) return; { swing(() -> { for (Component c : unnullForIteration(b)) if (c != null) a.add(c); }); } } static public void db() { conceptsAndBot(); } static public void db(Integer autoSaveInterval) { conceptsAndBot(autoSaveInterval); } static public void indexConceptFields(Object... params) { int i = 0; Concepts concepts; if (first(params) instanceof Concepts) { concepts = (Concepts) first(params); ++i; } else concepts = db_mainConcepts(); for (; i < l(params); i += 2) indexConceptField(concepts, (Class) params[i], (String) params[i + 1]); } static public Field getField(Object o, String field) { if (o == null) return null; return setOpt_findField(_getClass(o), field); } static public Object getField(Field field, Object o) { return fieldGet(field, o); } static public void setOpt_raw(Object o, String field, Object value) { try { if (o == null) return; if (o instanceof Class) setOpt_raw((Class) o, field, value); else { Field f = setOpt_raw_findField(o.getClass(), field); if (f != null) { makeAccessible(f); smartSet(f, o, value); } } } catch (Exception __e) { throw rethrow(__e); } } static public void setOpt_raw(Class c, String field, Object value) { try { if (c == null) return; Field f = setOpt_raw_findStaticField(c, field); if (f != null) { makeAccessible(f); smartSet(f, null, value); } } catch (Exception __e) { throw rethrow(__e); } } static public Field setOpt_raw_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static public Field setOpt_raw_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static 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 A setDyn(A o, String key, Object value) { setDynObjectValue(o, key, value); return o; } static public void setDyn(IMeta o, String key, Object value) { metaMapPut(o, key, value); } static public Thread _unregisterThread(Thread t) { _registerThread_threads.remove(t); return t; } static public void _unregisterThread() { _unregisterThread(currentThread()); } static public String callHtmlMethod(Object o, String uri) { return callHtmlMethod(o, uri, null); } static public String callHtmlMethod(Object o, String uri, Map params) { String s = (String) callOpt(o, "html", uri, params); if (s == null) s = (String) callOpt(o, "html", uri); if (s == null) s = (String) callOpt(o, "html"); return s; } static public String getClientIP_subBot() { Object session = call(getMainBot(), "getSession"); Map headers = (Map) (call(session, "getHeaders")); return getClientIPFromHeaders(headers); } static public String loadSecretTextFile(String name) { return loadTextFile(new File(getSecretProgramDir(), name)); } static public String loadSecretTextFile(String progID, String name) { return loadTextFile(new File(getSecretProgramDir(progID), name)); } static public void saveSecretTextFile(String name, String s) { saveTextFile(new File(getSecretProgramDir(), name), s); } static public void saveSecretTextFile(String progID, String name, String s) { saveTextFile(new File(getSecretProgramDir(progID), name), s); } static public String aGlobalID() { return randomID(globalIDLength()); } static public String aGlobalID(Random random) { return randomID(random, globalIDLength()); } 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 saveTextFile(String fileName, String contents) throws IOException { 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()); try { OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); } finally { _close(fileOutputStream); } } 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; } static public File saveTextFile(File fileName, String contents) { try { saveTextFile(fileName.getPath(), contents); return fileName; } catch (Exception __e) { throw rethrow(__e); } } static public int iceil(double d) { return (int) Math.ceil(d); } 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 List mapMethod(Object[] l, final String methodName) { return map(l, new F1() { public Object get(Object o) { try { return callOpt(o, methodName); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callOpt(o, methodName)"; } }); } static public List mapMethod(Iterable c, final String methodName) { return map(c, new F1() { public Object get(Object o) { try { return callOpt(o, methodName); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callOpt(o, methodName)"; } }); } static public List mapMethod(String methodName, Iterable c) { return mapMethod(c, methodName); } static public List mapMethod(String methodName, Enumeration c) { return mapMethod(methodName, enumerationToIterator(c)); } 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 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 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 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 List deleteConcepts(Class c, IF1 pred) { return deleteConcepts(db_mainConcepts(), c, pred); } static public List deleteConcepts(Concepts cc, Class c, IF1 pred) { var l = filter(list(cc, c), pred); deleteConcepts(l); return l; } static public List deleteConcepts(Concepts cc) { return deleteConcepts(cc, Concept.class); } 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 Thread currentThread() { return Thread.currentThread(); } 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 emptyString(String s) { return s == null || s.length() == 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 String javascriptQuote(String s) { return quote(s); } 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 loadLocalSnippet(String snippetID) { return loadLocalSnippet(psI(snippetID)); } static public String loadLocalSnippet(long snippetID) { return loadTextFile(localSnippetFile(snippetID)); } static public IResourceLoader vm_getResourceLoader() { return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader")); } static public String fsI(String id) { return formatSnippetID(id); } static public String fsI(long id) { return formatSnippetID(id); } static public String md5(String text) { try { if (text == null) return "-"; return bytesToHex(md5_impl(toUtf8(text))); } catch (Exception __e) { throw rethrow(__e); } } static public String md5(byte[] data) { if (data == null) return "-"; return bytesToHex(md5_impl(data)); } static public byte[] md5_impl(byte[] data) { try { return MessageDigest.getInstance("MD5").digest(data); } catch (Exception __e) { throw rethrow(__e); } } static public String md5(File file) { return md5OfFile(file); } static public String 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); } 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 File getGlobalCache() { File file = new File(javaxCachesDir(), "Binary Snippets"); file.mkdirs(); return file; } static public A setThreadLocal(ThreadLocal tl, A value) { if (tl == null) return null; A old = tl.get(); tl.set(value); return old; } 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 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 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 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 boolean isRelativeOrAbsoluteURL(String s) { return isAbsoluteURL(s) || isRelativeURL(s); } static public Object subBot_serveWithContentType(String text, String contentType) { return callMainBot("serveByteArray", toUtf8(unnull(text)), contentType); } 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 dataSnippetURL(String snippetID) { return dataSnippetLink(snippetID); } static public String fromLines(Iterable lines) { StringBuilder buf = new StringBuilder(); if (lines != null) for (Object line : lines) buf.append(str(line)).append('\n'); return buf.toString(); } static public String fromLines(String... lines) { return fromLines(asList(lines)); } static public IterableIterator toLines(File f) { return linesFromFile(f); } static public List toLines(String s) { List lines = new ArrayList(); if (s == null) return lines; int start = 0; while (true) { int i = toLines_nextLineBreak(s, start); if (i < 0) { if (s.length() > start) lines.add(s.substring(start)); break; } lines.add(s.substring(start, i)); if (s.charAt(i) == '\r' && i + 1 < s.length() && s.charAt(i + 1) == '\n') i += 2; else ++i; start = i; } return lines; } static public int toLines_nextLineBreak(String s, int start) { int n = s.length(); for (int i = start; i < n; i++) { char c = s.charAt(i); if (c == '\r' || c == '\n') return i; } return -1; } static public 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 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 Map emptyMap() { return new HashMap(); } 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 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 intToHex_flexLength(int i) { return Integer.toHexString(i); } 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 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 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 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 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 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 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); } 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 MultiMap mapKeys(IF1 f, MultiMap mm) { return mapMultiMapKeys(f, mm); } static public MultiSetMap mapKeys(IF1 f, MultiSetMap mm) { return mapMultiSetMapKeys(f, mm); } static public String deSquareBracket(String s) { if (startsWith(s, "[") && endsWith(s, "]")) return substring(s, 1, l(s) - 1); return s; } static public TreeMap litcimap(Object... x) { return litCIMap(x); } 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 boolean checkCondition(Object condition, Object... args) { return isTrue(callF(condition, args)); } static public boolean checkCondition(IF1 condition, A arg) { return isTrue(callF(condition, arg)); } static public 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 ThreadLocal print_byThread() { synchronized (print_byThread_lock) { if (print_byThread == null) print_byThread = new ThreadLocal(); } return print_byThread; } static public AutoCloseable tempInterceptPrint(F1 f) { return tempSetThreadLocal(print_byThread(), f); } static public void clear(Collection c) { if (c != null) c.clear(); } static public void clear(Map map) { if (map != null) map.clear(); } 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 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 Map synchroMap() { return synchroHashMap(); } static public Map synchroMap(Map map) { return new SynchronizedMap(map); } 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 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 a != null && b != null && 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 Map newWeakHashMap() { return _registerWeakMap(synchroMap(new WeakHashMap())); } static public Map vm_generalWeakSubMap(Object name) { synchronized (vm_generalMap()) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = newWeakMap()); return map; } } static public WeakReference weakRef(A a) { return newWeakReference(a); } 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 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 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 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 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 Concepts newConceptsWithClassFinder(String progID) { Concepts cc = new Concepts(progID); cc.classFinder = _defaultClassFinder(); return cc; } static public Concepts newConceptsWithClassFinder(File conceptsFile) { Concepts cc = new Concepts(assertNotNull(conceptsFile)); cc.classFinder = _defaultClassFinder(); return cc; } static public Concepts newConceptsWithClassFinder(File conceptsFile, IF1 classFinder) { Concepts cc = new Concepts(assertNotNull(conceptsFile)); cc.classFinder = classFinder; return cc; } static public String getDBProgramID_id; static public String getDBProgramID() { return nempty(getDBProgramID_id) ? getDBProgramID_id : programIDWithCase(); } 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 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 Object[] assertEvenLength(Object[] a) { assertTrue(even(l(a))); return a; } static public LinkedHashMap paramsToOrderedMap(Object... params) { return asLinkedHashMap(paramsToMap(params)); } static public Object[] mapToParams(Map map) { return mapToObjectArray(map); } static public void mapPut_noOverwrite(Map map, A key, B value) { if (map != null && key != null && value != null && !map.containsKey(key)) map.put(key, value); } static public String hstylesheetsrc(String src) { return tag("link", "", "rel", "stylesheet", "href", src); } static public String htmldecode_dropAllTags(String html) { return htmldecode(dropAllTags(html)); } static public boolean endsWithLetter(String s) { return nempty(s) && isLetter(last(s)); } 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 Map newDangerousWeakHashMap() { return _registerDangerousWeakMap(synchroMap(new WeakHashMap())); } static public Map newDangerousWeakHashMap(Object initFunction) { return _registerDangerousWeakMap(synchroMap(new WeakHashMap()), initFunction); } 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 call_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != l(args)) { 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 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 Object deref(Object o) { if (o instanceof IRef) return ((IRef) o).get(); return o; } static public String intern(String s) { return fastIntern(s); } static public String assertIdentifier(String s) { return assertIsIdentifier(s); } static public String assertIdentifier(String msg, String s) { return assertIsIdentifier(msg, s); } 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 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 void dynamicObject_dropRawField(DynamicObject o, Object key) { if (o == null) return; synchronized (o) { o.fieldValues = (LinkedHashMap) syncMapRemove_deleteMapIfEmpty((Map) o.fieldValues, key); } } static public boolean isPersistable(Object o) { return !isInAnonymousClass(o); } static public Object derefRef(Object o) { if (o instanceof Concept.Ref) o = ((Concept.Ref) o).get(); return o; } static public A derefRef(Concept.Ref r) { return r == null ? null : r.get(); } static public List lmap(IF1 f, Iterable l) { return lambdaMap(f, l); } static public List lmap(IF1 f, A[] l) { return lambdaMap(f, l); } static public boolean isTransient(Field f) { return (f.getModifiers() & java.lang.reflect.Modifier.TRANSIENT) != 0; } 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 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 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 Set vm_generalIdentityHashSet(Object name) { synchronized (vm_generalMap()) { Set set = (Set) (vm_generalMap_get(name)); if (set == null) vm_generalMap_put(name, set = syncIdentityHashSet()); return set; } } static public Map vm_generalHashMap(Object name) { synchronized (vm_generalMap()) { Map m = (Map) (vm_generalMap_get(name)); if (m == null) vm_generalMap_put(name, m = syncHashMap()); return m; } } static public int isAndroid_flag; static public boolean isAndroid() { if (isAndroid_flag == 0) isAndroid_flag = System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0 ? 1 : -1; return isAndroid_flag > 0; } static public Boolean isHeadless_cache; static public boolean isHeadless() { if (isHeadless_cache != null) return isHeadless_cache; if (isAndroid()) return isHeadless_cache = true; if (GraphicsEnvironment.isHeadless()) return isHeadless_cache = true; try { SwingUtilities.isEventDispatchThread(); return isHeadless_cache = false; } catch (Throwable e) { return isHeadless_cache = true; } } 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 String strOrNull(Object o) { return o == null ? null : str(o); } 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 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 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 List filterNempty(Collection c) { List l = new ArrayList(); for (String x : unnull(c)) if (nempty(x)) l.add(x); return l; } 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 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 List splitAtColon(String s) { return empty(s) ? emptyList() : asList(s.split(":")); } static public char charAt(String s, int i) { return s != null && i >= 0 && i < s.length() ? s.charAt(i) : '\0'; } 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 AutoCloseable tempDBLock(Concepts concepts) { return tempLock(concepts.lock); } static public AutoCloseable tempDBLock() { return tempDBLock(db_mainConcepts()); } 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 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 int csetAll(Concept c, Map values) { int n = 0; for (Map.Entry __0 : _entrySet(values)) { String field = __0.getKey(); Object value = __0.getValue(); n += cset(c, field, value); } return n; } static volatile public PersistableThrowable lastException_lastException; static public PersistableThrowable lastException() { return lastException_lastException; } static public void lastException(Throwable e) { lastException_lastException = persistableThrowable(e); } static public String hideCredentials(URL url) { return url == null ? null : hideCredentials(str(url)); } static public String hideCredentials(String url) { try { if (startsWithOneOf(url, "http://", "https://") && isAGIBlueDomain(hostNameFromURL(url))) return url; } catch (Throwable e) { print("HideCredentials", e); } return url.replaceAll("([&?])(_pass|key|cookie)=[^&\\s\"]*", "$1$2="); } static public String hideCredentials(Object o) { return hideCredentials(str(o)); } static public void rotateStringBuffer(StringBuffer buf, int max) { try { if (buf == null) return; synchronized (buf) { if (buf.length() <= max) return; try { int newLength = max / 2; int ofs = buf.length() - newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static public void rotateStringBuilder(StringBuilder buf, int max) { try { if (buf == null) return; synchronized (buf) { if (buf.length() <= max) return; try { int newLength = max / 2; int ofs = buf.length() - newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static public Object 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) { printStackTrace(__e); } return null; } static public B pcallF(F1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { printStackTrace(__e); } return null; } static public void pcallF(VF1 f, A a) { try { { if (f != null) f.get(a); } } catch (Throwable __e) { printStackTrace(__e); } } static public Object pcallF(Runnable r) { try { { if (r != null) r.run(); } } catch (Throwable __e) { printStackTrace(__e); } return null; } static public A pcallF(IF0 f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { printStackTrace(__e); } return null; } static public B pcallF(IF1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { printStackTrace(__e); } return null; } 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 boolean isStaticMethod(Method m) { return methodIsStatic(m); } static public Object[] massageArgsForVarArgsCall(Executable m, Object[] args) { Class[] types = m.getParameterTypes(); int n = types.length - 1, nArgs = l(args); 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); int nVarArgs = nArgs - n; Object varArgs = Array.newInstance(varArgType, nVarArgs); for (int i = 0; i < nVarArgs; i++) Array.set(varArgs, i, args[n + i]); newArgs[n] = varArgs; return newArgs; } static public List classNames(Collection l) { return getClassNames(l); } static public List classNames(Object[] l) { return getClassNames(asList(l)); } 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 localYear() { return localYear(now()); } static public int localYear(long time) { return parseInt(simpleDateFormat_local("yyyy").format(time)); } 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 TimeZone defaultTimeZone() { return TimeZone.getDefault(); } 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 clone(A o) { ArrayDeque q = new ArrayDeque(); Object x = clone_impl(o, new IdentityHashMap(), q); while (!q.isEmpty()) q.poll().run(); return (A) x; } static public Object clone_impl(Object o, final IdentityHashMap seen, final ArrayDeque q) { try { if (o == null) return null; Object y = seen.get(o); if (y != null) return y; if (o instanceof List) { final List l = new ArrayList(); seen.put(o, l); for (final Object x : (List) o) q.add(new Runnable() { public void run() { try { l.add(clone_impl(x, seen, q)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "l.add(clone_impl(x, seen, q))"; } }); return l; } if (o instanceof Map) { final Map m = similarEmptyMap((Map) o); seen.put(o, m); for (Object entry : ((Map) o).entrySet()) { final Map.Entry e = (Map.Entry) entry; q.add(new Runnable() { public void run() { try { m.put(clone_impl(e.getKey(), seen, q), clone_impl(e.getValue(), seen, q)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "m.put(clone_impl(e.getKey(), seen, q), clone_impl(e.getValue(), seen, q))"; } }); } return m; } if (o instanceof String || o instanceof Number || o instanceof Boolean) return o; if (o instanceof Object[]) { final Object[] l = (Object[]) o; final Object[] l2 = l.clone(); seen.put(o, l2); for (int i = 0; i < l.length; i++) { final int _i = i; q.add(new Runnable() { public void run() { try { l2[_i] = clone_impl(l[_i], seen, q); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "l2[_i] = clone_impl(l[_i], seen, q)"; } }); } return l2; } final Object clone = nuObjectWithoutArguments(o.getClass()); seen.put(o, clone); 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); q.add(new Runnable() { public void run() { try { field.set(clone, clone_impl(value, seen, q)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "field.set(clone, clone_impl(value, seen, q))"; } }); } c = c.getSuperclass(); } return clone; } catch (Exception __e) { throw rethrow(__e); } } static public String roundBracket(String s) { return "(" + s + ")"; } static public String roundBracket(Object s) { return roundBracket(str(s)); } 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(a, b, 0); } static public int indexOfIgnoreCase(String[] a, String b, int i) { int n = a == null ? 0 : a.length; for (; i < n; i++) if (eqic(a[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 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 Iterator emptyIterator() { return Collections.emptyIterator(); } 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 File programFile(String name) { return prepareProgramFile(name); } static public File programFile(String progID, String name) { return prepareProgramFile(progID, name); } static public String defaultProgramLogFileName() { return "log.txt"; } static public Object[] unrollParams(Object[] params) { if (l(params) == 1 && params[0] instanceof Map) return mapToParams((Map) params[0]); return params; } 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 MultiMap similarEmptyMultiMap(MultiMap m) { if (m instanceof TreeMultiMap) return new TreeMultiMap((TreeMultiMap) 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 formatWithThousandsSeparator(long l) { return NumberFormat.getInstance(new Locale("en_US")).format(l); } 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 : getDeclaredConstructors_cached(c)) if (empty(m.getParameterTypes())) { makeAccessible(m); return m; } throw fail("No default constructor found in " + c.getName()); } static public Map getDeclaredConstructors_cached_cache = newDangerousWeakHashMap(); static public Constructor[] getDeclaredConstructors_cached(Class c) { Constructor[] ctors; synchronized (getDeclaredConstructors_cached_cache) { ctors = getDeclaredConstructors_cached_cache.get(c); if (ctors == null) { getDeclaredConstructors_cached_cache.put(c, ctors = c.getDeclaredConstructors()); for (var ctor : ctors) makeAccessible(ctor); } } return ctors; } static public List getClasses(Object[] array) { List l = emptyList(l(array)); for (Object o : array) l.add(_getClass(o)); return l; } static public boolean isInstanceX(Class type, Object arg) { if (type == boolean.class) return arg instanceof Boolean; if (type == int.class) return arg instanceof Integer; if (type == long.class) return arg instanceof Long; if (type == float.class) return arg instanceof Float; if (type == short.class) return arg instanceof Short; if (type == char.class) return arg instanceof Character; if (type == byte.class) return arg instanceof Byte; if (type == double.class) return arg instanceof Double; return type.isInstance(arg); } static public 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 void failIfOddCount(Object... list) { if (odd(l(list))) throw fail("Odd list size: " + list); } static public Object callOpt_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.findMethod(method, args); if (me == null) { return null; } if ((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(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); } return null; } } catch (Exception __e) { throw rethrow(__e); } } 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 Map synchronizedMRUCache(int maxSize) { return synchroMap(new MRUCache(maxSize)); } 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 Object dm_current_generic() { return getWeakRef(dm_current_generic_tl().get()); } static public Object rcall(String method, Object o, Object... args) { return call_withVarargs(o, method, args); } static public Runnable _topLevelErrorHandling(Runnable r) { if (r == null) return null; Object info = _threadInfo(); Object mod = dm_current_generic(); Runnable r2 = r; if (info != null || mod == null) r2 = 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 ..."; } }; r2 = rPcall(r2); return r2; } 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 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 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 > 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 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 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 short[] subShortArray(short[] 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 short[0]; short[] x = new short[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public byte[] subByteArray(byte[] b, int start) { return subByteArray(b, start, l(b)); } static public byte[] subByteArray(byte[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new byte[0]; byte[] x = new byte[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static public byte[] subByteArray(byte[] b, IntRange r) { return r == null ? null : subByteArray(b, r.start, r.end); } static public double[] subDoubleArray(double[] b, int start) { return subDoubleArray(b, start, l(b)); } static public double[] subDoubleArray(double[] 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 double[0]; double[] x = new double[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } 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 interceptPrintInThisThread(Object f) { Object old = print_byThread().get(); print_byThread().set(f); return old; } static public String sourceCodeToHTML_noEncode(String html) { return "
" + html + "
"; } static public String htmlencode2(String s) { return htmlencode_noQuotes(s); } static public String appendColonIfNempty(String s) { return empty(s) ? "" : 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 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 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_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 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 isQuoted(String s) { if (isNormalQuoted(s)) return true; return isMultilineQuoted(s); } 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
A addComponents(A c, Collection components) { if (nempty(components)) { swing(() -> { for (Component comp : components) if (comp != null) c.add(comp); revalidate(c); }); } return c; } static public A addComponents(A c, Component... components) { return addComponents(c, asList(components)); } 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 Matcher regexpMatcherIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static public String codePointToString(int codePoint) { return new String(Character.toChars(codePoint)); } 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 beautifyStructure(String s) { List tok = javaTokForStructure(s); structure_addTokenMarkers(tok); jreplace(tok, "lhm", ""); return join(tok); } static public boolean structure_showTiming, structure_checkTokenCount; static public String structure(Object o) { return structure(o, new structure_Data()); } static public String structure(Object o, structure_Data d) { StringWriter sw = new StringWriter(); d.out = new PrintWriter(sw); structure_go(o, d); String s = str(sw); if (structure_checkTokenCount) { print("token count=" + d.n); assertEquals("token count", l(javaTokC(s)), d.n); } return s; } static public void structure_go(Object o, structure_Data d) { structure_1(o, d); while (nempty(d.stack)) popLast(d.stack).run(); } static public void structureToPrintWriter(Object o, PrintWriter out) { structureToPrintWriter(o, out, new structure_Data()); } static public void structureToPrintWriter(Object o, PrintWriter out, structure_Data d) { d.out = out; structure_go(o, d); } static public boolean structure_allowShortening = false; static public class structure_ClassInfo { public Class c; public String shortName; public List fields; public Method customSerializer; public IVF1 serializeObject; public boolean special = false; public boolean nullInstances = false; public boolean javafy = false; public Object emptyInstance; public void nullInstances(boolean b) { this.nullInstances = b; if (b) special = true; } public void javafy(boolean b) { this.javafy = b; if (b) special = true; } } static public class structure_Data { public PrintWriter out; public int stringSizeLimit; public int shareStringsLongerThan = 20; public boolean noStringSharing = false; public boolean storeBaseClasses = false; public boolean honorFieldOrder = true; public String mcDollar = actualMCDollar(); final public structure_Data setWarnIfUnpersistable(boolean warnIfUnpersistable) { return warnIfUnpersistable(warnIfUnpersistable); } public structure_Data warnIfUnpersistable(boolean warnIfUnpersistable) { this.warnIfUnpersistable = warnIfUnpersistable; return this; } final public boolean getWarnIfUnpersistable() { return warnIfUnpersistable(); } public boolean warnIfUnpersistable() { return warnIfUnpersistable; } public boolean warnIfUnpersistable = true; final public structure_Data setStackTraceIfUnpersistable(boolean stackTraceIfUnpersistable) { return stackTraceIfUnpersistable(stackTraceIfUnpersistable); } public structure_Data stackTraceIfUnpersistable(boolean stackTraceIfUnpersistable) { this.stackTraceIfUnpersistable = stackTraceIfUnpersistable; return this; } final public boolean getStackTraceIfUnpersistable() { return stackTraceIfUnpersistable(); } public boolean stackTraceIfUnpersistable() { return stackTraceIfUnpersistable; } public boolean stackTraceIfUnpersistable = true; final public structure_Data setSkipDefaultValues(boolean skipDefaultValues) { return skipDefaultValues(skipDefaultValues); } public structure_Data skipDefaultValues(boolean skipDefaultValues) { this.skipDefaultValues = skipDefaultValues; return this; } final public boolean getSkipDefaultValues() { return skipDefaultValues(); } public boolean skipDefaultValues() { return skipDefaultValues; } public boolean skipDefaultValues = false; transient public IF1 shouldIncludeField; public boolean shouldIncludeField(Field f) { return shouldIncludeField != null ? shouldIncludeField.get(f) : shouldIncludeField_base(f); } final public boolean shouldIncludeField_fallback(IF1 _f, Field f) { return _f != null ? _f.get(f) : shouldIncludeField_base(f); } public boolean shouldIncludeField_base(Field f) { return true; } public IdentityHashMap seen = new IdentityHashMap(); public HashMap strings = new HashMap(); public HashSet concepts = new HashSet(); public HashMap infoByClass = new HashMap(); public HashMap> persistenceInfo = new HashMap(); public int n; public List stack = new ArrayList(); public structure_Data append(String token) { out.print(token); ++n; return this; } public structure_Data append(int i) { out.print(i); ++n; return this; } public structure_Data append(String token, int tokCount) { out.print(token); n += tokCount; return this; } public structure_Data app(String token) { out.print(token); return this; } public structure_Data app(int i) { out.print(i); return this; } public structure_ClassInfo infoForClass(Class c) { structure_ClassInfo info = infoByClass.get(c); if (info == null) info = newClass(c); return info; } public structure_ClassInfo newClass(Class c) { structure_ClassInfo info = new structure_ClassInfo(); info.c = c; infoByClass.put(c, info); String name = c.getName(); String shortName = dropPrefix("main$", dropPrefix("loadableUtils.utils$", dropPrefix(mcDollar, name))); if (startsWithDigit(shortName)) shortName = name; info.shortName = shortName; try { if (isSyntheticOrAnonymous(c)) { info.nullInstances(true); return info; } if (c.isEnum()) { info.special = true; return info; } if (c.isArray()) { return info; } if ((info.customSerializer = findMethodNamed(c, "_serialize")) != null) info.special = true; if (storeBaseClasses) { Class sup = c.getSuperclass(); if (sup != Object.class) { append("bc "); append(shortDynClassNameForStructure(c)); out.print(" "); append(shortDynClassNameForStructure(sup)); out.print(" "); infoForClass(sup); } } if (eqOneOf(name, "java.awt.Color", "java.lang.ThreadLocal")) info.javafy(true); else if (name.startsWith("sun") || !isPersistableClass(c)) { info.javafy(true); if (warnIfUnpersistable) { String msg = "Class not persistable: " + c + " (anonymous or no default constructor), referenced from " + last(stack); if (stackTraceIfUnpersistable) printStackTrace(new Throwable(msg)); else print(msg); } } else if (skipDefaultValues) { var ctor = getDefaultConstructor(c); if (ctor != null) info.emptyInstance = invokeConstructor(ctor); } } catch (Throwable e) { printStackTrace(e); info.nullInstances(true); } return info; } public void setFields(structure_ClassInfo info, List fields) { info.fields = fields; } public void writeObject(Object o, String shortName, Map fv) { String singleField = fv.size() == 1 ? first(fv.keySet()) : null; append(shortName); n += countDots(shortName) * 2; int l = n; Iterator it = fv.entrySet().iterator(); class WritingObject implements Runnable { public String lastFieldWritten; public void run() { try { if (!it.hasNext()) { if (n != l) append(")"); } else { Map.Entry e = (Map.Entry) (it.next()); append(n == l ? "(" : ", "); append(lastFieldWritten = (String) e.getKey()).append("="); stack.add(this); structure_1(e.getValue(), structure_Data.this); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return shortName + "." + lastFieldWritten; } } stack.add(new WritingObject()); } } static public void structure_1(final Object o, final structure_Data d) { try { if (o == null) { d.append("null"); return; } Class c = o.getClass(); boolean concept = false; concept = o instanceof Concept; structure_ClassInfo info = d.infoForClass(c); List lFields = info.fields; if (lFields == null) { if (o instanceof Number) { PrintWriter out = d.out; if (o instanceof Integer) { int i = ((Integer) o).intValue(); out.print(i); d.n += i < 0 ? 2 : 1; return; } if (o instanceof Long) { long l = ((Long) o).longValue(); out.print(l); out.print("L"); d.n += l < 0 ? 2 : 1; return; } if (o instanceof Short) { short s = ((Short) o).shortValue(); d.append("sh "); out.print(s); d.n += s < 0 ? 2 : 1; return; } if (o instanceof Float) { d.append("fl ", 2); quoteToPrintWriter(str(o), out); return; } if (o instanceof Double) { d.append("d(", 3); quoteToPrintWriter(str(o), out); d.append(")"); return; } if (o instanceof BigInteger) { out.print("bigint("); out.print(o); out.print(")"); d.n += ((BigInteger) o).signum() < 0 ? 5 : 4; return; } } if (o instanceof Boolean) { d.append(((Boolean) o).booleanValue() ? "t" : "f"); return; } if (o instanceof Character) { d.append(quoteCharacter((Character) o)); return; } if (o instanceof File) { d.append("File ").append(quote(((File) o).getPath())); return; } Integer ref = d.seen.get(o); if (o instanceof String && ref == null) ref = d.strings.get((String) o); if (ref != null) { d.append("t").app(ref); return; } if (!(o instanceof String)) d.seen.put(o, d.n); else { String s = d.stringSizeLimit != 0 ? shorten((String) o, d.stringSizeLimit) : (String) o; if (!d.noStringSharing) { if (d.shareStringsLongerThan == Integer.MAX_VALUE) d.seen.put(o, d.n); if (l(s) >= d.shareStringsLongerThan) d.strings.put(s, d.n); } quoteToPrintWriter(s, d.out); d.n++; return; } if (o instanceof Set) { if (((Set) o) instanceof TreeSet) { d.append(isCISet_gen((Set) o) ? "ciset" : "treeset"); structure_1(new ArrayList((Set) o), d); return; } d.append(((Set) o) instanceof LinkedHashSet ? "lhs" : "hashset"); structure_1(new ArrayList((Set) o), d); return; } String name = c.getName(); if (o instanceof Collection && !isJavaXClassName(name)) { if (name.equals("java.util.Collections$SynchronizedList") || name.equals("java.util.Collections$SynchronizedRandomAccessList")) { d.append("sync "); { structure_1(unwrapSynchronizedList(((List) o)), d); return; } } else if (name.equals("java.util.LinkedList")) d.append("ll"); d.append("["); final int l = d.n; final Iterator it = cloneList((Collection) o).iterator(); d.stack.add(new Runnable() { public void run() { try { if (!it.hasNext()) d.append("]"); else { d.stack.add(this); if (d.n != l) d.append(", "); structure_1(it.next(), d); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!it.hasNext())\r\n d.append(\"]\");\r\n else {\r\n d.sta..."; } }); return; } if (o instanceof SynchronizedMap) { d.append("sync "); { structure_1(((SynchronizedMap) o).m, d); return; } } if (o instanceof Map && !startsWith(name, d.mcDollar)) { if (o instanceof LinkedHashMap) d.append("lhm"); else if (o instanceof HashMap) d.append("hm"); else if (o instanceof TreeMap) d.append(isCIMap_gen((TreeMap) o) ? "cimap" : "tm"); else if (name.equals("java.util.Collections$SynchronizedMap") || name.equals("java.util.Collections$SynchronizedSortedMap") || name.equals("java.util.Collections$SynchronizedNavigableMap")) { d.append("sync "); { structure_1(unwrapSynchronizedMap(((Map) o)), d); return; } } d.append("{"); final int l = d.n; final Iterator it = cloneMap((Map) o).entrySet().iterator(); d.stack.add(new Runnable() { public boolean v = false; public Map.Entry e; public void run() { if (v) { d.append("="); v = false; d.stack.add(this); structure_1(e.getValue(), d); } else { if (!it.hasNext()) d.append("}"); else { e = (Map.Entry) it.next(); v = true; d.stack.add(this); if (d.n != l) d.append(", "); structure_1(e.getKey(), d); } } } }); return; } if (c.isArray()) { if (o instanceof byte[]) { d.append("ba ").append(quote(bytesToHex((byte[]) o))); return; } final int n = Array.getLength(o); if (o instanceof boolean[]) { String hex = boolArrayToHex((boolean[]) o); int i = l(hex); while (i > 0 && hex.charAt(i - 1) == '0' && hex.charAt(i - 2) == '0') i -= 2; d.append("boolarray ").append(n).app(" ").append(quote(substring(hex, 0, i))); return; } String atype = "array"; if (o instanceof int[]) { atype = "intarray"; } else if (o instanceof double[]) { atype = "dblarray"; } else { Pair p = arrayTypeAndDimensions(c); if (p.a == int.class) atype = "intarray"; else if (p.a == byte.class) atype = "bytearray"; else if (p.a == boolean.class) atype = "boolarray"; else if (p.a == double.class) atype = "dblarray"; else if (p.a == String.class) { atype = "array S"; d.n++; } else atype = "array"; if (p.b > 1) { atype += "/" + p.b; d.n += 2; } } d.append(atype).append("{"); d.stack.add(new Runnable() { public int i; public void run() { if (i >= n) d.append("}"); else { d.stack.add(this); if (i > 0) d.append(", "); structure_1(Array.get(o, i++), d); } } }); return; } if (o instanceof Class) { d.append("class(", 2).append(quote(((Class) o).getName())).append(")"); return; } if (o instanceof Throwable) { d.append("exception(", 2).append(quote(((Throwable) o).getMessage())).append(")"); return; } if (o instanceof BitSet) { BitSet bs = (BitSet) o; d.append("bitset{", 2); int l = d.n; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { if (d.n != l) d.append(", "); d.append(i); } d.append("}"); return; } if (info.javafy) { d.append("j ").append(quote(str(o))); return; } if (info.special) { if (c.isEnum()) { d.append("enum "); d.append(info.shortName); d.out.append(' '); d.append(((Enum) o).ordinal()); return; } if (info.customSerializer != null) { Object o2 = invokeMethod(info.customSerializer, o); if (o2 == o) { } else { d.append("cu "); String shortName = dropPrefix(d.mcDollar, name); d.append(shortName); d.out.append(' '); structure_1(o2, d); return; } } else if (info.nullInstances) { d.append("null"); return; } else if (info.serializeObject != null) { info.serializeObject.get(o); return; } else throw fail("unknown special type"); } String dynName = shortDynClassNameForStructure(o); if (concept && !d.concepts.contains(dynName)) { d.concepts.add(dynName); d.append("c "); } TreeSet fields = new TreeSet(new Comparator() { public int compare(Field a, Field b) { return stdcompare(a.getName(), b.getName()); } }); Class cc = c; while (cc != Object.class) { for (Field field : getDeclaredFields_cached(cc)) { if (!d.shouldIncludeField(field)) continue; String fieldName = field.getName(); if (fieldName.equals("_persistenceInfo")) d.persistenceInfo.put(c, obj -> (Map) fieldGet(field, obj)); if ((field.getModifiers() & (java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.TRANSIENT)) != 0) continue; fields.add(field); } cc = cc.getSuperclass(); } Method persistenceInfoMethod = findInstanceMethod(c, "_persistenceInfo"); if (persistenceInfoMethod != null) d.persistenceInfo.put(c, obj -> (Map) invokeMethod(persistenceInfoMethod, obj)); lFields = asList(d.honorFieldOrder ? fieldObjectsInFieldOrder(c, fields) : fields); int n = l(lFields); for (int i = 0; i < n; i++) { Field f = lFields.get(i); if (f.getName().startsWith("this$")) { lFields.remove(i); lFields.add(0, f); break; } } d.setFields(info, lFields); } else { Integer ref = d.seen.get(o); if (ref != null) { d.append("t").app(ref); return; } d.seen.put(o, d.n); } IF1 piGetter = d.persistenceInfo.get(c); Map persistenceInfo = piGetter == null ? null : piGetter.get(o); if (piGetter == null && o instanceof DynamicObject) persistenceInfo = (Map) getOptDynOnly(((DynamicObject) o), "_persistenceInfo"); LinkedHashMap fv = new LinkedHashMap(); Object defaultInstance = info.emptyInstance; for (Field f : lFields) { Object value, defaultValue = null; try { value = f.get(o); defaultValue = defaultInstance == null ? null : f.get(defaultInstance); } catch (Exception e) { value = "?"; } if (!eq(defaultValue, value) && (persistenceInfo == null || !Boolean.FALSE.equals(persistenceInfo.get(f.getName())))) fv.put(f.getName(), value); } String shortName = info.shortName; if (concept && eq(fv.get("className"), shortName)) fv.remove("className"); if (o instanceof DynamicObject) { putAll(fv, (Map) fv.get("fieldValues")); fv.remove("fieldValues"); if (((DynamicObject) o).className != null) { shortName = shortDynClassNameForStructure((DynamicObject) o); fv.remove("className"); } } d.writeObject(o, shortName, fv); } catch (Exception __e) { throw rethrow(__e); } } static public String className(Object o) { return getClassName(o); } static public TreeSet caseInsensitiveSet_treeSet() { return new TreeSet(caseInsensitiveComparator()); } static public TreeSet caseInsensitiveSet_treeSet(Collection c) { return toCaseInsensitiveSet_treeSet(c); } static public Object swing(Object f) { return swingAndWait(f); } static public void swing(Runnable f) { swingAndWait(f); } static public A swing(F0 f) { return (A) swingAndWait(f); } static public A swing(IF0 f) { return (A) swingAndWait(f); } 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(); cc.programID = getDBProgramID(); try { if (cc.useFileLock) { if (!cc.fileLock().tryToLock()) { ensureDBNotRunning(dbBotStandardName()); cc.fileLock().forceLock(); } } else ensureDBNotRunning(dbBotStandardName()); } catch (Throwable e) { printStackTrace(e); cc.dontSave = true; throw rethrow(e); } cc.persist(autoSaveInterval); dbBot(false); if (conceptsAndBot_thinOnStart) { try { thinAProgramsBackups(getDBProgramID(), true); } catch (Throwable __e) { printStackTrace(__e); } } } static public Object fieldGet(Field f, Object o) { try { return f == null ? null : f.get(o); } catch (Exception __e) { throw rethrow(__e); } } 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 void setDynObjectValue(DynamicObject o, String field, Object value) { dynamicObject_setRawFieldValue(o, field, value); } static public void metaMapPut(IMeta o, Object key, Object value) { { if (o != null) o.metaPut(key, value); } } static public void metaMapPut(Object o, Object key, Object value) { var meta = initIMeta(o); { if (meta != null) meta.metaPut(key, value); } } 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 File getSecretProgramDir() { return getSecretProgramDir(actualProgramID()); } static public File getSecretProgramDir(String snippetID) { if (empty(snippetID)) return javaxSecretDir(); return newFile(javaxSecretDir(), formatSnippetID(snippetID)); } static public int globalIDLength() { return 16; } static public ThreadLocal> checkFileNotTooBigToRead_tl = new ThreadLocal(); static public void checkFileNotTooBigToRead(File f) { callF(checkFileNotTooBigToRead_tl.get(), f); } public static File mkdirsForFile(File file) { File dir = file.getParentFile(); if (dir != null) { dir.mkdirs(); if (!dir.isDirectory()) if (dir.isFile()) throw fail("Please delete the file " + f2s(dir) + " - it is supposed to be a directory!"); else throw fail("Unknown IO exception during mkdirs of " + f2s(file)); } return file; } public static String mkdirsForFile(String path) { mkdirsForFile(new File(path)); return path; } static public File copyFile(File src, File dest) { try { FileInputStream inputStream = new FileInputStream(src.getPath()); FileOutputStream outputStream = newFileOutputStream(dest.getPath()); try { copyStream(inputStream, outputStream); inputStream.close(); } finally { outputStream.close(); } return dest; } catch (Exception __e) { throw rethrow(__e); } } static public IterableIterator enumerationToIterator(final Enumeration e) { return e == null ? null : new IterableIterator() { public boolean hasNext() { return e.hasMoreElements(); } public A next() { return e.nextElement(); } }; } static public List reversedList(Iterable l) { List x = cloneList(l); Collections.reverse(x); return x; } static public String reversedString(String s) { return reverseString(s); } static public long 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, (long) 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 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 urlencode(String x) { try { return URLEncoder.encode(unnull(x), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } 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 leftArrow(String script) { GazelleV_LeftArrowScriptParser parser = new GazelleV_LeftArrowScriptParser(); parser.allowTheWorld(); return parser.parse(script).get(); } 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 double abs(Complex c) { return c.abs(); } 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); } public static boolean isSnippetID(String s) { try { parseSnippetID(s); return true; } catch (RuntimeException e) { return false; } } static public File localSnippetFile(long snippetID) { return localSnippetsDir(snippetID + ".text"); } static public File localSnippetFile(String snippetID) { return localSnippetFile(parseSnippetID(snippetID)); } static public Object vm_generalMap_get(Object key) { return vm_generalMap().get(key); } 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 byte[] toUtf8(String s) { try { return s.getBytes(utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } 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 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 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 boolean networkAllowanceTest(String url) { return isAllowed("networkAllowanceTest", url); } 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 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 A getAndClearThreadLocal(ThreadLocal tl) { A a = tl.get(); tl.set(null); return a; } 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 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 Map vm_generalSubMap(Object name) { synchronized (vm_generalMap()) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = synchroMap()); return map; } } static public InputStream urlConnection_getInputStream(URLConnection con) throws IOException { return con.getInputStream(); } static public GZIPInputStream newGZIPInputStream(File f) { return gzInputStream(f); } static public GZIPInputStream newGZIPInputStream(InputStream in) { return gzInputStream(in); } static public String toHex(byte[] bytes) { return bytesToHex(bytes); } static public String toHex(byte[] bytes, int ofs, int len) { return bytesToHex(bytes, ofs, len); } static public byte[] utf8(String s) { return toUtf8(s); } static public Matcher regexpMatcher(String pat, String s) { return compileRegexp(pat).matcher(unnull(s)); } static public Matcher regexpMatcher(java.util.regex.Pattern pat, String s) { return pat.matcher(unnull(s)); } 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 URLConnection setURLConnectionTimeouts(URLConnection con, long timeout) { con.setConnectTimeout(toInt(timeout)); con.setReadTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout || con.getReadTimeout() != timeout) print("Warning: Timeouts not set by JDK."); return con; } static public URLConnection setURLConnectionDefaultTimeouts(URLConnection con, long timeout) { if (con.getConnectTimeout() == 0) { con.setConnectTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout) print("Warning: URL connect timeout not set by JDK."); } if (con.getReadTimeout() == 0) { con.setReadTimeout(toInt(timeout)); if (con.getReadTimeout() != timeout) print("Warning: URL read timeout not set by JDK."); } return con; } static public boolean isURL(String s) { return startsWithOneOf(s, "http://", "https://", "file:"); } static public boolean isImageServerSnippet(long id) { return id >= 1100000 && id < 1200000; } static public String imageServerLink(String md5OrID) { if (possibleMD5(md5OrID)) return "https://botcompany.de/images/md5/" + md5OrID; return imageServerLink(parseSnippetID(md5OrID)); } static public String imageServerLink(long id) { return "https://botcompany.de/images/" + id; } static public 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 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 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 ArrayList litlist(A... a) { ArrayList l = new ArrayList(a.length); for (A x : a) l.add(x); return l; } static public boolean isAbsoluteURL(String s) { return isURL(s); } static public boolean isRelativeURL(String s) { return startsWithOneOf(s, "/", "./", "../"); } static public Object callMainBot(String method, Object... args) { return call(mainBot(), method, args); } 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 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 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 Random defaultRandomGenerator() { { Random r = customRandomizerForThisThread(); if (r != null) return r; } return ThreadLocalRandom.current(); } static public boolean isCISet(Iterable l) { return l instanceof TreeSet && ((TreeSet) l).comparator() == caseInsensitiveComparator(); } static public SimpleDateFormat simpleDateFormat_timeZone(String format, String timeZone) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(timeZone(timeZone)); return sdf; } static public boolean containsNulls(Collection c) { return contains(c, 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 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 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 Map mruCache(int maxSize) { return synchronizedMRUCache(maxSize); } 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 B pairB(Pair p) { return p == null ? null : p.b; } 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 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 A vmBus_timerStarted(A timer) { vmBus_send("timerStarted", timer, costCenter()); return timer; } static public long toMS(double seconds) { return (long) (seconds * 1000); } static public MultiMap mapMultiMapKeys(IF1 f, MultiMap mm) { MultiMap m = similarEmptyMultiMap(mm); for (var key : keys(mm)) m.put(f.get(key), mm.get(key)); return m; } static public MultiMap mapMultiMapKeys(MultiMap mm, IF1 f) { return mapMultiMapKeys(f, mm); } static public MultiSetMap mapMultiSetMapKeys(IF1 f, MultiSetMap mm) { MultiSetMap m = similarEmptyMultiSetMap(mm); for (var key : keys(mm)) m.put(f.get(key), mm.get(key)); return m; } static public MultiSetMap mapMultiSetMapKeys(MultiSetMap mm, IF1 f) { return mapMultiSetMapKeys(f, mm); } static public TreeMap litCIMap(Object... x) { TreeMap map = caseInsensitiveMap(); litmap_impl(map, x); return map; } 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 HashMap> callMC_cache = new HashMap(); static public String callMC_key; static public Method callMC_value; static public Object callMC(String method, String[] arg) { return callMC(method, new Object[] { arg }); } static public Object callMC(String method, Object... args) { try { Method me; if (callMC_cache == null) callMC_cache = new HashMap(); synchronized (callMC_cache) { me = method == callMC_key ? callMC_value : null; } if (me != null) try { return invokeMethod(me, null, args); } catch (IllegalArgumentException e) { throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e); } List m; synchronized (callMC_cache) { m = callMC_cache.get(method); } if (m == null) { if (callMC_cache.isEmpty()) { callMC_makeCache(); m = callMC_cache.get(method); } if (m == null) throw fail("Method named " + method + " not found in main"); } int n = m.size(); if (n == 1) { me = m.get(0); synchronized (callMC_cache) { callMC_key = method; callMC_value = me; } try { return invokeMethod(me, null, args); } catch (IllegalArgumentException e) { throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e); } } for (int i = 0; i < n; i++) { me = m.get(i); if (call_checkArgs(me, args, false)) return invokeMethod(me, null, args); } throw fail("No method called " + method + " with arguments (" + joinWithComma(getClasses(args)) + ") found in main"); } catch (Exception __e) { throw rethrow(__e); } } static public void callMC_makeCache() { synchronized (callMC_cache) { callMC_cache.clear(); Class _c = (Class) mc(), c = _c; while (c != null) { for (Method m : c.getDeclaredMethods()) if ((m.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) { makeAccessible(m); multiMapPut(callMC_cache, m.getName(), m); } c = c.getSuperclass(); } } } static public Class javax() { return getJavaX(); } static public List synchroList() { return synchroList(new ArrayList()); } static public List synchroList(List l) { return new SynchronizedList(l); } static public Map synchroHashMap() { return synchronizedMap(new HashMap()); } 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 List _registerWeakMap_preList; static public A _registerWeakMap(A map) { if (javax() == null) { if (_registerWeakMap_preList == null) _registerWeakMap_preList = synchroList(); _registerWeakMap_preList.add(map); return map; } try { call(javax(), "_registerWeakMap", map); } catch (Throwable e) { printException(e); print("Upgrade JavaX!!"); } return map; } static public void _onLoad_registerWeakMap() { assertNotNull(javax()); if (_registerWeakMap_preList == null) return; for (Object o : _registerWeakMap_preList) _registerWeakMap(o); _registerWeakMap_preList = null; } 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_put(Object key, Object value) { return mapPutOrRemove(vm_generalMap(), key, value); } static public Map newWeakMap() { return newWeakHashMap(); } static public WeakReference newWeakReference(A a) { return a == null ? null : new WeakReference(a); } static public Map castMapToMapO(Map map) { return map; } static public char lastChar(String s) { return empty(s) ? '\0' : s.charAt(l(s) - 1); } static public Object _defaultClassFinder_value = defaultDefaultClassFinder(); static public Object _defaultClassFinder() { return _defaultClassFinder_value; } static public String programIDWithCase() { return nempty(caseID()) ? programID() + "/" + quoteUnlessIdentifierOrInteger(caseID()) : programID(); } static public void _registerIO(Object object, String path, boolean opened) { } 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 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 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 Object[] mapToObjectArray(IF1 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 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 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) { if (!contains(html, '<')) return html; return join(dropAllTags(htmlcoarsetok(html))); } static public boolean isLetter(char c) { return Character.isLetter(c); } 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", () -> { Runnable value = (Runnable) (callF_gen(vm_generalMap_get("newPing_valueForNewThread"))); var tl = new x30_pkg.x30_util.BetterThreadLocal(); tl.set(value); return tl; }); return newPing_actionTL; } 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 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 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 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 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 > C syncMapRemove_deleteMapIfEmpty(C map, A key) { if (map != null && key != null) synchronized (collectionMutex(map)) { map.remove(key); if (map.isEmpty()) return null; } return map; } static public boolean isInAnonymousClass(Object o) { if (o == null) return false; return isAnonymousClassName(className(o)); } 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 int boolToInt(boolean b) { return b ? 1 : 0; } static public Object callFunction(Object f, Object... args) { return callF(f, args); } static public Throwable _storeException_value; static public void _storeException(Throwable e) { _storeException_value = e; } static public Set syncIdentityHashSet() { return (Set) synchronizedSet(identityHashSet()); } static public Map syncHashMap() { return synchroHashMap(); } static public A[] arrayOfSameType(A[] a, int n) { return newObjectArrayOfSameType(a, n); } 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 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 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 PersistableThrowable persistableThrowable(Throwable e) { return e == null ? null : new PersistableThrowable(e); } static public boolean isAGIBlueDomain(String domain) { return domainIsUnder(domain, theAGIBlueDomain()); } static public Object pcallFunction(Object f, Object... args) { try { return callFunction(f, args); } catch (Throwable __e) { printStackTrace(__e); } return null; } 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, int destPos, int n) { arraycopy(src, srcPos, src, destPos, n); } 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 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 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 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 File standardLogFile() { return getProgramFile("log"); } 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 prepareProgramFile(String name) { return mkdirsForFile(getProgramFile(name)); } static public File prepareProgramFile(String progID, String name) { return mkdirsForFile(getProgramFile(progID, name)); } 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 List nlTok(String s) { return javaTokPlusPeriod(s); } static public A getWeakRef(Reference ref) { return ref == null ? null : ref.get(); } static public x30_pkg.x30_util.BetterThreadLocal dm_current_generic_tl; static public x30_pkg.x30_util.BetterThreadLocal dm_current_generic_tl() { if (dm_current_generic_tl == null) dm_current_generic_tl = vm_generalMap_getOrCreate("currentModule", () -> new x30_pkg.x30_util.BetterThreadLocal()); return dm_current_generic_tl; } static public List> _threadInfo_makers = synchroList(); static public Object _threadInfo() { if (empty(_threadInfo_makers)) return null; HashMap map = new HashMap(); pcallFAll(_threadInfo_makers, map); return map; } static public List> _threadInheritInfo_retrievers = synchroList(); static public void _threadInheritInfo(Object info) { if (info == null) return; pcallFAll(_threadInheritInfo_retrievers, (Map) info); } static public Runnable rPcall(Runnable r) { return r == null ? null : () -> { try { r.run(); } catch (Throwable __e) { printStackTrace(__e); } }; } 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 Map compileRegexpIC_cache = syncMRUCache(10); static public java.util.regex.Pattern compileRegexpIC(String pat) { java.util.regex.Pattern p = compileRegexpIC_cache.get(pat); if (p == null) { try { compileRegexpIC_cache.put(pat, p = java.util.regex.Pattern.compile(pat, Pattern.CASE_INSENSITIVE)); } catch (PatternSyntaxException e) { throw rethrow(wrapPatternSyntaxException(e)); } } return p; } static public boolean startsWithLetterOrDigit(String s) { return nempty(s) && Character.isLetterOrDigit(s.charAt(0)); } static public String regexpQuote(String s) { return s.length() == 0 ? "" : Pattern.quote(s); } static public 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 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 A revalidate(final A c) { if (c == null || !c.isShowing()) return c; { swing(() -> { c.revalidate(); c.repaint(); }); } return c; } static public void revalidate(JFrame f) { revalidate((Component) f); } static public void revalidate(JInternalFrame f) { revalidate((Component) f); } 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 List javaTokForStructure(String s) { return javaTok_noMLS(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 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 A assertEquals(Object x, A y) { return assertEquals("", x, y); } static public A assertEquals(String msg, Object x, A y) { if (assertVerbose()) return assertEqualsVerbose(msg, x, y); if (!(x == null ? y == null : x.equals(y))) throw fail((msg != null ? msg + ": " : "") + y + " != " + x); return y; } static public 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 A popLast(List l) { return liftLast(l); } static public List popLast(int n, List l) { return liftLast(n, l); } static public String actualMCDollar() { return actualMC().getName() + "$"; } static public boolean startsWithDigit(String s) { return nempty(s) && isDigit(s.charAt(0)); } static public boolean isSyntheticOrAnonymous(Class c) { return c != null && (c.isSynthetic() || isAnonymousClassName(c.getName())); } 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 String shortDynClassNameForStructure(Object o) { if (o instanceof DynamicObject && ((DynamicObject) o).className != null) return ((DynamicObject) o).className; if (o == null) return null; Class c = o instanceof Class ? (Class) o : o.getClass(); String name = c.getName(); return name.startsWith("dyn.") ? classNameToVM(name) : shortenClassName(name); } static public boolean isPersistableClass(Class c) { String name = c.getName(); if (isSubtypeOf(c, TransientObject.class)) return false; if (isAnonymousClassName(name)) return false; if (isBoxedType(c)) return true; if (isArrayType(c)) return true; if (c == Class.class || c == String.class || c == File.class || c == Color.class) return true; if (name.startsWith("java.util.Collections$Synchronized")) return true; if (hasThisDollarFields(c)) return hasSingleArgumentConstructor(c); else return getDefaultConstructor(c) != null; } static public Constructor getDefaultConstructor(Class c) { if (c != null) for (Constructor m : getDeclaredConstructors_cached(c)) if (empty(m.getParameterTypes())) return m; return null; } static public Object invokeConstructor(Constructor m, Object... args) { try { makeAccessible(m); return m.newInstance(args); } catch (Exception __e) { throw rethrow(__e); } } static public int countDots(String s) { int n = l(s), count = 0; for (int i = 0; i < n; i++) if (s.charAt(i) == '.') ++count; return count; } static public void quoteToPrintWriter(String s, PrintWriter out) { if (s == null) { out.print("null"); return; } out.print('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') { out.print('\\'); out.print(c); } else if (c == '\r') out.print("\\r"); else if (c == '\n') out.print("\\n"); else if (c == '\0') out.print("\\0"); else out.print(c); } out.print('"'); } static public String quoteCharacter(char c) { if (c == '\'') return "'\\''"; if (c == '\\') return "'\\\\'"; if (c == '\r') return "'\\r'"; if (c == '\n') return "'\\n'"; if (c == '\t') return "'\\t'"; return "'" + c + "'"; } static public boolean isCISet_gen(Iterable l) { return l instanceof TreeSet && className(((TreeSet) l).comparator()).contains("CIComp"); } static public boolean isJavaXClassName(String s) { return startsWithOneOf(s, "main$", "loadableUtils."); } static public List unwrapSynchronizedList(List l) { if (l instanceof SynchronizedList) return ((SynchronizedList) l).list; if (eqOneOf(className(l), "java.util.Collections$SynchronizedList", "java.util.Collections$SynchronizedRandomAccessList")) return (List) get_raw(l, "list"); return l; } static public boolean isCIMap_gen(Map map) { return map instanceof TreeMap && className(((TreeMap) map).comparator()).contains("CIComp"); } static public Map unwrapSynchronizedMap(Map map) { if (eqOneOf(shortClassName(map), "SynchronizedMap", "SynchronizedSortedMap", "SynchronizedNavigableMap")) return (Map) get_raw(map, "m"); return map; } static public String boolArrayToHex(boolean[] a) { return bytesToHex(boolArrayToBytes(a)); } static public Pair arrayTypeAndDimensions(Object o) { return arrayTypeAndDimensions(_getClass(o)); } static public Pair arrayTypeAndDimensions(Class c) { if (c == null || !c.isArray()) return null; Class elem = c.getComponentType(); if (elem.isArray()) return mapPairB(arrayTypeAndDimensions(elem), dim -> dim + 1); return pair(elem, 1); } static public Map getDeclaredFields_cache = newDangerousWeakHashMap(); static public Field[] getDeclaredFields_cached(Class c) { Field[] fields; synchronized (getDeclaredFields_cache) { fields = getDeclaredFields_cache.get(c); if (fields == null) { getDeclaredFields_cache.put(c, fields = c.getDeclaredFields()); for (Field f : fields) makeAccessible(f); } } return fields; } static public Method findInstanceMethod(Class c, String method, Object... args) { while (c != null) { for (Method m : c.getDeclaredMethods()) if (m.getName().equals(method) && findMethod_checkArgs(m, args, false)) return m; c = c.getSuperclass(); } return null; } static public Set fieldObjectsInFieldOrder(Class c, Set fields) { try { var byName = mapToKey(f -> f.getName(), fields); LinkedHashSet out = new LinkedHashSet(); for (String name : unnullForIteration(getFieldOrder(c))) { Field f = byName.get(name); if (f != null) { byName.remove(name); out.add(f); } } addAll(out, fields); return out; } catch (Throwable __0) { printStackTrace(__0); return fields; } } static public Comparator caseInsensitiveComparator() { return betterCIComparator(); } 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 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 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) { printStackTrace(__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) { File dir = programDir(progID); thinAProgramsBackups(dir, doIt); } static public void thinAProgramsBackups(File dir, 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*)$"); print("Processing backups in " + dir); 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 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 IMeta initIMeta(Object o) { if (o == null) return null; if (o instanceof IMeta) return ((IMeta) o); if (o instanceof JComponent) return initMetaOfJComponent((JComponent) o); if (o instanceof BufferedImage) return optCast(IMeta.class, ((BufferedImage) o).getProperty("meta")); return null; } static public String actualProgramID() { return programID(); } 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 f2s(File f) { return f == null ? null : f.getAbsolutePath(); } static public String f2s(String s) { return f2s(newFile(s)); } static public String f2s(java.nio.file.Path p) { return p == null ? null : f2s(p.toFile()); } static public void copyStream(InputStream in, OutputStream out) { try { byte[] buf = new byte[65536]; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); } } catch (Exception __e) { throw rethrow(__e); } } static public String reverseString(String s) { return empty(s) ? s : new StringBuilder(s).reverse().toString(); } static public String stringOptPar(Object[] params, String name) { return (String) optPar(params, name); } static public String charToString(char c) { return String.valueOf(c); } static public String charToString(int c) { return String.valueOf((char) c); } 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 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 File localSnippetsDir() { return javaxDataDir("Personal Programs"); } static public File localSnippetsDir(String sub) { return newFile(localSnippetsDir(), sub); } 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 File getProgramDir() { return programDir(); } static public File getProgramDir(String snippetID) { return programDir(snippetID); } 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 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 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 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 String hmsWithColons() { return hmsWithColons(now()); } static public String hmsWithColons(long time) { return new SimpleDateFormat("HH:mm:ss").format(time); } 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 String getComputerID_quick() { return computerID(); } 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 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 boolean possibleMD5(String s) { return isMD5(s); } 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 List htmlTok(String s) { return htmlcoarsetok(s); } static public List replaceSublist(List l, List x, List y) { if (x == null) return l; int i = 0; while (true) { i = indexOfSubList(l, x, i); if (i < 0) break; replaceSublist(l, i, i + l(x), y); i += l(y); } return l; } static public List replaceSublist(List l, int fromIndex, int toIndex, List y) { int n = y.size(), toIndex_new = fromIndex + n; if (toIndex_new < toIndex) { removeSubList(l, toIndex_new, toIndex); copyListPart(y, 0, l, fromIndex, n); } else { copyListPart(y, 0, l, fromIndex, toIndex - fromIndex); if (toIndex_new > toIndex) l.addAll(toIndex, subList(y, toIndex - fromIndex)); } return l; } static public List replaceSublist(List l, IntRange r, List y) { return replaceSublist(l, r.start, r.end, y); } static public String 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 BufferedImage loadImage2(String snippetIDOrURL) { return loadBufferedImage(snippetIDOrURL); } static public BufferedImage loadImage2(File file) { return loadBufferedImage(file); } 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"; } static public CloseableIterableIterator emptyCloseableIterableIterator_instance = new CloseableIterableIterator() { public Object next() { throw fail(); } public boolean hasNext() { return false; } }; static public CloseableIterableIterator emptyCloseableIterableIterator() { return emptyCloseableIterableIterator_instance; } static public CloseableIterableIterator linesFromReader(Reader r) { 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 "return 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 Random customRandomizerForThisThread() { return customRandomizerForThisThread_tl().get(); } static public Object[] changeParam(Object[] params, String name, Object value) { if (eq(optPar(params, name), value)) return params; Map map = paramsToOrderedMap(params); map.put(name, value); return mapToParams(map); } static public Object 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 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 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 File loadLibrary(String snippetID) { return loadBinarySnippet(snippetID); } 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 Object costCenter() { return mc(); } static public MultiSetMap similarEmptyMultiSetMap(MultiSetMap m) { return similarEmptyMultiSetMap(m == null ? null : m.data); } static public MultiSetMap similarEmptyMultiSetMap(Map m) { MultiSetMap mm = new MultiSetMap(); if (m != null) mm.data = similarEmptyMap(m); return mm; } static public TreeMap caseInsensitiveMap() { return new TreeMap(caseInsensitiveComparator()); } 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 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 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 Class __javax; static public Class getJavaX() { try { return __javax; } catch (Exception __e) { throw rethrow(__e); } } static public void __setJavaX(Class j) { __javax = j; _onJavaXSet(); } static public Map synchronizedMap() { return synchroMap(); } static public Map synchronizedMap(Map map) { return synchroMap(map); } static public A printException(A e) { printStackTrace(e); return e; } 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 Object defaultDefaultClassFinder() { return new F1() { public Class get(String name) { name = replacePrefix("main$main$", "main$", 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 volatile public String caseID_caseID; static public String caseID() { return caseID_caseID; } static public void caseID(String id) { caseID_caseID = id; } static public String quoteUnlessIdentifierOrInteger(String s) { return quoteIfNotIdentifierOrInteger(s); } static 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 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 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 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 A callF_gen(F0 f) { return f == null ? null : f.get(); } static public B callF_gen(F1 f, A a) { return f == null ? null : f.get(a); } static public A callF_gen(IF0 f) { return f == null ? null : f.get(); } static public B callF_gen(IF1 f, A a) { return f == null ? null : f.get(a); } static public B callF_gen(A a, IF1 f) { return f == null ? null : f.get(a); } static public C callF_gen(IF2 f, A a, B b) { return f == null ? null : f.get(a, b); } static public void callF_gen(VF1 f, A a) { { if (f != null) f.get(a); } } static public void callF_gen(A a, IVF1 f) { { if (f != null) f.get(a); } } static public void callF_gen(IVF1 f, A a) { { if (f != null) f.get(a); } } static public Object callF_gen(Runnable r) { { if (r != null) r.run(); } return null; } static public Object callF_gen(Object f, Object... args) { return callF(f, args); } 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 Set getPlural_specials = litciset("sheep", "fish"); static public String getPlural(String s) { if (contains(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 void upgradeJavaXAndRestart() { run("#1001639"); restart(); sleep(); } static public boolean isIdentifier(String s) { return isJavaIdentifier(s); } static public boolean isAnonymousClassName(String s) { for (int i = 0; i < l(s); i++) if (s.charAt(i) == '$' && Character.isDigit(s.charAt(i + 1))) return true; return false; } 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 synchronizedSet() { return synchroHashSet(); } static public Set synchronizedSet(Set set) { return new SynchronizedSet(set); } static public Set identityHashSet() { return Collections.newSetFromMap(new IdentityHashMap()); } 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 domainIsUnder(String domain, String mainDomain) { return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain); } static public String theAGIBlueDomain() { return "agi.blue"; } 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 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 void pcallFAll(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) pcallF(f, args); } static public void pcallFAll(Iterator it, Object... args) { while (it.hasNext()) pcallF(it.next(), args); } static public 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 Number boxedIntOrLong(long l) { return l != (int) l ? boxed(l) : boxed((int) l); } 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 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 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 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 int indexOfSubList(List x, List y) { return indexOfSubList(x, y, 0); } static public int indexOfSubList(List x, List y, int i) { outer: for (; i + l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i + j), y.get(j))) continue outer; return i; } return -1; } static public int indexOfSubList(List x, A[] y, int i) { outer: for (; i + l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i + j), y[j])) continue outer; return i; } return -1; } static public String trimJoin(List s) { return trim(join(s)); } static public 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 Map javaTokForJFind_array_cache = synchronizedMRUCache(1000); static public String[] javaTokForJFind_array(String s) { String[] tok = javaTokForJFind_array_cache.get(s); if (tok == null) javaTokForJFind_array_cache.put(s, tok = codeTokensAsStringArray(jfind_preprocess(javaTok(s)))); return tok; } static public int findCodeTokens(List tok, String... tokens) { return findCodeTokens(tok, 1, false, tokens); } static public int findCodeTokens(List tok, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, 1, ignoreCase, tokens); } static public int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, startIdx, ignoreCase, tokens, null); } static public HashSet findCodeTokens_specials = lithashset("*", "", "", "", "\\*"); static public int findCodeTokens_bails, findCodeTokens_nonbails; static public interface findCodeTokens_Matcher { public boolean get(String token); } static public int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String[] tokens, Object condition) { int end = tok.size() - tokens.length * 2 + 2, nTokens = tokens.length; int i = startIdx | 1; 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 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 ThreadLocal assertVerbose_value = new ThreadLocal(); static public void assertVerbose(boolean b) { assertVerbose_value.set(b); } static public boolean assertVerbose() { return isTrue(assertVerbose_value.get()); } static public 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 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 Class actualMC() { return or((Class) realMC(), mc()); } 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 boolean isBoxedType(Class type) { return type == Boolean.class || type == Integer.class || type == Long.class || type == Float.class || type == Short.class || type == Character.class || type == Byte.class || type == Double.class; } static public boolean isArrayType(Class type) { return type != null && type.isArray(); } static public boolean hasThisDollarFields(Object o) { Matches m = new Matches(); for (var f : allFieldObjects_dontMakeAccessible(o)) if (startsWith(f.getName(), "this$", m) && isInteger(m.rest())) return true; return false; } static public boolean hasSingleArgumentConstructor(Class c) { if (c != null) for (Constructor m : getDeclaredConstructors_cached(c)) if (l(m.getParameterTypes()) == 1) return true; return false; } 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 byte[] boolArrayToBytes(boolean[] a) { byte[] b = new byte[(l(a) + 7) / 8]; for (int i = 0; i < l(a); i++) if (a[i]) b[i / 8] |= 1 << (i & 7); return b; } static public List> mapPairB(final Object f, Iterable> l) { return map(l, new F1, Pair>() { public Pair get(Pair p) { try { return p == null ? null : pair(p.a, (C) callF(f, p.b)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "p == null ? null : pair(p.a, (C) callF(f, p.b))"; } }); } static public List> mapPairB(final F1 f, Iterable> l) { return mapPairB((Object) f, l); } static public List> mapPairB(final IF1 f, Iterable> l) { return mapPairB((Object) f, l); } static public List> mapPairB(Iterable> l, IF1 f) { return mapPairB((Object) f, l); } static public Pair mapPairB(IF1 f, Pair p) { return pairMapB(f, p); } static public Pair mapPairB(Pair p, IF1 f) { return pairMapB(f, p); } 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 Map mapToKey(Iterable l, IF1 f) { return mapToKeys(l, f); } static public Map mapToKey(IF1 f, Iterable l) { return mapToKeys(f, l); } static public Map> getFieldOrder_cache = weakMap(); static public List getFieldOrder(Object o) { return getFieldOrder(_getClass(o)); } static public List getFieldOrder(Class c) { if (c == null) return null; return getOrCreate(getFieldOrder_cache, c, () -> splitAtSpace(toStringOpt(getOpt(c, "_fieldOrder")))); } 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 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 boolean hasBot(String searchPattern) { try { DialogIO io = findBot(searchPattern); if (io != null) { io.close(); return true; } else return false; } catch (Exception __e) { throw rethrow(__e); } } 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 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 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 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 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(__62 -> isLetterOrDigit(__62), s); else return "" + first(s); } static public IMeta initMetaOfJComponent(JComponent c) { if (c == null) return null; IMeta meta = (IMeta) (c.getClientProperty(IMeta.class)); if (meta == null) c.putClientProperty(IMeta.class, meta = new Meta()); return meta; } static public A optCast(Class c, Object o) { return isInstance(c, o) ? (A) o : null; } static public Throwable getException(Runnable r) { try { callF(r); return null; } catch (Throwable e) { return e; } } 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 A _registerIOWrap(A wrapper, Object wrapped) { return wrapper; } static public boolean isMD5(String s) { return l(s) == 32 && isLowerHexString(s); } static public void removeSubList(List l, int from, int to) { if (l != null) subList(l, from, to).clear(); } static public void removeSubList(List l, int from) { if (l != null) subList(l, from).clear(); } static public void copyListPart(List a, int i1, List b, int i2, int n) { if (a == null || b == null) return; for (int i = 0; i < n; i++) b.set(i2 + i, a.get(i1 + i)); } static public 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 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 (isSnippetID(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; } else return loadBufferedImage(new File(snippetIDOrURLOrFile)); } catch (Exception __e) { throw rethrow(__e); } } static public BufferedImage loadBufferedImage(File file) { return loadBufferedImageFile(file); } static public File muricaPasswordFile() { return new File(javaxSecretDir(), "murica/muricaPasswordFile"); } 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 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 ThreadLocal customRandomizerForThisThread_tl = new ThreadLocal(); static public ThreadLocal customRandomizerForThisThread_tl() { return customRandomizerForThisThread_tl; } 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 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 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 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 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 void _onJavaXSet() { } static public String replacePrefix(String prefix, String replacement, String s) { if (!startsWith(s, prefix)) return s; return replacement + substring(s, l(prefix)); } static public Object get2(Object o, String field1, String field2) { return get(get(o, field1), field2); } 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 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 public String quoteIfNotIdentifierOrInteger(String s) { if (s == null) return null; return isJavaIdentifier(s) || isInteger(s) ? s : quote(s); } static public IF0 f0ToIF0(F0 f) { return f == null ? null : () -> f.get(); } 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 Class run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static public void restart() { Object j = getJavaX(); call(j, "cleanRestart", get(j, "fullArgs")); } static public Set synchroHashSet() { return synchronizedSet(new HashSet()); } 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() { AutoCloseable result = null; result = tempSetTL(ping_isCleanUpThread, true); return result; } static public void closeAllWriters(Collection l) { for (Writer w : unnull(l)) { try { w.close(); } catch (Throwable __e) { printStackTrace(__e); } } } static public Integer boxed(int i) { return i; } static public Long boxed(long l) { return l; } static public String multiLineQuoteWithSpaces(String s) { return multiLineQuote(" " + s + " "); } 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 List javaTokPlusBrackets2(String s) { return tok_combineRoundCurlySquareBrackets_keep(javaTok(s)); } 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 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, (ITokCondition) 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, IIntPred condition) { return jfind(tok, 1, in, condition); } static public int jfind(List tok, int startIndex, String in, IIntPred condition) { return jfind(tok, startIndex, in, tokCondition(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 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 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 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 boolean isEmpty(AppendableChain c) { return c == null; } static public Object realMC() { return getThreadLocal(realMC_tl()); } 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 List allFieldObjects_dontMakeAccessible(Object o) { List fields = new ArrayList(); Class _c = _getClass(o); do { addAll(fields, _c.getDeclaredFields()); _c = _c.getSuperclass(); } while (_c != null); return fields; } static public Pair pairMapB(Object f, Pair p) { return p == null ? null : pair(p.a, callF(f, p.b)); } static public Pair pairMapB(IF1 f, Pair p) { return p == null ? null : pair(p.a, f.get(p.b)); } static public Pair pairMapB(Pair p, Object f) { return pairMap(f, p); } 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 Map mapToKeys(Iterable l, IF1 f) { if (l == null) return null; HashMap map = new HashMap(); for (A a : l) map.put(f.get(a), a); return map; } static public Map mapToKeys(IF1 f, A[] l) { return mapToKeys(f, asList(l)); } static public Map mapToKeys(IF1 f, Iterable l) { return mapToKeys(l, f); } static public Map weakMap() { return newWeakHashMap(); } static public List splitAtSpace(String s) { return empty(s) ? emptyList() : asList(s.split("\\s+")); } static public String toStringOpt(Object o) { return o instanceof String ? ((String) o) : null; } static public Runnable asRunnable(Object o) { return toRunnable(o); } static public void _inheritThreadInfo(Object info) { _threadInheritInfo(info); } static public Map findBot_cache = synchroHashMap(); static public int findBot_timeout = 5000; static public DialogIO findBot(String searchPattern) { String subBot = null; int i = searchPattern.indexOf('/'); if (i >= 0 && (isJavaIdentifier(searchPattern.substring(0, i)) || isInteger(searchPattern.substring(0, i)))) { subBot = searchPattern.substring(i + 1); searchPattern = searchPattern.substring(0, i); if (!isInteger(searchPattern)) searchPattern = "Multi-Port at " + searchPattern + "."; } if (isInteger(searchPattern)) return talkToSubBot(subBot, talkTo(parseInt(searchPattern))); if (eq(searchPattern, "remote")) return talkToSubBot(subBot, talkTo("second.tinybrain.de", 4999)); Integer port = findBot_cache.get(searchPattern); if (port != null) try { DialogIO io = talkTo("localhost", port); io.waitForLine(); String line = io.readLineNoBlock(); if (indexOfIgnoreCase(line, searchPattern) == 0) { call(io, "pushback", line); return talkToSubBot(subBot, io); } } catch (Exception e) { e.printStackTrace(); } List bots = quickBotScan(); for (ProgramScan.Program p : bots) { if (indexOfIgnoreCase(p.helloString, searchPattern) == 0) { findBot_cache.put(searchPattern, p.port); return talkToSubBot(subBot, talkTo("localhost", p.port)); } } for (ProgramScan.Program p : bots) { String botName = firstPartOfHelloString(p.helloString); boolean isVM = startsWithIgnoreCase(p.helloString, "This is a JavaX VM."); boolean shouldRecurse = startsWithIgnoreCase(botName, "Multi-Port") || isVM; if (shouldRecurse) try { Map subBots = (Map) unstructure(sendToLocalBotQuietly(p.port, "list bots")); for (Number vport : subBots.keySet()) { String name = subBots.get(vport); if (startsWithIgnoreCase(name, searchPattern)) return talkToSubBot(vport.longValue(), talkTo("localhost", p.port)); } } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } return null; } static public boolean swic(String a, String b) { return startsWithIgnoreCase(a, b); } static public boolean swic(String a, String b, Matches m) { if (!swic(a, b)) return false; m.m = new String[] { substring(a, l(b)) }; return true; } static public String sendToLocalBotOpt(String bot, String text, Object... args) { if (bot == null) return null; text = format(text, args); DialogIO channel = findBot(bot); try { if (channel == null) { print(quote(bot) + " not found, skipping send: " + quote(text)); return null; } try { channel.readLine(); print(shorten(bot + "> " + text, 200)); channel.sendLine(text); String s = channel.readLine(); print(shorten(bot + "< " + s, 200)); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } 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 boolean sameSnippetID(String a, String b) { if (!isSnippetID(a) || !isSnippetID(b)) return false; return parseSnippetID(a) == parseSnippetID(b); } static public List listFilesOnly(String dir) { return listFilesOnly(new File(dir)); } static public List listFilesOnly(File... dirs) { return concatMap(dir -> listFilesWithSuffix("", dir), 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 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 boolean isLetterOrDigit(char c) { return Character.isLetterOrDigit(c); } 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 File computerIDFile() { return javaxDataDir("Basic Info/computer-id.txt"); } 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 BufferedImage imageIO_readURL(String url) { try { return ImageIO.read(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } 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 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 File DiskSnippetCache_getLibrary(String snippetID) { try { return DiskSnippetCache_getLibrary(psI(snippetID)); } catch (Exception __e) { throw rethrow(__e); } } public static void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException { saveBinaryFile(DiskSnippetCache_file(snippetID), data); } static public byte[] loadDataSnippetImpl(String snippetID) throws IOException { byte[] data; try { URL url = new URL(dataSnippetLink(snippetID)); print("Loading library: " + hideCredentials(url)); try { data = loadBinaryPage(url.openConnection()); } catch (RuntimeException e) { data = null; } if (data == null || data.length == 0) { url = new URL(tb_mainServer() + "/blobs/" + parseSnippetID(snippetID)); print("Loading library: " + hideCredentials(url)); data = loadBinaryPage(url.openConnection()); } print("Bytes loaded: " + data.length); } catch (FileNotFoundException e) { throw new IOException("Binary snippet #" + snippetID + " not found or not public"); } return data; } static public long fileSize(String path) { return getFileSize(path); } static public long fileSize(File f) { return getFileSize(f); } static public File loadDataSnippetToFile(String snippetID) { try { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadDataSnippetToFile_noResourceLoader(snippetID); } catch (Exception __e) { throw rethrow(__e); } } static public File loadDataSnippetToFile_noResourceLoader(String snippetID) { try { snippetID = fsI(snippetID); File f = DiskSnippetCache_file(parseSnippetID(snippetID)); List urlsTried = new ArrayList(); List errors = new ArrayList(); try { URL url = addAndReturn(urlsTried, new URL(dataSnippetLink(snippetID))); print("Loading library: " + hideCredentials(url)); try { loadBinaryPageToFile(openConnection(url), f); if (fileSize(f) == 0) throw fail(); } catch (Throwable e) { errors.add(e); url = addAndReturn(urlsTried, new URL(tb_mainServer() + "/blobs/" + psI(snippetID))); print(e); print("Trying other server: " + hideCredentials(url)); loadBinaryPageToFile(openConnection(url), f); print("Got bytes: " + fileSize(f)); } if (fileSize(f) == 0) throw fail(); System.err.println("Bytes loaded: " + fileSize(f)); } catch (Throwable e) { errors.add(e); throw fail("Binary snippet " + snippetID + " not found or not public. URLs tried: " + allToString(urlsTried) + ", errors: " + allToString(errors)); } return f; } catch (Exception __e) { throw rethrow(__e); } } static public Object callJavaX(String method, Object... args) { return callOpt(getJavaX(), method, args); } static public String mcName() { return mc().getName(); } 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 String multiLineQuote(String s) { for (int i = 0; ; i++) { String closer = "]" + rep('=', i) + "]"; if (!contains(s, closer)) return "[" + rep('=', i) + "[" + s + closer; } } 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 ITokCondition tokCondition(IIntPred condition) { return condition == null ? null : (tok, nIdx) -> condition.get(nIdx); } static public ThreadLocal realMC_tl_tl = new ThreadLocal(); static public ThreadLocal realMC_tl() { return realMC_tl_tl; } static public Pair pairMap(Object f, Pair p) { return p == null ? null : pair(callF(f, p.a), callF(f, p.b)); } static public Pair pairMap(IF1 f, Pair p) { return p == null ? null : pair(callF(f, p.a), callF(f, p.b)); } static public Pair pairMap(Pair p, Object f) { return pairMap(f, p); } static public DialogIO talkToSubBot(final long vport, final DialogIO io) { return talkToSubBot(String.valueOf(vport), io); } static public DialogIO talkToSubBot(final String subBot, final DialogIO io) { if (subBot == null) return io; return new talkToSubBot_IO(subBot, io); } static public class talkToSubBot_IO extends DialogIO { public String subBot; public DialogIO io; public talkToSubBot_IO(String subBot, DialogIO io) { this.io = io; this.subBot = subBot; } public boolean isStillConnected() { return io.isStillConnected(); } public String readLineImpl() { return io.readLineImpl(); } public boolean isLocalConnection() { return io.isLocalConnection(); } public Socket getSocket() { return io.getSocket(); } public void close() { try { io.close(); } catch (Exception __e) { throw rethrow(__e); } } public void sendLine(String line) { io.sendLine(format3("please forward to bot *: *", subBot, line)); } } static public DialogIO talkTo(int port) { return talkTo("localhost", port); } static public int talkTo_defaultTimeout = 10000; static public int talkTo_timeoutForReads = 0; static public ThreadLocal> talkTo_byThread = new ThreadLocal(); static public DialogIO talkTo(String ip, int port) { try { String full = ip + ":" + port; Map map = talkTo_byThread.get(); if (map != null && map.containsKey(full)) return map.get(full); if (isLocalhost(ip) && port == vmPort()) return talkToThisVM(); return new talkTo_IO(ip, port); } catch (Exception __e) { throw rethrow(__e); } } static public class talkTo_IO extends DialogIO { public String ip; public int port; public Socket s; public Writer w; public BufferedReader in; public talkTo_IO(String ip, int port) { this.port = port; this.ip = ip; try { s = new Socket(); try { if (talkTo_timeoutForReads != 0) s.setSoTimeout(talkTo_timeoutForReads); s.connect(new InetSocketAddress(ip, port), talkTo_defaultTimeout); } catch (Throwable e) { throw fail("Tried talking to " + ip + ":" + port, e); } w = new OutputStreamWriter(s.getOutputStream(), "UTF-8"); in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8")); } catch (Exception __e) { throw rethrow(__e); } } public boolean isLocalConnection() { return s.getInetAddress().isLoopbackAddress(); } public boolean isStillConnected() { return !(eos || s.isClosed()); } public void sendLine(String line) { try { Lock __0 = lock; lock(__0); try { w.write(line + "\n"); w.flush(); } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } public String readLineImpl() { try { return in.readLine(); } catch (Exception __e) { throw rethrow(__e); } } public void close() { try { if (!noClose) s.close(); } catch (IOException e) { } } public Socket getSocket() { return s; } } static public List quickBotScan() { return ProgramScan.quickBotScan(); } static public List quickBotScan(int[] preferredPorts) { return ProgramScan.quickBotScan(preferredPorts); } static public List quickBotScan(String searchPattern) { List l = new ArrayList(); for (ProgramScan.Program p : ProgramScan.quickBotScan()) if (indexOfIgnoreCase(p.helloString, searchPattern) == 0) l.add(p); return l; } static public String firstPartOfHelloString(String s) { int i = s.lastIndexOf('/'); return i < 0 ? s : rtrim(s.substring(0, i)); } static public boolean startsWithIgnoreCase(String a, String b) { return regionMatchesIC(a, 0, b, 0, b.length()); } 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); } public interface unstructure_Handler { public void parse(int refID, int tokIndex, unstructure_Receiver out); } 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 List stack = new ArrayList(); public Map baseClassMap = new HashMap(); public HashMap innerClassConstructors = new HashMap(); public String curT; public char[] unquoteBuf = new char[unstructure_unquoteBufSize]; final public HashMap handlers = new HashMap(); public X() { try { Class mc = (Class) (callF(_classFinder, "
")); if (mc != null) mcDollar = mc.getName() + "$"; } catch (Throwable __e) { printStackTrace(__e); } makeHandlers(); } public void makeHandlers() { unstructure_Handler h; handlers.put("bigint", (unstructure_Handler) (refID, tokIndex, out) -> out.set(parseBigInt())); handlers.put("d", (unstructure_Handler) (refID, tokIndex, out) -> out.set(parseDouble())); handlers.put("fl", (unstructure_Handler) (refID, tokIndex, out) -> out.set(parseFloat())); handlers.put("sh", (unstructure_Handler) (refID, tokIndex, out) -> { consume(); String t = tpp(); if (t.equals("-")) { t = tpp(); out.set((short) (-parseInt(t))); return; } out.set((short) parseInt(t)); }); handlers.put("enum", (unstructure_Handler) (refID, tokIndex, out) -> { consume(); String t = tpp(); assertTrue(isJavaIdentifier(t)); String fullClassName = mcDollar + t; Class _c = findAClass(fullClassName); if (_c == null) throw fail("Enum class not found: " + fullClassName); int ordinal = parseInt(tpp()); out.set(_c.getEnumConstants()[ordinal]); }); handlers.put("false", h = (unstructure_Handler) (refID, tokIndex, out) -> { consume(); out.set(false); }); handlers.put("f", h); handlers.put("true", h = (unstructure_Handler) (refID, tokIndex, out) -> { consume(); out.set(true); }); handlers.put("t", h); handlers.put("{", (unstructure_Handler) (refID, tokIndex, out) -> parseMap(out)); handlers.put("[", (unstructure_Handler) (refID, tokIndex, out) -> { ArrayList l = new ArrayList(); if (refID >= 0) refs.put(refID, l); this.parseList(l, out); }); handlers.put("bitset", (unstructure_Handler) (refID, tokIndex, out) -> parseBitSet(out)); handlers.put("array", h = (unstructure_Handler) (refID, tokIndex, out) -> parseArray(out)); handlers.put("intarray", h); handlers.put("dblarray", h); } 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(); Object handler = handlers.get(t); if (handler instanceof unstructure_Handler) { ((unstructure_Handler) handler).parse(refID, tokIndex, out); return; } Class c = (Class) handler; 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("-")) { 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("-")) { 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("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); handlers.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); handlers.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; try { 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; } } catch (Throwable __e) { printStackTrace(__e); } if (o == null && dO == null) dO = new DynamicObject(); 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 String sendToLocalBotQuietly(String bot, String text, Object... args) { text = format3(text, args); DialogIO channel = newFindBot2(bot); try { if (channel == null) throw fail(quote(bot) + " not found"); try { channel.readLine(); channel.sendLine(text); String s = channel.readLine(); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static public String sendToLocalBotQuietly(int port, String text, Object... args) { text = format3(text, args); DialogIO channel = talkTo(port); try { try { channel.readLine(); channel.sendLine(text); String s = channel.readLine(); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static public String format(String pat, Object... args) { return format3(pat, args); } static public void assertNotOnAWTThread() { assertFalse("Can't do this in AWT thread", isAWTThread()); } static public Object[] asObjectArray(Collection l) { return toObjectArray(l); } 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) { printStackTrace(__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 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 > List concatMap(IF1 f, A[] l) { return concatMap((Object) f, 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 List listFilesWithSuffix(String suffix, File dir) { return listFilesWithSuffix(dir, suffix); } 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 boolean isFile(File f) { return f != null && f.isFile(); } static public boolean isFile(String path) { return isFile(newFile(path)); } 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 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 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 int findEndOfBracketPart2(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eqOneOf(cnc.get(j), "{", "(", "[")) ++level; else if (eqOneOf(cnc.get(j), "}", ")", "]")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static public String format3(String pat, Object... args) { if (args.length == 0) return pat; List tok = javaTokPlusPeriod(pat); int argidx = 0; for (int i = 1; i < tok.size(); i += 2) if (tok.get(i).equals("*")) tok.set(i, format3_formatArg(argidx < args.length ? args[argidx++] : "null")); return join(tok); } static public String format3_formatArg(Object arg) { if (arg == null) return "null"; if (arg instanceof String) { String s = (String) arg; return isIdentifier(s) || isNonNegativeInteger(s) ? s : quote(s); } if (arg instanceof Integer || arg instanceof Long) return String.valueOf(arg); return quote(structure(arg)); } static public boolean isLocalhost(String ip) { return isLoopbackIP(ip) || eqic(ip, "localhost"); } static public int vmPort() { return myVMPort(); } static public DialogIO talkToThisVM() { return new talkToThisVM_IO(); } static public class talkToThisVM_IO extends DialogIO { public List answers = ll(thisVMGreeting()); public boolean isLocalConnection() { return true; } public boolean isStillConnected() { return true; } public int getPort() { return vmPort(); } public void sendLine(String line) { answers.add(or2(sendToThisVM_newThread(line), "?")); } public String readLineImpl() { try { return popFirst(answers); } catch (Exception __e) { throw rethrow(__e); } } public void close() { } public Socket getSocket() { return null; } } 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 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 BigInteger parseBigInt(String s) { return new BigInteger(s); } static public float parseFloat(String s) { return Float.parseFloat(s); } 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 boolean isLongConstant(String s) { if (!s.endsWith("L")) return false; s = s.substring(0, l(s) - 1); return isInteger(s); } 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 TreeMap ciMap() { return caseInsensitiveMap(); } static public List parseList(String s) { return (List) safeUnstructure(s); } static public List synchroLinkedList() { return synchroList(new LinkedList()); } static public NavigableMap synchroNavigableMap(NavigableMap map) { return new SynchronizedNavigableMap(map); } static public SortedMap synchroSortedMap(SortedMap map) { return new 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 boolean isAbstract(Class c) { return (c.getModifiers() & Modifier.ABSTRACT) != 0; } static public boolean isAbstract(Method m) { return (m.getModifiers() & Modifier.ABSTRACT) != 0; } 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 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 : getDeclaredConstructors_cached(c)) if (m.getParameterTypes().length == 0) return m; throw fail("No default constructor declared in " + c.getName()); } 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) { printStackTrace(__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 pcallOpt_noArgs(Object o, String method) { try { callOpt_noArgs(o, method); } catch (Throwable __e) { printStackTrace(__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 ThreadLocal DynamicObject_loading = or((ThreadLocal) get(getClass("x30_pkg.x30_util"), "DynamicObject_loading"), new ThreadLocal()); static public ThreadLocal dynamicObjectIsLoading_threadLocal() { return DynamicObject_loading; } static public Map newFindBot2_cache = synchroHashMap(); static public boolean newFindBot2_verbose = false; static public DialogIO newFindBot2(String name) { Integer port = newFindBot2_cache.get(name); if (port != null) { if (newFindBot2_verbose) print("newFindBot2: testing " + name + " => " + port); DialogIO io = talkTo(port); String q = format("has bot *", name); String s = io.ask(q); if (match("yes", s)) { io = talkToSubBot(name, io); call(io, "pushback", "?"); return io; } newFindBot2_cache.remove(name); if (newFindBot2_verbose) print("newFindBot2: dropping " + name + " => " + port); } DialogIO io = findBot(name); if (io != null) { newFindBot2_cache.put(name, io.getPort()); if (newFindBot2_verbose) print("newFindBot2: remembering " + name + " => " + port); } return io; } 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 indentx(Object s) { return indentx(strOrEmpty(s)); } 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 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 A println(A a) { return print(a); } 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 void setOptIfNotNull(Object o, String field, Object value) { if (value != null) setOpt(o, field, value); } static public boolean isNonNegativeInteger(String s) { int n = l(s); if (n == 0) return false; int i = 0; while (i < n) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static public boolean isLoopbackIP(String ip) { return eq(ip, "127.0.0.1"); } static public int myVMPort() { List records = (List) (get(getJavaX(), "record_list")); Object android = last(records); return or0((Integer) get(android, "port")); } static public String thisVMGreeting() { List record_list = (List) (get(getJavaX(), "record_list")); Object android = first(record_list); return getString(android, "greeting"); } static public String sendToThisVM_newThread(String s, Object... args) { final String _s = format(s, args); try { return (String) evalInNewThread(new F0() { public Object get() { try { return callStaticAnswerMethod(getJavaX(), _s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return callStaticAnswerMethod(getJavaX(), _s);"; } }); } catch (Throwable e) { e = getInnerException(e); printStackTrace(e); return str(e); } } static public A popFirst(List l) { if (empty(l)) return null; A a = first(l); l.remove(0); return a; } static public A popFirst(Collection l) { if (empty(l)) return null; A a = first(l); l.remove(a); return a; } static public Pair popFirst(Map map) { if (map == null) return null; var it = map.entrySet().iterator(); if (!it.hasNext()) return null; var p = mapEntryToPair(it.next()); it.remove(); return p; } static public List popFirst(int n, List l) { List part = cloneSubList(l, 0, n); removeSubList(l, 0, n); return part; } static public AppendableChain popFirst(AppendableChain a) { return a == null ? null : a.popFirst(); } static public String quickSubstring(String s, int i, int j) { if (i >= j) return ""; return s.substring(i, j); } static public boolean addToCollection(Collection c, A a) { return c != null && c.add(a); } 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 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 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 Class getClass(String name) { return _getClass(name); } static public Class getClass(Object o) { return _getClass(o); } static public Class getClass(Object realm, String name) { return _getClass(realm, name); } 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 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 + replace(unnull(s), "\n", "\n" + indent); } static public String indent(String s) { return indent(indent_default, s); } static public List indent(String indent, List lines) { List l = new ArrayList(); if (lines != null) for (String s : lines) l.add(indent + s); return l; } static public String 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 int or0(Integer i) { return i == null ? 0 : i; } static public long or0(Long l) { return l == null ? 0L : l; } static public double or0(Double d) { return d == null ? 0.0 : d; } static public Object evalInNewThread(final Object f) { final Flag flag = new Flag(); final Var var = new Var(); final Var exception = new Var(); { startThread(new Runnable() { public void run() { try { try { var.set(callF(f)); } catch (Throwable e) { exception.set(e); } flag.raise(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "try {\r\n var.set(callF(f));\r\n } catch (Throwable e) {\r\n exception..."; } }); } flag.waitUntilUp(); if (exception.has()) throw rethrow(exception.get()); return var.get(); } 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 Object[] toArray(Collection c) { return toObjectArray(c); } static public A[] toArray(Class type, Iterable c) { return toArray(c, type); } static public A[] toArray(Class type, Collection c) { return toArray(c, type); } static public A[] toArray(Collection 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(Iterable c, Class type) { var c2 = asList(c); A[] a = arrayOfType(l(c2), type); if (a.length == 0) return a; c2.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 boolean reflection_isForbiddenMethod(Method m) { return m.getDeclaringClass() == Object.class && eqOneOf(m.getName(), "finalize", "clone", "registerNatives"); } static public void nohupJavax(final String javaxargs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs);"; } }); } } static public void nohupJavax(final String javaxargs, final String vmArgs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs, vmArgs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs, vmArgs);"; } }); } } static public void consoleClearInput() { consoleSetInput(""); } static public Lock downloadLock_lock = fairLock(); static public Lock downloadLock() { return downloadLock_lock; } static public String getSnippetTitleOpt(String s) { try { return isSnippetID(s) ? getSnippetTitle(s) : s; } catch (Throwable __e) { printStackTrace(__e); } return s; } 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 A[] arrayOfType(Class type, int n) { return makeArray(type, n); } static public A[] arrayOfType(int n, Class type) { return arrayOfType(type, n); } static public Class hotwireOnce(String programID) { return hotwireCached(programID, false); } static public void consoleSetInput(final String text) { if (headless()) return; setTextAndSelectAll(consoleInputField(), text); focusConsole(); } static public 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 char firstChar(String s) { return s.charAt(0); } static public A[] makeArray(Class type, int n) { return (A[]) Array.newInstance(type, n); } 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 boolean headless() { return isHeadless(); } static public JTextField setTextAndSelectAll(final JTextField tf, final String text) { if (tf != null) { swing(() -> { tf.setText(text); tf.selectAll(); }); } return tf; } static public JTextField consoleInputField() { Object console = get(getJavaX(), "console"); return (JTextField) getOpt(console, "tfInput"); } static public void focusConsole(String s) { setConsoleInput(s); focusConsole(); } static public void focusConsole() { JComponent tf = consoleInputFieldOrComboBox(); if (tf != null) { tf.requestFocus(); } } 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 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 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 boolean saveTextFileIfDifferent(File f, String contents) { if (eq(loadTextFile(f), contents)) return false; { saveTextFile(f, contents); return true; } } static public List dependentClasses() { return cleanUpAndGetWeakReferencesList(hotwire_classes); } static public String getOneLineFileInfoField(File f, String field) { File infoFile = associatedInfosFile(f); List lines = lines(loadTextFile(infoFile)); return firstStartingWithIC_drop(lines, field + ": "); } static public File fileInSameDir(File f, String newName) { return newFile(parentFile(f), newName); } 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> 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 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 File parentFile(File f) { return dirOfFile(f); } 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 File dirOfFile(File f) { return f == null ? null : f.getParentFile(); } static public String fileExtension(File f) { if (f == null) return null; return fileExtension(f.getName()); } static public String fileExtension(String s) { return substring(s, smartLastIndexOf(s, '.')); } static public String dropSuffixIC(String suffix, String s) { return s == null ? null : ewic(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static public String addPrefixOptIfNempty(String prefix, String s) { return addPrefixIfNotEmpty2(prefix, s); } static public String addPrefixIfNotEmpty2(String prefix, String s) { return empty(s) ? "" : addPrefix(prefix, s); } static abstract public class VF1 implements IVF1 { public abstract void get(A a); } static public class Meta implements IMeta { volatile public Object meta; public void _setMeta(Object meta) { this.meta = meta; } public Object _getMeta() { return meta; } final public boolean scaffolding() { return scaffoldingEnabled(); } public boolean scaffoldingEnabled() { return main.scaffoldingEnabled(this); } public boolean scaffoldingEnabled(Object o) { return main.scaffoldingEnabled(o); } } static public class MultiSetMap implements IMultiMap { 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 List getAndClear(A key) { synchronized (data) { List l = cloneList(data.get(key)); remove(key); return l; } } 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); } } final public Set keys() { return keySet(); } public Set keySet() { 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()); } } final public int keyCount() { return keysSize(); } 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 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 void clear() { set(null); } public String toString() { return str(this.get()); } } static public interface Visitable { public void visitUsing(IVF1 f); } 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 public class PingSource { final public PingSource setAction(IF0 action) { return action(action); } public PingSource action(IF0 action) { this.action = action; return this; } final public IF0 getAction() { return action(); } public IF0 action() { return action; } volatile public IF0 action; public String text; public ThreadPool threadPool; public PingSource() { } public PingSource(ThreadPool threadPool) { this.threadPool = threadPool; } public PingSource(ThreadPool threadPool, String text) { this.text = text; this.threadPool = threadPool; } public PingSource(IF0 action) { this.action = action; } final public boolean get() { var a = action; return a != null && a.get(); } final public void ping() { var a = action; if (a != null) a.get(); } public void cancel() { action = new Cancelled(); } public class Cancelled implements IF0 { public Boolean get() { throw new PingSourceCancelledException(PingSource.this); } } public class Encapsulated implements Runnable, IFieldsToList { public Runnable r; public Encapsulated() { } public Encapsulated(Runnable r) { this.r = r; } public Object[] _fieldsToList() { return new Object[] { r }; } public void run() { try { try { pingSource_tl().set(PingSource.this); ping(); r.run(); } finally { pingSource_tl().set(null); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return PingSource.this + ": " + r; } } public void dO(Runnable r) { if (r == null) return; threadPool.acquireThreadOrQueue(new Encapsulated(r)); } public String toString() { String t = text; return nempty(t) ? t : super.toString(); } public ISleeper_v2 sleeper() { return threadPool.sleeper(); } } static public int concepts_internStringsLongerThan = 10; static public ThreadLocal concepts_unlisted = new ThreadLocal(); static public boolean concepts_unlistedByDefault = true; public interface IConceptIndex { public void update(Concept c); public void remove(Concept c); } public interface IFieldIndex { public Collection getAll(Val val); public List allValues(); public MultiSet allValues_multiSet(); public IterableIterator objectIterator(); } static public class ConceptsChange { } static public class ConceptCreate extends ConceptsChange implements IFieldsToList { public Concept c; public ConceptCreate() { } public ConceptCreate(Concept c) { this.c = c; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ConceptCreate)) return false; ConceptCreate __3 = (ConceptCreate) o; return eq(c, __3.c); } public int hashCode() { int h = -1751266972; h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { c }; } } static public class ConceptChange extends ConceptsChange implements IFieldsToList { public Concept c; public ConceptChange() { } public ConceptChange(Concept c) { this.c = c; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ConceptChange)) return false; ConceptChange __4 = (ConceptChange) o; return eq(c, __4.c); } public int hashCode() { int h = -1760609256; h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { c }; } } static public class ConceptDelete extends ConceptsChange implements IFieldsToList { static final public String _fieldOrder = "id c"; public long id; public Concept c; public ConceptDelete() { } public ConceptDelete(long id, Concept c) { this.c = c; this.id = id; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + id + ", " + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ConceptDelete)) return false; ConceptDelete __5 = (ConceptDelete) o; return id == __5.id && eq(c, __5.c); } public int hashCode() { int h = -1734431213; h = boostHashCombine(h, _hashCode(id)); h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { id, c }; } } static public class FullChange extends ConceptsChange implements IFieldsToList { public FullChange() { } public String toString() { return shortClassName_dropNumberPrefix(this); } public boolean equals(Object o) { return o instanceof FullChange; } public int hashCode() { int h = 733452095; return h; } public Object[] _fieldsToList() { return null; } } static public class Concepts implements AutoCloseable { public SortedMap concepts = synchroTreeMap(); final public long getIdCounter() { return idCounter(); } public long idCounter() { return idCounter; } public long idCounter; transient public HashMap perClassData; transient public Map miscMap; transient public String programID; transient public File conceptsFile; transient public Concepts parent; transient volatile public long changes, changesWritten, lastChange; transient volatile public java.util.Timer autoSaver; transient volatile public boolean dontSave = false; transient volatile public boolean savingConcepts, noXFullGrab; transient public boolean vmBusSend = true; transient public boolean initialSave = false; transient public int autoSaveInterval = -1000; transient public boolean useGZIP = true, quietSave; transient public ReentrantLock lock = new ReentrantLock(true); transient public ReentrantLock saverLock = new ReentrantLock(true); transient public long lastSaveTook = -1, lastSaveWas, loadTook, uncompressedSize; transient public float maxAutoSavePercentage = 10; transient public List conceptIndices; transient public Map, Map> fieldIndices; transient public Map, Map> ciFieldIndices; transient public List preSave; transient public Object classFinder = _defaultClassFinder(); transient public List onAllChanged = synchroList(); transient public Set onChange = new HashSet(); transient public Object saveWrapper; final public Concepts setModifyOnCreate(boolean modifyOnCreate) { return modifyOnCreate(modifyOnCreate); } public Concepts modifyOnCreate(boolean modifyOnCreate) { this.modifyOnCreate = modifyOnCreate; return this; } final public boolean getModifyOnCreate() { return modifyOnCreate(); } public boolean modifyOnCreate() { return modifyOnCreate; } transient public boolean modifyOnCreate = false; transient public boolean modifyOnBackRef = false; transient public boolean useFileLock = true; transient public FileBasedLock fileLock; transient public boolean storeBaseClassesInStructure = false; transient public boolean useBackRefsForSearches = false; transient public boolean defunct = false; transient public int newBackupEveryXMinutes = 60; public Concepts() { } public Concepts(String programID) { this.programID = programID; } public Concepts(File conceptsFile) { this.conceptsFile = conceptsFile; } synchronized public long internalID() { do { ++idCounter; } while (hasConcept(idCounter)); return idCounter; } synchronized public HashMap perClassData() { if (perClassData == null) perClassData = new HashMap(); return perClassData; } public void initProgramID() { if (programID == null) programID = getDBProgramID(); } public Concepts load(String structure) { return load(structure, false); } public Concepts load(String structure, boolean allDynamic) { clearConcepts(); Map map = unstructureMap(structure, allDynamic, classFinder); concepts.putAll(map); assignConceptsToUs(); calcIdCounter(); return this; } public Concepts load() { initProgramID(); Object dbGrabber = miscMapGet("dbGrabber"); if (dbGrabber != null && !isFalse(callF(dbGrabber))) return this; try { if (tryToGrab()) return this; } catch (Throwable e) { if (!exceptionMessageContains(e, "no xfullgrab")) printShortException(e); print("xfullgrab failed - loading DB of " + programID + " from disk"); } return loadFromDisk(); } public Concepts loadFromDisk() { if (nempty(concepts)) clearConcepts(); long time = now(); Map _concepts = (Map) (unstructureGZFile(conceptsFile(), toIF1(classFinder))); putAll(concepts, _concepts); assignConceptsToUs(); loadTook = now() - time; done("Loaded " + n2(l(concepts), "concept"), time); calcIdCounter(); return this; } public Concepts loadConcepts() { return load(); } public boolean tryToGrab() { if (sameSnippetID(programID, getDBProgramID())) return false; RemoteDB db = connectToDBOpt(programID); try { if (db != null) { loadGrab(db.fullgrab()); return true; } return false; } finally { _close(db); } } public Concepts loadGrab(String grab) { clearConcepts(); DynamicObject_loading.set(true); try { Map map = (Map) unstructure(grab, false, classFinder); concepts.putAll(map); assignConceptsToUs(); for (long l : map.keySet()) idCounter = max(idCounter, l); } finally { DynamicObject_loading.set(null); } return this; } public void assignConceptsToUs() { for (Pair p : mapToPairs((Map) (Map) concepts)) if (!(p.b instanceof Concept)) { print("DROPPING non-existant concept " + p.a + ": " + dynShortName(p.b)); concepts.remove(p.a); } for (Concept c : values(concepts)) c._concepts = this; for (Concept c : values(concepts)) c._doneLoading2(); } public String progID() { return programID == null ? getDBProgramID() : programID; } public Concept getConcept(String id) { return empty(id) ? null : getConcept(parseLong(id)); } public Concept getConcept(long id) { return (Concept) concepts.get((long) id); } public Concept getConcept(RC ref) { return ref == null ? null : getConcept(ref.longID()); } public boolean hasConcept(long id) { return concepts.containsKey((long) id); } public void deleteConcept(long id) { Concept c = getConcept(id); if (c == null) print("Concept " + id + " not found"); else c.delete(); } public void calcIdCounter() { Long lastID = lastKey(concepts); idCounter = lastID == null ? 1 : lastID + 1; } public File conceptsDir() { return dirOfFile(conceptsFile()); } public Concepts conceptsFile(File conceptsFile) { this.conceptsFile = conceptsFile; return this; } public File conceptsFile() { if (conceptsFile != null) return conceptsFile; return getProgramFile(programID, useGZIP ? "concepts.structure.gz" : "concepts.structure"); } public File lockFile() { return newFile(conceptsDir(), "concepts.lock"); } public FileBasedLock fileLock() { if (fileLock == null) fileLock = new FileBasedLock(lockFile()); return fileLock; } public void saveConceptsIfDirty() { saveConcepts(); } public void save() { saveConcepts(); } public void saveConcepts() { vmBus_send("saveConceptsCalled", Concepts.this); if (dontSave) return; initProgramID(); saverLock.lock(); savingConcepts = true; long start = now(), time; try { String s = null; long _changes = changes; if (_changes == changesWritten) return; File f = conceptsFile(); lock.lock(); long fullTime = now(); try { if (useGZIP) { vmBus_send("callingSaveWrapper", Concepts.this, saveWrapper); callRunnableWithWrapper(saveWrapper, new Runnable() { public void run() { try { vmBus_send("callingPreSave", Concepts.this, preSave); callFAll(preSave); vmBus_send("writingFile", Concepts.this, f); uncompressedSize = saveGZStructureToFile(f, cloneMap(concepts), makeStructureData()); vmBus_send("gzFileSaved", Concepts.this, f, uncompressedSize); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "vmBus_send callingPreSave(Concepts.this, preSave);\r\n callFAll(preS..."; } }); newFile(conceptsDir(), "concepts.structure").delete(); } else s = fullStructure(); } finally { lock.unlock(); } changesWritten = _changes; if (!useGZIP) { time = now() - start; if (!quietSave) print("Saving " + toM(l(s)) + "M chars (" + time + " ms)"); start = now(); saveTextFile(f, javaTokWordWrap(s)); newFile(conceptsDir(), "concepts.structure.gz").delete(); } File conceptsFile = conceptsFile(); File backupFile = newFile(conceptsDir(), "backups/" + fileName(conceptsFile) + ".backup" + ymd() + "-" + formatInt(hours(), 2) + (newBackupEveryXMinutes >= 60 ? "" : formatInt(roundDownTo_rev(minutes(), newBackupEveryXMinutes), 2))); copyFile(f, backupFile); time = now() - start; if (!quietSave) print("Saved " + toK(f.length()) + " K, " + n(concepts, "concepts") + " (" + time + " ms)"); lastSaveWas = fullTime; lastSaveTook = now() - fullTime; } finally { savingConcepts = false; saverLock.unlock(); } } public void _autoSaveConcepts() { if (autoSaveInterval < 0 && maxAutoSavePercentage != 0) { long pivotTime = Math.round(lastSaveWas + lastSaveTook * 100.0 / maxAutoSavePercentage); if (now() < pivotTime) { return; } } try { saveConcepts(); } catch (Throwable e) { print("Concept save failed, will try again"); printStackTrace(e); } } public String fullStructure() { return structure(cloneMap(concepts), makeStructureData()); } transient public IF0 makeStructureData; public structure_Data makeStructureData() { return makeStructureData != null ? makeStructureData.get() : makeStructureData_base(); } final public structure_Data makeStructureData_fallback(IF0 _f) { return _f != null ? _f.get() : makeStructureData_base(); } public structure_Data makeStructureData_base() { return finishStructureData(new structure_Data()); } public structure_Data finishStructureData(structure_Data data) { if (storeBaseClassesInStructure) data.storeBaseClasses = true; return data; } public void clearConcepts() { for (Concept c : allConcepts()) c.delete(); } public void fireLegacyChangeEvent() { synchronized (this) { ++changes; lastChange = sysNow(); } if (vmBusSend) vmBus_send("conceptsChanged", this); pcallFAll(onAllChanged); } synchronized public void autoSaveConcepts() { if (autoSaver == null) { if (isTransient()) throw fail("Can't persist transient database"); autoSaver = doEvery_daemon("Concepts Saver for " + conceptsDir(), abs(autoSaveInterval), new Runnable() { public void run() { try { _autoSaveConcepts(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_autoSaveConcepts()"; } }); } } public void close() { cleanMeUp(); } public void cleanMeUp() { try { defunct = true; boolean shouldSave = autoSaver != null; if (autoSaver != null) { autoSaver.cancel(); autoSaver = null; } while (savingConcepts) sleepInCleanUp(10); if (shouldSave) saveConceptsIfDirty(); } catch (Throwable __e) { printStackTrace(__e); } { cleanUp(fileLock); fileLock = null; } } public Map getIDsAndNames() { Map map = new HashMap(); Map cloned = cloneMap(concepts); for (long id : keys(cloned)) map.put(id, cloned.get(id).className); return map; } public void deleteConcepts(List l) { ping(); if (l != null) for (Object o : cloneList(l)) if (o instanceof Long) { Concept c = concepts.get(o); if (c != null) c.delete(); } else if (o instanceof Concept) ((Concept) o).delete(); else warn("Can't delete " + getClassName(o)); } public A conceptOfType(Class type) { IConceptCounter counter = conceptCounterForClass(type); if (counter != null) return (A) first(counter.allConcepts()); return firstOfType(allConcepts(), type); } public List conceptsOfType(Class type) { List l = conceptsOfType_noParent(type); if (parent == null) return l; return concatLists_conservative(l, parent.conceptsOfType(type)); } public List conceptsOfType_noParent(Class type) { ping(); IConceptCounter counter = conceptCounterForClass(type); if (counter != null) return (List) cloneList(counter.allConcepts()); return filterByType(allConcepts(), type); } public List listConcepts(Class type) { return conceptsOfType(type); } public List list(Class type) { return conceptsOfType(type); } public List list_noParent(Class type) { return conceptsOfType_noParent(type); } public List list(String type) { return conceptsOfType(type); } public List conceptsOfType(String type) { return filterByDynamicType(allConcepts(), "main$" + type); } public boolean hasConceptOfType(Class type) { return hasType(allConcepts(), type); } public void persistConcepts() { loadConcepts(); autoSaveConcepts(); } public void conceptPersistence() { persistConcepts(); } public Concepts persist() { persistConcepts(); return this; } public void persist(Integer interval) { if (interval != null) autoSaveInterval = interval; persist(); } public A ensureHas(Class c, Runnable r) { A a = conceptOfType(c); if (a == null) { r.run(); a = conceptOfType(c); if (a == null) throw fail("Concept not made by " + r + ": " + shortClassName(c)); } return a; } public void ensureHas(Class c1, Class c2, Object func) { for (Concept a : conceptsOfType(c1)) { Concept b = findBackRef(a, c2); if (b == null) { callF(func, a); b = findBackRef(a, c2); if (b == null) throw fail("Concept not made by " + func + ": " + shortClassName(c2)); } } } public void forEvery(Class type, Object func) { for (Concept c : conceptsOfType(type)) callF(func, c); } public int deleteAll(Class type) { List l = (List) conceptsOfType(type); for (Concept c : l) c.delete(); return l(l); } public Collection allConcepts() { synchronized (concepts) { return new ArrayList(values(concepts)); } } public IConceptCounter conceptCounterForClass(Class c) { for (IFieldIndex idx : values(mapGet(fieldIndices, c))) if (idx instanceof IConceptCounter) return ((IConceptCounter) idx); for (IFieldIndex idx : values(mapGet(ciFieldIndices, c))) if (idx instanceof IConceptCounter) return ((IConceptCounter) idx); return null; } public int countConcepts(Class c, Object... params) { int n = countConcepts_noParent(c, params); if (parent == null) return n; return n + parent.countConcepts(c, params); } public int countConcepts_noParent(Class c, Object... params) { ping(); if (empty(params)) { IConceptCounter counter = conceptCounterForClass(c); if (counter != null) return counter.countConcepts(); return l(list_noParent(c)); } int n = 0; for (A x : list_noParent(c)) if (checkConceptFields(x, params)) ++n; return n; } public int countConcepts(String c, Object... params) { ping(); if (empty(params)) return l(list(c)); int n = 0; for (Concept x : list(c)) if (checkConceptFields(x, params)) ++n; return n; } public int countConcepts() { return l(concepts); } synchronized public List clonedConceptIndices() { return cloneList(conceptIndices); } synchronized public void addConceptIndex(IConceptIndex index) { if (conceptIndices == null) conceptIndices = new ArrayList(); conceptIndices.add(index); } synchronized public void removeConceptIndex(IConceptIndex index) { if (conceptIndices == null) return; conceptIndices.remove(index); if (empty(conceptIndices)) conceptIndices = null; } synchronized public void addFieldIndex(Class c, String field, IFieldIndex index) { if (fieldIndices == null) fieldIndices = new HashMap(); Map map = fieldIndices.get(c); if (map == null) fieldIndices.put(c, map = new HashMap()); map.put(field, index); } synchronized public void removeFieldIndex(Class c, String field, IFieldIndex index) { Map map = mapGet(fieldIndices, c); mapRemove(map, field); } synchronized public IFieldIndex getFieldIndex(Class c, String field) { if (fieldIndices == null) return null; Map map = fieldIndices.get(c); return map == null ? null : map.get(field); } synchronized public IFieldIndex getAnyIndexForClass(Class c) { return firstValue(fieldIndices == null ? null : fieldIndices.get(c)); } synchronized public void addCIFieldIndex(Class c, String field, IFieldIndex index) { if (ciFieldIndices == null) ciFieldIndices = new HashMap(); Map map = ciFieldIndices.get(c); if (map == null) ciFieldIndices.put(c, map = new HashMap()); map.put(field, index); } synchronized public void removeCIFieldIndex(Class c, String field) { Map map = mapGet(ciFieldIndices, c); mapRemove(map, field); } synchronized public IFieldIndex getCIFieldIndex(Class c, String field) { if (ciFieldIndices == null) return null; Map map = ciFieldIndices.get(c); return map == null ? null : map.get(field); } public RC xnew(String name, Object... values) { return new RC(cnew(name, values)); } public void xset(long id, String field, Object value) { xset(new RC(id), field, value); } public void xset(RC c, String field, Object value) { if (value instanceof RC) value = getConcept((RC) value); cset(getConcept(c), field, value); } public Object xget(long id, String field) { return xget(new RC(id), field); } public Object xget(RC c, String field) { return xgetPost(cget(getConcept(c), field)); } public Object xgetPost(Object o) { o = deref(o); if (o instanceof Concept) return new RC((Concept) o); return o; } public void xdelete(long id) { xdelete(new RC(id)); } public void xdelete(RC c) { getConcept(c).delete(); } public void xdelete(List l) { for (RC c : l) xdelete(c); } public List xlist() { return map("toPassRef", allConcepts()); } public List xlist(String className) { return map("toPassRef", conceptsOfType(className)); } public boolean isTransient() { return eq(programID, "-"); } public String xfullgrab() { if (noXFullGrab) throw fail("no xfullgrab (DB too large)"); Lock __1 = lock(); lock(__1); try { if (changes == changesWritten && !isTransient()) return loadConceptsStructure(programID); return fullStructure(); } finally { unlock(__1); } } public void xshutdown() { cleanKillVM(); } public long xchangeCount() { return changes; } public int xcount() { return countConcepts(); } public void register(Concept c) { ping(); if (c._concepts == this) return; if (c._concepts != null) throw fail("Can't re-register"); c.id = internalID(); c.created = now(); if (modifyOnCreate) c._setModified(c.created); register_phase2(c); vmBus_send("conceptCreated", c); fireChange(new ConceptCreate(c)); } public void register_phase2(Concept c) { c._concepts = this; concepts.put((long) c.id, c); for (Concept.Ref r : c._refs()) r.index(); c.change(); c._onRegistered(); } public void registerKeepingID(Concept c) { if (c._concepts == this) return; if (c._concepts != null) throw fail("Can't re-register"); c._concepts = this; concepts.put((long) c.id, c); c.change(); } public void conceptChanged(Concept c) { fireChange(new ConceptChange(c)); if (conceptIndices != null) for (IConceptIndex index : clonedConceptIndices()) index.update(c); } public boolean hasUnsavedData() { return changes != changesWritten || savingConcepts; } synchronized public Object miscMapGet(Object key) { return mapGet(miscMap, key); } synchronized public Object miscMapPut(Object key, Object value) { if (miscMap == null) miscMap = new HashMap(); return miscMap.put(key, value); } synchronized public void miscMapRemove(Object key) { mapRemove(miscMap, key); } synchronized public A miscMapGetOrCreate(Object key, IF0 create) { if (containsKey(miscMap, key)) return (A) miscMap.get(key); A value = create.get(); miscMapPut(key, value); return value; } public void setParent(Concepts parent) { this.parent = parent; } public void fireChange(ConceptsChange change) { if (change == null) return; pcallFAll(onChange, change); fireLegacyChangeEvent(); } final public void onChange(IVF1 l) { addChangeListener(l); } public void addChangeListener(IVF1 l) { syncAdd(onChange, l); } public void removeChangeListener(IVF1 l) { syncRemove(onChange, l); } public void addPreSave(Runnable r) { preSave = syncAddOrCreate(preSave, r); } public String toString() { return nConcepts(concepts) + " (" + conceptsDir() + ", hash: " + identityHashCode(this) + ")"; } } public interface IConcept { public long _conceptID(); public Concepts concepts(); } static public class Concept extends DynamicObject implements IConcept, ChangeTriggerable { transient public Concepts _concepts; public long id; public long created, _modified; public List backRefs; public Concept(String className) { super(className); _created(); } public Concept() { if (!_loading()) { _created(); } } public Concept(boolean unlisted) { if (!unlisted) _created(); } public boolean includeZeroIDInToString() { return false; } public String toString() { String s = shortDynamicClassName(this); long id = this.id; if (id != 0 || includeZeroIDInToString()) s += " " + id; return s; } static public boolean loading() { return _loading(); } static public boolean _loading() { return dynamicObjectIsLoading(); } public void _created() { if (!concepts_unlistedByDefault && !eq(concepts_unlisted.get(), true)) db_mainConcepts().register(this); } public class TypedRef extends Ref { public TypedRef() { } public Class bType; public TypedRef(Class bType) { this.bType = bType; } public TypedRef(Class bType, B value) { this.bType = bType; set((A) value); } public TypedRef(B value) { set((A) value); } public boolean set(A a) { return super.set(checkValue(a)); } public void check() { checkValue(get()); } public C checkValue(C a) { if (bType != null && a != null) assertIsInstance(a, bType); return a; } public B b() { return (B) value; } } public class Ref implements IRef { public A value; public Ref() { if (!dynamicObjectIsLoading()) registerRef(); } public void registerRef() { vmBus_send("registeringConceptRef", this); } public Ref(A value) { this.value = value; registerRef(); index(); } public Concept concept() { return Concept.this; } public A get() { return value; } public boolean has() { return value != null; } public boolean set(A a) { if (a == value) return false; unindex(); value = a; index(); change(); return true; } public void setIfEmpty(A a) { if (!has()) set(a); } public void set(Ref ref) { set(ref.get()); } public void clear() { set((A) null); } public boolean validRef() { return value != null && _concepts != null && _concepts == value._concepts; } public void index() { if (validRef()) { value._addBackRef(this); change(); } } public Ref unindex() { if (validRef()) { value._removeBackRef(this); change(); } return this; } public void unindexAndDrop() { unindex(); _removeRef(this); } public void change() { Concept.this.change(); } public String toString() { return str(value); } } public class RefL extends AbstractList { public List> l = new ArrayList(); public RefL() { } public RefL(List l) { replaceWithList(l); } public void clear() { while (!isEmpty()) removeLast(this); } public void replaceWithList(List l) { clear(); for (A a : unnullForIteration(l)) add(a); } public A set(int i, A o) { Ref ref = syncGet(l, i); A prev = ref.get(); ref.set(o); return prev; } public void add(int i, A o) { syncAdd(l, i, new Ref(o)); } public A get(int i) { return syncGet(l, i).get(); } public A remove(int i) { return syncRemove(l, i).get(); } public int size() { return syncL(l); } public boolean contains(Object o) { if (o instanceof Concept) for (Ref r : l) if (eq(r.get(), o)) return true; return super.contains(o); } } public void delete() { for (Ref r : unnullForIteration(_refs())) r.unindex(); for (Ref r : cloneList(backRefs)) r.set((Concept) null); backRefs = null; var _concepts = this._concepts; if (_concepts != null) { _concepts.concepts.remove(id); _concepts.fireChange(new ConceptDelete(id, this)); if (_concepts.conceptIndices != null) for (IConceptIndex index : _concepts.conceptIndices) index.remove(this); this._concepts = null; } id = 0; } public BaseXRef export() { return new BaseXRef(_concepts.progID(), id); } final public void _change() { change(); } public void change() { _setModified(now()); _change_withoutUpdatingModifiedField(); } public void _setModified(long modified) { _modified = modified; } final public void _change_withoutUpdatingModifiedField() { _onChange(); if (_concepts != null) _concepts.conceptChanged(this); } public void _onChange() { } public String _programID() { return _concepts == null ? getDBProgramID() : _concepts.progID(); } public void _addBackRef(Concept.Ref ref) { backRefs = addDyn_quickSync(backRefs, ref); _backRefsModified(); } public void _backRefsModified() { if (_concepts != null && _concepts.modifyOnBackRef) change(); } public void _removeBackRef(Concept.Ref ref) { backRefs = removeDyn_quickSync(backRefs, ref); _backRefsModified(); } public void _removeRef(Concept.Ref ref) { } public int _backRefCount() { return syncL(backRefs); } final public void setField(String field, Object value) { _setField(field, value); } public void _setField(String field, Object value) { cset(this, field, value); } public boolean setField_trueIfChanged(String field, Object value) { return cset(this, field, value) != 0; } public A setFieldAndReturn(String field, A value) { setField(field, value); return value; } final public void setFields(Object... values) { _setFields(values); } public void _setFields(Object... values) { cset(this, values); } public Concepts concepts() { return _concepts; } public boolean isDeleted() { return id == 0; } public void _doneLoading() { } public void _doneLoading2() { Map map = _fieldMigrations(); if (map != null) for (Map.Entry __0 : _entrySet(map)) { String oldField = __0.getKey(); FieldMigration m = __0.getValue(); crenameField_noOverwrite(this, oldField, m.newField); } } static public class FieldMigration implements IFieldsToList { public String newField; public FieldMigration() { } public FieldMigration(String newField) { this.newField = newField; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + newField + ")"; } public boolean equals(Object o) { if (!(o instanceof FieldMigration)) return false; FieldMigration __6 = (FieldMigration) o; return eq(newField, __6.newField); } public int hashCode() { int h = 558692372; h = boostHashCombine(h, _hashCode(newField)); return h; } public Object[] _fieldsToList() { return new Object[] { newField }; } } public Map _fieldMigrations() { return null; } public Collection _refs() { return scanConceptForRefs(this); } public Concepts _concepts() { return _concepts; } public boolean _conceptsDefunct() { return _concepts != null && _concepts.defunct; } public boolean _conceptsDefunctOrUnregistered() { return _concepts == null || _concepts.defunct; } public void _onRegistered() { } public boolean addAndChange(Collection cl, A a) { if (cl == null || !cl.add(a)) return false; change(); return true; } public void clearAndChange(Collection cl) { if (cl == null) return; cl.clear(); change(); } public File conceptsDir() { var concepts = concepts(); return concepts == null ? null : concepts.conceptsDir(); } public File fileInConceptsDir(String name) { var dir = conceptsDir(); return dir == null ? null : newFile(dir, name); } public long _conceptID() { return id; } } static public class RC { transient public Object owner; public String id; public RC() { } public RC(long id) { this.id = str(id); } public RC(Object owner, long id) { this.id = str(id); this.owner = owner; } public RC(Concept c) { this(c.id); } public long longID() { return parseLong(id); } public String toString() { return id; } transient public RemoteDB db; public String getString(String field) { return db.xS(this, field); } public Object get(String field) { return db.xget(this, field); } public void set(String field, Object value) { db.xset(this, field, value); } } static public class BaseXRef { public String programID; public long id; public BaseXRef() { } public BaseXRef(String programID, long id) { this.id = id; this.programID = programID; } public boolean equals(Object o) { if (!(o instanceof BaseXRef)) return false; BaseXRef r = (BaseXRef) o; return eq(programID, r.programID) && eq(id, r.id); } public int hashCode() { return programID.hashCode() + (int) id; } } static public class XRef extends Concept { public BaseXRef ref; public XRef() { } public XRef(BaseXRef ref) { this.ref = ref; _doneLoading2(); } public void _doneLoading2() { getIndex().put(ref, this); } public HashMap getIndex() { return getXRefIndex(_concepts); } } static synchronized public HashMap getXRefIndex(Concepts concepts) { HashMap cache = (HashMap) concepts.perClassData().get(XRef.class); if (cache == null) concepts.perClassData.put(XRef.class, cache = new HashMap()); return cache; } static public XRef lookupOrCreateXRef(BaseXRef ref) { XRef xref = getXRefIndex(db_mainConcepts()).get(ref); if (xref == null) xref = new XRef(ref); return xref; } static public void loadAndAutoSaveConcepts() { db_mainConcepts().persist(); } static public void loadAndAutoSaveConcepts(int interval) { db_mainConcepts().persist(interval); } static public RC toPassRef(Concept c) { return new RC(c); } static public void concepts_setUnlistedByDefault(boolean b) { concepts_unlistedByDefault = b; } static public class HCRUD extends HAbstractRenderable { public HCRUD_Data data; public boolean mutationRights = true; public boolean allowCreateOrDelete = true; public boolean allowCreate = true; public boolean allowEdit = true; public boolean singleton = false; public boolean cmdsLeft = false; public boolean showEntryCountInTitle = false; public boolean allowFieldRenaming = false; public int defaultTextFieldCols = 80; public int valueDisplayLength = 1000; public String tableClass; public String formTableClass; public String checkBoxClass = "crud_chkbox"; public String customTitle; public boolean showTextFieldsAsAutoExpandingTextAreas = false; public Set unshownFields; public Set uneditableFields; public Set unlistedFields; public boolean showCheckBoxes = false; public boolean cleanItemIDs = false; public boolean haveJQuery, haveSelectizeJS, haveSelectizeClickable; public boolean needsJQuery = false; public boolean paginate = false; public boolean sortable = false; public boolean buttonsOnTop, buttonsOnBottom = true; public boolean duplicateInNewTab = false; public String formID = "crudForm"; public boolean showQuickSaveButton = false; public boolean enableMultiSelect = true; public boolean cellColumnToolTips = false; public boolean showSearchField = false; public String searchQuery; public Map params; public HTMLPaginator paginator = new HTMLPaginator(); public String sortByField = "id"; public String sortParameter = "sort"; public boolean descending = false; public int flexibleLengthListLeeway = 5; public Object objectIDToHighlight; public boolean showOnlySelected = false; public String fieldPrefix = "f_"; public int entryCount; public HCRUD() { } public HCRUD(HCRUD_Data data) { this.data = data; } public HCRUD(String baseLink, HCRUD_Data data) { this.data = data; this.baseLink = baseLink; } public String newLink() { return appendQueryToURL(baseLink, "cmd", "new"); } public String deleteLink(Object id) { return appendQueryToURL(baseLink, "delete_" + id, 1); } public String editLink(Object id) { return appendQueryToURL(baseLink, "edit", id); } public String duplicateLink(Object id) { return appendQueryToURL(baseLink, "duplicate", id); } public void setParams(Map params) { this.params = params; if (objectIDToHighlight == null) objectIDToHighlight = params.get("selectObj"); if (eq("1", params.get("showOnlySelected"))) showOnlySelected = true; } public String render(boolean withCmds, Map params) { setParams(params); if (!withCmds) return renderTable(false); { String __3 = handleCommands(params); if (!empty(__3)) return __3; } return renderMsgs(params) + divUnlessEmpty(nav()) + renderTable(withCmds); } transient public IF0 nav; public String nav() { return nav != null ? nav.get() : nav_base(); } final public String nav_fallback(IF0 _f) { return _f != null ? _f.get() : nav_base(); } public String nav_base() { List l = new ArrayList(); if (actuallyAllowCreate()) l.add(ahref(newLink(), "New " + itemName())); if (showSearchField) l.add(hInlineSearchForm("search", searchQuery, "")); return joinWithVBar(l); } public String handleCommands(Map params) { List msgs = new ArrayList(); if (eqGet(params, "action", "create")) { if (!actuallyAllowCreate()) throw fail("Creating objects not allowed"); processRenames(params); Object id = data.createObject(preprocessUpdateParams(params), fieldPrefix); msgs.add(itemName() + " created (ID: " + id + ")"); objectIDToHighlight = id; } if (eqGet(params, "action", "update")) { if (!actuallyAllowEdit()) throw fail("Editing objects not allowed"); String id = params.get("id"); processRenames(params); msgs.add(data.updateObject(id, preprocessUpdateParams(params), fieldPrefix)); objectIDToHighlight = id; } List toDeleteList = keysDeprefixNemptyValue(params, "delete_"); if (eq(params.get("bulkAction"), "deleteSelected")) toDeleteList.addAll(keysDeprefixNemptyValue(params, "obj_")); for (String toDelete : toDeleteList) { if (!actuallyAllowDelete()) throw fail("Deleting objects not allowed"); msgs.add(data.deleteObject(toDelete)); } return empty(msgs) ? "" : refreshAfterCommand(params, msgs); } transient public IF2, List, String> refreshAfterCommand; public String refreshAfterCommand(Map params, List msgs) { return refreshAfterCommand != null ? refreshAfterCommand.get(params, msgs) : refreshAfterCommand_base(params, msgs); } final public String refreshAfterCommand_fallback(IF2, List, String> _f, Map params, List msgs) { return _f != null ? _f.get(params, msgs) : refreshAfterCommand_base(params, msgs); } public String refreshAfterCommand_base(Map params, List msgs) { String redirectAfterSave = mapGet(params, "redirectAfterSave"); if (nempty(redirectAfterSave)) return hrefresh(redirectAfterSave); return refreshWithMsgs(msgs, "anchor", objectIDToHighlight == null ? null : "obj" + objectIDToHighlight, "params", objectIDToHighlight == null ? null : litmap("selectObj", objectIDToHighlight)); } public String encodeField(String s) { return or(data.fieldNameToHTML(s), s); } transient public IF2 renderValue; public String renderValue(String field, Object value) { return renderValue != null ? renderValue.get(field, value) : renderValue_base(field, value); } final public String renderValue_fallback(IF2 _f, String field, Object value) { return _f != null ? _f.get(field, value) : renderValue_base(field, value); } public String renderValue_base(String field, Object value) { if (value instanceof HTML) return ((HTML) value).html; value = deref(value); if (value instanceof SecretValue) return hhiddenStuff(renderValue_inner(((SecretValue) value).get())); return renderValue_inner(value); } transient public IF1 renderValue_inner; public String renderValue_inner(Object value) { return renderValue_inner != null ? renderValue_inner.get(value) : renderValue_inner_base(value); } final public String renderValue_inner_fallback(IF1 _f, Object value) { return _f != null ? _f.get(value) : renderValue_inner_base(value); } public String renderValue_inner_base(Object value) { if (value instanceof Boolean) return yesNo_short((Boolean) value); return htmlEncode_nlToBr_withIndents(shorten(valueDisplayLength, strOrEmpty(value))); } public String renderTable(boolean withCmds) { return renderTable(withCmds, data.list()); } public String valueToSortable(Object value) { if (value instanceof HTML) return ((HTML) value).get(); return strOrNull(value); } public String renderTable(boolean withCmds, List> l) { entryCount = l(l); if (empty(l)) return p("No entries"); if (!eq(data.defaultSortField(), pair(sortByField, descending))) { if (nempty(sortByField)) { print("Sorting " + nEntries(l) + " by " + sortByField); l = sortByTransformedMapKey_alphaNum(__89 -> valueToSortable(__89), l, sortByField); } if (descending) l = reversed(l); } Map keyEncoding = new HashMap(); List> l2 = lazyMap(l, _map -> { Object id = itemID(_map); return data.new Item(id) { public Map calcFullMap() { Map map = _map; map = mapMinusKeys(map, joinSets(unshownFields, unlistedFields)); Map map2 = postProcessTableRow(map, mapToMap((key, value) -> pair(mapPut_returnValue(keyEncoding, key, encodeField(key)), renderValue(key, value)), map)); if (singleton) map2.remove(encodeField(data.idField())); if (withCmds) map2 = addCmdsToTableRow(map, map2); map2.put(firstKey(map2), aname("obj" + id, firstValue(map2))); return map2; } }; }); List out = new ArrayList(); if (paginate) { paginator.processParams(params); paginator.baseLink = addParamsToURL(baseLink, filterKeys(__90 -> keepParamInPagination(__90), params)); paginator.max = l(l2); out.add(divUnlessEmpty(paginator.renderNav())); List> l3 = subListOrFull(l2, paginator.visibleRange()); if (objectIDToHighlight != null && (showOnlySelected || !any(__63 -> isHighlighted(__63), l3))) { l3 = llNonNulls(firstThat(__64 -> isHighlighted(__64), l2)); } l2 = l3; } Map replaceHeaders = new HashMap(); if (sortable && !singleton) for (Map.Entry __1 : _entrySet(keyEncoding)) { String key = __1.getKey(); String html = __1.getValue(); boolean sortedByField = eq(sortByField, key); boolean showDescendingLink = sortedByField && !descending; String htmlOld = html; if (sortedByField) { String title = showDescendingLink ? "Click here to sort descending" : "Click here to sort ascending"; String titleSorted = "Sorted by this field (" + (descending ? "descending" : "ascending") + ")"; title = titleSorted + ". " + title; html = span_title(title, unicode_downOrUpPointingTriangle(descending)) + " " + html; } String sortLink = appendQueryToURL(baseLink, sortParameter, showDescendingLink ? "-" + key : key); replaceHeaders.put(htmlOld, ahref(sortLink, html)); } Map paramsByColName = null; if (cellColumnToolTips) { paramsByColName = new HashMap(); for (Map map : l2) for (String key : keys(map)) if (!paramsByColName.containsKey(key)) paramsByColName.put(key, litobjectarray("title", nullIfEmpty(htmldecode_dropTagsAndComments(key)))); } out.add(hpostform(htmlTable2_noHtmlEncode(l2, paramsPlus(tableParams(), "replaceHeaders", replaceHeaders, "paramsByColName", paramsByColName)) + (!withCmds || !showCheckBoxes ? "" : "\n" + divUnlessEmpty(renderBulkCmds())), "action", baseLink)); if (showCheckBoxes && haveJQuery && enableMultiSelect) out.add(hCheckBoxMultiSelect_v2()); return lines_rtrim(out); } public Object mapToID(Map item) { return item == null ? null : dropAllTags(strOrNull(item.get(encodeField(idField())))); } public boolean isHighlighted(Map item) { Object id = mapToID(item); return eq(id, objectIDToHighlight); } transient public IF0 renderBulkCmds; public String renderBulkCmds() { return renderBulkCmds != null ? renderBulkCmds.get() : renderBulkCmds_base(); } final public String renderBulkCmds_fallback(IF0 _f) { return _f != null ? _f.get() : renderBulkCmds_base(); } public String renderBulkCmds_base() { return "Bulk action: " + hselect("bulkAction", litorderedmap("", "", "deleteSelected", "Delete selected")) + " " + hsubmit("OK", "onclick", "return confirm('Are you sure?')"); } public Map addCmdsToTableRow(Map map, Map map2) { if (showCheckBoxes) { Object id = itemID(map); map2.put(checkBoxKey(), hcheckbox("obj_" + id, false, "title", "Select this object for a bulk action", "class", checkBoxClass)); map2 = putKeysFirst(map2, checkBoxKey()); } map2.put(cmdsKey(), renderCmds(map)); if (cmdsLeft) map2 = putKeysFirst(map2, cmdsKey()); return map2; } public Object[] tableParams() { return litparams("tdParams", litparams("valign", "top"), "tableParams", litparams("class", tableClass)); } public String renderForm(Map map) { AutoCloseable __5 = tempSetTL(htmlencode_forParams_useV2, true); try { map = mapMinusKeys(map, joinSets(unshownFields, uneditableFields, data.filteredFields())); Map mapWithoutID = mapWithoutKey(map, data.idField()); List> matrix = map(mapWithoutID, (field, value) -> { String help = data.fieldHelp(field); return ll(allowFieldRenaming ? hinputfield("rename_" + field, field, "class", "field-rename", "style", "border: none; text-align: right", "title", "Edit this to rename field " + quote(field) + " or clear to delete field") : encodeField(field), addHelpText(help, renderInput(field, value))); }); massageFormMatrix(map, matrix); return htableRaw_valignTop(matrix, empty(formTableClass) ? litparams("border", 1, "cellpadding", 4) : litparams("class", formTableClass)); } finally { _close(__5); } } public String renderInput(String field, Object value) { String name = fieldPrefix + field; return renderInput(name, data.getRenderer(field, value), value); } public String renderInput(String name, HCRUD_Data.Renderer r, Object value) { if (r != null) value = r.preprocessValue(value); String meta = r == null ? "" : renderMetaInfo(r.metaInfo, name); if (r instanceof HCRUD_Data.AceEditor) { HTMLAceEditor ace = new HTMLAceEditor(strOrEmpty(value)); ace.name = name; ace.divParams.put("style", "width: " + ((HCRUD_Data.AceEditor) r).cols + "ch; height: " + ((HCRUD_Data.AceEditor) r).rows + "em"); customizeACEEditor(ace); return meta + ace.headStuff() + ace.html(); } if (r instanceof HCRUD_Data.TextArea) return meta + htextarea(strOrEmpty(value), "name", name, "cols", ((HCRUD_Data.TextArea) r).cols, "rows", ((HCRUD_Data.TextArea) r).rows); if (r instanceof HCRUD_Data.TextField) return meta + renderTextField(name, strOrEmpty(value), ((HCRUD_Data.TextField) r).cols); if (r instanceof HCRUD_Data.ComboBox) return meta + renderComboBox(name, ((HCRUD_Data.ComboBox) r).valueToEntry(value), ((HCRUD_Data.ComboBox) r).entries, ((HCRUD_Data.ComboBox) r).editable); if (r instanceof HCRUD_Data.DynamicComboBox) return meta + renderDynamicComboBox(name, ((HCRUD_Data.DynamicComboBox) r).valueToEntry(value), ((HCRUD_Data.DynamicComboBox) r).info, ((HCRUD_Data.DynamicComboBox) r).editable, ((HCRUD_Data.DynamicComboBox) r).url); if (r instanceof HCRUD_Data.CheckBox) return meta + htrickcheckboxWithText(name, "", isTrue(value)); if (r instanceof HCRUD_Data.FlexibleLengthList) { List list = (List) value; List rows = new ArrayList(); int n = l(list) + flexibleLengthListLeeway; for (int i = 0; i < n; i++) { Object item = _get(list, i); rows.add(tr(td(i + 1 + ".", "align", "right") + td(renderInput(name + "_" + i, ((HCRUD_Data.FlexibleLengthList) r).itemRenderer, item)))); } return meta + htag("table", lines(rows)); } if (r instanceof HCRUD_Data.NotEditable) return "Not editable"; return renderInput_default(name, value); } transient public IVF1 customizeACEEditor; public void customizeACEEditor(HTMLAceEditor ace) { if (customizeACEEditor != null) customizeACEEditor.get(ace); else customizeACEEditor_base(ace); } final public void customizeACEEditor_fallback(IVF1 _f, HTMLAceEditor ace) { if (_f != null) _f.get(ace); else customizeACEEditor_base(ace); } public void customizeACEEditor_base(HTMLAceEditor ace) { } public String renderMetaInfo(String metaInfo, String name) { if (empty(metaInfo)) return ""; return hhidden("metaInfo_" + dropPrefix(fieldPrefix, name), metaInfo); } public String renderInput_default(String name, Object value) { return renderTextField(name, strOrEmpty(value), defaultTextFieldCols); } public String renderTextField(String name, String value, int cols) { if (showTextFieldsAsAutoExpandingTextAreas) { return htextarea(value, "name", name, "class", "auto-expand", "style", "width: " + cols + "ch", "autofocus", eq(mapGet(params, "autofocus"), name) ? html_valueLessParam() : null, "onkeydown", jquery_submitFormOnCtrlEnter()); } return htextfield(name, value, "size", cols, "style", "font-family: monospace"); } public String renderNewForm() { return renderNewForm(data.emptyObject()); } public String renderNewFormWithParams(Map params) { Map filteredMap = subMapStartingWith_dropPrefix(params, fieldPrefix); Map map = joinMaps(data.emptyObject(), (Map) filteredMap); data.rawFormValues = params; for (Map.Entry __0 : _entrySet(filteredMap)) { String key = __0.getKey(); String value = __0.getValue(); List l = splitAt(key, "_"); if (l(l) == 2) { String field = first(l); int idx = parseInt(second(l)); List list = (List) (map.get(field)); if (!(list instanceof ArrayList)) map.put(field, list = new ArrayList()); listPut(list, idx, value); } } return renderNewForm(map); } public String renderNewForm(Map map) { String buttons = p(hsubmit("Create")); return hpostform(hhidden("action", "create") + formExtraHiddens() + stringIf(buttonsOnTop, buttons) + renderForm(map) + stringIf(buttonsOnBottom, buttons), paramsPlus(formParameters(), "action", baseLink)); } transient public IF0 formParameters; public Object[] formParameters() { return formParameters != null ? formParameters.get() : formParameters_base(); } final public Object[] formParameters_fallback(IF0 _f) { return _f != null ? _f.get() : formParameters_base(); } public Object[] formParameters_base() { return litparams("id", formID); } public String idField() { return data.idField(); } public String renderEditForm(String id) { if (!actuallyAllowEdit()) return "Can't edit objects in this table"; if (!data.objectCanBeEdited(id)) return htmlEncode2("Object " + id + " can't be edited"); Map map = data.getObjectForEdit(id); if (map == null) return htmlEncode2("Entry " + id + " not found"); String onlyFields = mapGet(params, "onlyFields"); if (nempty(onlyFields)) map = onlyKeys(map, itemPlus(idField(), tok_identifiersOnly(onlyFields))); String buttons = p_vbar(hsubmit("Save changes"), !showQuickSaveButton ? "" : hbuttonOnClick_noSubmit("Save & keep editing", "\r\n $.ajax({\r\n type: 'POST',\r\n url: $('#crudForm').attr('action'),\r\n data: $('#crudForm').serialize(), \r\n success: function(response) { successNotification(\"Saved\"); },\r\n }).error(function() { errorNotification(\"Couldn't save\"); });\r\n "), deleteObjectHTML(id)); return hpostform(hhidden("action", "update") + formExtraHiddens() + hhidden("id", id) + p("Object ID: " + htmlEncode2(id)) + stringIf(buttonsOnTop, buttons) + renderForm(map) + stringIf(buttonsOnBottom, buttons), paramsPlus(formParameters(), "action", baseLink + "#obj" + id)); } public String renderPage(Map params) { setParams(params); { String __4 = handleComboSearch(params); if (!empty(__4)) return __4; } if (eqGet(params, "cmd", "new")) { if (!actuallyAllowCreate()) return "Can't create objects in ths table"; return frame(customTitleOr("New " + itemName()), renderNewFormWithParams(params)); } if (nempty(params.get("edit"))) return frame("Edit " + itemName(), renderEditForm(params.get("edit"))); if (nempty(params.get("duplicate"))) return frame("New " + itemName(), renderNewForm(data.getObjectForDuplication(params.get("duplicate")))); String rendered = render(mutationRights, params); String title = null; if (singleton) title = ahref(baseLink, firstToUpper(data.itemName())); else { if (objectIDToHighlight != null) title = data.titleForObjectID(objectIDToHighlight); if (empty(title)) title = (showEntryCountInTitle ? n2(entryCount) + " " : "") + ahref(baseLink, firstToUpper(data.itemNamePlural())); } return frame(customTitleOr(title), rendered); } public HCRUD makeFrame(MakeFrame makeFrame) { super.makeFrame(makeFrame); return this; } public String cmdsKey() { return ""; } public String checkBoxKey() { return ""; } public String itemName() { return data.itemName(); } transient public IF2, Map, Map> postProcessTableRow; public Map postProcessTableRow(Map data, Map rendered) { return postProcessTableRow != null ? postProcessTableRow.get(data, rendered) : postProcessTableRow_base(data, rendered); } final public Map postProcessTableRow_fallback(IF2, Map, Map> _f, Map data, Map rendered) { return _f != null ? _f.get(data, rendered) : postProcessTableRow_base(data, rendered); } public Map postProcessTableRow_base(Map data, Map rendered) { return rendered; } public Object itemID(Map item) { Object id = mapGet(item, data.idField()); if (cleanItemIDs) id = htmlDecode_dropTags(strOrNull(getVarOpt(id))); return id; } public long itemIDAsLong(Map item) { return parseLong(itemID(item)); } transient public IF1, List> additionalCmds; public List additionalCmds(Map item) { return additionalCmds != null ? additionalCmds.get(item) : additionalCmds_base(item); } final public List additionalCmds_fallback(IF1, List> _f, Map item) { return _f != null ? _f.get(item) : additionalCmds_base(item); } public List additionalCmds_base(Map item) { return null; } transient public IF1, String> renderCmds; public String renderCmds(Map item) { return renderCmds != null ? renderCmds.get(item) : renderCmds_base(item); } final public String renderCmds_fallback(IF1, String> _f, Map item) { return _f != null ? _f.get(item) : renderCmds_base(item); } public String renderCmds_base(Map item) { Object id = itemID(item); List additionalCmds = additionalCmds(item); return joinNemptiesWithVBar(!actuallyAllowEdit() || !data.objectCanBeEdited(id) ? null : ahref(editLink(id), "EDIT"), deleteObjectHTML(id), !actuallyAllowCreate() ? null : targetBlankIf(duplicateInNewTab, duplicateLink(id), "dup", "title", "duplicate"), empty(additionalCmds) ? null : hPopDownButton(additionalCmds)); } public boolean actuallyAllowCreate() { return !singleton && allowCreateOrDelete && allowCreate; } public boolean actuallyAllowEdit() { return allowCreateOrDelete && allowEdit; } public boolean actuallyAllowDelete() { return !singleton && allowCreateOrDelete; } transient public IVF2, List>> massageFormMatrix; public void massageFormMatrix(Map map, List> matrix) { if (massageFormMatrix != null) massageFormMatrix.get(map, matrix); else massageFormMatrix_base(map, matrix); } final public void massageFormMatrix_fallback(IVF2, List>> _f, Map map, List> matrix) { if (_f != null) _f.get(map, matrix); else massageFormMatrix_base(map, matrix); } public void massageFormMatrix_base(Map map, List> matrix) { } public String renderComboBox(String name, String value, List entries, boolean editable) { if (haveSelectizeJS) { String id = aGlobalID(); return hselect_list(entries, value, "name", name, "id", id) + hjs("$('#" + id + "').selectize" + "\r\n ({\r\n searchField: 'text',\r\n openOnFocus: true,\r\n dropdownParent: 'body',\r\n create: " + jsBool(editable) + "\r\n /*allowEmptyOption: true*/\r\n " + unnull(moreSelectizeOptions2(name)) + "\r\n });\r\n ") + selectizeLayoutFix(); } if (haveJQuery) { String id = aGlobalID(); return tag("datalist", mapToLines(__65 -> hoption(__65), entries), "id", id) + tag("input", "", "name", name, "list", id); } if (editable) return hinputfield(name, value); return hselect_list(entries, value, "name", name); } public String renderDynamicComboBox(String name, String value, String info, boolean editable) { return renderDynamicComboBox(name, value, info, editable, null); } public String renderDynamicComboBox(String name, String value, String info, boolean editable, String url) { assertTrue("haveSelectizeJS", haveSelectizeJS); String id = aGlobalID(); String ajaxURL = or2(url, baseLink); return hselect_list(llNempties(value), value, "name", name, "id", id) + hjs("$('#" + id + "').selectize" + "\r\n ({\r\n searchField: 'text',\r\n valueField: 'text',\r\n labelField: 'text',\r\n openOnFocus: true,\r\n dropdownParent: 'body',\r\n create: " + jsBool(editable) + ",\r\n load: function(query, callback) {\r\n if (!query.length) return callback();\r\n var data = {\r\n comboSearchInfo: " + jsQuote(info) + ",\r\n comboSearchQuery: query\r\n };\r\n console.log(\"Loading \" + " + jsQuote(baseLink) + " + \" with \" + JSON.stringify(data));\r\n $.ajax({\r\n url: " + jsQuote(ajaxURL) + ",\r\n type: 'GET',\r\n dataType: 'json',\r\n data: data,\r\n error: function() {\r\n console.log(\"Got error\");\r\n callback();\r\n },\r\n success: function(res) {\r\n //console.log(\"Got data: \" + res);\r\n var converted = res.map(x => { return {text: x}; });\r\n //console.log(\"Converted: \" + converted);\r\n callback(converted);\r\n }\r\n });\r\n }\r\n /*allowEmptyOption: true*/\r\n " + moreSelectizeOptions2(name) + "\r\n });\r\n ") + selectizeLayoutFix(); } public void processSortParameter(Map params) { String sort = mapGet(params, sortParameter); if (nempty(sort)) if (startsWith(sort, "-")) { descending = true; sortByField = substring(sort, 1); } else { descending = false; sortByField = sort; } } public String deleteObjectHTML(Object id) { return !actuallyAllowDelete() ? null : !data.objectCanBeDeleted(id) ? span_title("Object can't be deleted, either there are references to it or you are not authorized", htmlEncode2(unicode_DEL())) : ahrefWithConfirm("Really delete item " + id + "?", deleteLink(id), htmlEncode2(unicode_DEL()), "title", "delete"); } public String addHelpText(String helpText, String html) { return empty(helpText) ? html : html + p(small(helpText), "style", "text-align: right"); } public String moreSelectizeOptions2(String name) { return unnull(moreSelectizeOptions(name)) + (!haveSelectizeClickable ? "" : "\r\n , plugins: ['clickable']\r\n , render: {\r\n option: function(item) {\r\n var id = item.text.match(/\\d+/)[0];\r\n return '';\r\n }\r\n }\r\n "); } transient public IF1 moreSelectizeOptions; public String moreSelectizeOptions(String name) { return moreSelectizeOptions != null ? moreSelectizeOptions.get(name) : moreSelectizeOptions_base(name); } final public String moreSelectizeOptions_fallback(IF1 _f, String name) { return _f != null ? _f.get(name) : moreSelectizeOptions_base(name); } public String moreSelectizeOptions_base(String name) { return ""; } public String handleComboSearch(Map params) { String query = params.get("comboSearchQuery"); if (nempty(query)) { String info = params.get("comboSearchInfo"); return jsonEncode_shallowLineBreaks(data.comboBoxSearch(info, query)); } return null; } transient public IF1, Map> preprocessUpdateParams; public Map preprocessUpdateParams(Map params) { return preprocessUpdateParams != null ? preprocessUpdateParams.get(params) : preprocessUpdateParams_base(params); } final public Map preprocessUpdateParams_fallback(IF1, Map> _f, Map params) { return _f != null ? _f.get(params) : preprocessUpdateParams_base(params); } public Map preprocessUpdateParams_base(Map params) { return params; } public void disableAllMutationRights() { mutationRights = allowCreateOrDelete = allowCreate = allowEdit = false; } transient public IF1 keepParamInPagination; public boolean keepParamInPagination(String name) { return keepParamInPagination != null ? keepParamInPagination.get(name) : keepParamInPagination_base(name); } final public boolean keepParamInPagination_fallback(IF1 _f, String name) { return _f != null ? _f.get(name) : keepParamInPagination_base(name); } public boolean keepParamInPagination_base(String name) { return eq(name, "search"); } public String customTitleOr(String title) { return or2(customTitle, or2(mapGet(params, "title"), title)); } transient public IF0 selectizeLayoutFix; public String selectizeLayoutFix() { return selectizeLayoutFix != null ? selectizeLayoutFix.get() : selectizeLayoutFix_base(); } final public String selectizeLayoutFix_fallback(IF0 _f) { return _f != null ? _f.get() : selectizeLayoutFix_base(); } public String selectizeLayoutFix_base() { return hcss(".selectize-input, .selectize-control { min-width: 300px }"); } public String formExtraHiddens() { String redirectAfterSave = mapGet(params, "redirectAfterSave"); return empty(redirectAfterSave) ? "" : hhidden("redirectAfterSave", redirectAfterSave); } public void processRenames(Map params) { if (!allowFieldRenaming) return; for (String key1 : keysList(params)) { String field = dropPrefixOrNull("rename_", key1); if (field == null) continue; String newName = trim(params.get(key1)); if (newName == null || eq(field, newName)) continue; print("Renaming " + field + " to " + or2(newName, "")); params.remove("rename_" + field); String re = "^([^_]+_)" + regexpQuote(field) + "(_[^_]+)?$"; for (String key : keysList(params)) { List groups = regexpGroups(re, key); if (groups != null) { String newKey = empty(newName) ? null : first(groups) + newName + unnull(second(groups)); mapPut(params, newKey, params.get(key)); params.put(key, ""); print("Renaming key: " + key + " => " + newKey); } } } } } static public class AppendableChain extends MinimalChain implements Iterable { public MinimalChain last; public int size; public AppendableChain() { } public AppendableChain(A element) { this.element = element; size = 1; last = this; } public AppendableChain(A element, AppendableChain next) { this.next = next; this.element = element; if (next == null) return; MinimalChain b = new MinimalChain(); b.element = next.element; b.next = next.next; this.next = b; last = next.last; size = next.size + 1; } public String toString() { return str(toList()); } public boolean add(A a) { MinimalChain newLast = new MinimalChain(a); last.next = newLast; last = newLast; ++size; return true; } public AppendableChain popFirst() { if (next == null) return null; element = next.element; if (last == next) last = this; next = next.next; --size; return this; } public ArrayList toList() { ArrayList l = emptyList(size); MinimalChain c = this; while (c != null) { l.add(c.element); c = c.next; } return l; } public class ACIt extends IterableIterator { public MinimalChain c = AppendableChain.this; public boolean hasNext() { return c != null; } public A next() { var a = c.element; c = c.next; return a; } } public IterableIterator iterator() { return new ACIt(); } } 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 Fail extends RuntimeException implements IFieldsToList { public Object[] objects; public Fail() { } public Fail(Object... objects) { this.objects = objects; } public Object[] _fieldsToList() { return new Object[] { objects }; } public Fail(Throwable cause, Object... objects) { super(cause); this.objects = objects; } public String toString() { return joinNemptiesWithColon("Fail", commaCombine(getCause(), objects)); } } static public class Rect implements WidthAndHeight, IFieldsToList { static final public String _fieldOrder = "x y w h"; public int x; public int y; public int w; public int h; public Rect() { } public Rect(int x, int y, int w, int h) { this.h = h; this.w = w; this.y = y; this.x = x; } public boolean equals(Object o) { if (!(o instanceof Rect)) return false; Rect __1 = (Rect) o; return x == __1.x && y == __1.y && w == __1.w && h == __1.h; } public int hashCode() { int h = 2543108; h = boostHashCombine(h, _hashCode(x)); h = boostHashCombine(h, _hashCode(y)); h = boostHashCombine(h, _hashCode(w)); h = boostHashCombine(h, _hashCode(h)); return h; } public Object[] _fieldsToList() { return new Object[] { x, y, w, h }; } public Rect(Rectangle r) { x = r.x; y = r.y; w = r.width; h = r.height; } public Rect(Pt p, int w, int h) { this.h = h; this.w = w; x = p.x; y = p.y; } public Rect(Rect r) { x = r.x; y = r.y; w = r.w; h = r.h; } final public Rectangle getRectangle() { return new Rectangle(x, y, w, h); } public String toString() { return x + "," + y + " / " + w + "," + h; } final public int x1() { return x; } final public int y1() { return y; } final public int x2() { return x + w; } final public int y2() { return y + h; } final public boolean contains(Pt p) { return contains(p.x, p.y); } final public boolean contains(int _x, int _y) { return _x >= x && _y >= y && _x < x + w && _y < y + h; } final public boolean contains(Rectangle r) { return rectContains(this, r); } final public boolean empty() { return w <= 0 || h <= 0; } final public int getWidth() { return w; } final public int getHeight() { return h; } final public int area() { return w * h; } } static public class ProgramScan { static public int threads = isWindows() ? 500 : 10; static public int timeout = 5000; static public String ip = "127.0.0.1"; static public int quickScanFrom = 10000, quickScanTo = 10999; static public int maxNumberOfVMs_android = 4; static public int maxNumberOfVMs_nonAndroid = 50; static public int maxNumberOfVMs; static public boolean verbose = false; static public class Program { public int port; public String helloString; public Program(int port, String helloString) { this.helloString = helloString; this.port = port; } } static public List scan() { try { return scan(1, 65535); } catch (Exception __e) { throw rethrow(__e); } } static public List scan(int fromPort, int toPort) { return scan(fromPort, toPort, new int[0]); } static public List scan(int fromPort, int toPort, int[] preferredPorts) { try { Set preferredPortsSet = new HashSet(asList(preferredPorts)); int scanSize = toPort - fromPort + 1; String name = toPort < 10000 ? "bot" : "program"; int threads = isWindows() ? min(500, scanSize) : min(scanSize, 10); final ExecutorService es = Executors.newFixedThreadPool(threads); if (verbose) print(firstToUpper(name) + "-scanning " + ip + " with timeout " + timeout + " ms in " + threads + " threads."); startTiming(); List> futures = new ArrayList(); List ports = new ArrayList(); for (int port : preferredPorts) { futures.add(checkPort(es, ip, port, timeout)); ports.add(port); } for (int port = fromPort; port <= toPort; port++) if (!preferredPortsSet.contains(port) && !forbiddenPort(port)) { futures.add(checkPort(es, ip, port, timeout)); ports.add(port); } es.shutdown(); List programs = new ArrayList(); long time = now(); int i = 0; for (final Future f : futures) { if (verbose) print("Waiting for port " + get(ports, i++) + " at time " + (now() - time)); Program p = f.get(); if (p != null) programs.add(p); } if (verbose) print("Found " + programs.size() + " " + name + "(s) on " + ip); return programs; } catch (Exception __e) { throw rethrow(__e); } } static public Future checkPort(final ExecutorService es, final String ip, final int port, final int timeout) { return es.submit(new Callable() { @Override public Program call() { try { Socket socket = new Socket(); try { socket.setSoTimeout(timeout); socket.connect(new InetSocketAddress(ip, port), timeout); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); String hello = or(in.readLine(), "?"); return new Program(port, hello); } finally { socket.close(); } } catch (Exception ex) { return null; } } }); } static public List quickScan() { return scan(quickScanFrom, quickScanTo); } static public List quickBotScan() { return quickBotScan(new int[0]); } static public List quickBotScan(int[] preferredPorts) { if (maxNumberOfVMs == 0) maxNumberOfVMs = isAndroid() ? maxNumberOfVMs_android : maxNumberOfVMs_nonAndroid; return scan(4999, 5000 + maxNumberOfVMs - 1, preferredPorts); } } static public class Pt implements Comparable, IDoublePt { public int x, y; public Pt() { } public Pt(Point p) { x = p.x; y = p.y; } public Pt(int x, int y) { this.y = y; this.x = x; } public Point getPoint() { return new Point(x, y); } public boolean equals(Object o) { return o instanceof Pt && x == ((Pt) o).x && y == ((Pt) o).y; } public int hashCode() { return boostHashCombine(x, y); } public int compareTo(Pt p) { if (y != p.y) return cmp(y, p.y); return cmp(x, p.x); } public String toString() { return x + ", " + y; } public double length() { return sqrt(x * x + y * y); } public Pt minus(Pt p) { return ptMinus(this, p); } public double x_double() { return x; } public double y_double() { return y; } } 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) { } } static abstract public class F0 { abstract public A get(); } static abstract public class F1 { abstract public B get(A a); } static abstract public class IterableIterator implements Iterator, Iterable { public Iterator iterator() { return this; } public void remove() { unsupportedOperation(); } } static public class TreeMultiMap extends MultiMap { public TreeMultiMap() { super(true); } public TreeMultiMap(MultiMap map) { this(); putAll(map); } } 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() { try { while (!up) { wait(); } } catch (Exception __e) { throw rethrow(__e); } } public boolean waitUntilUp(double timeout) { if (timeout == infinity()) { waitUntilUp(); return isUp(); } else return waitUntilUp(toMS(timeout)); } public synchronized boolean waitUntilUp(long timeout) { try { if (!up) { wait(timeout); } return isUp(); } catch (Exception __e) { throw rethrow(__e); } } 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 GoogleAccess { public GoogleCredential credential; public HttpTransport transport_cache; public HttpTransport transport() { if (transport_cache == null) transport_cache = transport_load(); return transport_cache; } public HttpTransport transport_load() { try { return GoogleNetHttpTransport.newTrustedTransport(); } catch (Exception __e) { throw rethrow(__e); } } public JsonFactory jsonFactory_cache; public JsonFactory jsonFactory() { if (jsonFactory_cache == null) jsonFactory_cache = jsonFactory_load(); return jsonFactory_cache; } public JsonFactory jsonFactory_load() { try { return JacksonFactory.getDefaultInstance(); } catch (Exception __e) { throw rethrow(__e); } } public GoogleClientSecrets clientSecrets_cache; public GoogleClientSecrets clientSecrets() { if (clientSecrets_cache == null) clientSecrets_cache = clientSecrets_load(); return clientSecrets_cache; } public GoogleClientSecrets clientSecrets_load() { try { InputStream in = newFileInputStream(javaxSecretDir("google-botcompany-credentials.json")); try { return GoogleClientSecrets.load(jsonFactory(), new InputStreamReader(in)); } finally { _close(in); } } catch (Exception __e) { throw rethrow(__e); } } public GoogleCredential credentialFromTokens(String accessToken, String refreshToken) { return credential = new GoogleCredential.Builder().setTransport(transport()).setJsonFactory(jsonFactory()).setClientSecrets(clientSecrets()).build().setAccessToken(accessToken).setRefreshToken(refreshToken); } public GoogleCredential credentialFromJavaXSecret() { try { return GoogleCredential.fromStream(fileInputStream(assertFileExists(javaxSecretDir("google-access.json")))); } catch (Exception __e) { throw rethrow(__e); } } } static public class SynchronizedNavigableMap extends SynchronizedSortedMap implements NavigableMap { public SynchronizedNavigableMap() { } public NavigableMap innerMap() { return (NavigableMap) m; } public SynchronizedNavigableMap(NavigableMap m) { super(m); } public SynchronizedNavigableMap(NavigableMap m, Object mutex) { super(m, mutex); } public Entry lowerEntry(K key) { synchronized (mutex) { return innerMap().lowerEntry(key); } } public K lowerKey(K key) { synchronized (mutex) { return innerMap().lowerKey(key); } } public Entry floorEntry(K key) { synchronized (mutex) { return innerMap().floorEntry(key); } } public K floorKey(K key) { synchronized (mutex) { return innerMap().floorKey(key); } } public Entry ceilingEntry(K key) { synchronized (mutex) { return innerMap().ceilingEntry(key); } } public K ceilingKey(K key) { synchronized (mutex) { return innerMap().ceilingKey(key); } } public Entry higherEntry(K key) { synchronized (mutex) { return innerMap().higherEntry(key); } } public K higherKey(K key) { synchronized (mutex) { return innerMap().higherKey(key); } } public Entry firstEntry() { synchronized (mutex) { return innerMap().firstEntry(); } } public Entry lastEntry() { synchronized (mutex) { return innerMap().lastEntry(); } } public Entry pollFirstEntry() { synchronized (mutex) { return innerMap().pollFirstEntry(); } } public Entry pollLastEntry() { synchronized (mutex) { return innerMap().pollLastEntry(); } } public NavigableMap descendingMap() { synchronized (mutex) { return new SynchronizedNavigableMap<>(innerMap().descendingMap(), mutex); } } public NavigableSet keySet() { return navigableKeySet(); } public NavigableSet navigableKeySet() { synchronized (mutex) { return new SynchronizedNavigableSet<>(innerMap().navigableKeySet(), mutex); } } public NavigableSet descendingKeySet() { synchronized (mutex) { return new SynchronizedNavigableSet<>(innerMap().descendingKeySet(), mutex); } } public SortedMap subMap(K fromKey, K toKey) { synchronized (mutex) { return new SynchronizedNavigableMap<>(innerMap().subMap(fromKey, true, toKey, false), mutex); } } public SortedMap headMap(K toKey) { synchronized (mutex) { return new SynchronizedNavigableMap<>(innerMap().headMap(toKey, false), mutex); } } public SortedMap tailMap(K fromKey) { synchronized (mutex) { return new SynchronizedNavigableMap<>(innerMap().tailMap(fromKey, true), mutex); } } public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { synchronized (mutex) { return new SynchronizedNavigableMap<>(innerMap().subMap(fromKey, fromInclusive, toKey, toInclusive), mutex); } } public NavigableMap headMap(K toKey, boolean inclusive) { synchronized (mutex) { return new SynchronizedNavigableMap<>(innerMap().headMap(toKey, inclusive), mutex); } } public NavigableMap tailMap(K fromKey, boolean inclusive) { synchronized (mutex) { return new SynchronizedNavigableMap<>(innerMap().tailMap(fromKey, inclusive), mutex); } } } public static interface IF0 { public A get(); } static public interface Hasher { public int hashCode(A a); public boolean equals(A a, A b); } static abstract public class CloseableIterableIterator extends IterableIterator implements AutoCloseable { public void close() throws Exception { } } 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 IF2 { public C get(A a, B b); } static public interface Producer { public A next(); } static public interface IF1 { public B get(A a); } static public interface IVF1 { public void get(A a); } static public interface IIntPred { public boolean get(int a); } static public class SynchronizedList extends SynchronizedCollection implements List { public SynchronizedList() { } public List list; public SynchronizedList(List list) { super(list); this.list = list; } public SynchronizedList(List list, Object mutex) { super(list, mutex); this.list = list; } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) { return list.equals(o); } } public int hashCode() { synchronized (mutex) { return list.hashCode(); } } public E get(int index) { synchronized (mutex) { return list.get(index); } } public E set(int index, E element) { synchronized (mutex) { return list.set(index, element); } } public void add(int index, E element) { synchronized (mutex) { list.add(index, element); } } public E remove(int index) { synchronized (mutex) { return list.remove(index); } } public int indexOf(Object o) { synchronized (mutex) { return list.indexOf(o); } } public int lastIndexOf(Object o) { synchronized (mutex) { return list.lastIndexOf(o); } } public boolean addAll(int index, Collection c) { synchronized (mutex) { return list.addAll(index, c); } } public ListIterator listIterator() { return list.listIterator(); } public ListIterator listIterator(int index) { return list.listIterator(index); } public List subList(int fromIndex, int toIndex) { synchronized (mutex) { return new SynchronizedList<>(list.subList(fromIndex, toIndex), mutex); } } @Override public void replaceAll(java.util.function.UnaryOperator operator) { synchronized (mutex) { list.replaceAll(operator); } } @Override public void sort(Comparator c) { synchronized (mutex) { list.sort(c); } } @java.io.Serial final public Object readResolve() { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : this); } } static public class WebChatBotMsg { public String fullHTML; public boolean fromUser = false; public String msgHTML, msgText; public String toString() { return (fromUser ? "U" : "B") + ": " + msgText; } } 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; java.lang.Module myModule = getClass().getModule(); boolean anyHiddenClasses = false; while (_c != null) { boolean exported = classIsExportedTo(_c, myModule); if (!exported) anyHiddenClasses = true; else for (Method m : _c.getDeclaredMethods()) if ((anyHiddenClasses || !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 ((anyHiddenClasses || 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 class Matches { public String[] m; public Matches() { } public Matches(String... m) { this.m = m; } public String get(int i) { return i < m.length ? m[i] : null; } public String unq(int i) { return unquote(get(i)); } public String tlc(int i) { return unq(i).toLowerCase(); } public boolean bool(int i) { return "true".equals(unq(i)); } public String rest() { return m[m.length - 1]; } public int psi(int i) { return Integer.parseInt(unq(i)); } public String toString() { return "Matches(" + joinWithComma(quoteAll(asList(m))) + ")"; } public int hashCode() { return _hashCode(toList(m)); } public boolean equals(Object o) { return o instanceof Matches && arraysEqual(m, ((Matches) o).m); } } 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 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() { } }; } default public Object getMeta(Object obj, Object key) { return metaGet(obj, key); } default public Object metaGet(Object obj, Object key) { return metaMapGet(obj, key); } default public Object metaGet(String key, Object obj) { return metaMapGet(obj, key); } default public Object getMeta(Object key) { return metaGet(key); } default public Object metaGet(Object key) { if (key == null) return null; Object meta = _getMeta(); if (meta instanceof Map) return ((Map) meta).get(key); return null; } default public void metaSet(IMeta obj, Object key, Object value) { metaPut(obj, key, value); } default public void metaPut(IMeta obj, Object key, Object value) { metaMapPut(obj, key, value); } default public void metaSet(Object key, Object value) { metaPut(key, value); } default public void metaPut(Object key, Object value) { if (key == null) return; Map map = convertObjectMetaToMap(this); syncMapPutOrRemove(map, key, value); } } static public class HCRUD_Concepts extends HCRUD_Data { public Concepts cc = db_mainConcepts(); public Class cClass; public List> onCreateOrUpdate = new ArrayList(); public List> onCreate = new ArrayList(); public IVF2> afterUpdate; public Map filters; public Map ciFilters; public IF1, Collection> customFilter; public ValueConverterForField valueConverter; public boolean referencesBlockDeletion = false; public boolean trimAllSingleLineValues = false; public Set fieldsToHideInCreationForm; public boolean lockDB = false; public boolean verbose = false; public boolean dropEmptyListValues = true; public boolean lsMagic = false; public boolean convertConceptValuesToRefs = false; public A currentConcept; public boolean useDynamicComboBoxes = false; public IF1 useDynamicComboBoxesForField; public int dynamicComboBoxesThreshold = 1000; public HCRUD_Concepts(Class cClass) { this.cClass = cClass; } public HCRUD_Concepts(Concepts cc, Class cClass) { this.cClass = cClass; this.cc = cc; } transient public IF0 itemName; public String itemName() { return itemName != null ? itemName.get() : itemName_base(); } final public String itemName_fallback(IF0 _f) { return _f != null ? _f.get() : itemName_base(); } public String itemName_base() { return humanizeShortName(cClass); } transient public IF0 itemNamePlural; public String itemNamePlural() { return itemNamePlural != null ? itemNamePlural.get() : itemNamePlural_base(); } final public String itemNamePlural_fallback(IF0 _f) { return _f != null ? _f.get() : itemNamePlural_base(); } public String itemNamePlural_base() { return super.itemNamePlural(); } public List itemsForListing() { return defaultSort(asList(listConcepts())); } @Override public List> list() { return lazyMap(itemsForListing(), a -> new Item(str(a.id)) { public Map calcFullMap() { return itemToMapForList(a); } }); } @Override public List> list(IntRange range) { return lambdaMap(__66 -> itemToMapForList(__66), subListOrFull(itemsForListing(), range)); } public Collection listConcepts() { Collection l = listConcepts_firstStep(); return postProcess(customFilter, l); } transient public IF0> listConcepts_firstStep; public Collection listConcepts_firstStep() { return listConcepts_firstStep != null ? listConcepts_firstStep.get() : listConcepts_firstStep_base(); } final public Collection listConcepts_firstStep_fallback(IF0> _f) { return _f != null ? _f.get() : listConcepts_firstStep_base(); } public Collection listConcepts_firstStep_base() { if (empty(ciFilters)) return conceptsWhere(cc, cClass, mapToParams(filters)); else if (empty(filters)) return conceptsWhereCI(cc, cClass, mapToParams(ciFilters)); else { Collection l = conceptsWhere(cc, cClass, mapToParams(filters)); return filterConceptsIC(l, mapToParams(ciFilters)); } } transient public IF0> defaultSortField; public Pair defaultSortField() { return defaultSortField != null ? defaultSortField.get() : defaultSortField_base(); } final public Pair defaultSortField_fallback(IF0> _f) { return _f != null ? _f.get() : defaultSortField_base(); } public Pair defaultSortField_base() { return pair("id", true); } transient public IF1, List> defaultSort; public List defaultSort(List l) { return defaultSort != null ? defaultSort.get(l) : defaultSort_base(l); } final public List defaultSort_fallback(IF1, List> _f, List l) { return _f != null ? _f.get(l) : defaultSort_base(l); } public List defaultSort_base(List l) { return sortedByConceptIDDesc(l); } transient public IF0 emptyConcept; public A emptyConcept() { return emptyConcept != null ? emptyConcept.get() : emptyConcept_base(); } final public A emptyConcept_fallback(IF0 _f) { return _f != null ? _f.get() : emptyConcept_base(); } public A emptyConcept_base() { return unlisted(cClass); } transient public IF0> emptyObject; public Map emptyObject() { return emptyObject != null ? emptyObject.get() : emptyObject_base(); } final public Map emptyObject_fallback(IF0> _f) { return _f != null ? _f.get() : emptyObject_base(); } public Map emptyObject_base() { A c = emptyConcept(); Map map = itemToMap(c); return mapMinusKeys(fieldsToHideInCreationForm, map); } public Map itemToMap(A c) { if (c == null) return null; return putKeysFirst(getFieldOrder(c), conceptToMap_gen_withNullValues(c)); } public Map itemToMapForList(A c) { if (c == null) return null; Map map = itemToMap(c); massageItemMapForList(c, map); return map; } transient public IVF2> massageItemMapForList; public void massageItemMapForList(A c, Map map) { if (massageItemMapForList != null) massageItemMapForList.get(c, map); else massageItemMapForList_base(c, map); } final public void massageItemMapForList_fallback(IVF2> _f, A c, Map map) { if (_f != null) _f.get(c, map); else massageItemMapForList_base(c, map); } public void massageItemMapForList_base(A c, Map map) { } transient public IVF2> massageItemMapForUpdate; public void massageItemMapForUpdate(A c, Map map) { if (massageItemMapForUpdate != null) massageItemMapForUpdate.get(c, map); else massageItemMapForUpdate_base(c, map); } final public void massageItemMapForUpdate_fallback(IVF2> _f, A c, Map map) { if (_f != null) _f.get(c, map); else massageItemMapForUpdate_base(c, map); } public void massageItemMapForUpdate_base(A c, Map map) { Collection refLFields = nonStaticNonTransientFieldObjectsOfType(Concept.RefL.class, c); printVars_str("refLFields", refLFields, "c", c); for (Field f : refLFields) { TreeMap values = new TreeMap(); Matches m = new Matches(); for (Map.Entry __2 : _entrySet(cloneMap(map))) { String key = __2.getKey(); Object value = __2.getValue(); if (startsWith(key, f.getName() + "_", m) && isInteger(m.rest())) { Concept concept = getConceptFromString((String) value); if (concept != null || !dropEmptyListValues) values.put(parseInt(m.rest()), concept); map.remove(key); } } if (!dropEmptyListValues) while (nempty(values) && lastValue(values) == null) { if (verbose) print("Dropping value " + lastEntry(values)); removeLastKey(values); } map.put(f.getName(), valuesAsList(values)); } for (String name : cloneKeys(map)) { String metaInfo = metaInfoFromForm(name); print("metaInfo for " + name + ": " + metaInfo); if (eqic(metaInfo, "concept")) replaceStringValueWithConcept(map, name); else if (eqic(metaInfo, "bool")) replaceStringValueWithBool(map, name); } for (Field f : nonStaticNonTransientFieldObjectsOfType(Concept.Ref.class, c)) replaceStringValueWithConcept(map, f.getName()); if (trimAllSingleLineValues) for (Map.Entry e : map.entrySet()) { String val = optCastString(e.getValue()); if (val != null && isSingleLine(val) && isUntrimmed(val)) e.setValue(trim(val)); } if (lsMagic) for (Field f : nonStaticNonTransientFieldObjectsOfType(List.class, c)) { if (eqOneOf(f.getName(), "refs", "backRefs")) continue; TreeMap values = new TreeMap(); Matches m = new Matches(); for (Map.Entry __1 : _entrySet(cloneMap(map))) { String key = __1.getKey(); Object value = __1.getValue(); if (startsWith(key, f.getName() + "_", m) && isInteger(m.rest())) { if (!dropEmptyListValues || nempty((String) value)) { if (verbose) print("Adding value " + m.rest() + " / " + value); mapPut(values, parseInt(m.rest()), (String) value); } map.remove(key); } } if (!dropEmptyListValues) while (nempty(values) && empty(lastValue(values))) { if (verbose) print("Dropping value " + lastEntry(values)); removeLastKey(values); } map.put(f.getName(), valuesAsList(values)); } for (Field f : nonStaticNonTransientFieldObjectsOfType(SecretValue.class, c)) map.remove(f.getName()); } public void replaceStringValueWithConcept(Map map, String key) { Object value = map.get(key); if (value instanceof String) { Concept concept = getConceptFromString((String) value); map.put(key, concept); } } public void replaceStringValueWithBool(Map map, String key) { Object value = map.get(key); if (value instanceof String) { map.put(key, englishStringToBool((String) value)); } } transient public IF1> getObject; public Map getObject(Object id) { return getObject != null ? getObject.get(id) : getObject_base(id); } final public Map getObject_fallback(IF1> _f, Object id) { return _f != null ? _f.get(id) : getObject_base(id); } public Map getObject_base(Object id) { return itemToMap(conceptForID(id)); } public Map getObjectForEdit(Object id) { currentConcept = conceptForID(id); return getObject(id); } public Object createObject(Map fullMap, String fieldPrefix) { rawFormValues = fullMap; try { Map map = extractFieldValues(fullMap, fieldPrefix); A c = cnew(cc, cClass); setValues(c, mapMinusKeys(map, filteredFields()), true); cset(c, mapToParams(filters)); cset(c, mapToParams(ciFilters)); pcallFAll(onCreate, c); pcallFAll(onCreateOrUpdate, c); callOpt(c, "_onCreated"); return c.id; } finally { rawFormValues = null; } } public void setValues(A c, Map map, boolean creating) { Lock __3 = lockDB && !creating ? dbLock(cc) : null; lock(__3); try { Map map2 = (Map) cloneMap(map); massageItemMapForUpdate(c, map2); if (verbose) { print("setValues " + map); print("backRefs: " + c.backRefs); } Map oldValues = !creating && afterUpdate != null ? cgetAll_cloneLists(c, keys(map2)) : null; if (convertConceptValuesToRefs) convertAllConceptValuesToRefs(c, map2); if (valueConverter == null) cSmartSet(c, mapToParams(map2)); else cSmartSet_withConverter_pcall(verbose, valueConverter, c, mapToParams(map2)); if (oldValues != null) callF(afterUpdate, c, oldValues); if (verbose) print("backRefs: " + c.backRefs); } finally { unlock(__3); } } public void convertAllConceptValuesToRefs(A c, Map map) { for (Map.Entry __0 : _entrySet(cloneMap(map))) { String key = __0.getKey(); Object value = __0.getValue(); if (value instanceof Concept) if (!hasField(c, key)) { print("Converting value to ref: " + key); map.put(key, c.new Ref((Concept) value)); } } } public A conceptForID(Object id) { return _getConcept(cc, cClass, toLong(id)); } public String updateObject(Object id, Map fullMap, String fieldPrefix) { rawFormValues = fullMap; try { Map map = extractFieldValues(fullMap, fieldPrefix); A c = conceptForID(id); if (c == null) return "Object " + id + " not found"; { String __5 = checkFilters(c); if (!empty(__5)) return __5; } setValues(c, map, false); pcallFAll(onCreateOrUpdate, c); return "Object " + id + " updated"; } finally { rawFormValues = null; } } public String deleteObject(Object id) { A c = conceptForID(id); if (c == null) return "Object " + id + " not found"; { String __6 = checkFilters(c); if (!empty(__6)) return __6; } actuallyDeleteConcept(c); return "Object " + id + " deleted"; } transient public IVF1 actuallyDeleteConcept; public void actuallyDeleteConcept(A c) { if (actuallyDeleteConcept != null) actuallyDeleteConcept.get(c); else actuallyDeleteConcept_base(c); } final public void actuallyDeleteConcept_fallback(IVF1 _f, A c) { if (_f != null) _f.get(c); else actuallyDeleteConcept_base(c); } public void actuallyDeleteConcept_base(A c) { deleteConcept(c); } public String checkFilters(A c) { if (!checkConceptFields(c, mapToParams(filters)) || !checkConceptFieldsIC(c, mapToParams(ciFilters))) return "Object " + c.id + " not in view"; return ""; } public HCRUD_Concepts addFilters(Map map) { for (Map.Entry __7 : _entrySet(unnullForIteration(map))) { String field = __7.getKey(); Object value = __7.getValue(); addFilter(field, value); } return this; } public HCRUD_Concepts addFilter(String field, Object value) { filters = orderedMapPutOrCreate(filters, field, value); return this; } transient public IF1 isEditableValue; public boolean isEditableValue(Object value) { return isEditableValue != null ? isEditableValue.get(value) : isEditableValue_base(value); } final public boolean isEditableValue_fallback(IF1 _f, Object value) { return _f != null ? _f.get(value) : isEditableValue_base(value); } public boolean isEditableValue_base(Object value) { if (value instanceof List) return true; if (value instanceof Collection) return false; return true; } public Renderer getRenderer(String field) { if (!isEditableValue(currentValue)) return new NotEditable(); Class type = fieldType(or(currentConcept, cClass), field); String metaInfo = metaInfoFromForm(field); if (eq(type, boolean.class)) return new CheckBox(); if (eq(type, Boolean.class)) return new ComboBox(ll("", "yes", "no"), b -> trueFalseNull((Boolean) b, "yes", "no", "")); if (isSubtypeOf(type, Concept.Ref.class)) { Class c = fieldTypeArg(field); AbstractComboBox cb = makeConceptsComboBox(field, c); cb.metaInfo = "concept"; return cb; } Object val = deref(currentValue); if (val instanceof Concept) { Class c = ((Concept) val).getClass(); AbstractComboBox cb = makeConceptsComboBox(field, c); cb.metaInfo = "concept"; return cb; } if (eqic(metaInfo, "concept")) { printVars_str("metaInfo value", "field", field, "val", val); AbstractComboBox cb = makeConceptsComboBox(field, Concept.class); cb.metaInfo = "concept"; return cb; } if (eq(type, Concept.RefL.class)) { Class c = fieldTypeArg(field); return new FlexibleLengthList(makeConceptsComboBox(field, c)); } if (eq(type, List.class)) { return new FlexibleLengthList(new TextField(80)); } if (val instanceof Boolean) return new CheckBox(); return super.getRenderer(field); } public DynamicComboBox makeDynamicComboBox(String field, Class c) { DynamicComboBox cb = new DynamicComboBox(field); cb.valueToEntry = value -> { value = deref(value); long id = 0; if (value instanceof Concept) id = conceptID((Concept) value); else if (value instanceof String && isInteger((String) value)) id = parseLong(value); if (id != 0) return comboBoxItem(_getConcept(cc, id)); return null; }; return cb; } public AbstractComboBox makeConceptsComboBox(String field, Class c) { if (c == null) throw fail(("Null type for field " + field + ". currentConcept: ") + currentConcept); if (useDynamicComboBoxes || useDynamicComboBoxesForField != null && useDynamicComboBoxesForField.get(field)) return makeDynamicComboBox(field, c); Collection concepts = listConceptClass(c); if (l(concepts) >= dynamicComboBoxesThreshold) return makeDynamicComboBox(field, c); List entries = comboBoxItems(concepts); ComboBox cb = new ComboBox(entries); cb.valueToEntry = value -> { value = deref(value); long id = 0; if (value instanceof Concept) id = conceptID((Concept) value); else if (value instanceof String && isInteger((String) value)) id = parseLong(value); if (id != 0) { String entry = firstWhereFirstLongIs(entries, id); return entry; } return null; }; return cb; } public Collection listConceptClass(Class c) { return cc.list(c); } public List comboBoxItemsForConceptClass(Class c) { return comboBoxItems(listConceptClass(c)); } public List comboBoxItems(Collection l) { return comboBoxItems_static(l); } static public List comboBoxItems_static(Collection l) { return itemPlus("", lmap(__67 -> comboBoxItem_static(__67), l)); } public String comboBoxItem(Concept val) { return comboBoxItem_static(val); } static public String comboBoxItem_static(Concept val) { return val == null ? null : shorten(val.id + ": " + val); } transient public IF1 objectCanBeDeleted; public boolean objectCanBeDeleted(Object id) { return objectCanBeDeleted != null ? objectCanBeDeleted.get(id) : objectCanBeDeleted_base(id); } final public boolean objectCanBeDeleted_fallback(IF1 _f, Object id) { return _f != null ? _f.get(id) : objectCanBeDeleted_base(id); } public boolean objectCanBeDeleted_base(Object id) { return !referencesBlockDeletion || !hasBackRefs(conceptForID(id)); } public Set filteredFields() { return joinSets(keys(filters), keys(ciFilters)); } public Class fieldTypeArg(String field) { return getTypeArgumentAsClass(genericFieldType(or(currentConcept, cClass), field)); } transient public IF2> conceptClassForComboBoxSearch; public Class conceptClassForComboBoxSearch(String info, String query) { return conceptClassForComboBoxSearch != null ? conceptClassForComboBoxSearch.get(info, query) : conceptClassForComboBoxSearch_base(info, query); } final public Class conceptClassForComboBoxSearch_fallback(IF2> _f, String info, String query) { return _f != null ? _f.get(info, query) : conceptClassForComboBoxSearch_base(info, query); } public Class conceptClassForComboBoxSearch_base(String info, String query) { if (!isIdentifier(info)) return cClass; String field = info; Class c = fieldTypeArg(field); if (c == null) c = cClass; return c; } transient public IF2> comboBoxSearchBaseItems; public List comboBoxSearchBaseItems(String info, String query) { return comboBoxSearchBaseItems != null ? comboBoxSearchBaseItems.get(info, query) : comboBoxSearchBaseItems_base(info, query); } final public List comboBoxSearchBaseItems_fallback(IF2> _f, String info, String query) { return _f != null ? _f.get(info, query) : comboBoxSearchBaseItems_base(info, query); } public List comboBoxSearchBaseItems_base(String info, String query) { var c = conceptClassForComboBoxSearch(info, query); if (c == null) return emptyList(); return comboBoxItemsForConceptClass(c); } public List comboBoxSearch(String info, String query) { List items = comboBoxSearchBaseItems(info, query); return takeFirst(10, scoredSearch(query, items)); } public A conceptForMap(Map map) { if (map == null) return null; long id = toLong(map.get(idField())); return id == 0 ? null : (A) _getConcept(cc, id); } public A getConcept(Map map) { return conceptForMap(map); } public Map extractFieldValues(Map fullMap, String fieldPrefix) { return subMapStartingWith_dropPrefix(fullMap, fieldPrefix); } public Concept getConceptFromString(String s) { long conceptID = parseFirstLong(s); return _getConcept(cc, conceptID); } public String metaInfoFromForm(String field) { return mapGet(rawFormValues, "metaInfo_" + field); } public void addCIFilter(String field, String value) { ciFilters = putOrCreate(ciFilters, field, value); } transient public IF1 titleForObjectID; public String titleForObjectID(Object id) { return titleForObjectID != null ? titleForObjectID.get(id) : titleForObjectID_base(id); } final public String titleForObjectID_fallback(IF1 _f, Object id) { return _f != null ? _f.get(id) : titleForObjectID_base(id); } public String titleForObjectID_base(Object id) { return htmlEncode2(strOrNull(conceptForID(id))); } } 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 { try { vmBus_send("threadStarted", this); if (target != null) target.run(); } finally { vmBus_send("threadEnded", this); } } catch (Exception __e) { throw rethrow(__e); } } public Runnable getTarget() { return target; } } 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 long unixDate() { return date; } public String toString() { return formatLocalDateWithSeconds(date); } public int compareTo(Timestamp t) { return t == null ? 1 : cmp(date, t.date); } public Timestamp plus(Seconds seconds) { return plus(seconds == null ? null : seconds.getDouble()); } final public Timestamp plusSeconds(double seconds) { return plus(seconds); } public Timestamp plus(double seconds) { return new Timestamp(date + toMS(seconds)); } public long minus(Timestamp ts) { return unixDate() - ts.unixDate(); } public long sysTime() { return clockTimeToSystemTime(date); } public Duration minusAsDuration(Timestamp ts) { return Duration.ofMillis(minus(ts)); } } static public class GazelleV_LeftArrowScriptParser extends SimpleLeftToRightParser { public ClassNameResolver classNameResolver; public List functionContainers = new ArrayList(); final public GazelleV_LeftArrowScriptParser setLasClassLoader(ILASClassLoader lasClassLoader) { return lasClassLoader(lasClassLoader); } public GazelleV_LeftArrowScriptParser lasClassLoader(ILASClassLoader lasClassLoader) { this.lasClassLoader = lasClassLoader; return this; } final public ILASClassLoader getLasClassLoader() { return lasClassLoader(); } public ILASClassLoader lasClassLoader() { return lasClassLoader; } public ILASClassLoader lasClassLoader; final public GazelleV_LeftArrowScriptParser setClassDefPrefix(String classDefPrefix) { return classDefPrefix(classDefPrefix); } public GazelleV_LeftArrowScriptParser classDefPrefix(String classDefPrefix) { this.classDefPrefix = classDefPrefix; return this; } final public String getClassDefPrefix() { return classDefPrefix(); } public String classDefPrefix() { return classDefPrefix; } public String classDefPrefix; final public GazelleV_LeftArrowScriptParser setOptimize(boolean optimize) { return optimize(optimize); } public GazelleV_LeftArrowScriptParser optimize(boolean optimize) { this.optimize = optimize; return this; } final public boolean getOptimize() { return optimize(); } public boolean optimize() { return optimize; } public boolean optimize = true; final public GazelleV_LeftArrowScriptParser setUseFixedVarContexts(boolean useFixedVarContexts) { return useFixedVarContexts(useFixedVarContexts); } public GazelleV_LeftArrowScriptParser useFixedVarContexts(boolean useFixedVarContexts) { this.useFixedVarContexts = useFixedVarContexts; return this; } final public boolean getUseFixedVarContexts() { return useFixedVarContexts(); } public boolean useFixedVarContexts() { return useFixedVarContexts; } public boolean useFixedVarContexts = false; public LASScope scope; public LinkedHashMap knownVars = new LinkedHashMap(); public List varAccessesToFix = new ArrayList(); public Set closerTokens = litset(";", "}", ")"); public BuildingScript currentReturnableScript; public BuildingScript currentLoop; public boolean inParens = false; public int idCounter; public Map classDefs = new HashMap(); transient public Set>> onKnownVarsSnapshot; public GazelleV_LeftArrowScriptParser onKnownVarsSnapshot(IVF1> f) { onKnownVarsSnapshot = createOrAddToSyncLinkedHashSet(onKnownVarsSnapshot, f); return this; } public GazelleV_LeftArrowScriptParser removeKnownVarsSnapshotListener(IVF1> f) { main.remove(onKnownVarsSnapshot, f); return this; } public void knownVarsSnapshot(Map knownVars) { if (onKnownVarsSnapshot != null) for (var listener : onKnownVarsSnapshot) pcallF_typed(listener, knownVars); } static public class MethodOnObject implements IFieldsToList { static final public String _fieldOrder = "object method"; public Object object; public String method; public MethodOnObject() { } public MethodOnObject(Object object, String method) { this.method = method; this.object = object; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + object + ", " + method + ")"; } public boolean equals(Object o) { if (!(o instanceof MethodOnObject)) return false; MethodOnObject __15 = (MethodOnObject) o; return eq(object, __15.object) && eq(method, __15.method); } public int hashCode() { int h = 791808543; h = boostHashCombine(h, _hashCode(object)); h = boostHashCombine(h, _hashCode(method)); return h; } public Object[] _fieldsToList() { return new Object[] { object, method }; } } static public class EvaluableWrapper implements IFieldsToList { public GazelleV_LeftArrowScript.Evaluable expr; public EvaluableWrapper() { } public EvaluableWrapper(GazelleV_LeftArrowScript.Evaluable expr) { this.expr = expr; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + expr + ")"; } public boolean equals(Object o) { if (!(o instanceof EvaluableWrapper)) return false; EvaluableWrapper __16 = (EvaluableWrapper) o; return eq(expr, __16.expr); } public int hashCode() { int h = 700525824; h = boostHashCombine(h, _hashCode(expr)); return h; } public Object[] _fieldsToList() { return new Object[] { expr }; } } public class BuildingScript { public int id = ++idCounter; final public BuildingScript setReturnable(boolean returnable) { return returnable(returnable); } public BuildingScript returnable(boolean returnable) { this.returnable = returnable; return this; } final public boolean getReturnable() { return returnable(); } public boolean returnable() { return returnable; } public boolean returnable = false; final public BuildingScript setIsLoopBody(boolean isLoopBody) { return isLoopBody(isLoopBody); } public BuildingScript isLoopBody(boolean isLoopBody) { this.isLoopBody = isLoopBody; return this; } final public boolean getIsLoopBody() { return isLoopBody(); } public boolean isLoopBody() { return isLoopBody; } public boolean isLoopBody = false; public BuildingScript returnableParent, loopParent; final public BuildingScript setScope(LASScope scope) { return scope(scope); } public BuildingScript scope(LASScope scope) { this.scope = scope; return this; } final public LASScope getScope() { return scope(); } public LASScope scope() { return scope; } public LASScope scope; public GazelleV_LeftArrowScript.Script script = new GazelleV_LeftArrowScript.Script(); public List steps = new ArrayList(); public Map functionDefs = new HashMap(); public BuildingScript(boolean returnable) { this(); this.returnable = returnable; } public BuildingScript(boolean returnable, boolean isLoopBody) { this(); this.isLoopBody = isLoopBody; this.returnable = returnable; } public BuildingScript() { scope = currentScope(); } public void add(GazelleV_LeftArrowScript.Evaluable step) { if (step != null) steps.add(step); } public GazelleV_LeftArrowScript.Evaluable get() { script.scope = scope; var lastStep = last(steps); if (lastStep instanceof GazelleV_LeftArrowScript.ReturnFromScript) if (((GazelleV_LeftArrowScript.ReturnFromScript) lastStep).script == script) replaceLast(steps, ((GazelleV_LeftArrowScript.ReturnFromScript) lastStep).value); if (!returnable && l(steps) == 1 && empty(functionDefs)) return first(steps); if (nempty(functionDefs)) script.functionDefs = functionDefs; script.steps = toTypedArray(GazelleV_LeftArrowScript.Evaluable.class, steps); return script; } public String toStringLong() { return pnlToLines(steps); } public String toString() { return formatRecordVars("BuildingScript", "id", id, "returnable", returnable, "returnableParent", returnableParent, "script", script); } } public GazelleV_LeftArrowScript.Script parse(String text) { setText(text); init(); return parse(); } public GazelleV_LeftArrowScript.Script parse() { GazelleV_LeftArrowScript.Script script = parseReturnableScript(); for (var varAccess : varAccessesToFix) varAccess.resolve(); if (optimize) script = script.optimizeScript(); return script; } public GazelleV_LeftArrowScript.Script parseReturnableScript() { return (GazelleV_LeftArrowScript.Script) parseScript(new BuildingScript().returnable(true)); } public GazelleV_LeftArrowScript.Evaluable parseScript(BuildingScript script) { return linkToSrc(() -> { script.returnableParent = currentReturnableScript; script.loopParent = currentLoop; if (script.returnable) currentReturnableScript = script; if (script.isLoopBody) currentLoop = script; return parseBuildingScript(script); }); } public GazelleV_LeftArrowScript.Evaluable parseBuildingScript(BuildingScript script) { try { parseScript_2(script); var builtScript = script.get(); currentReturnableScript = script.returnableParent; currentLoop = script.loopParent; return builtScript; } catch (Throwable e) { if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("Parsed so far:\n" + script); throw rethrowAndAppendToMessage(e, squareBracketed(str(lineAndColumn(-1)))); } } public void parseScript_2(BuildingScript script) { AutoCloseable __6 = tempRestoreMap(knownVars); try { AssureAdvance assure = new AssureAdvance(); while (assure.get()) { knownVarsSnapshot(knownVars); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("parseScript_2: Next token is " + quote(token())); if (is(";")) { next(); continue; } if (isOneOf("}", ")")) break; GazelleV_LeftArrowScript.Evaluable instruction = linkToSrc(() -> parseInstruction(script)); if (instruction != null) script.add(instruction); } if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("parseScript_2 done"); knownVarsSnapshot(knownVars); } finally { _close(__6); } } public GazelleV_LeftArrowScript.Evaluable parseInstruction(BuildingScript script) { if (is("def")) { parseFunctionDefinition(currentReturnableScript.functionDefs); return null; } if (is("param")) { consume(); String var = assertIdentifier(tpp()); LASValueDescriptor valueDescriptor = new LASValueDescriptor(); if (is(":")) { var type = parseColonType(); valueDescriptor = LASValueDescriptor.nonExactCanBeNull(type); } knownVars.put(var, valueDescriptor); return null; } if (is("throw")) { consume(); return new GazelleV_LeftArrowScript.Throw(parseExpr()); } if (is("try")) { consume(); GazelleV_LeftArrowScript.Evaluable body = parseCurlyBlock(new BuildingScript()); consume("catch"); String var = consumeIdentifier(); AutoCloseable __7 = tempAddKnownVars(var); try { GazelleV_LeftArrowScript.Evaluable catchBlock = parseCurlyBlock(new BuildingScript()); return new GazelleV_LeftArrowScript.TryCatch(body, var, catchBlock); } finally { _close(__7); } } if (isOneOf("return", "ret")) { consume(); GazelleV_LeftArrowScript.Evaluable expr; if (atCmdEnd()) expr = _const(null); else expr = parseAssignmentOrExpr(); return new GazelleV_LeftArrowScript.ReturnFromScript(currentReturnableScript.script, expr); } if (is("continue")) { consume(); assertCmdEnd(); if (currentLoop == null) throw fail("continue outside of loop"); return new GazelleV_LeftArrowScript.Continue(currentLoop.script); } if (is("temp")) { consume(); GazelleV_LeftArrowScript.Evaluable tempExpr = parseExpr(); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("tempExpr", tempExpr); GazelleV_LeftArrowScript.Evaluable body = parseScript(new BuildingScript()); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("body", body); return new GazelleV_LeftArrowScript.TempBlock(tempExpr, body); } if (is("class")) return new GazelleV_LeftArrowScript.ClassDef(new ResolvableLASClass(lasClassLoader, parseClassDef())); return parseAssignmentOrExpr(); } public GazelleV_LeftArrowScript.Evaluable parseAssignmentOrExpr() { { var __3 = parseAssignmentOpt(); if (__3 != null) return __3; } return parseExpr(); } public GazelleV_LeftArrowScript.Evaluable parseAssignmentOpt() { String t = token(); if (isIdentifier(t) && eq(token(1), "<") && eq(token(2), "-")) { if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("Found assignment"); next(3); GazelleV_LeftArrowScript.Evaluable rhs = parseExpr(); assertNotNull("Expression expected", rhs); boolean newVar = !knownVars.containsKey(t); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) printVars("newVar", newVar, "t", t, "knownVars", knownVars); knownVars.put(t, new LASValueDescriptor()); return newVar ? new GazelleV_LeftArrowScript.VarDeclaration(t, null, rhs) : new GazelleV_LeftArrowScript.Assignment(t, rhs); } return null; } public GazelleV_LeftArrowScript.Evaluable parseOptionalInnerExpression() { if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) printVars("parseOptionalInnerExpression", "token", token()); if (atCmdEnd() || isOneOf("{", ",")) return null; return parseInnerExpr(); } public GazelleV_LeftArrowScript.Evaluable _const(Object o) { return new GazelleV_LeftArrowScript.Const(o); } public GazelleV_LeftArrowScript.Evaluable parseInnerExpr() { return parseExpr(true); } public GazelleV_LeftArrowScript.Evaluable parseExpr() { if (metaGet("scaffolding") != null) scaffoldCalled(this, "parseExpr"); return parseExpr(false); } public GazelleV_LeftArrowScript.Evaluable parseExpr(boolean inner) { GazelleV_LeftArrowScript.Evaluable e = linkToSrc(() -> inner ? parseExpr_impl(true) : parseExprPlusOptionalComma()); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("parseExpr done:\n" + GazelleV_LeftArrowScript.indentedScriptStruct(e)); return e; } public GazelleV_LeftArrowScript.Evaluable parseExprPlusOptionalComma() { GazelleV_LeftArrowScript.Evaluable expr = parseExpr_impl(false); while (consumeOpt(",")) { expr = parseCall_noCmdEndCheck(expr); } return expr; } public GazelleV_LeftArrowScript.Evaluable parseExpr_impl(boolean inner) { if (atEnd()) return null; String t = token(); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) printVars("parseExpr", "token", t); if (is(";")) return null; if (is("{")) return parseCurlyBlock(new BuildingScript()); if (is("-") && empty(nextSpace()) && startsWithDigit(token(1)) || startsWithDigit(t)) { var e = parseNumberLiteral(); return inner ? e : parseCall(e); } if (isQuoted(t)) { consume(); var e = _const(unquote(t)); return inner ? e : parseCall(e); } if (startsWith(t, '\'')) { consume(); var e = _const(first(unquote(t))); return inner ? e : parseCall(e); } if (isIdentifier(t)) { if (is("while")) return parseWhileLoop(); if (is("for")) return parseForEach(); if (is("if")) return parseIfStatement(); if (is("repeat")) return parseRepeatStatement(); if (is("outer")) { consume(); var a = parseAssignmentOpt(); if (!(a instanceof GazelleV_LeftArrowScript.Assignment)) throw fail("Assignment expected"); return new GazelleV_LeftArrowScript.AssignmentToOuterVar(((GazelleV_LeftArrowScript.Assignment) a).var, ((GazelleV_LeftArrowScript.Assignment) a).expression); } consume(); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("Consumed identifier " + t + ", next token: " + token() + ", inner: " + inner); return parseExprStartingWithIdentifier(t, inner); } if (eq(t, "(")) { boolean inParensOld = inParens; inParens = true; consume(); var e = parseExpr(); consume(")"); inParens = inParensOld; return inner ? e : parseCall(e); } if (isOneOf("&", "|") && empty(nextSpace()) && is(1, token())) { return parseBinaryOperator(); } throw fail("Identifier, literal, operator or opening parentheses expected (got: " + quote(t)); } public GazelleV_LeftArrowScript.Evaluable parseNumberLiteral() { String t = consumeMultiTokenLiteral(); if (swic(t, "0x")) return _const(parseHexInt(dropFirst(t, 2))); if (swic(t, "0b")) return _const(intFromBinary(dropFirst(t, 2))); if (isInteger(t)) return _const(parseInt(t)); if (endsWith(t, "f")) return _const(parseFloat(t)); if (endsWith(t, "L")) return _const(parseLong(t)); return _const(parseDouble(t)); } public GazelleV_LeftArrowScript.Evaluable parseBinaryOperator() { boolean and = is("&"); next(2); GazelleV_LeftArrowScript.Evaluable a = parseInnerExpr(); GazelleV_LeftArrowScript.Evaluable b = parseInnerExpr(); return and ? new GazelleV_LeftArrowScript.BoolAnd(a, b) : new GazelleV_LeftArrowScript.BoolOr(a, b); } public boolean qualifiedNameContinues() { return empty(prevSpace()) && eq(token(), ".") && empty(nextSpace()) && isIdentifier(token(1)); } public GazelleV_LeftArrowScript.Evaluable parseExprStartingWithIdentifier(String t, boolean inner) { if (eq(t, "true")) return _const(true); if (eq(t, "false")) return _const(false); if (eq(t, "null")) return _const(null); if (eq(t, "new")) { String className = assertIdentifier(tpp()); parseTypeArguments(null); LASClassDef cd = classDefs.get(className); if (cd != null) return new GazelleV_LeftArrowScript.NewObject_LASClass(new ResolvableLASClass(lasClassLoader, cd)); var type = knownVars.get(className); if (type != null) return new GazelleV_LeftArrowScript.NewObject_UnknownClass(new GazelleV_LeftArrowScript.GetVar(className), parseArguments()); Object o = findExternalObject(className); if (o instanceof Class) { Class c = (Class) o; if (c == List.class) c = ArrayList.class; else if (c == Map.class) c = HashMap.class; else if (c == Set.class) c = HashSet.class; return new GazelleV_LeftArrowScript.NewObject(c, parseArguments()); } throw new ClassNotFound(className); } if (scope != null && scope.useFixedVars) { var type = scope.declaredVars.get(t); if (type != null) { var e = new GazelleV_LeftArrowScript.GetFixedVar(scope, t); e.scope(scope); e.returnType(type); varAccessesToFix.add(e); return inner ? e : parseCall(e); } } var type = knownVars.get(t); if (type != null) { var e = new GazelleV_LeftArrowScript.GetVar(t).returnType(type); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("Found var acccess: " + e + ", " + (!inner ? "Checking for call" : "Returning expression")); return inner ? e : parseCall(e); } if (!inner) { var fdef = lookupFunction(t); if (fdef != null) return new GazelleV_LeftArrowScript.CallFunction(fdef, parseArguments()); } if (eq(t, "_context")) return new GazelleV_LeftArrowScript.GetVarContext(); Object o = findExternalObject(t); if (o == null) { throw new UnknownObject(t); } else if (o instanceof EvaluableWrapper) { return inner ? ((EvaluableWrapper) o).expr : parseCall(((EvaluableWrapper) o).expr); } else if (inner) return _const(o); else if (o instanceof Class) { return parseExprStartingWithClass((Class) o); } else if (o instanceof MethodOnObject) { if (inner) throw fail("Can't call methods in arguments"); return new GazelleV_LeftArrowScript.CallMethod(_const(((MethodOnObject) o).object), ((MethodOnObject) o).method, parseArguments()); } else return parseCall(_const(o)); } public GazelleV_LeftArrowScript.Evaluable parseExprStartingWithClass(Class c) { if (atCmdEnd()) return _const(c); if (is("(")) return new GazelleV_LeftArrowScript.NewObject(c, parseArguments()); { var __4 = parseLambdaOpt(c); if (__4 != null) return __4; } if (isIdentifier()) { String name = tpp(); if (hasStaticMethodNamed(c, name)) return new GazelleV_LeftArrowScript.CallMethod(_const(c), name, parseArguments()); if (isInterface(c)) return parseLambdaMethodRef(c, name); var field = getField(c, name); if (field != null) { assertCmdEnd(); if (!isStaticField(field)) throw fail(field + " is not a static field"); return new GazelleV_LeftArrowScript.GetStaticField(field); } throw fail(name + " not found in " + c + " (looked for method or field)"); } else throw fail("Method name expected: " + token()); } public GazelleV_LeftArrowScript.Evaluable parseLambdaOpt(Class c) { int nArgs = 0; while (isIdentifier(token(nArgs))) nArgs++; if (!(is(nArgs, "-") && is(nArgs + 1, ">"))) return null; String[] argNames = consumeArray(nArgs); AutoCloseable __8 = tempAddKnownVars(argNames); try { skip(2); GazelleV_LeftArrowScript.Evaluable body; if (is("{")) body = parseReturnableScript(); else body = parseExpr(); var lambda = new GazelleV_LeftArrowScript.LambdaDef(c, argNames, body); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("parseLambdaOpt done:\n" + GazelleV_LeftArrowScript.indentedScriptStruct(lambda)); return lambda; } finally { _close(__8); } } public GazelleV_LeftArrowScript.Evaluable parseLambdaMethodRef(Class c, String name) { var fdef = lookupFunction(name); if (fdef != null) { GazelleV_LeftArrowScript.Evaluable[] curriedArguments = parseArguments(); return new GazelleV_LeftArrowScript.CurriedScriptFunctionLambda(c, fdef, curriedArguments); } Object function = findExternalObject(name); if (function == null) throw new UnknownObject(name); if (function instanceof MethodOnObject) { Object target = ((MethodOnObject) function).object; String targetMethod = ((MethodOnObject) function).method; GazelleV_LeftArrowScript.Evaluable[] curriedArguments = parseArguments(); return new GazelleV_LeftArrowScript.CurriedMethodLambda(c, target, targetMethod, curriedArguments); } else if (function instanceof Class) { Class c2 = (Class) function; assertCmdEnd(); var ctors = constructorsWithNumberOfArguments(c2, 1); if (empty(ctors)) throw fail("No single argument constructor found in " + c2); return new GazelleV_LeftArrowScript.CurriedConstructorLambda(c, toArray(Constructor.class, ctors), null); } else throw fail(function + " is not an instantiable class or callable method"); } public GazelleV_LeftArrowScript.FunctionDef lookupFunction(String name) { var script = currentReturnableScript; while (script != null) { var f = script.functionDefs.get(name); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) printVars("lookupFunction", "script", script, "name", name, "f", f); if (f != null) return f; script = script.returnableParent; } return null; } public GazelleV_LeftArrowScript.Evaluable[] parseArguments() { return toArrayOrNull(GazelleV_LeftArrowScript.Evaluable.class, parseArgumentsAsList()); } public List parseArgumentsAsList() { List l = new ArrayList(); try { while (true) { GazelleV_LeftArrowScript.Evaluable a = parseOptionalInnerExpression(); if (a == null) break; l.add(a); } return l; } catch (Throwable _e) { if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("Arguments parsed so far: " + l); throw rethrow(_e); } } public String consumeMultiTokenLiteral() { return consumeUntilSpaceOr(() -> atCmdEnd() || is(",")); } public boolean atCmdEnd() { return !inParens && atEndOrLineBreak() || closerTokens.contains(token()); } public void assertCmdEnd() { if (!atCmdEnd()) throw fail("Expected end of command, token is: " + quote(token())); } public GazelleV_LeftArrowScript.Evaluable parseCall(GazelleV_LeftArrowScript.Evaluable target) { if (atCmdEnd()) return target; return parseCall_noCmdEndCheck(target); } public GazelleV_LeftArrowScript.Evaluable parseCall_noCmdEndCheck(GazelleV_LeftArrowScript.Evaluable target) { if (!isIdentifier()) return target; var start = ptr(); String name = tpp(); if (eq(token(), "<") && eq(token(1), "-")) { next(2); GazelleV_LeftArrowScript.Evaluable rhs = parseExpr(); return new GazelleV_LeftArrowScript.SetField(target, name, rhs); } var args = parseArguments(); if (nempty(args)) return new GazelleV_LeftArrowScript.CallMethod(target, name, args); else return linkToSrc(start, new GazelleV_LeftArrowScript.CallMethodOrGetField(target, name)); } public A linkToSrc(ListAndIndex start, A a) { if (a instanceof IHasTokenRangeWithSrc) ((IHasTokenRangeWithSrc) a).setTokenRangeWithSrc(new TokenRangeWithSrc(start, ptr().plus(-1))); return a; } public A linkToSrc(IF0 a) { var start = ptr(); return linkToSrc(start, a.get()); } transient public IF1 findExternalObject; public Object findExternalObject(String name) { return findExternalObject != null ? findExternalObject.get(name) : findExternalObject_base(name); } final public Object findExternalObject_fallback(IF1 _f, String name) { return _f != null ? _f.get(name) : findExternalObject_base(name); } public Object findExternalObject_base(String name) { { var __5 = parsePrimitiveType(name); if (__5 != null) return __5; } if (qualifiedNameContinues()) { int idx = idx() - 2; do next(2); while (qualifiedNameContinues()); String fqn = joinSubList(tok, idx, idx() - 1); return classForName(fqn); } String fullName = globalClassNames().get(name); if (fullName != null) return classForName(fullName); for (var container : unnullForIteration(functionContainers)) { if (hasMethodNamed(container, name)) return new MethodOnObject(container, name); var field = getField(container, name); if (field != null && isStaticField(field)) return new EvaluableWrapper(new GazelleV_LeftArrowScript.GetStaticField(field)); } return null; } public GazelleV_LeftArrowScriptParser allowTheWorld() { return allowTheWorld(mc()); } public GazelleV_LeftArrowScriptParser allowTheWorld(Object... functionContainers) { for (Object o : unnullForIteration(reversed(functionContainers))) if (!contains(this.functionContainers, o)) { this.functionContainers.add(0, o); globalClassNames_cache = null; } return this; } public void printFunctionDefs(GazelleV_LeftArrowScript.Script script) { if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print(values(script.functionDefs)); } public AutoCloseable tempAddKnownVars(String... vars) { return tempAddKnownVars(asList(vars)); } public AutoCloseable tempAddKnownVars(Iterable vars) { var newVars = mapWithSingleValue(vars, new LASValueDescriptor()); if (scope != null) for (var __1 : _entrySet(newVars)) { var name = __1.getKey(); var type = __1.getValue(); scope.addDeclaredVar(name, type); } return tempMapPutAll(knownVars, newVars); } public GazelleV_LeftArrowScript.FunctionDef parseFunctionDefinition(Map functionDefsToAddTo) { consume("def"); String functionName = assertIdentifier(tpp()); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("parseFunctionDefinition " + functionName); List args = new ArrayList(); while (isIdentifier()) args.add(tpp()); var scope = newScope(); scope.useFixedVars(useFixedVarContexts); AutoCloseable __9 = tempScope(scope); try { AutoCloseable __10 = tempAddKnownVars(args); try { if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("Parsing function body"); var functionBody = parseReturnableCurlyBlock(); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("Defined function " + functionName + ", adding to " + functionDefsToAddTo); var fd = new GazelleV_LeftArrowScript.FunctionDef(functionName, args, functionBody); fd.scope(scope); { if (functionDefsToAddTo != null) functionDefsToAddTo.put(functionName, fd); } return fd; } finally { _close(__10); } } finally { _close(__9); } } public LASScope newScope() { return new LASScope(scope); } public LASScope currentScope() { return scope; } public AutoCloseable tempScope(LASScope scope) { var oldScope = currentScope(); this.scope = scope; return () -> { scope.resolve(); this.scope = oldScope; }; } public GazelleV_LeftArrowScript.Script parseReturnableCurlyBlock() { return (GazelleV_LeftArrowScript.Script) parseCurlyBlock(new BuildingScript().returnable(true)); } public GazelleV_LeftArrowScript.Evaluable parseCurlyBlock(BuildingScript script) { consume("{"); boolean inParensOld = inParens; inParens = false; var body = parseScript(script); consume("}"); inParens = inParensOld; return body; } public GazelleV_LeftArrowScript.Evaluable parseWhileLoop() { consume("while"); var condition = parseExpr(); var body = parseCurlyBlock(new BuildingScript().isLoopBody(true)); return new GazelleV_LeftArrowScript.While(condition, body); } public GazelleV_LeftArrowScript.Evaluable parseForEach() { return new ParseForEach().get(); } public class ParseForEach { public GazelleV_LeftArrowScript.Evaluable collection, body; public IF0 finish; public Set vars = new HashSet(); public String addVar(String var) { return addAndReturn(vars, var); } public String consumeVar() { return addVar(consumeIdentifier()); } public void parseBody() { AutoCloseable __11 = tempAddKnownVars(vars); try { body = parseCurlyBlock(new BuildingScript().isLoopBody(true)); } finally { _close(__11); } } public GazelleV_LeftArrowScript.Evaluable get() { consume("for"); if (is(1, "to")) { String var = consumeVar(); consume("to"); GazelleV_LeftArrowScript.Evaluable endValue = parseExpr(); parseBody(); return new GazelleV_LeftArrowScript.ForIntTo(endValue, var, body); } int iIn = relativeIndexOf("in"); if (iIn < 0) throw fail("for without in"); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("iIn", iIn); if (iIn == 1) { String var = consumeVar(); finish = () -> new GazelleV_LeftArrowScript.ForEach(collection, var, body); } else if (iIn == 2) { if (consumeOpt("iterator")) { String var = consumeVar(); finish = () -> new GazelleV_LeftArrowScript.ForIterator(collection, var, body); } else if (consumeOpt("nested")) { String var = consumeVar(); finish = () -> new GazelleV_LeftArrowScript.ForNested(collection, var, body); } else throw fail("Unknown pattern for 'for' loop"); } else if (iIn == 3) { if (isOneOf("pair", "Pair")) { consume(); String varA = consumeVar(); String varB = consumeVar(); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) printVars("varA", varA, "varB", varB); finish = () -> new GazelleV_LeftArrowScript.ForPairs(collection, body, varA, varB); } else { String varA = consumeVar(); consume(","); String varB = consumeVar(); finish = () -> new GazelleV_LeftArrowScript.ForKeyValue(collection, body, varA, varB); } } else if (iIn == 4) { consume("index"); String varIndex = consumeVar(); consume(","); String varElement = consumeVar(); finish = () -> new GazelleV_LeftArrowScript.ForIndex(collection, body, varIndex, varElement); } else throw fail("Unknown pattern for 'for' loop"); consume("in"); collection = parseExpr(); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) print("collection", collection); parseBody(); return finish.get(); } } public GazelleV_LeftArrowScript.Evaluable parseIfStatement() { consume("if"); GazelleV_LeftArrowScript.Evaluable condition, body, elseBranch = null; { AutoCloseable __12 = tempAdd(closerTokens, "then"); try { condition = parseExpr(); } finally { _close(__12); } } if (consumeOpt("then")) { AutoCloseable __13 = tempAdd(closerTokens, "else"); try { body = parseExpr(); if (consumeOpt("else")) elseBranch = parseExpr(); } finally { _close(__13); } } else { body = parseCurlyBlock(new BuildingScript()); if (consumeOpt("else")) { if (is("if")) elseBranch = parseIfStatement(); else elseBranch = parseCurlyBlock(new BuildingScript()); } } return new GazelleV_LeftArrowScript.IfThen(condition, body, elseBranch); } public GazelleV_LeftArrowScript.Evaluable parseRepeatStatement() { consume("repeat"); var n = parseExpr(); var body = parseCurlyBlock(new BuildingScript()); return new GazelleV_LeftArrowScript.RepeatN(n, body); } public void addVar(String var) { addVar(var, new LASValueDescriptor()); } public void addVar(String var, LASValueDescriptor type) { knownVars.put(var, type); } public void addVar(String var, Class type, boolean canBeNull) { addVar(var, new LASValueDescriptor.NonExact(type, canBeNull)); } public Map globalClassNames_cache; public Map globalClassNames() { if (globalClassNames_cache == null) globalClassNames_cache = globalClassNames_load(); return globalClassNames_cache; } public Map globalClassNames_load() { var packages = mapToTreeSet(importedPackages(), pkg -> pkg + "."); Map out = new HashMap(); for (var fc : functionContainers) if (fc instanceof Class) { if (isAnonymousClass((Class) fc)) continue; out.put(shortClassName((Class) fc), className((Class) fc)); } var classContainers = classContainerPrefixes(); TreeSet classContainerSet = asTreeSet(classContainers); out.put("List", "java.util.List"); for (var className : classNameResolver().allFullyQualifiedClassNames()) { if (isAnonymousClassName(className)) continue; if (!contains(className, '$')) { String pkg = longestPrefixInTreeSet(className, packages); if (pkg != null) { String shortName = dropPrefix(pkg, className); if (!shortName.contains(".") && !out.containsKey(shortName)) out.put(shortName, className); } } String container = longestPrefixInTreeSet(className, classContainerSet); if (container != null) { String shortName = dropPrefix(container, className); String existing = out.get(shortName); if (existing != null) { int priority = indexOf(classContainers, container); String oldContainer = longestPrefixInTreeSet(existing, classContainerSet); int oldPriority = indexOf(classContainers, oldContainer); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) printVars("className", className, "shortName", shortName, "container", container, "priority", priority, "existing", existing, "oldPriority", oldPriority); if (priority > oldPriority) continue; } out.put(shortName, className); } } for (var __0 : _entrySet(javaxClassShortcuts())) { var key = __0.getKey(); var val = __0.getValue(); String fullName = out.get(val); if (fullName != null) out.put(key, fullName); } return out; } transient public IF0> importedPackages; public Collection importedPackages() { return importedPackages != null ? importedPackages.get() : importedPackages_base(); } final public Collection importedPackages_fallback(IF0> _f) { return _f != null ? _f.get() : importedPackages_base(); } public Collection importedPackages_base() { return itemPlus("java.lang", standardImports_fullyImportedPackages()); } public void addClassAlias(String alias, String longName) { String fullName = globalClassNames().get(longName); if (fullName != null) globalClassNames().put(alias, fullName); } public List classContainerPrefixes() { return map(functionContainers, fc -> className(fc) + "$"); } static public class UnknownObject extends RuntimeException implements IFieldsToList { public String name; public UnknownObject() { } public UnknownObject(String name) { this.name = name; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + name + ")"; } public Object[] _fieldsToList() { return new Object[] { name }; } public String getMessage() { return "Unknown object: " + name; } } static public class ClassNotFound extends UnknownObject { public ClassNotFound(String className) { super(className); } public String getMessage() { return "Class not found: " + name; } } public LASClassDef parseClassDef() { consume("class"); LASClassDef classDef = new LASClassDef(); classDef.verbose(scaffoldingEnabled()); if (nempty(classDefPrefix)) classDef.classDefPrefix(classDefPrefix); String name = consumeIdentifier(); classDef.userGivenName(name); consume("{"); while (!is("}")) { if (is(";")) { next(); continue; } if (is("def")) { AutoCloseable __14 = tempAddKnownVars("this"); try { GazelleV_LeftArrowScript.FunctionDef fd = parseFunctionDefinition(null); if (GazelleV_LeftArrowScriptParser.this.scaffoldingEnabled()) printVars("knownVarsAfterFunctionDef", knownVars); classDef.methods.add(fd); continue; } finally { _close(__14); } } LASClassDef.FieldDef fd = new LASClassDef.FieldDef(); fd.name(consumeIdentifier()); var type = parseColonType(); fd.type(type); classDef.fields.add(fd); } consume("}"); classDefs.put(name, classDef); return classDef; } public Type parseColonType() { consume(":"); String typeName = consumeIdentifier(); Object type = findExternalObject(typeName); if (!(type instanceof Class)) throw fail("Class not found: " + typeName); return parseTypeArguments((Type) type); } public Type parseTypeArguments(Type type) { if (is("<") && isIdentifier(token(1))) { next(); Object arg = findExternalObject(consume()); consume(">"); if (!(arg instanceof Class)) throw fail("Class not found: " + arg); if (type != null) type = new ParameterizedTypeImpl(null, type, (Class) arg); } return type; } transient public IF1 classForName; public Class classForName(String name) { return classForName != null ? classForName.get(name) : classForName_base(name); } final public Class classForName_fallback(IF1 _f, String name) { return _f != null ? _f.get(name) : classForName_base(name); } public Class classForName_base(String name) { try { return Class.forName(name); } catch (Exception __e) { throw rethrow(__e); } } public void copyFunctionContainersFrom(GazelleV_LeftArrowScriptParser parser) { functionContainers = cloneList(parser.functionContainers); globalClassNames_cache = parser.globalClassNames(); } public ClassNameResolver classNameResolver() { if (classNameResolver == null) classNameResolver = new ClassNameResolver().byteCodePath(assertNotNull(getBytecodePathForClass(this))).init(); return classNameResolver; } public GazelleV_LeftArrowScriptParser classNameResolver(ClassNameResolver classNameResolver) { this.classNameResolver = classNameResolver; return this; } } static public class MultiMap implements IMultiMap { 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 getAndClear(A key) { synchronized (data) { List l = cloneList(data.get(key)); remove(key); return l; } } 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); } } } final public Set keys() { return keySet(); } public Set keySet() { synchronized (data) { return data.keySet(); } } public void remove(A key) { synchronized (data) { fullSize -= l(this.getOpt(key)); data.remove(key); } } final public void remove(Pair p) { removePair(p); } public void removePair(Pair p) { if (p != null) remove(p.a, p.b); } 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 class SynchronizedSet extends SynchronizedCollection implements Set { public SynchronizedSet() { } public SynchronizedSet(Set s) { super(s); } public SynchronizedSet(Set s, Object mutex) { super(s, mutex); } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) { return c.equals(o); } } public int hashCode() { synchronized (mutex) { return c.hashCode(); } } } final static public class LongRange { public long start, end; public LongRange() { } public LongRange(long start, long end) { this.end = end; this.start = start; } public boolean equals(Object o) { if (o instanceof LongRange) return start == ((LongRange) o).start && end == ((LongRange) o).end; return false; } public int hashCode() { return boostHashCombine(hashOfLong(start), hashOfLong(end)); } public long length() { return end - start; } static public String _fieldOrder = "start end"; public String toString() { return "[" + start + ";" + end + "]"; } } static public class SynchronizedMap implements Map, Serializable { public SynchronizedMap() { } public Map m; public Object mutex; public SynchronizedMap(Map m) { this.m = Objects.requireNonNull(m); mutex = this; } public SynchronizedMap(Map m, Object mutex) { this.m = m; this.mutex = mutex; } public Map innerMap() { return m; } public int size() { synchronized (mutex) { return m.size(); } } public boolean isEmpty() { synchronized (mutex) { return m.isEmpty(); } } public boolean containsKey(Object key) { synchronized (mutex) { return m.containsKey(key); } } public boolean containsValue(Object value) { synchronized (mutex) { return m.containsValue(value); } } public V get(Object key) { synchronized (mutex) { return m.get(key); } } public V put(K key, V value) { synchronized (mutex) { return m.put(key, value); } } public V remove(Object key) { synchronized (mutex) { return m.remove(key); } } public void putAll(Map map) { synchronized (mutex) { m.putAll(map); } } public void clear() { synchronized (mutex) { m.clear(); } } transient public Set keySet; transient public Set> entrySet; transient public Collection values; public Set keySet() { synchronized (mutex) { if (keySet == null) keySet = new SynchronizedSet<>(m.keySet(), mutex); return keySet; } } public Set> entrySet() { synchronized (mutex) { if (entrySet == null) entrySet = new SynchronizedSet<>(m.entrySet(), mutex); return entrySet; } } public Collection values() { synchronized (mutex) { if (values == null) values = new SynchronizedCollection<>(m.values(), mutex); return values; } } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) { return m.equals(o); } } public int hashCode() { synchronized (mutex) { return m.hashCode(); } } public String toString() { synchronized (mutex) { return m.toString(); } } @Override public V getOrDefault(Object k, V defaultValue) { synchronized (mutex) { return m.getOrDefault(k, defaultValue); } } @Override public void forEach(BiConsumer action) { synchronized (mutex) { m.forEach(action); } } @Override public void replaceAll(BiFunction function) { synchronized (mutex) { m.replaceAll(function); } } @Override public V putIfAbsent(K key, V value) { synchronized (mutex) { return m.putIfAbsent(key, value); } } @Override public boolean remove(Object key, Object value) { synchronized (mutex) { return m.remove(key, value); } } @Override public boolean replace(K key, V oldValue, V newValue) { synchronized (mutex) { return m.replace(key, oldValue, newValue); } } @Override public V replace(K key, V value) { synchronized (mutex) { return m.replace(key, value); } } @Override public V computeIfAbsent(K key, java.util.function.Function mappingFunction) { synchronized (mutex) { return m.computeIfAbsent(key, mappingFunction); } } @Override public V computeIfPresent(K key, BiFunction remappingFunction) { synchronized (mutex) { return m.computeIfPresent(key, remappingFunction); } } @Override public V compute(K key, BiFunction remappingFunction) { synchronized (mutex) { return m.compute(key, remappingFunction); } } @Override public V merge(K key, V value, BiFunction remappingFunction) { synchronized (mutex) { return m.merge(key, value, remappingFunction); } } @java.io.Serial final public void writeObject(ObjectOutputStream s) throws IOException { synchronized (mutex) { s.defaultWriteObject(); } } } 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 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(); } } public interface TransientObject { } 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 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 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(); { var __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 class Pair implements Comparable> { final public Pair setA(A a) { return a(a); } public Pair a(A a) { this.a = a; return this; } final public A getA() { return a(); } public A a() { return a; } public A a; final public Pair setB(B b) { return b(b); } public Pair b(B b) { this.b = b; return this; } final public B getB() { return b(); } public B b() { return b; } 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 interface IResourceHolder { public A add(A a); public Collection takeAll(); } 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 DateInterpretationConfig implements IFieldsToList { static final public String _fieldOrder = "timeZone now assumeFuture"; public TimeZone timeZone; public long now; public boolean assumeFuture = false; public DateInterpretationConfig(TimeZone timeZone, long now, boolean assumeFuture) { this.assumeFuture = assumeFuture; this.now = now; this.timeZone = timeZone; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + timeZone + ", " + now + ", " + assumeFuture + ")"; } public boolean equals(Object o) { if (!(o instanceof DateInterpretationConfig)) return false; DateInterpretationConfig __1 = (DateInterpretationConfig) o; return eq(timeZone, __1.timeZone) && now == __1.now && eq(assumeFuture, __1.assumeFuture); } public int hashCode() { int h = 1673400408; h = boostHashCombine(h, _hashCode(timeZone)); h = boostHashCombine(h, _hashCode(now)); h = boostHashCombine(h, _hashCode(assumeFuture)); return h; } public Object[] _fieldsToList() { return new Object[] { timeZone, now, assumeFuture }; } public DateInterpretationConfig() { timeZone = localTimeZone(); now = now(); assumeFuture = true; } } static public class IntRange { public int start, end; public IntRange() { } public IntRange(int start, int end) { this.end = end; this.start = start; } public IntRange(IntRange r) { start = r.start; end = r.end; } public boolean equals(Object o) { return stdEq2(this, o); } public int hashCode() { return stdHash2(this); } final public int length() { return end - start; } final public boolean empty() { return start >= end; } final public boolean isEmpty() { return start >= end; } static public String _fieldOrder = "start end"; public String toString() { return "[" + start + ";" + end + "]"; } } static public interface Transformable { public Object transformUsing(IF1 f); } static public class DateStructures { abstract static public class SomeDate { } abstract static public class SomeDateDate extends SomeDate { } abstract static public class SomeTime extends SomeDate { } abstract static public class SomeWeek extends SomeDateDate { } abstract static public class DateProp extends SomeDate { } static public class Year extends SomeDateDate implements IFieldsToList, Transformable, Visitable { public int year; public Year() { } public Year(int year) { this.year = year; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + year + ")"; } public boolean equals(Object o) { if (!(o instanceof Year)) return false; Year __0 = (Year) o; return year == __0.year; } public int hashCode() { int h = 2751581; h = boostHashCombine(h, _hashCode(year)); return h; } public Object[] _fieldsToList() { return new Object[] { year }; } public Object transformUsing(IF1 f) { return new Year((int) f.get(year)); } public void visitUsing(IVF1 f) { f.get(year); } } static public class CurrentYearPlus extends SomeDateDate implements IFieldsToList, Transformable, Visitable { public int nYears; public CurrentYearPlus() { } public CurrentYearPlus(int nYears) { this.nYears = nYears; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + nYears + ")"; } public boolean equals(Object o) { if (!(o instanceof CurrentYearPlus)) return false; CurrentYearPlus __1 = (CurrentYearPlus) o; return nYears == __1.nYears; } public int hashCode() { int h = -283479056; h = boostHashCombine(h, _hashCode(nYears)); return h; } public Object[] _fieldsToList() { return new Object[] { nYears }; } public Object transformUsing(IF1 f) { return new CurrentYearPlus((int) f.get(nYears)); } public void visitUsing(IVF1 f) { f.get(nYears); } } static public class Month extends SomeDateDate implements IFieldsToList, Transformable, Visitable { public int month; public Year year; public Month() { } public Month(int month, Year year) { this.year = year; this.month = month; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + month + ", " + year + ")"; } public boolean equals(Object o) { if (!(o instanceof Month)) return false; Month __2 = (Month) o; return month == __2.month && eq(year, __2.year); } public int hashCode() { int h = 74527328; h = boostHashCombine(h, _hashCode(month)); h = boostHashCombine(h, _hashCode(year)); return h; } public Object[] _fieldsToList() { return new Object[] { month, year }; } public Object transformUsing(IF1 f) { return new Month((int) f.get(month), (Year) f.get(year)); } public void visitUsing(IVF1 f) { f.get(month); f.get(year); } public Month(int month) { this(month, null); } } static public class CurrentMonthPlus extends SomeDateDate implements IFieldsToList, Transformable, Visitable { public int nMonths; public CurrentMonthPlus() { } public CurrentMonthPlus(int nMonths) { this.nMonths = nMonths; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + nMonths + ")"; } public boolean equals(Object o) { if (!(o instanceof CurrentMonthPlus)) return false; CurrentMonthPlus __3 = (CurrentMonthPlus) o; return nMonths == __3.nMonths; } public int hashCode() { int h = -1003838751; h = boostHashCombine(h, _hashCode(nMonths)); return h; } public Object[] _fieldsToList() { return new Object[] { nMonths }; } public Object transformUsing(IF1 f) { return new CurrentMonthPlus((int) f.get(nMonths)); } public void visitUsing(IVF1 f) { f.get(nMonths); } } static public class Week extends SomeWeek implements IFieldsToList, Transformable, Visitable { public int week; public Year year; public Week() { } public Week(int week, Year year) { this.year = year; this.week = week; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + week + ", " + year + ")"; } public boolean equals(Object o) { if (!(o instanceof Week)) return false; Week __4 = (Week) o; return week == __4.week && eq(year, __4.year); } public int hashCode() { int h = 2692116; h = boostHashCombine(h, _hashCode(week)); h = boostHashCombine(h, _hashCode(year)); return h; } public Object[] _fieldsToList() { return new Object[] { week, year }; } public Object transformUsing(IF1 f) { return new Week((int) f.get(week), (Year) f.get(year)); } public void visitUsing(IVF1 f) { f.get(week); f.get(year); } } static public class CurrentWeekPlus extends SomeWeek implements IFieldsToList, Transformable, Visitable { public int nWeeks; public CurrentWeekPlus() { } public CurrentWeekPlus(int nWeeks) { this.nWeeks = nWeeks; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + nWeeks + ")"; } public boolean equals(Object o) { if (!(o instanceof CurrentWeekPlus)) return false; CurrentWeekPlus __5 = (CurrentWeekPlus) o; return nWeeks == __5.nWeeks; } public int hashCode() { int h = 633919527; h = boostHashCombine(h, _hashCode(nWeeks)); return h; } public Object[] _fieldsToList() { return new Object[] { nWeeks }; } public Object transformUsing(IF1 f) { return new CurrentWeekPlus((int) f.get(nWeeks)); } public void visitUsing(IVF1 f) { f.get(nWeeks); } } static public class Day extends SomeDate implements IFieldsToList, Transformable, Visitable { public int day; public Month month; public Day() { } public Day(int day, Month month) { this.month = month; this.day = day; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + day + ", " + month + ")"; } public boolean equals(Object o) { if (!(o instanceof Day)) return false; Day __6 = (Day) o; return day == __6.day && eq(month, __6.month); } public int hashCode() { int h = 68476; h = boostHashCombine(h, _hashCode(day)); h = boostHashCombine(h, _hashCode(month)); return h; } public Object[] _fieldsToList() { return new Object[] { day, month }; } public Object transformUsing(IF1 f) { return new Day((int) f.get(day), (Month) f.get(month)); } public void visitUsing(IVF1 f) { f.get(day); f.get(month); } } static public class TodayPlus extends SomeDate implements IFieldsToList, Transformable, Visitable { public int nDays; public TodayPlus() { } public TodayPlus(int nDays) { this.nDays = nDays; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + nDays + ")"; } public boolean equals(Object o) { if (!(o instanceof TodayPlus)) return false; TodayPlus __7 = (TodayPlus) o; return nDays == __7.nDays; } public int hashCode() { int h = 123418715; h = boostHashCombine(h, _hashCode(nDays)); return h; } public Object[] _fieldsToList() { return new Object[] { nDays }; } public Object transformUsing(IF1 f) { return new TodayPlus((int) f.get(nDays)); } public void visitUsing(IVF1 f) { f.get(nDays); } } static public class Weekday extends SomeDateDate implements IFieldsToList, Transformable, Visitable { public int weekday; public SomeWeek week; public Weekday() { } public Weekday(int weekday, SomeWeek week) { this.week = week; this.weekday = weekday; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + weekday + ", " + week + ")"; } public boolean equals(Object o) { if (!(o instanceof Weekday)) return false; Weekday __8 = (Weekday) o; return weekday == __8.weekday && eq(week, __8.week); } public int hashCode() { int h = -1403451640; h = boostHashCombine(h, _hashCode(weekday)); h = boostHashCombine(h, _hashCode(week)); return h; } public Object[] _fieldsToList() { return new Object[] { weekday, week }; } public Object transformUsing(IF1 f) { return new Weekday((int) f.get(weekday), (SomeWeek) f.get(week)); } public void visitUsing(IVF1 f) { f.get(weekday); f.get(week); } public Weekday(int weekday) { this.weekday = weekday; } } static public class Hour extends SomeTime implements IFieldsToList, Transformable, Visitable { public int hour; public Boolean isPM; public Day day; public Hour() { } public Hour(int hour, Boolean isPM, Day day) { this.day = day; this.isPM = isPM; this.hour = hour; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + hour + ", " + isPM + ", " + day + ")"; } public boolean equals(Object o) { if (!(o instanceof Hour)) return false; Hour __9 = (Hour) o; return hour == __9.hour && eq(isPM, __9.isPM) && eq(day, __9.day); } public int hashCode() { int h = 2255364; h = boostHashCombine(h, _hashCode(hour)); h = boostHashCombine(h, _hashCode(isPM)); h = boostHashCombine(h, _hashCode(day)); return h; } public Object[] _fieldsToList() { return new Object[] { hour, isPM, day }; } public Object transformUsing(IF1 f) { return new Hour((int) f.get(hour), (Boolean) f.get(isPM), (Day) f.get(day)); } public void visitUsing(IVF1 f) { f.get(hour); f.get(isPM); f.get(day); } public Hour(int hour, Boolean isPM) { this(hour, isPM, null); } } static public class CurrentHourPlus extends SomeTime implements IFieldsToList, Transformable, Visitable { public int nHours; public CurrentHourPlus() { } public CurrentHourPlus(int nHours) { this.nHours = nHours; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + nHours + ")"; } public boolean equals(Object o) { if (!(o instanceof CurrentHourPlus)) return false; CurrentHourPlus __10 = (CurrentHourPlus) o; return nHours == __10.nHours; } public int hashCode() { int h = 1011201559; h = boostHashCombine(h, _hashCode(nHours)); return h; } public Object[] _fieldsToList() { return new Object[] { nHours }; } public Object transformUsing(IF1 f) { return new CurrentHourPlus((int) f.get(nHours)); } public void visitUsing(IVF1 f) { f.get(nHours); } } static public class Minute extends SomeTime implements IFieldsToList, Transformable, Visitable { public int minute; public Hour hour; public Minute() { } public Minute(int minute, Hour hour) { this.hour = hour; this.minute = minute; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + minute + ", " + hour + ")"; } public boolean equals(Object o) { if (!(o instanceof Minute)) return false; Minute __11 = (Minute) o; return minute == __11.minute && eq(hour, __11.hour); } public int hashCode() { int h = -1990159820; h = boostHashCombine(h, _hashCode(minute)); h = boostHashCombine(h, _hashCode(hour)); return h; } public Object[] _fieldsToList() { return new Object[] { minute, hour }; } public Object transformUsing(IF1 f) { return new Minute((int) f.get(minute), (Hour) f.get(hour)); } public void visitUsing(IVF1 f) { f.get(minute); f.get(hour); } } static public class CurrentMinutePlus extends SomeTime implements IFieldsToList, Transformable, Visitable { public int nMinutes; public CurrentMinutePlus() { } public CurrentMinutePlus(int nMinutes) { this.nMinutes = nMinutes; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + nMinutes + ")"; } public boolean equals(Object o) { if (!(o instanceof CurrentMinutePlus)) return false; CurrentMinutePlus __12 = (CurrentMinutePlus) o; return nMinutes == __12.nMinutes; } public int hashCode() { int h = -1844800505; h = boostHashCombine(h, _hashCode(nMinutes)); return h; } public Object[] _fieldsToList() { return new Object[] { nMinutes }; } public Object transformUsing(IF1 f) { return new CurrentMinutePlus((int) f.get(nMinutes)); } public void visitUsing(IVF1 f) { f.get(nMinutes); } } static public class Second extends SomeTime implements IFieldsToList, Transformable, Visitable { public int second; public Minute minute; public Second() { } public Second(int second, Minute minute) { this.minute = minute; this.second = second; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + second + ", " + minute + ")"; } public boolean equals(Object o) { if (!(o instanceof Second)) return false; Second __13 = (Second) o; return second == __13.second && eq(minute, __13.minute); } public int hashCode() { int h = -1822412652; h = boostHashCombine(h, _hashCode(second)); h = boostHashCombine(h, _hashCode(minute)); return h; } public Object[] _fieldsToList() { return new Object[] { second, minute }; } public Object transformUsing(IF1 f) { return new Second((int) f.get(second), (Minute) f.get(minute)); } public void visitUsing(IVF1 f) { f.get(second); f.get(minute); } } static public class BeginningOfTime extends SomeDate implements IFieldsToList, Transformable, Visitable { public BeginningOfTime() { } public String toString() { return shortClassName_dropNumberPrefix(this); } public boolean equals(Object o) { return o instanceof BeginningOfTime; } public int hashCode() { int h = -1618841503; return h; } public Object[] _fieldsToList() { return null; } public Object transformUsing(IF1 f) { return this; } public void visitUsing(IVF1 f) { } } static public class EndOfTime extends SomeDate implements IFieldsToList, Transformable, Visitable { public EndOfTime() { } public String toString() { return shortClassName_dropNumberPrefix(this); } public boolean equals(Object o) { return o instanceof EndOfTime; } public int hashCode() { int h = -810134049; return h; } public Object[] _fieldsToList() { return null; } public Object transformUsing(IF1 f) { return this; } public void visitUsing(IVF1 f) { } } static public class Between extends DateProp implements IFieldsToList, Transformable, Visitable { public SomeDate from; public SomeDate to; public Between() { } public Between(SomeDate from, SomeDate to) { this.to = to; this.from = from; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + from + ", " + to + ")"; } public boolean equals(Object o) { if (!(o instanceof Between)) return false; Between __14 = (Between) o; return eq(from, __14.from) && eq(to, __14.to); } public int hashCode() { int h = 1448018920; h = boostHashCombine(h, _hashCode(from)); h = boostHashCombine(h, _hashCode(to)); return h; } public Object[] _fieldsToList() { return new Object[] { from, to }; } public Object transformUsing(IF1 f) { return new Between((SomeDate) f.get(from), (SomeDate) f.get(to)); } public void visitUsing(IVF1 f) { f.get(from); f.get(to); } } static public class Or extends DateProp implements IFieldsToList, Transformable, Visitable { public DateProp a; public DateProp b; public Or() { } public Or(DateProp a, DateProp b) { this.b = b; this.a = a; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + a + ", " + b + ")"; } public boolean equals(Object o) { if (!(o instanceof Or)) return false; Or __15 = (Or) o; return eq(a, __15.a) && eq(b, __15.b); } public int hashCode() { int h = 2563; 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 Or((DateProp) f.get(a), (DateProp) f.get(b)); } public void visitUsing(IVF1 f) { f.get(a); f.get(b); } } static public class And extends DateProp implements IFieldsToList, Transformable, Visitable { public DateProp a; public DateProp b; public And() { } public And(DateProp a, DateProp 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 __16 = (And) o; return eq(a, __16.a) && eq(b, __16.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((DateProp) f.get(a), (DateProp) f.get(b)); } public void visitUsing(IVF1 f) { f.get(a); f.get(b); } } static public class Not extends DateProp implements IFieldsToList, Transformable, Visitable { public DateProp a; public Not() { } public Not(DateProp a) { this.a = a; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + a + ")"; } public boolean equals(Object o) { if (!(o instanceof Not)) return false; Not __17 = (Not) o; return eq(a, __17.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((DateProp) f.get(a)); } public void visitUsing(IVF1 f) { f.get(a); } } static public boolean containsTimes(SomeDate d) { return defaultMetaTransformer().any(o -> o instanceof SomeTime, d); } static public boolean containsDateDates(SomeDate d) { return defaultMetaTransformer().any(o -> o instanceof SomeDateDate, d); } } static public class MRUCache extends LinkedHashMap { public int maxSize = 10; public MRUCache() { } public MRUCache(int maxSize) { this.maxSize = maxSize; } public boolean removeEldestEntry(Map.Entry eldest) { return size() > maxSize; } public Object _serialize() { return ll(maxSize, cloneLinkedHashMap(this)); } static public MRUCache _deserialize(List l) { MRUCache m = new MRUCache(); m.maxSize = (int) first(l); m.putAll((LinkedHashMap) second(l)); return m; } } static public class PersistableThrowable extends DynamicObject { public String className; public String msg; public String stacktrace; public PersistableThrowable() { } public PersistableThrowable(Throwable e) { if (e == null) className = "Crazy Null Error"; else { className = getClassName(e).replace('/', '.'); msg = e.getMessage(); stacktrace = getStackTrace_noRecord(e); } } public String toString() { return nempty(msg) ? className + ": " + msg : className; } public RuntimeException asRuntimeException() { return new Fail(this); } } static public class SynchronizedSortedMap extends SynchronizedMap implements SortedMap { public SynchronizedSortedMap() { } public SortedMap innerMap() { return (SortedMap) m; } public SynchronizedSortedMap(SortedMap m) { super(m); } public SynchronizedSortedMap(SortedMap m, Object mutex) { super(m, mutex); } public Comparator comparator() { synchronized (mutex) { return innerMap().comparator(); } } public SortedMap subMap(K fromKey, K toKey) { synchronized (mutex) { return new SynchronizedSortedMap<>(innerMap().subMap(fromKey, toKey), mutex); } } public SortedMap headMap(K toKey) { synchronized (mutex) { return new SynchronizedSortedMap<>(innerMap().headMap(toKey), mutex); } } public SortedMap tailMap(K fromKey) { synchronized (mutex) { return new SynchronizedSortedMap<>(innerMap().tailMap(fromKey), mutex); } } public K firstKey() { synchronized (mutex) { return innerMap().firstKey(); } } public K lastKey() { synchronized (mutex) { return innerMap().lastKey(); } } } static public class EnglishDateParser extends DateStructures { public boolean assumeFuture = true; public List tok; public int maxTokens = 3; public List> topDogs(String s) { return pwt_topDogs(pwt_filterByType(SomeDate.class, allParses(s))); } public SomeDate parse(String s) { return getVar(first(topDogs(s))); } public IterableIterator allParses(String s) { List> initials = pwt_initial(tok = javaTok(s), maxTokens); List out = new ArrayList(); List> numbers = pwt_transform(number(), initials); List> ordinals = new ArrayList(); for (ParsedWithTokens number : numbers) for (ParsedWithTokens ord : parseToTheRight(fixedToken("st", "nd", "rd", "th"), number)) ordinals.add(pwt_combine(number, ord)); for (ParsedWithTokens number : numbers) for (ParsedWithTokens in : parseToTheLeft(fixedToken("in"), number)) for (ParsedWithTokens days : parseToTheRight(fixedToken("day", "days"), number)) out.add(pwt_combine(new TodayPlus(number.get()), in, days)); for (ParsedWithTokens number : numbers) for (ParsedWithTokens daysFromNow : parseToTheRight(fixedToken("day from now", "days from now"), number)) out.add(pwt_combine(new TodayPlus(number.get()), number, daysFromNow)); List> years = pwt_filter(__91 -> isYear(__91), numbers); out.addAll(years); List> months = pwt_filter(__92 -> isMonthNr(__92), numbers); List> dayOfMonths = pwt_filter(__93 -> isDayOfMonth(__93), numbers); List> weekdays = pwt_transform(weekday(), initials); out.addAll(weekdays); List> monthNames = pwt_transform(monthName(), initials); out.addAll(monthNames); out.addAll(pwt_combine(monthNames, years, (month, year) -> new Month(month.month, new Year(year)))); out.addAll(pwt_combine(monthNames, ordinals, (month, ord) -> new Day(ord, month))); out.addAll(pwt_transform(t -> eqic(t, "yesterday") ? new TodayPlus(-1) : eqic(t, "today") ? new TodayPlus(0) : new TodayPlus(1), pwt_transform(fixedToken("yesterday", "today", "tomorrow"), initials))); for (ParsedWithTokens week : pwt_transform(fixedToken("week"), initials)) for (ParsedWithTokens which : parseToTheLeft(fixedToken("last", "this", "next"), week)) out.add(pwt_combine(new CurrentWeekPlus(eqic(which.get(), "last") ? -1 : eqic(which.get(), "this") ? 0 : 1), which, week)); for (ParsedWithTokens weekday : weekdays) for (ParsedWithTokens next : parseToTheLeft(fixedToken("next"), weekday)) out.add(pwt_combine(new Weekday(weekday.get().weekday, new CurrentWeekPlus(1)), next, weekday)); for (ParsedWithTokens year : years) for (ParsedWithTokens slash : parseToTheRight(fixedToken("/"), year)) for (ParsedWithTokens month : pwt_toTheRightOf(months, slash)) for (ParsedWithTokens slash2 : parseToTheRight(fixedToken("/"), month)) for (ParsedWithTokens day : pwt_toTheRightOf(dayOfMonths, slash2)) out.add(pwt_combine(new Day(day.get(), new Month(month.get(), new Year(year.get()))), year, day)); List> hours = pwt_transform(__94 -> numberToHour(__94), numbers); List> minutes = pwt_filter(__95 -> isMinute(__95), numbers); List> seconds = minutes; List> colons = pwt_filter(t -> eq(t, ":"), initials); List> hoursAndMinutes = pwt_combine(hours, colons, minutes, (h, __, m) -> new Minute(m, h)); out.addAll(hoursAndMinutes); List> hoursAndMinutesAndSeconds = pwt_combine(hoursAndMinutes, colons, seconds, (hm, __, second) -> new Second(second, hm)); out.addAll(hoursAndMinutesAndSeconds); List> amPMs = pwt_transform(fixedToken("am", "pm"), initials); List> amPMTimes = pwt_combine(numbers, amPMs, (hour, amPM) -> !between(hour, 1, 12) ? null : new Hour(hour, eqic(amPM, "pm"))); out.addAll(amPMTimes); for (ParsedWithTokens time : amPMTimes) for (ParsedWithTokens and : parseToTheLeft(fixedToken("and"), time)) for (ParsedWithTokens hour : pwt_toTheLeftOf(hours, and)) out.add(pwt_combine(new Between(new Hour(hour.get().hour, time.get().isPM), time.get()), time, hour)); return itIt(out); } public IF1 number() { return s -> isInteger(s) ? parseInt(s) : null; } public boolean isYear(int n) { return between(n, 1900, 2100); } public boolean isMonthNr(int n) { return between(n, 1, 12); } public boolean isDayOfMonth(int n) { return between(n, 1, 31); } public boolean isHour(int n) { return between(n, 0, 23); } public boolean isMinute(int n) { return between(n, 0, 59); } public boolean isSecond(int n) { return between(n, 0, 59); } public Hour numberToHour(int n) { return !isHour(n) ? null : n > 12 ? new Hour(n - 12, true) : new Hour(n, null); } public IF1 fixedToken(String... tokens) { return fixedToken(litciset(tokens)); } public IF1 fixedToken(Set set) { return t -> contains(set, t) ? t : null; } public IF1 weekday() { return s -> { int n = parseEnglishWeekday(s); return n == 0 ? null : new Weekday(n); }; } public IF1 monthName() { return s -> { int n = parseEnglishMonthName(s); return n == 0 ? null : new Month(n); }; } public List> parseToTheLeft(IF1 f, ParsedWithTokens p) { return pwt_transform(f, pwt_precedingTokens(1, maxTokens, p.start())); } public List> parseToTheRight(IF1 f, ParsedWithTokens p) { return pwt_transform(f, pwt_followingTokens(1, maxTokens, p.remaining())); } } static public class WebBotTester implements AutoCloseable { public String botURL; public String cookie = "test_" + aGlobalID(); public int n; public Thread grabThread; volatile public boolean closed = false; public List allHtml = syncList(); public List msgs = new ArrayList(); public double readTimeout = 120.0, sendTimeout = 20.0; public double waitForMessagesTimeout = 20.0; public Map params = new LinkedHashMap(); public WebBotTester(String botID) { botURL = "https://botcompany.de/" + psI(botID) + "/raw"; } public void close() { closed = true; cancelAndInterruptThread(grabThread); } public WebBotTester start() { if (grabThread == null) grabThread = startThread(new Runnable() { public void run() { try { _grabLoop(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_grabLoop();"; } }); return this; } public void _grabLoop() { while (!closed) { String html = loadPageWithTimeout(botURL + "/incremental" + hquery(mapPlus(params, "cookie", cookie, "a", n)), readTimeout); allHtml.add(html); printWithIndent("> ", html); msgs.addAll(webBotTester_extractMsgs(html)); String comment = first(getHTMLComments(html)); int n = parseFirstIntOrMinus1(comment); if (n >= 0) this.n = n; sleepSeconds(1); } } public void sendMsg(String message) { print(doPostWithTimeout(mapPlus(params, "cookie", cookie, "message", message), botURL + "/msg", toMS_int(sendTimeout))); } public void waitForMessages(int n) { waitUntil(50, waitForMessagesTimeout, () -> l(msgs) >= n); } } static public class LASValueDescriptor { public LASValueDescriptor() { } public boolean knownValue() { return false; } public Object value() { return null; } public Class javaClass() { return null; } public boolean javaClassIsExact() { return false; } public boolean canBeNull() { return true; } public boolean canFail() { return false; } public boolean willFail() { return false; } static public class Exact extends LASValueDescriptor implements IFieldsToList { public Class c; public boolean canBeNull = false; public Exact() { } public Exact(Class c, boolean canBeNull) { this.canBeNull = canBeNull; this.c = c; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + c + ", " + canBeNull + ")"; } public boolean equals(Object o) { if (!(o instanceof Exact)) return false; Exact __1 = (Exact) o; return eq(c, __1.c) && eq(canBeNull, __1.canBeNull); } public int hashCode() { int h = 67394271; h = boostHashCombine(h, _hashCode(c)); h = boostHashCombine(h, _hashCode(canBeNull)); return h; } public Object[] _fieldsToList() { return new Object[] { c, canBeNull }; } public Class javaClass() { return c; } public boolean javaClassIsExact() { return true; } public boolean canBeNull() { return canBeNull; } } static public class NonExact extends LASValueDescriptor implements IFieldsToList { public Class c; public boolean canBeNull = false; public NonExact() { } public NonExact(Class c, boolean canBeNull) { this.canBeNull = canBeNull; this.c = c; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + c + ", " + canBeNull + ")"; } public boolean equals(Object o) { if (!(o instanceof NonExact)) return false; NonExact __2 = (NonExact) o; return eq(c, __2.c) && eq(canBeNull, __2.canBeNull); } public int hashCode() { int h = 1445514322; h = boostHashCombine(h, _hashCode(c)); h = boostHashCombine(h, _hashCode(canBeNull)); return h; } public Object[] _fieldsToList() { return new Object[] { c, canBeNull }; } public Class javaClass() { return c; } public boolean javaClassIsExact() { return false; } public boolean canBeNull() { return canBeNull; } } static public LASValueDescriptor nonExactCanBeNull(Type c) { return new NonExact(typeToClass(c), true); } static public class KnownValue extends LASValueDescriptor implements IFieldsToList { public Object value; public KnownValue() { } public KnownValue(Object value) { this.value = value; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + value + ")"; } public boolean equals(Object o) { if (!(o instanceof KnownValue)) return false; KnownValue __3 = (KnownValue) o; return eq(value, __3.value); } public int hashCode() { int h = -1456305138; h = boostHashCombine(h, _hashCode(value)); return h; } public Object[] _fieldsToList() { return new Object[] { value }; } public boolean knownValue() { return true; } public Object value() { return value; } public Class javaClass() { return value == null ? null : value.getClass(); } public boolean javaClassIsExact() { return value != null; } public boolean canBeNull() { return value == null; } } static public class WillFail extends LASValueDescriptor { public boolean canFail() { return true; } public boolean willFail() { return true; } } static public LASValueDescriptor fromClass(Class c) { return new NonExact(c, true); } } static public class PingSourceCancelledException extends RuntimeException implements IFieldsToList { public PingSource pingSource; public PingSourceCancelledException() { } public PingSourceCancelledException(PingSource pingSource) { this.pingSource = pingSource; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + pingSource + ")"; } public Object[] _fieldsToList() { return new Object[] { pingSource }; } } static public class TokenRangeWithSrc extends TokenRange { public List tok; public TokenRangeWithSrc() { } public TokenRangeWithSrc(List tok, int start) { this.start = start; end = start; } public TokenRangeWithSrc(List tok, int start, int end) { this.end = end; this.start = start; } public TokenRangeWithSrc(ListAndIndex startPtr, ListAndIndex endPtr) { assertNotNull("startPtr", startPtr); assertNotNull("endPtr", endPtr); assertSame(tok = startPtr.list(), endPtr.list()); start = startPtr.idx(); end = endPtr.idx(); } public ListAndIndex startPtr() { return new ListAndIndex(tok, start); } public ListAndIndex endPtr() { return new ListAndIndex(tok, end); } public LineAndColumn startLineAndCol() { return tokenToLineAndColumn(startPtr()); } public LineAndColumn endLineAndCol() { return tokenToLineAndColumn(endPtr()); } public String text() { return joinSubList(tok, start, end); } public String toString() { var start = startLineAndCol(); if (eq(start, end)) return str(start); return start + " to " + endLineAndCol(); } public String fullSourceText() { return join(tok); } } static public class FileBasedLock implements AutoCloseable { public File lockFile; public double timeout = 60.0; public boolean verbose = false; public boolean haveLock = false; public java.util.Timer touchTimer; final public FileBasedLock setContentsForLockFile(String contentsForLockFile) { return contentsForLockFile(contentsForLockFile); } public FileBasedLock contentsForLockFile(String contentsForLockFile) { this.contentsForLockFile = contentsForLockFile; return this; } final public String getContentsForLockFile() { return contentsForLockFile(); } public String contentsForLockFile() { return contentsForLockFile; } public String contentsForLockFile; public FileBasedLock() { } public FileBasedLock(File lockFile) { this.lockFile = lockFile; } public FileBasedLock(File lockFile, double timeout) { this.timeout = timeout; this.lockFile = lockFile; } synchronized public boolean tryToLock() { if (haveLock) return true; if (fileExists(lockFile)) { double age = fileAgeInSeconds(lockFile); double remaining = timeout - age; print("Lock file age: " + lockFile + ": " + iround(age) + " s" + (remaining <= 0 ? " - old, deleting" : " - please start again in " + nSeconds(iceil(remaining)))); if (remaining <= 0) { print("Deleting old lock file (program crashed?): " + lockFile + " (age: " + iround(age) + " seconds)"); deleteFile(lockFile); } } try { mkdirsForFile(lockFile); java.nio.file.Files.createFile(toPath(lockFile)); if (nempty(contentsForLockFile)) writeContents(); acquired(); return true; } catch (Throwable e) { printExceptionShort("Can't lock", e); return false; } } public void writeContents() { saveTextFileWithoutTemp(lockFile, unnull(contentsForLockFile)); } final public void acquired() { haveLock = true; startTouchTimer(); } public void forceLock() { try { print("Force-locking " + lockFile); writeContents(); acquired(); } catch (Exception __e) { throw rethrow(__e); } } public String lockError() { return "Couldn't aquire lock file: " + lockFile; } public void lockOrFail() { if (!tryToLock()) throw fail(lockError()); } synchronized public void startTouchTimer() { if (touchTimer != null) return; double interval = timeout / 2; touchTimer = doEvery(interval, new Runnable() { public void run() { try { doTouch(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "doTouch();"; } }); if (verbose) print("Touch timer started for " + lockFile + " (" + interval + "s)"); } synchronized public void doTouch() { try { if (haveLock) { if (verbose) print("Touching lock file: " + lockFile); touchExistingFile(lockFile); } } catch (Throwable __e) { printStackTrace(__e); } } public synchronized void close() { try { { cleanUp(touchTimer); touchTimer = null; } if (haveLock) { haveLock = false; if (verbose) print("Deleting lock file: " + lockFile); deleteFile(lockFile); } } catch (Throwable __e) { printStackTrace(__e); } } synchronized public void _simulateCrash() { { cleanUp(touchTimer); touchTimer = null; } } public void deleteOnExit() { if (haveLock) lockFile.deleteOnExit(); } public String actualContents() { return loadTextFile(lockFile); } public boolean hasExpectedContents() { return eq(unnull(contentsForLockFile), actualContents()); } } static public class LASScope { final public LASScope setUseFixedVars(boolean useFixedVars) { return useFixedVars(useFixedVars); } public LASScope useFixedVars(boolean useFixedVars) { this.useFixedVars = useFixedVars; return this; } final public boolean getUseFixedVars() { return useFixedVars(); } public boolean useFixedVars() { return useFixedVars; } public boolean useFixedVars = false; final public Map getDeclaredVars() { return declaredVars(); } public Map declaredVars() { return declaredVars; } public Map declaredVars = new HashMap(); final public LASScope setParentScope(LASScope parentScope) { return parentScope(parentScope); } public LASScope parentScope(LASScope parentScope) { this.parentScope = parentScope; return this; } final public LASScope getParentScope() { return parentScope(); } public LASScope parentScope() { return parentScope; } public LASScope parentScope; final public LASScope setParentIsDetached(boolean parentIsDetached) { return parentIsDetached(parentIsDetached); } public LASScope parentIsDetached(boolean parentIsDetached) { this.parentIsDetached = parentIsDetached; return this; } final public boolean getParentIsDetached() { return parentIsDetached(); } public boolean parentIsDetached() { return parentIsDetached; } public boolean parentIsDetached = false; public String[] names; public LASScope() { } public LASScope(LASScope parentScope) { this.parentScope = parentScope; } public boolean resolved() { return names != null; } public void addDeclaredVar(String name, LASValueDescriptor type) { if (resolved()) throw fail("Can't add variables to resolved scope"); declaredVars.put(name, type); } public int resolveVar(String name) { resolve(); int idx = indexOfInSortedArray(names, name); if (idx < 0) throw fail("Variable not found in scope: " + name); return idx; } public void resolve() { if (names != null) return; names = empty(declaredVars) ? null : toStringArray(sortedKeys(declaredVars)); } } static public interface ValueConverterForField { public OrError convertValue(Object object, Field field, Object value); } static public class ClassNameResolver { final public ClassNameResolver setByteCodePath(File byteCodePath) { return byteCodePath(byteCodePath); } public ClassNameResolver byteCodePath(File byteCodePath) { this.byteCodePath = byteCodePath; return this; } final public File getByteCodePath() { return byteCodePath(); } public File byteCodePath() { return byteCodePath; } public File byteCodePath = byteCodePathForClass(getClass()); public List importedPackages = itemPlusList("java.lang", endingWith_dropSuffix(standardImports(), ".*")); public Set allFullyQualifiedClassNames_cache; public Set allFullyQualifiedClassNames() { if (allFullyQualifiedClassNames_cache == null) allFullyQualifiedClassNames_cache = allFullyQualifiedClassNames_load(); return allFullyQualifiedClassNames_cache; } public Set allFullyQualifiedClassNames_load() { Set set = new HashSet(); assertNotNull(byteCodePath); set.addAll(classNamesInJarOrDir(byteCodePath)); printVars("ClassNameResolver", "byteCodePath", byteCodePath, "classesFound", l(set)); set.addAll(classNamesInLoadedJigsawModules()); return set; } public ClassNameResolver init() { allFullyQualifiedClassNames(); return this; } public String findClass(String name) { for (String pkg : importedPackages) { String fullName = pkg + "." + name; if (allFullyQualifiedClassNames().contains(fullName)) return fullName; } return null; } public void printMe() { printVars("ClassNameResolver", "byteCodePath", byteCodePath); print("importedPackages", importedPackages); } } static public class ThreadPool implements AutoCloseable { public int max = numberOfCores(); public List all = new ArrayList(); public Set used = new HashSet(); public Set free = new HashSet(); public boolean verbose, retired; public class InternalPingSource extends PingSource { } public InternalPingSource internalPingSource = new InternalPingSource(); public MultiSleeper sleeper = new MultiSleeper(); public ThreadPool() { } public ThreadPool(int max) { this.max = max; } synchronized public int maxSize() { return max; } synchronized public int total() { return l(used) + l(free); } transient public Set onCustomerMustWaitAlert; public ThreadPool onCustomerMustWaitAlert(Runnable r) { onCustomerMustWaitAlert = createOrAddToSyncLinkedHashSet(onCustomerMustWaitAlert, r); return this; } public ThreadPool removeCustomerMustWaitAlertListener(Runnable r) { main.remove(onCustomerMustWaitAlert, r); return this; } public void customerMustWaitAlert() { if (onCustomerMustWaitAlert != null) for (var listener : onCustomerMustWaitAlert) pcallF_typed(listener); } public void fireCustomerMustWaitAlert() { vmBus_send("customerMustWaitAlert", this, currentThread()); customerMustWaitAlert(); } public PooledThread acquireThreadOrQueue(Runnable action) { if (action == null) return null; PooledThread t; synchronized (this) { if (_hasFreeAfterCreating()) { t = _firstFreeThread(); markUsed(t); } else t = _anyThread(); } t.addWork(action); return t; } public boolean _hasFreeAfterCreating() { checkNotRetired(); if (nempty(free)) return true; if (total() < max) { PooledThread t = newThread(); all.add(t); free.add(t); return true; } return false; } public PooledThread acquireThreadOrWait(Runnable action) { try { if (action == null) return null; PooledThread t; while (true) { synchronized (this) { if (_hasFreeAfterCreating()) { t = _firstFreeThread(); break; } else _waitWaitWait(); } } t.addWork(action); return t; } catch (Exception __e) { throw rethrow(__e); } } public PooledThread _firstFreeThread() { return first(free); } public PooledThread _anyThread() { return random(used); } public class PooledThread extends Thread { public PooledThread(String name) { super(name); } public AppendableChain q; synchronized public Runnable _grabWorkOrSleep() { try { Runnable r = first(q); if (r == null) { markFree(this); if (verbose) print("Thread sleeps"); synchronized (this) { wait(); } if (verbose) print("Thread woke up"); return null; } q = popFirst(q); return r; } catch (Exception __e) { throw rethrow(__e); } } public void run() { try { pingSource_tl().set(internalPingSource); while (!retired()) { ping(); Runnable r = _grabWorkOrSleep(); if (verbose) print(this + " work: " + r); if (r != null) try { if (verbose) print(this + " running: " + r); r.run(); pingSource_tl().set(internalPingSource); if (verbose) print(this + " done"); } catch (Throwable e) { pingSource_tl().set(internalPingSource); if (verbose) print(this + " error"); printStackTrace(e); } finally { pingSource_tl().set(internalPingSource); if (verbose) print("ThreadPool finally"); } } } catch (Exception __e) { throw rethrow(__e); } } synchronized public boolean isEmpty() { return empty(q); } public void addWork(Runnable r) { if (verbose) print("Added work to " + this + ": " + r); synchronized (this) { q = chainPlus(q, r); notifyAll(); } } } public PooledThread newThread() { PooledThread t = new PooledThread("Thread Pool Inhabitant " + n2(total() + 1)); t.start(); return t; } synchronized public void markFree(PooledThread t) { used.remove(t); free.add(t); notifyAll(); } synchronized public void markUsed(PooledThread t) { free.remove(t); used.add(t); } synchronized public String toString() { return retired() ? "Retired ThreadPool" : "ThreadPool " + roundBracket(commaCombine(n2(used) + " used out of " + n2(total()), max <= total() ? null : "could grow to " + n2(max))); } synchronized public boolean retired() { return retired; } synchronized public void retire() { if (verbose) print("ThreadPool Retiring"); retired = true; for (var thread : free) syncNotifyAll(thread); } public void checkNotRetired() { if (retired()) throw fail("retired"); } synchronized public void close() { try { retire(); } catch (Exception __e) { throw rethrow(__e); } } public void _waitWaitWait() { try { do { fireCustomerMustWaitAlert(); wait(); checkNotRetired(); } while (empty(free)); } catch (Exception __e) { throw rethrow(__e); } } public void dO(String text, Runnable r) { if (r == null) return; new PingSource(this, text).dO(r); } public ISleeper_v2 sleeper() { return sleeper; } } static public class HTML implements IF0, IFieldsToList { public String html; public HTML() { } public HTML(String html) { this.html = html; } public boolean equals(Object o) { if (!(o instanceof HTML)) return false; HTML __1 = (HTML) o; return eq(html, __1.html); } public int hashCode() { int h = 2228139; h = boostHashCombine(h, _hashCode(html)); return h; } public Object[] _fieldsToList() { return new Object[] { html }; } public String get() { return html; } public String toString() { return html; } } static public class SecretValue extends Var { public SecretValue() { } public SecretValue(A a) { super(a); } public String toString() { return "Secret value"; } } static final public class ParameterizedTypeImpl implements ParameterizedType { public ParameterizedTypeImpl() { } public Type ownerType; public Type rawType; 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(); } } public interface ILASClassLoader { public Class defineLASClass(String name, IF0 generateClass); public Object rememberClassBytes(boolean rememberClassBytes); } static public class ParsedWithTokens extends Var { public List tok; public int iStart; public int iRemaining; public ParsedWithTokens() { } public ParsedWithTokens(A a) { super(a); } public ParsedWithTokens(A a, List tok, int iStart, int iRemaining) { super(a); this.iRemaining = iRemaining; this.iStart = iStart; this.tok = tok; } public String parsedText() { return joinSubList(tok, iStart | 1, iRemaining & ~1); } public ListAndIndex remaining() { return new ListAndIndex(tok, iRemaining); } public ListAndIndex start() { return new ListAndIndex(tok, iStart); } public int length() { return iRemaining - iStart; } public ParsedWithTokens withValue(B b) { return new ParsedWithTokens(b, tok, iStart, iRemaining); } public String toString() { return "Parsed " + quote(parsedText()) + " as " + super.toString(); } public void replaceTokens(String s) { main.replaceTokens(tok, iStart, iRemaining, s); } } static public class LASClassDef { final public LASClassDef setUserGivenName(String userGivenName) { return userGivenName(userGivenName); } public LASClassDef userGivenName(String userGivenName) { this.userGivenName = userGivenName; return this; } final public String getUserGivenName() { return userGivenName(); } public String userGivenName() { return userGivenName; } public String userGivenName; final public LASClassDef setClassDefPrefix(String classDefPrefix) { return classDefPrefix(classDefPrefix); } public LASClassDef classDefPrefix(String classDefPrefix) { this.classDefPrefix = classDefPrefix; return this; } final public String getClassDefPrefix() { return classDefPrefix(); } public String classDefPrefix() { return classDefPrefix; } public String classDefPrefix = "userCode."; final public LASClassDef setFullCompilation(boolean fullCompilation) { return fullCompilation(fullCompilation); } public LASClassDef fullCompilation(boolean fullCompilation) { this.fullCompilation = fullCompilation; return this; } final public boolean getFullCompilation() { return fullCompilation(); } public boolean fullCompilation() { return fullCompilation; } public boolean fullCompilation = false; final public LASClassDef setVerbose(boolean verbose) { return verbose(verbose); } public LASClassDef verbose(boolean verbose) { this.verbose = verbose; return this; } final public boolean getVerbose() { return verbose(); } public boolean verbose() { return verbose; } public boolean verbose = true; public List fields = new ArrayList(); public List methods = new ArrayList(); public List methodBodies = new ArrayList(); static public class FieldDef { final public FieldDef setName(String name) { return name(name); } public FieldDef name(String name) { this.name = name; return this; } final public String getName() { return name(); } public String name() { return name; } public String name; final public FieldDef setType(Type type) { return type(type); } public FieldDef type(Type type) { this.type = type; return this; } final public Type getType() { return type(); } public Type type() { return type; } public Type type; } public String structForHash() { return GazelleV_LeftArrowScript.scriptStruct(litorderedmap("userGivenName", userGivenName, "fields", fields, "methods", methods, "fullCompilation", fullCompilation)); } public String classHash_cache; public String classHash() { if (classHash_cache == null) classHash_cache = classHash_load(); return classHash_cache; } public String classHash_load() { String struct = structForHash(); if (verbose) print("structForHash", struct); return md5(struct); } public String finalClassName() { return classDefPrefix() + finalClassNameWithoutPrefix(); } public String finalClassNameWithoutPrefix() { return or2(userGivenName, "C") + "_" + classHash(); } public byte[] toBytes_cache; public byte[] toBytes() { if (toBytes_cache == null) toBytes_cache = toBytes_load(); return toBytes_cache; } public byte[] toBytes_load() { ClassMaker classMaker = new ClassMaker(finalClassName()); var cp = classMaker.getConstantPool(); for (var field : fields) { var type = field.type; var fg = new FieldGen(Const.ACC_PUBLIC, typeToBCELType(type), field.name, cp); if (type instanceof ParameterizedType) fg.addAttribute(new org.apache.bcel.classfile.Signature(cp.addUtf8("Signature"), 2, cp.addUtf8(typeToVMSignature((ParameterizedType) type)), cp.getConstantPool())); classMaker.addField(fg); } for (var method : methods) if (fullCompilation) fullyCompileMethod(classMaker, method); else semiCompileMethod(classMaker, method); classMaker.addDefaultConstructor(); return classMaker.toBytes(); } public void semiCompileMethod(ClassMaker classMaker, GazelleV_LeftArrowScript.FunctionDef method) { int iMethod = l(methodBodies); methodBodies.add(method); String bodyFieldName = "_body" + iMethod; classMaker.addField(new FieldGen(Const.ACC_PUBLIC | Const.ACC_STATIC, classToBCELType(GazelleV_LeftArrowScript.Evaluable.class), bodyFieldName, classMaker.getConstantPool())); int nArgs = l(method.args); MethodMaker mm = new MethodMaker(classMaker, Object.class, method.name, repArray(Class.class, Object.class, nArgs)); int iThis = 0, iFirstArg = 1, iCtx = iFirstArg + nArgs; mm.newObject(FlexibleVarContext.class); mm.astore(iCtx); mm.aload(iCtx); mm.stringConstant("this"); mm.aload(iThis); mm.invokeVirtual(VarContext.class, void.class, "put", String.class, Object.class); for (int iArg = 0; iArg < nArgs; iArg++) { mm.aload(iCtx); mm.stringConstant(method.args[iArg]); mm.aload(iFirstArg + iArg); mm.invokeVirtual(VarContext.class, void.class, "put", String.class, Object.class); } mm.getStaticField(classMaker.className(), bodyFieldName, GazelleV_LeftArrowScript.Evaluable.class); mm.aload(iCtx); mm.invokeInterface(GazelleV_LeftArrowScript.Evaluable.class, Object.class, "get", VarContext.class); mm.areturn(); mm.done(); } public void fullyCompileMethod(ClassMaker classMaker, GazelleV_LeftArrowScript.FunctionDef method) { MethodMaker mm = new MethodMaker(classMaker, Object.class, method.name, repArray(Class.class, Object.class, l(method.args))); var tbc = new LASToByteCode(mm) { public JVMStackCellType compileGetVar(GazelleV_LeftArrowScript.GetVar code) { if (eq(code.var, "this")) { mm.aload(0); return JVMStackCellType.objValue; } int iArg = indexOf(method.args, code.var); if (iArg >= 0) { mm.aload(iArg + 1); return JVMStackCellType.objValue; } return super.compileGetVar(code); } }; tbc.postConversion = stackTop -> mm.convertToObject(stackTop); tbc.compileScript(method.body); mm.areturn(); mm.done(); } public void init(Class c) { for (int iMethod = 0; iMethod < l(methodBodies); iMethod++) { String bodyFieldName = "_body" + iMethod; set(c, bodyFieldName, methodBodies.get(iMethod).body); } } } 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() { try { concepts.removeConceptIndex(this); } catch (Exception __e) { throw rethrow(__e); } } } static public class SynchronizedCollection implements Collection, Serializable { public SynchronizedCollection() { } @java.io.Serial static final public long serialVersionUID = 3053995032091335093L; @SuppressWarnings("serial") public Collection c; @SuppressWarnings("serial") public Object mutex; public SynchronizedCollection(Collection c) { this.c = Objects.requireNonNull(c); mutex = this; } public SynchronizedCollection(Collection c, Object mutex) { this.c = Objects.requireNonNull(c); this.mutex = Objects.requireNonNull(mutex); } public int size() { synchronized (mutex) { return c.size(); } } public boolean isEmpty() { synchronized (mutex) { return c.isEmpty(); } } public boolean contains(Object o) { synchronized (mutex) { return c.contains(o); } } public Object[] toArray() { synchronized (mutex) { return c.toArray(); } } public T[] toArray(T[] a) { synchronized (mutex) { return c.toArray(a); } } public T[] toArray(java.util.function.IntFunction f) { synchronized (mutex) { return c.toArray(f); } } public Iterator iterator() { return c.iterator(); } public boolean add(E e) { synchronized (mutex) { return c.add(e); } } public boolean remove(Object o) { synchronized (mutex) { return c.remove(o); } } public boolean containsAll(Collection coll) { synchronized (mutex) { return c.containsAll(coll); } } public boolean addAll(Collection coll) { synchronized (mutex) { return c.addAll(coll); } } public boolean removeAll(Collection coll) { synchronized (mutex) { return c.removeAll(coll); } } public boolean retainAll(Collection coll) { synchronized (mutex) { return c.retainAll(coll); } } public void clear() { synchronized (mutex) { c.clear(); } } public String toString() { synchronized (mutex) { return c.toString(); } } @Override public void forEach(java.util.function.Consumer consumer) { synchronized (mutex) { c.forEach(consumer); } } @Override public boolean removeIf(java.util.function.Predicate filter) { synchronized (mutex) { return c.removeIf(filter); } } @Override public Spliterator spliterator() { return c.spliterator(); } @Override public java.util.stream.Stream stream() { return c.stream(); } @Override public java.util.stream.Stream parallelStream() { return c.parallelStream(); } @java.io.Serial final public void writeObject(ObjectOutputStream s) throws IOException { synchronized (mutex) { s.defaultWriteObject(); } } } static public class SynchronizedRandomAccessList extends SynchronizedList implements RandomAccess { public SynchronizedRandomAccessList() { } public SynchronizedRandomAccessList(List list) { super(list); } public SynchronizedRandomAccessList(List list, Object mutex) { super(list, mutex); } public List subList(int fromIndex, int toIndex) { synchronized (mutex) { return new SynchronizedRandomAccessList<>(list.subList(fromIndex, toIndex), mutex); } } @java.io.Serial static final public long serialVersionUID = 1530674583602358482L; @java.io.Serial final public Object writeReplace() { return new SynchronizedList<>(list); } } static public class HTMLAceEditor implements Htmlable { public String text; public String name = "text"; public String id; public Map divParams = litmap("style", "width: 80ch; height: 20em"); public String onKeyDown; public HTMLAceEditor() { } public HTMLAceEditor(String text) { this.text = text; } public String headStuff() { return hscriptsrc("https://botcompany.de/ace-builds/src-noconflict/ace.js") + hscriptsrc("https://botcompany.de/ace-builds/src-noconflict/ext-language_tools.js"); } public String html() { id = "ace_" + name; return div(htmlEncode2(text), params_stylePlus("display: none", paramsPlus(mapToParams(divParams), "id", id))) + hhiddenWithIDAndName(name) + hscript(replaceDollarVars(" (function() {\r\n ace.require(\"ace/ext/language_tools\");\r\n var editor = ace.edit($id);\r\n editor.setTheme(\"ace/theme/ambience\");\r\n editor.getSession().setTabSize(2);\r\n editor.getSession().setUseSoftTabs(true);\r\n editor.getSession().setUseWrapMode(true);\r\n document.getElementById($id).style.fontSize='15px';\r\n editor.setOptions({\r\n enableBasicAutocompletion: true\r\n });\r\n \r\n var div = $(\"#\" + $id);\r\n var hiddenVal = document.getElementById($name);\r\n function updateHidden() {\r\n div.trigger('input'); // for auto-expand\r\n //hiddenVal.value = editor.getValue();\r\n var newVal = editor.getValue();\r\n if (hiddenVal.value != newVal)\r\n $(hiddenVal).val(newVal).trigger('change');\r\n }\r\n updateHidden();\r\n \r\n editor.session.on('change', updateHidden);\r\n $onKeyDown\r\n \r\n div.show();\r\n //editor.focus();\r\n })() ", "id", jsQuote(id), "name", jsQuote(name), "onKeyDown", empty(onKeyDown) ? "" : "editor.textInput.getElement().onkeydown = " + onKeyDown + ";")); } public String complete() { return linesLL(headStuff(), html()); } } static public class VStack implements Steppable, IVStack { 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; } public void push(Computable computation) { stack.add(assertNotNull(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(Object value) { newResult = sentinel(value); pop(); } final public void replace(Computable computation) { tailCall(computation); } public void tailCall(Computable computation) { pop(); 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()); } public Computable caller() { return nextToLast(stack); } public void pop() { removeLast(stack); } public boolean isEmpty() { return empty(stack); } } static public class SimpleLeftToRightParser extends Meta { public String text; public List tok; final public ListAndIndex getPtr() { return ptr(); } public ListAndIndex ptr() { return ptr; } public ListAndIndex ptr; public ListAndIndex mainLoopPtr; public String currentToken; public boolean caseInsensitive = false; public List warnings = new ArrayList(); public SimpleLeftToRightParser() { } public SimpleLeftToRightParser(String text) { this.text = text; } public SimpleLeftToRightParser(List tok) { this.tok = tok; } transient public IF1> tokenize; public List tokenize(String text) { return tokenize != null ? tokenize.get(text) : tokenize_base(text); } final public List tokenize_fallback(IF1> _f, String text) { return _f != null ? _f.get(text) : tokenize_base(text); } public List tokenize_base(String text) { return javaTok(text); } final public String token() { return t(); } public String t() { return currentToken; } public String token(int i) { return get(tok, ptr.idx() + i * 2); } final public String consume() { return next(); } final public String tpp() { return next(); } public String next() { var t = t(); next(1); return t; } final public String prevSpace() { return lastSpace(); } public String lastSpace() { return get(tok, ptr.idx() - 1); } public String nextSpace() { return get(tok, ptr.idx() + 1); } public String space(int i) { return get(tok, ptr.idx() + i * 2 + 1); } public void unconsume() { next(-1); } final public boolean eqTok(String a, String b) { return tokEq(a, b); } public boolean tokEq(String a, String b) { return eqOrEqic(caseInsensitive, a, b); } public boolean tokEqOneOf(String a, String... l) { return any(l, b -> tokEq(a, b)); } public boolean is(int i, String t) { return tokEq(token(i), t); } public boolean is(String t) { return tokEq(currentToken, t); } public boolean was(String t) { return tokEq(token(-1), t); } public boolean isOneOf(String... tokens) { return tokEqOneOf(currentToken, tokens); } public String[] consumeArray(int n) { String[] array = new String[n]; for (int i = 0; i < n; i++) array[i] = consume(); return array; } public boolean isInteger() { return isInteger(t()); } public boolean isInteger(String s) { return main.isInteger(s); } public boolean isIdentifier() { return isIdentifier(t()); } public boolean isIdentifier(String s) { return main.isIdentifier(s); } public String consumeIdentifier() { return assertIdentifier(consume()); } public boolean consumeOpt(String token) { if (!is(token)) return false; consume(); return true; } public void consume(String token) { if (!is(token)) throw fail("Expected " + quote(token) + ", got " + describeToken(token())); consume(); } public String describeToken(String token) { return token == null ? "EOF" : quote(token); } public String consumeOneOf(String... tokens) { if (!isOneOf(tokens)) throw fail("Expected one of " + asList(tokens)); return consume(); } public void ptr(ListAndIndex ptr) { this.ptr = ptr; fetch(); } final public int tokIdx() { return idx(); } public int idx() { return ptr.idx(); } public int lTok() { return l(tok); } public int nRemainingTokens() { return (lTok() - idx()) / 2; } final public boolean endOfText() { return atEnd(); } public boolean atEnd() { return ptr.atEnd(); } public void fetch() { currentToken = ptr.get(); } public boolean lineBreak() { return containsLineBreak(get(tok, ptr.idx() - 1)); } public boolean atEndOrLineBreak() { return atEnd() || lineBreak(); } public void init() { if (tok == null) tok = tokenize(text); if (ptr == null) ptr(new ListAndIndex(tok, 1)); } public boolean mainLoop() { init(); if (atEnd()) return false; if (eq(mainLoopPtr, ptr)) throw fail("main loop didn't advance (current token: " + quote(token()) + ")"); mainLoopPtr = ptr; return true; } public class AssureAdvance { public ListAndIndex cur; { init(); } public boolean get() { if (atEnd()) return false; if (eq(cur, ptr)) throw fail("Parse loop didn't advance (current token: " + quote(token()) + ")"); cur = ptr; return true; } } public void unknownToken() { warn("Unknown token: " + t()); } public void warn(String msg) { warnings.add(print(msg)); } final public void skip(int n) { next(n); } public void next(int n) { ptr(min(lTok(), ptr.idx() + n * 2)); } public void ptr(int i) { ptr(new ListAndIndex(tok, min(i | 1, l(tok)))); } public LineAndColumn lineAndColumn() { return tokenToLineAndColumn(ptr); } public LineAndColumn lineAndColumn(int idx) { return tokenToLineAndColumn(ptr.plus(idx * 2)); } public String consumeUntilSpaceOr(IF0 pred) { int i = idx(); do next(); while (!atEnd() && empty(lastSpace()) && !pred.get()); return joinSubList(tok, i, idx() - 1); } public void setText(String text) { this.text = text; tok = null; ptr = null; } public int relativeIndexOf(String token) { int n = nRemainingTokens(); for (int i = 0; i < n; i++) if (eqTok(token(i), token)) return i; return -1; } } public interface IMultiMap { public Set keySet(); public Collection get(A a); public int size(); public int keyCount(); } static public class MultiSet implements IMultiSet { public Map map = new HashMap(); public int size; public MultiSet(boolean useTreeMap) { if (useTreeMap) map = new TreeMap(); } public MultiSet(TreeMap map) { this.map = map; } public MultiSet() { } public MultiSet(Iterable c) { addAll(c); } public MultiSet(MultiSet ms) { synchronized (ms) { for (A a : ms.keySet()) add(a, ms.get(a)); } } public synchronized int add(A key) { return add(key, 1); } synchronized public void addAll(Iterable c) { if (c != null) for (A a : c) add(a); } synchronized public void addAll(MultiSet ms) { for (A a : ms.keySet()) add(a, ms.get(a)); } synchronized public int add(A key, int count) { if (count <= 0) return 0; size += count; Integer i = map.get(key); map.put(key, i != null ? (count += i) : count); return count; } synchronized public void put(A key, int count) { int oldCount = get(key); if (count == oldCount) return; size += count - oldCount; if (count != 0) map.put(key, count); else map.remove(key); } public synchronized int get(A key) { Integer i = map.get(key); return i != null ? i : 0; } synchronized public boolean contains(A key) { return map.containsKey(key); } synchronized public void remove(A key) { Integer i = map.get(key); if (i != null) { --size; if (i > 1) map.put(key, i - 1); else map.remove(key); } } synchronized public List topTen() { return getTopTen(); } synchronized public List getTopTen() { return getTopTen(10); } synchronized public List getTopTen(int maxSize) { List list = getSortedListDescending(); return list.size() > maxSize ? list.subList(0, maxSize) : list; } synchronized public List highestFirst() { return getSortedListDescending(); } synchronized public List lowestFirst() { return reversedList(getSortedListDescending()); } synchronized public List getSortedListDescending() { List list = new ArrayList(map.keySet()); Collections.sort(list, new Comparator() { public int compare(A a, A b) { return map.get(b).compareTo(map.get(a)); } }); return list; } synchronized public int getNumberOfUniqueElements() { return map.size(); } synchronized public int uniqueSize() { return map.size(); } synchronized public Set asSet() { return map.keySet(); } synchronized public NavigableSet navigableSet() { return navigableKeys((NavigableMap) map); } synchronized public Set keySet() { return map.keySet(); } synchronized public A getMostPopularEntry() { int max = 0; A a = null; for (Map.Entry entry : map.entrySet()) { if (entry.getValue() > max) { max = entry.getValue(); a = entry.getKey(); } } return a; } synchronized public void removeAll(A key) { size -= get(key); map.remove(key); } synchronized public int size() { return size; } synchronized public MultiSet mergeWith(MultiSet set) { MultiSet result = new MultiSet(); for (A a : set.asSet()) { result.add(a, set.get(a)); } return result; } synchronized public boolean isEmpty() { return map.isEmpty(); } synchronized public String toString() { return str(map); } synchronized public void clear() { map.clear(); size = 0; } final public Map toMap() { return asMap(); } synchronized public Map asMap() { return cloneMap(map); } } static public class HTMLPaginator { public String startParam = "start"; public String baseLink; public int start, step = 50; public int max; public void processParams(Map params) { start = parseInt(mapGet(params, startParam)); } public String renderNav(Object... __) { return pageNav2(baseLink, max, start, step, startParam, __); } public IntRange visibleRange() { return intRange(start, min(max, start + step)); } } static public class HCRUD_Data { public Map renderers = new HashMap(); public Map fieldHelp = new HashMap(); public Object currentValue; public boolean humanizeFieldNames = true; public Map rawFormValues; abstract static public class Renderer { public String metaInfo; transient public IF1 preprocessValue; public Object preprocessValue(Object value) { return preprocessValue != null ? preprocessValue.get(value) : preprocessValue_base(value); } final public Object preprocessValue_fallback(IF1 _f, Object value) { return _f != null ? _f.get(value) : preprocessValue_base(value); } public Object preprocessValue_base(Object value) { return value; } } static public class NotEditable extends Renderer { } static public class TextArea extends Renderer implements IFieldsToList { public int cols; public int rows; public TextArea() { } public TextArea(int cols, int rows) { this.rows = rows; this.cols = cols; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + cols + ", " + rows + ")"; } public boolean equals(Object o) { if (!(o instanceof TextArea)) return false; TextArea __1 = (TextArea) o; return cols == __1.cols && rows == __1.rows; } public int hashCode() { int h = -939552902; h = boostHashCombine(h, _hashCode(cols)); h = boostHashCombine(h, _hashCode(rows)); return h; } public Object[] _fieldsToList() { return new Object[] { cols, rows }; } public TextArea(int cols, int rows, IF1 preprocessValue) { this.cols = cols; this.rows = rows; this.preprocessValue = preprocessValue; } } static public class AceEditor extends TextArea { public AceEditor() { } public AceEditor(int cols, int rows) { this.rows = rows; this.cols = cols; } } static public class TextField extends Renderer implements IFieldsToList { public int cols; public TextField() { } public TextField(int cols) { this.cols = cols; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + cols + ")"; } public boolean equals(Object o) { if (!(o instanceof TextField)) return false; TextField __2 = (TextField) o; return cols == __2.cols; } public int hashCode() { int h = 942981037; h = boostHashCombine(h, _hashCode(cols)); return h; } public Object[] _fieldsToList() { return new Object[] { cols }; } } static public class AbstractComboBox extends Renderer implements IFieldsToList { public AbstractComboBox() { } public String toString() { return shortClassName_dropNumberPrefix(this); } public boolean equals(Object o) { return o instanceof AbstractComboBox; } public int hashCode() { int h = -1802496065; return h; } public Object[] _fieldsToList() { return null; } public boolean editable = false; transient public IF1 valueToEntry; public String valueToEntry(Object value) { return valueToEntry != null ? valueToEntry.get(value) : valueToEntry_base(value); } final public String valueToEntry_fallback(IF1 _f, Object value) { return _f != null ? _f.get(value) : valueToEntry_base(value); } public String valueToEntry_base(Object value) { return strOrNull(value); } } static public class ComboBox extends AbstractComboBox implements IFieldsToList { public List entries; public ComboBox() { } public ComboBox(List entries) { this.entries = entries; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + entries + ")"; } public boolean equals(Object o) { if (!(o instanceof ComboBox)) return false; ComboBox __3 = (ComboBox) o; return eq(entries, __3.entries); } public int hashCode() { int h = -547674755; h = boostHashCombine(h, _hashCode(entries)); return h; } public Object[] _fieldsToList() { return new Object[] { entries }; } public ComboBox(String... entries) { this(asList(entries)); } public ComboBox(boolean editable, String... entries) { this(entries); this.editable = editable; } public ComboBox(boolean editable, List entries) { this(entries); this.editable = editable; } public ComboBox(List entries, IF1 valueToEntry) { this.entries = entries; this.valueToEntry = valueToEntry; } } static public class DynamicComboBox extends AbstractComboBox implements IFieldsToList { public String info; public DynamicComboBox() { } public DynamicComboBox(String info) { this.info = info; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + info + ")"; } public boolean equals(Object o) { if (!(o instanceof DynamicComboBox)) return false; DynamicComboBox __4 = (DynamicComboBox) o; return eq(info, __4.info); } public int hashCode() { int h = -737505636; h = boostHashCombine(h, _hashCode(info)); return h; } public Object[] _fieldsToList() { return new Object[] { info }; } public String url; } static public class CheckBox extends Renderer implements IFieldsToList { public CheckBox() { } public String toString() { return shortClassName_dropNumberPrefix(this); } public boolean equals(Object o) { return o instanceof CheckBox; } public int hashCode() { int h = 1601505219; return h; } public Object[] _fieldsToList() { return null; } { metaInfo = "Bool"; } } static public class FlexibleLengthList extends Renderer implements IFieldsToList { public Renderer itemRenderer; public FlexibleLengthList() { } public FlexibleLengthList(Renderer itemRenderer) { this.itemRenderer = itemRenderer; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + itemRenderer + ")"; } public boolean equals(Object o) { if (!(o instanceof FlexibleLengthList)) return false; FlexibleLengthList __5 = (FlexibleLengthList) o; return eq(itemRenderer, __5.itemRenderer); } public int hashCode() { int h = -1874811153; h = boostHashCombine(h, _hashCode(itemRenderer)); return h; } public Object[] _fieldsToList() { return new Object[] { itemRenderer }; } } public String itemName() { return "object"; } public String itemNamePlural() { return plural(itemName()); } public List> list() { return null; } public List> list(IntRange range) { return subListOrFull(list(), range); } public String idField() { return "id"; } public Map emptyObject() { return null; } public Map getObject(Object id) { return null; } public Map getObjectForEdit(Object id) { return getObject(id); } transient public IF1> getObjectForDuplication; public Map getObjectForDuplication(Object id) { return getObjectForDuplication != null ? getObjectForDuplication.get(id) : getObjectForDuplication_base(id); } final public Map getObjectForDuplication_fallback(IF1> _f, Object id) { return _f != null ? _f.get(id) : getObjectForDuplication_base(id); } public Map getObjectForDuplication_base(Object id) { return getObject(id); } public Object createObject(Map fullMap, String fieldPrefix) { throw unimplemented(); } public String deleteObject(Object id) { throw unimplemented(); } public boolean objectCanBeDeleted(Object id) { return true; } transient public IF1 objectCanBeEdited; public boolean objectCanBeEdited(Object id) { return objectCanBeEdited != null ? objectCanBeEdited.get(id) : objectCanBeEdited_base(id); } final public boolean objectCanBeEdited_fallback(IF1 _f, Object id) { return _f != null ? _f.get(id) : objectCanBeEdited_base(id); } public boolean objectCanBeEdited_base(Object id) { return true; } public String updateObject(Object id, Map fullMap, String fieldPrefix) { throw unimplemented(); } public Renderer getRenderer(String field) { return renderers.get(field); } final public Renderer getRenderer(String field, Object value) { this.currentValue = value; try { return getRenderer(field); } finally { this.currentValue = null; } } public String fieldHelp(String field) { return fieldHelp.get(field); } public HCRUD_Data addRenderer(String field, Renderer renderer) { renderers.put(field, renderer); return this; } public HCRUD_Data fieldHelp(String field, String help, String... more) { fieldHelp.put(field, help); for (int i = 0; i + 1 < l(more); i += 2) fieldHelp.put(more[i], more[i + 1]); return this; } public String fieldNameToHTML(String name) { String help = fieldHelp.get(name); return spanTitle(help, htmlencode2(humanizeFieldNames ? humanizeLabel(name) : name)); } public Set filteredFields() { return null; } public List comboBoxSearch(String info, String query) { return null; } public String titleForObjectID(Object id) { return null; } public Pair defaultSortField() { return null; } abstract public class Item extends AbstractMap { public Object id; public Map fullMap; public Item(Object id) { this.id = id; } abstract public Map calcFullMap(); public Map fullMap() { if (fullMap == null) fullMap = calcFullMap(); return fullMap; } public int size() { return l(fullMap()); } public Set> entrySet() { return fullMap().entrySet(); } public boolean containsKey(Object o) { return fullMap().containsKey(o); } public Object get(Object o) { if (fullMap == null && eq(o, idField())) return id; return fullMap().get(o); } public Object put(String key, Object value) { return fullMap().put(key, value); } } } static public class ResolvableLASClass { public ResolvableLASClass() { } transient public ILASClassLoader lasClassLoader; public LASClassDef classDef; public Class resolvedClass; public ResolvableLASClass(ILASClassLoader lasClassLoader, LASClassDef classDef) { this.classDef = classDef; this.lasClassLoader = lasClassLoader; } public Class get() { if (resolvedClass == null) { if (lasClassLoader == null) throw fail("Need LASClassLoader to define " + classDef.userGivenName); resolvedClass = lasClassLoader.defineLASClass(classDef.finalClassName(), () -> classDef.toBytes()); classDef.init(resolvedClass); } return resolvedClass; } public String toString() { if (resolvedClass != null) return className(resolvedClass); { var __1 = classDef.userGivenName; if (__1 != null) return __1; } if (classDef.classHash_cache != null) return classDef.finalClassNameWithoutPrefix(); return or2(classDef.userGivenName, "script-defined class") + " [unresolved]"; } } static public class MinimalChain implements Iterable { public A element; public MinimalChain next; public MinimalChain() { } public MinimalChain(A element) { this.element = element; } public MinimalChain(A element, MinimalChain next) { this.next = next; this.element = element; } public String toString() { return str(toList()); } public ArrayList toList() { ArrayList l = new ArrayList(); MinimalChain c = this; while (c != null) { l.add(c.element); c = c.next; } return l; } public void setElement(A a) { element = a; } public void setNext(MinimalChain next) { this.next = next; } public Iterator iterator() { return toList().iterator(); } public A get() { return element; } } static public interface ISetter { public void set(A a); } static public interface IConceptCounter { public Class conceptClass(); public int countConcepts(); public Collection allConcepts(); } static public interface IAutoCloseableF0 extends IF0, AutoCloseable { } abstract static public class HAbstractRenderable { public String baseLink = ""; public MakeFrame makeFrame = (title, contents) -> h1_title(title) + contents; static public interface MakeFrame { public String makeFrame(String title, String contents); } public HAbstractRenderable() { } public HAbstractRenderable(String baseLink) { this.baseLink = baseLink; } public HAbstractRenderable makeFrame(MakeFrame makeFrame) { this.makeFrame = makeFrame; return this; } public String baseLinkPlus(String uri) { return nempty(uri) ? appendSlash(baseLink) + uri : baseLink; } public String frame(String title, String contents) { return makeFrame.makeFrame(title, contents); } public String refreshWithMsgs(String... msgs) { return refreshWithMsgs(asList(msgs)); } public String refreshWithMsgs(List msgs, Object... __) { String anchor = (String) (optPar("anchor", __)); Map params = (Map) (optPar("params", __)); return hrefresh(addAnchorToURL(appendQueryToURL(baseLink, mapPlus(params, "msg", htmlEncode_nlToBr(lines_rtrim(msgs)))), anchor)); } public String renderMsgs(Map params) { return pUnlessEmpty(params.get("msg")); } } static public class RemoteDB implements AutoCloseable { public DialogIO db; public String name; public RemoteDB(String s) { this(s, false); } public RemoteDB(String s, boolean autoStart) { name = s; if (isSnippetID(s)) name = dbBotName(s); db = findBot(name); if (db == null) if (autoStart) { nohupJavax(fsI(s)); waitForBotStartUp(name); assertNotNull("Weird problem", db = findBot(s)); } else throw fail("DB " + s + " not running"); } public boolean functional() { return db != null; } public List list() { return adopt((List) rpc(db, "xlist")); } public List list(String className) { return adopt((List) rpc(db, "xlist", className)); } public List xlist() { return list(); } public List xlist(String className) { return list(className); } public List adopt(List l) { if (l != null) for (RC rc : l) adopt(rc); return l; } public RC adopt(RC rc) { if (rc != null) rc.db = this; return rc; } public Object adopt(Object o) { if (o instanceof RC) return adopt((RC) o); return o; } public String xclass(RC o) { return (String) rpc(db, "xclass", o); } public Object xget(RC o, String field) { return adopt(rpc(db, "xget", o, field)); } public String xS(RC o, String field) { return (String) xget(o, field); } public RC xgetref(RC o, String field) { return adopt((RC) xget(o, field)); } public void xset(RC o, String field, Object value) { rpc(db, "xset", o, field, value); } public RC uniq(String className) { RC ref = first(list(className)); if (ref == null) ref = xnew(className); return ref; } public RC xuniq(String className) { return uniq(className); } public RC xnew(String className, Object... values) { return adopt((RC) rpc(db, "xnew", className, values)); } public void xdelete(RC o) { rpc(db, "xdelete", o); } public void xdelete(List l) { rpc(db, "xdelete", l); } public void close() { _close(db); } public String fullgrab() { return (String) rpc(db, "xfullgrab"); } public String xfullgrab() { return fullgrab(); } public void xshutdown() { rpc(db, "xshutdown"); } public long xchangeCount() { return (long) rpc(db, "xchangeCount"); } public int xcount() { return (int) rpc(db, "xcount"); } public void reconnect() { close(); db = findBot(name); } public RC rc(long id) { return new RC(this, id); } } public interface ChangeTriggerable { public void change(); } 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)); } } 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 IFieldsToList { public Object[] _fieldsToList(); } static public interface ISleeper_v2 { public Sleeping doLater(Timestamp targetTime, Runnable r); public default Sleeping doAfter(double seconds, Runnable r) { return doLater(tsNow().plusSeconds(seconds), r); } } 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()); } } public interface IHasTokenRangeWithSrc { public void setTokenRangeWithSrc(TokenRangeWithSrc src); public TokenRangeWithSrc tokenRangeWithSrc(); default public String srcText() { var src = tokenRangeWithSrc(); return src == null ? null : src.text(); } } static public class Seconds implements Comparable, IFieldsToList { public double seconds; public Seconds() { } public Seconds(double seconds) { this.seconds = seconds; } public boolean equals(Object o) { if (!(o instanceof Seconds)) return false; Seconds __1 = (Seconds) o; return seconds == __1.seconds; } public int hashCode() { int h = -660217249; h = boostHashCombine(h, _hashCode(seconds)); return h; } public Object[] _fieldsToList() { return new Object[] { seconds }; } final public double get() { return seconds(); } final public double getDouble() { return seconds(); } public double seconds() { return seconds; } public String toString() { return formatDouble(seconds, 3) + " s"; } public int compareTo(Seconds s) { return cmp(seconds, s.seconds); } public Seconds div(double x) { return new Seconds(get() / x); } public Seconds minus(Seconds x) { return new Seconds(get() - x.get()); } } static public class GazelleV_LeftArrowScript { abstract static public class Base extends HasTokenRangeWithSrc { public RuntimeException rethrowWithSrc(Throwable e) { return rethrowWithSrc("", e); } public RuntimeException rethrowWithSrc(String msg, Throwable e) { if (src != null) throw rethrowAndAppendToMessage(e, squareBracketed(joinNemptiesWithComma(msg, src))); else throw rethrow(e); } } public interface Evaluable extends IF0, IHasTokenRangeWithSrc { public default Object get() { return get(new FlexibleVarContext()); } public Object get(VarContext ctx); public default LASValueDescriptor returnType() { return null; } public default Evaluable optimize() { return this; } public default Evaluable optimizeForReturnValueNotNeeded() { return this; } } abstract static public class EvaluableBase extends Base implements Evaluable { final public EvaluableBase setReturnType(LASValueDescriptor returnType) { return returnType(returnType); } public EvaluableBase returnType(LASValueDescriptor returnType) { this.returnType = returnType; return this; } final public LASValueDescriptor getReturnType() { return returnType(); } public LASValueDescriptor returnType() { return returnType; } public LASValueDescriptor returnType; public boolean returnValueNeeded = true; public Evaluable optimizeForReturnValueNotNeeded() { returnValueNeeded = false; return optimize(); } } static public AtomicLong scriptIDCounter = new AtomicLong(); static public long scriptID() { return incAtomicLong(scriptIDCounter); } static public class Script extends EvaluableBase { transient public long id = scriptID(); public Map functionDefs; public Evaluable[] steps; final public Script setScope(LASScope scope) { return scope(scope); } public Script scope(LASScope scope) { this.scope = scope; return this; } final public LASScope getScope() { return scope(); } public LASScope scope() { return scope; } public LASScope scope; public Object get(VarContext ctx) { Object result = null; var pingSource = pingSource(); for (var step : steps) { ping(pingSource); result = step.get(ctx); var exiting = ctx.exitFromScript; if (exiting != null) { if (exiting == this) { ctx.exitFromScript = null; result = ctx.returnValue; ctx.returnValue(null); return result; } return null; } } return result; } public String toStringLong() { return pnlToLines(steps); } public String toString() { return "Script " + n2(id); } public FunctionDef getFunction(String name) { return mapGet(functionDefs, name); } final public Script optimize() { return optimizeScript(); } public Script optimizeScript() { int n = returnValueNeeded ? steps.length - 1 : steps.length; for (int i = 0; i < n; i++) steps[i] = steps[i].optimizeForReturnValueNotNeeded(); for (var f : values(functionDefs)) f.optimize(); return this; } } static public class FunctionDef extends Base implements IFieldsToList { public String name; public String[] args; public Script body; public FunctionDef() { } public FunctionDef(String name, String[] args, Script body) { this.body = body; this.args = args; this.name = name; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + name + ", " + args + ", " + body + ")"; } public Object[] _fieldsToList() { return new Object[] { name, args, body }; } final public FunctionDef setScope(LASScope scope) { return scope(scope); } public FunctionDef scope(LASScope scope) { this.scope = scope; return this; } final public LASScope getScope() { return scope(); } public LASScope scope() { return scope; } public LASScope scope; public FunctionDef(String name, List args, Script body) { this.args = toStringArray(args); this.body = body; this.name = name; } public Object call(VarContext ctx, Object... args) { VarContext ctx2 = scope != null && scope.useFixedVars ? new FixedVarContext(ctx, scope.names) : new FlexibleVarContext(ctx); int n = min(l(args), l(this.args)); for (int i = 0; i < n; i++) ctx2.put(this.args[i], args[i]); return body.get(ctx2); } public void optimize() { body = body.optimize(); } } static public class Assignment extends EvaluableBase implements IFieldsToList { public String var; public Evaluable expression; public Assignment() { } public Assignment(String var, Evaluable expression) { this.expression = expression; this.var = var; } public Object[] _fieldsToList() { return new Object[] { var, expression }; } public Object get(VarContext ctx) { Object o = expression.get(ctx); ctx.set(var, o); return o; } public String toString() { return var + " <- " + expression; } } abstract static public class FixedVarBase extends EvaluableBase { final public FixedVarBase setScope(LASScope scope) { return scope(scope); } public FixedVarBase scope(LASScope scope) { this.scope = scope; return this; } final public LASScope getScope() { return scope(); } public LASScope scope() { return scope; } public LASScope scope; public String var; public int varIdx; public String varToStr() { return var + " [" + varIdx + "]"; } public void assertResolved() { if (varIdx < 0) throw fail("Unresolved variable access: " + var); } public void resolve() { varIdx = scope.resolveVar(var); } } static public class FixedVarAssignment extends FixedVarBase { public FixedVarAssignment() { } public Evaluable expression; public FixedVarAssignment(LASScope scope, String var, Evaluable expression) { this.expression = expression; this.var = var; this.scope = scope; } public Object get(VarContext ctx) { Object o = expression.get(ctx); ((FixedVarContext) ctx).set(varIdx, o); return o; } public String toString() { return varToStr() + " <- " + expression; } } static public class VarDeclaration extends EvaluableBase implements IFieldsToList { public String var; public Class type; public Evaluable expression; public VarDeclaration() { } public VarDeclaration(String var, Class type, Evaluable expression) { this.expression = expression; this.type = type; this.var = var; } public Object[] _fieldsToList() { return new Object[] { var, type, expression }; } public Object get(VarContext ctx) { Object o = expression == null ? null : expression.get(ctx); ctx.set(var, o); return o; } public String toString() { return "var " + var + " <- " + expression; } } static public class AssignmentToOuterVar extends EvaluableBase implements IFieldsToList { public String var; public Evaluable expression; public AssignmentToOuterVar() { } public AssignmentToOuterVar(String var, Evaluable expression) { this.expression = expression; this.var = var; } public Object[] _fieldsToList() { return new Object[] { var, expression }; } public Object get(VarContext ctx) { var parent = ctx.parent(); assertNotNull("No outer variable context", parent); Object o = expression.get(ctx); parent.set(var, o); return o; } public String toString() { return "outer " + var + " <- " + expression; } } static public class NewObject extends EvaluableBase { public NewObject() { } public Class c; public Evaluable[] args; public NewObject(Class c) { this.c = c; } public NewObject(Class c, Evaluable[] args) { this.args = args; this.c = c; } public Object get(VarContext ctx) { try { return preciseNuObject(c, mapToArrayOrNull(args, arg -> arg.get(ctx))); } catch (Throwable e) { throw rethrowWithSrc(e); } } public String toString() { return "new " + formatFunctionCall(className(c), args); } } static public class NewObject_LASClass extends NewObject { public NewObject_LASClass() { } public ResolvableLASClass lasClass; public NewObject_LASClass(ResolvableLASClass lasClass) { this.lasClass = lasClass; } public NewObject_LASClass(ResolvableLASClass lasClass, Evaluable[] args) { this.args = args; this.lasClass = lasClass; } public void resolve() { if (c == null) c = lasClass.get(); } public Object get(VarContext ctx) { resolve(); return super.get(ctx); } public String toString() { return "new " + formatFunctionCall(str(lasClass), args); } } static public class NewObject_UnknownClass extends NewObject implements IFieldsToList { public Evaluable classExpr; public Evaluable[] args; public NewObject_UnknownClass() { } public NewObject_UnknownClass(Evaluable classExpr, Evaluable[] args) { this.args = args; this.classExpr = classExpr; } public Object[] _fieldsToList() { return new Object[] { classExpr, args }; } public Object get(VarContext ctx) { try { Class c = (Class) (classExpr.get(ctx)); return preciseNuObject(c, mapToArrayOrNull(args, arg -> arg.get(ctx))); } catch (Throwable e) { throw rethrowWithSrc(e); } } public String toString() { return "new " + formatFunctionCall(classExpr, args); } } static public class CallFunction extends EvaluableBase implements IFieldsToList { public FunctionDef f; public Evaluable[] args; public CallFunction() { } public CallFunction(FunctionDef f, Evaluable[] args) { this.args = args; this.f = f; } public Object[] _fieldsToList() { return new Object[] { f, args }; } public Object get(VarContext ctx) { var evaledArgs = mapToArrayOrNull(args, a -> a.get(ctx)); if (ctx.exiting()) return null; return f.call(ctx, evaledArgs); } public String toString() { return formatFunctionCall(f.name, args); } } static public class GetVar extends EvaluableBase implements IFieldsToList { public String var; public GetVar() { } public GetVar(String var) { this.var = var; } public Object[] _fieldsToList() { return new Object[] { var }; } public Object get(VarContext ctx) { return ctx.get(var); } public String toString() { return var; } } static public class GetFixedVar extends FixedVarBase { public GetFixedVar() { } public GetFixedVar(LASScope scope, String var) { this.var = var; this.scope = scope; } public Object get(VarContext ctx) { assertResolved(); try { return ((FixedVarContext) ctx).get(varIdx); } catch (ArrayIndexOutOfBoundsException e) { assertResolved(); throw e; } } public String toString() { return var + " [" + varIdx + "]"; } } static public class Const extends EvaluableBase implements IFieldsToList { public Object value; public Const() { } public Const(Object value) { this.value = value; } public Object[] _fieldsToList() { return new Object[] { value }; } public Object get(VarContext ctx) { return value; } public String toString() { return strOrClassName(value); } public LASValueDescriptor returnType() { return new LASValueDescriptor.KnownValue(value); } public Object _serialize() { boolean ok = isUnproblematicValue(value); return ok ? this : toStringWithClass(value); } } static public class GetStaticField extends EvaluableBase implements IFieldsToList { public Field field; public GetStaticField() { } public GetStaticField(Field field) { this.field = field; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + field + ")"; } public Object[] _fieldsToList() { return new Object[] { field }; } public Object get(VarContext ctx) { try { return field.get(null); } catch (Exception __e) { throw rethrow(__e); } } public String _serialize() { return str(field); } } static public class CallMethodOrGetField extends EvaluableBase implements IFieldsToList { public Evaluable target; public String name; public CallMethodOrGetField() { } public CallMethodOrGetField(Evaluable target, String name) { this.name = name; this.target = target; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + target + ", " + name + ")"; } public Object[] _fieldsToList() { return new Object[] { target, name }; } final public CallMethodOrGetField setAllowNullReference(boolean allowNullReference) { return allowNullReference(allowNullReference); } public CallMethodOrGetField allowNullReference(boolean allowNullReference) { this.allowNullReference = allowNullReference; return this; } final public boolean getAllowNullReference() { return allowNullReference(); } public boolean allowNullReference() { return allowNullReference; } public boolean allowNullReference = false; public Object handleNullReference() { if (allowNullReference) return null; else throw new NullPointerException(); } public Object get(VarContext ctx) { try { Object object = target.get(ctx); if (object == null) return handleNullReference(); return preciseGetOrCallMethod(object, name); } catch (Throwable e) { throw rethrowWithSrc("Was getting " + name, e); } } } static public class GetVarContext extends EvaluableBase { public Object get(VarContext ctx) { return ctx; } } static public class ThrowMethodNotFoundException extends EvaluableBase implements IFieldsToList { public CallMethod instruction; public ThrowMethodNotFoundException() { } public ThrowMethodNotFoundException(CallMethod instruction) { this.instruction = instruction; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + instruction + ")"; } public Object[] _fieldsToList() { return new Object[] { instruction }; } public Object get(VarContext ctx) { throw fail("Method not found: " + instruction); } } static public class ThrowNullPointerException extends EvaluableBase implements IFieldsToList { public CallMethod instruction; public ThrowNullPointerException() { } public ThrowNullPointerException(CallMethod instruction) { this.instruction = instruction; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + instruction + ")"; } public Object[] _fieldsToList() { return new Object[] { instruction }; } public Object get(VarContext ctx) { throw fail("Null pointer exception: " + instruction); } } static public class CallMethod extends EvaluableBase implements IFieldsToList { public Evaluable target; public String methodName; public Evaluable[] args; public CallMethod() { } public CallMethod(Evaluable target, String methodName, Evaluable[] args) { this.args = args; this.methodName = methodName; this.target = target; } public Object[] _fieldsToList() { return new Object[] { target, methodName, args }; } public Object get(VarContext ctx) { return newPreciseCall(target.get(ctx), methodName, mapToArrayOrNull(args, arg -> arg.get(ctx))); } public String toString() { return target + "." + formatFunctionCall(methodName, args); } public Evaluable optimize() { var targetType = target.returnType(); if (targetType != null && targetType.knownValue()) { Object o = targetType.value(); if (o == null) return new ThrowNullPointerException(this); Class[] argTypes = new Class[l(args)]; for (int i = 0; i < l(args); i++) { var type = args[i].returnType(); if (type == null || !type.javaClassIsExact()) return this; argTypes[i] = type.javaClass(); } List methods = findMethodsNamed_cached(o, methodName); if (any(methods, m -> m.isVarArgs())) return this; var __4 = findMethod_withPrimitiveWidening_onTypes(o, methodName, argTypes); var method = __4.a; var widening = __4.b; if (method == null) return new ThrowMethodNotFoundException(this); return new DirectMethodCallOnKnownTarget(widening, o instanceof Class ? null : o, method, args); } return this; } } static public class LambdaDef extends EvaluableBase implements IFieldsToList { public Class intrface; public String[] args; public Evaluable body; public LambdaDef() { } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + intrface + ", " + args + ", " + body + ")"; } public Object[] _fieldsToList() { return new Object[] { intrface, args, body }; } public Method implementedMethod; public LambdaDef(Class intrface, String[] args, Evaluable body) { this.body = body; this.args = args; this.intrface = intrface; implementedMethod = findSingleInterfaceMethodOrFail(intrface); if (implementedMethod.getParameterCount() != l(args)) throw fail("Bad parameter count for lambda: " + implementedMethod + " vs: " + joinWithComma(args)); } public Object get(VarContext ctx) { return proxyFromInvocationHandler(intrface, (proxy, method, actualArgs) -> { ping(); if (method.getDeclaringClass() == intrface) { var ctx2 = new FlexibleVarContext(ctx); var argNames = args; for (int i = 0; i < l(args); i++) ctx2.put(argNames[i], actualArgs[i]); return body.get(ctx2); } else return handleObjectMethodsInProxyInvocationHandler(this, implementedMethod, method, proxy, actualArgs); }); } } abstract static public class CurriedLambdaBase extends EvaluableBase implements IFieldsToList { public Class intrface; public Evaluable[] curriedArgs; public CurriedLambdaBase() { } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + intrface + ", " + curriedArgs + ")"; } public Object[] _fieldsToList() { return new Object[] { intrface, curriedArgs }; } public Method implementedMethod; public CurriedLambdaBase(Class intrface, Evaluable[] curriedArgs) { this.curriedArgs = curriedArgs; this.intrface = intrface; implementedMethod = findSingleInterfaceMethodOrFail(intrface); } public Object get(VarContext ctx) { Object[] curriedArguments = mapToArrayOrNull(curriedArgs, arg -> arg.get(ctx)); return proxyFromInvocationHandler(intrface, (proxy, method, actualArgs) -> { if (method.getDeclaringClass() == intrface) return forwardCall(ctx, concatMethodArgs(curriedArguments, actualArgs)); else return handleObjectMethodsInProxyInvocationHandler(this, implementedMethod, method, proxy, actualArgs); }); } abstract public Object forwardCall(VarContext ctx, Object[] args); } static public class CurriedMethodLambda extends CurriedLambdaBase { public Object target; public String targetMethod; public CurriedMethodLambda(Class intrface, Object target, String targetMethod, Evaluable[] curriedArgs) { super(intrface, curriedArgs); this.targetMethod = targetMethod; this.target = target; } public Object forwardCall(VarContext ctx, Object[] args) { return call(target, targetMethod, args); } } static public class CurriedScriptFunctionLambda extends CurriedLambdaBase { public FunctionDef f; public CurriedScriptFunctionLambda(Class intrface, FunctionDef f, Evaluable[] curriedArgs) { super(intrface, curriedArgs); this.f = f; } public Object forwardCall(VarContext ctx, Object[] args) { return f.call(ctx, args); } } static public class CurriedConstructorLambda extends CurriedLambdaBase { public Constructor[] ctors; public CurriedConstructorLambda(Class intrface, Constructor[] ctors, Evaluable[] curriedArgs) { super(intrface, curriedArgs); this.ctors = ctors; } public Object forwardCall(VarContext ctx, Object[] args) { return preciseNuObject(ctors, args); } } static public class DirectMethodCallOnKnownTarget extends EvaluableBase implements IFieldsToList { public boolean widening = false; public Object target; public Method method; public Evaluable[] args; public DirectMethodCallOnKnownTarget() { } public DirectMethodCallOnKnownTarget(boolean widening, Object target, Method method, Evaluable[] args) { this.args = args; this.method = method; this.target = target; this.widening = widening; } public Object[] _fieldsToList() { return new Object[] { widening, target, method, args }; } public Object get(VarContext ctx) { var evaluatedArgs = mapToArrayOrNull(args, arg -> arg.get(ctx)); return widening ? invokeMethodWithWidening(method, target, evaluatedArgs) : invokeMethod(method, target, evaluatedArgs); } public String toString() { return (target == null ? "" : target + ".") + formatFunctionCall(str(method), args); } public LASValueDescriptor returnType() { return LASValueDescriptor.fromClass(method.getReturnType()); } } static public class While extends EvaluableBase implements IFieldsToList { public Evaluable condition; public Evaluable body; public While() { } public While(Evaluable condition, Evaluable body) { this.body = body; this.condition = condition; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + condition + ", " + body + ")"; } public Object[] _fieldsToList() { return new Object[] { condition, body }; } public Object get(VarContext ctx) { while (!ctx.exiting() && (Boolean) condition.get(ctx)) { body.get(ctx); } return null; } } abstract static public class ForEachBase extends EvaluableBase implements IFieldsToList { public Evaluable collection; public Evaluable body; public ForEachBase() { } public ForEachBase(Evaluable collection, Evaluable body) { this.body = body; this.collection = collection; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + collection + ", " + body + ")"; } public Object[] _fieldsToList() { return new Object[] { collection, body }; } public Object get(VarContext ctx) { var coll = collection.get(ctx); Iterator iterator; List out; try { if (coll instanceof Object[]) { out = emptyList(((Object[]) coll).length); for (var element : ((Object[]) coll)) { if (ctx.exiting()) return null; processElement(ctx, out, element); } } else if (coll instanceof Iterable) { out = emptyList((Iterable) coll); for (var element : ((Iterable) coll)) { if (ctx.exiting()) return null; processElement(ctx, out, element); } } else if (coll == null) out = new ArrayList(); else throw fail("Not iterable: " + className(coll)); } finally { loopDone(ctx); } return out; } abstract public void processElement(VarContext ctx, List out, Object o); abstract public void loopDone(VarContext ctx); } static public class ForEach extends ForEachBase { public ForEach() { } public String var; public ForEach(Evaluable collection, String var, Evaluable body) { this.body = body; this.var = var; this.collection = collection; } public void processElement(VarContext ctx, List out, Object o) { ctx.set(var, o); out.add(body.get(ctx)); } public void loopDone(VarContext ctx) { ctx.unset(var); } } static public class ForIterator extends EvaluableBase implements IFieldsToList { static final public String _fieldOrder = "iterable var body"; public Evaluable iterable; public String var; public Evaluable body; public ForIterator() { } public ForIterator(Evaluable iterable, String var, Evaluable body) { this.body = body; this.var = var; this.iterable = iterable; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + iterable + ", " + var + ", " + body + ")"; } public boolean equals(Object o) { if (!(o instanceof ForIterator)) return false; ForIterator __5 = (ForIterator) o; return eq(iterable, __5.iterable) && eq(var, __5.var) && eq(body, __5.body); } public int hashCode() { int h = -214906825; h = boostHashCombine(h, _hashCode(iterable)); h = boostHashCombine(h, _hashCode(var)); h = boostHashCombine(h, _hashCode(body)); return h; } public Object[] _fieldsToList() { return new Object[] { iterable, var, body }; } public Object get(VarContext ctx) { VarContext subContext = new FlexibleVarContext(ctx); var iterable = this.iterable.get(ctx); Iterator iterator = iterator_gen(iterable); return mapI(iterator, value -> { subContext.set(var, value); return body.get(subContext); }); } } static public class ForNested extends EvaluableBase implements IFieldsToList { static final public String _fieldOrder = "iterable var body"; public Evaluable iterable; public String var; public Evaluable body; public ForNested() { } public ForNested(Evaluable iterable, String var, Evaluable body) { this.body = body; this.var = var; this.iterable = iterable; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + iterable + ", " + var + ", " + body + ")"; } public boolean equals(Object o) { if (!(o instanceof ForNested)) return false; ForNested __6 = (ForNested) o; return eq(iterable, __6.iterable) && eq(var, __6.var) && eq(body, __6.body); } public int hashCode() { int h = -1363247360; h = boostHashCombine(h, _hashCode(iterable)); h = boostHashCombine(h, _hashCode(var)); h = boostHashCombine(h, _hashCode(body)); return h; } public Object[] _fieldsToList() { return new Object[] { iterable, var, body }; } public Object get(VarContext ctx) { VarContext subContext = new FlexibleVarContext(ctx); var iterable = this.iterable.get(ctx); Iterator iterator = iterator_gen(iterable); return nestedIterator(iterator, value -> { subContext.set(var, value); return iterator_gen(body.get(subContext)); }); } } static public class ForPairs extends ForEachBase { public ForPairs() { } public String varA, varB; public ForPairs(Evaluable collection, Evaluable body, String varA, String varB) { this.varB = varB; this.varA = varA; this.body = body; this.collection = collection; } public void processElement(VarContext ctx, List out, Object o) { Pair p = (Pair) o; ctx.set(varA, p.a); ctx.set(varB, p.b); out.add(body.get(ctx)); } public void loopDone(VarContext ctx) { ctx.unset(varA); ctx.unset(varB); } } static public class ForKeyValue extends EvaluableBase implements IFieldsToList { public Evaluable map; public Evaluable body; public String varA; public String varB; public ForKeyValue() { } public ForKeyValue(Evaluable map, Evaluable body, String varA, String varB) { this.varB = varB; this.varA = varA; this.body = body; this.map = map; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + map + ", " + body + ", " + varA + ", " + varB + ")"; } public Object[] _fieldsToList() { return new Object[] { map, body, varA, varB }; } public Object get(VarContext ctx) { Map theMap = (Map) map.get(ctx); List out; try { if (theMap != null) { out = emptyList(theMap.size()); for (var entry : theMap.entrySet()) { if (ctx.exiting()) return null; ctx.set(varA, entry.getKey()); ctx.set(varB, entry.getValue()); out.add(body.get(ctx)); } } else out = new ArrayList(); } finally { ctx.unset(varA); ctx.unset(varB); } return out; } } static public class ForIntTo extends EvaluableBase implements IFieldsToList { public Evaluable endValue; public String var; public Evaluable body; public ForIntTo() { } public ForIntTo(Evaluable endValue, String var, Evaluable body) { this.body = body; this.var = var; this.endValue = endValue; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + endValue + ", " + var + ", " + body + ")"; } public Object[] _fieldsToList() { return new Object[] { endValue, var, body }; } public Evaluable optimize() { if (!returnValueNeeded) body = body.optimizeForReturnValueNotNeeded(); return this; } public Object get(VarContext ctx) { int n = (Integer) endValue.get(ctx), i = 0; List out = returnValueNeeded ? new ArrayList() : null; try { ctx.put(var, i); while (i < n) { if (ctx.exiting()) return null; Object o = body.get(ctx); { if (out != null) out.add(o); } ctx.set(var, i = (Integer) ctx.get(var) + 1); } } finally { ctx.unset(var); } return out; } } static public class ForIndex extends EvaluableBase { public ForIndex() { } public Evaluable collection, body; public String varIndex, varElement; public ForIndex(Evaluable collection, Evaluable body, String varIndex, String varElement) { this.varElement = varElement; this.varIndex = varIndex; this.body = body; this.collection = collection; } public Object get(VarContext ctx) { return new ForIndex_instance(collection, body, varIndex, varElement).get(ctx); } } static public class ForIndex_instance extends ForEachBase { public String varIndex, varElement; public int index; public ForIndex_instance(Evaluable collection, Evaluable body, String varIndex, String varElement) { this.varElement = varElement; this.varIndex = varIndex; this.body = body; this.collection = collection; } public void processElement(VarContext ctx, List out, Object o) { ctx.set(varIndex, index++); ctx.set(varElement, o); out.add(body.get(ctx)); } public void loopDone(VarContext ctx) { ctx.unset(varIndex); ctx.unset(varElement); } } static public class IfThen extends EvaluableBase implements IFieldsToList { public Evaluable condition; public Evaluable body; public Evaluable elseBranch; public IfThen() { } public IfThen(Evaluable condition, Evaluable body, Evaluable elseBranch) { this.elseBranch = elseBranch; this.body = body; this.condition = condition; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + condition + ", " + body + ", " + elseBranch + ")"; } public Object[] _fieldsToList() { return new Object[] { condition, body, elseBranch }; } public IfThen(Evaluable condition, Evaluable body) { this.condition = condition; this.body = body; } public Object get(VarContext ctx) { if ((Boolean) condition.get(ctx)) return body.get(ctx); else if (elseBranch != null) return elseBranch.get(ctx); else return null; } } static public class ReturnFromScript extends EvaluableBase implements IFieldsToList { public Script script; public Evaluable value; public ReturnFromScript() { } public ReturnFromScript(Script script, Evaluable value) { this.value = value; this.script = script; } public Object[] _fieldsToList() { return new Object[] { script, value }; } public Object get(VarContext ctx) { Object result = value.get(ctx); ctx.exitFromScript(script); ctx.returnValue(result); return null; } public String toString() { return formatFunctionCall("ReturnFromScript", script, value); } } static public class Continue extends EvaluableBase implements IFieldsToList { public Script loopBody; public Continue() { } public Continue(Script loopBody) { this.loopBody = loopBody; } public Object[] _fieldsToList() { return new Object[] { loopBody }; } public Object get(VarContext ctx) { ctx.exitFromScript(loopBody); ctx.returnValue(null); return null; } public String toString() { return formatFunctionCall("Continue", loopBody); } } static public class RepeatN extends EvaluableBase implements IFieldsToList { public Evaluable n; public Evaluable body; public RepeatN() { } public RepeatN(Evaluable n, Evaluable body) { this.body = body; this.n = n; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + n + ", " + body + ")"; } public Object[] _fieldsToList() { return new Object[] { n, body }; } public Object get(VarContext ctx) { long count = ((Number) n.get(ctx)).longValue(); for (int _repeat_0 = 0; _repeat_0 < count; _repeat_0++) { if (ctx.exiting()) return null; body.get(ctx); } return null; } } static public class BoolAnd extends EvaluableBase implements IFieldsToList { public Evaluable a; public Evaluable b; public BoolAnd() { } public BoolAnd(Evaluable a, Evaluable b) { this.b = b; this.a = a; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + a + ", " + b + ")"; } public boolean equals(Object o) { if (!(o instanceof BoolAnd)) return false; BoolAnd __7 = (BoolAnd) o; return eq(a, __7.a) && eq(b, __7.b); } public int hashCode() { int h = 1729330797; h = boostHashCombine(h, _hashCode(a)); h = boostHashCombine(h, _hashCode(b)); return h; } public Object[] _fieldsToList() { return new Object[] { a, b }; } public Object get(VarContext ctx) { if (!((Boolean) a.get(ctx))) return false; return b.get(ctx); } } static public class BoolOr extends EvaluableBase implements IFieldsToList { public Evaluable a; public Evaluable b; public BoolOr() { } public BoolOr(Evaluable a, Evaluable b) { this.b = b; this.a = a; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + a + ", " + b + ")"; } public boolean equals(Object o) { if (!(o instanceof BoolOr)) return false; BoolOr __8 = (BoolOr) o; return eq(a, __8.a) && eq(b, __8.b); } public int hashCode() { int h = 1995447949; h = boostHashCombine(h, _hashCode(a)); h = boostHashCombine(h, _hashCode(b)); return h; } public Object[] _fieldsToList() { return new Object[] { a, b }; } public Object get(VarContext ctx) { if (((Boolean) a.get(ctx))) return true; return b.get(ctx); } } static public class TempBlock extends EvaluableBase implements IFieldsToList { public Evaluable tempExpr; public Evaluable body; public TempBlock() { } public TempBlock(Evaluable tempExpr, Evaluable body) { this.body = body; this.tempExpr = tempExpr; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + tempExpr + ", " + body + ")"; } public Object[] _fieldsToList() { return new Object[] { tempExpr, body }; } public Object get(VarContext ctx) { AutoCloseable __2 = (AutoCloseable) (tempExpr.get(ctx)); try { return body.get(ctx); } finally { _close(__2); } } } static public class ClassDef extends EvaluableBase implements IFieldsToList { public ResolvableLASClass lasClass; public ClassDef() { } public ClassDef(ResolvableLASClass lasClass) { this.lasClass = lasClass; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + lasClass + ")"; } public boolean equals(Object o) { if (!(o instanceof ClassDef)) return false; ClassDef __9 = (ClassDef) o; return eq(lasClass, __9.lasClass); } public int hashCode() { int h = 757052301; h = boostHashCombine(h, _hashCode(lasClass)); return h; } public Object[] _fieldsToList() { return new Object[] { lasClass }; } public Object get(VarContext ctx) { return lasClass.get(); } } static public class SetField extends EvaluableBase implements IFieldsToList { public Evaluable target; public String name; public Evaluable expr; public SetField() { } public SetField(Evaluable target, String name, Evaluable expr) { this.expr = expr; this.name = name; this.target = target; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + target + ", " + name + ", " + expr + ")"; } public Object[] _fieldsToList() { return new Object[] { target, name, expr }; } final public SetField setAllowNullReference(boolean allowNullReference) { return allowNullReference(allowNullReference); } public SetField allowNullReference(boolean allowNullReference) { this.allowNullReference = allowNullReference; return this; } final public boolean getAllowNullReference() { return allowNullReference(); } public boolean allowNullReference() { return allowNullReference; } public boolean allowNullReference = false; public Object handleNullReference() { if (allowNullReference) return null; else throw new NullPointerException(); } public Object get(VarContext ctx) { try { Object value = expr.get(ctx); Object object = target.get(ctx); if (object == null) handleNullReference(); else set(object, name, value); return value; } catch (Throwable e) { throw rethrowWithSrc(e); } } } static public class Throw extends EvaluableBase implements IFieldsToList { public Evaluable expr; public Throw() { } public Throw(Evaluable expr) { this.expr = expr; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + expr + ")"; } public Object[] _fieldsToList() { return new Object[] { expr }; } public Object get(VarContext ctx) { throw asRuntimeException((Throwable) expr.get(ctx)); } } static public class TryCatch extends EvaluableBase implements IFieldsToList { public Evaluable body; public String var; public Evaluable catchBlock; public TryCatch() { } public TryCatch(Evaluable body, String var, Evaluable catchBlock) { this.catchBlock = catchBlock; this.var = var; this.body = body; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + body + ", " + var + ", " + catchBlock + ")"; } public Object[] _fieldsToList() { return new Object[] { body, var, catchBlock }; } public Object get(VarContext ctx) { try { return body.get(ctx); } catch (Throwable e) { AutoCloseable __3 = ctx.tempPut(var, e); try { return catchBlock.get(ctx); } finally { _close(__3); } } } } static public structure_Data structureDataForLAS() { structure_Data d = new structure_Data(); d.skipDefaultValues(true); d.shouldIncludeField = field -> { String c = shortClassName(field.getDeclaringClass()); String f = field.getName(); boolean shouldInclude = !(eq(c, "HasTokenRangeWithSrc") && eq(f, "src")); return shouldInclude; }; return d; } static public boolean isUnproblematicValue(Object o) { return o == null || o instanceof Number || o instanceof String || o instanceof Boolean || o instanceof Class; } static public String scriptStruct(Object o) { String s = struct(o, structureDataForLAS()); List tok = structTok(s); String prefix = shortName(GazelleV_LeftArrowScript.class) + "$"; for (int i = 1; i < l(tok); i += 2) tok.set(i, replacePrefix(prefix, "$", tok.get(i))); return join(tok); } static public String indentedScriptStruct(Object o) { return indentStructureString(scriptStruct(o)); } } static public interface IVF2 { public void get(A a, B b); } public interface IDoublePt { public double x_double(); public double y_double(); } static public interface IVar extends IF0 { public void set(A a); public A get(); default public Class getType() { return null; } default public boolean has() { return get() != null; } default public void clear() { set(null); } } static public interface WidthAndHeight { default public int w() { return getWidth(); } public int getWidth(); default public int h() { return getHeight(); } public int getHeight(); public default Rect bounds() { return rect(0, 0, getWidth(), getHeight()); } default public int area() { return toInt(areaAsLong()); } default public long areaAsLong() { return longMul(w(), h()); } } static public class SynchronizedNavigableSet extends SynchronizedSortedSet implements NavigableSet { public SynchronizedNavigableSet() { } @java.io.Serial static final public long serialVersionUID = -5505529816273629798L; @SuppressWarnings("serial") public NavigableSet ns; public SynchronizedNavigableSet(NavigableSet s) { super(s); ns = s; } public SynchronizedNavigableSet(NavigableSet s, Object mutex) { super(s, mutex); ns = s; } public E lower(E e) { synchronized (mutex) { return ns.lower(e); } } public E floor(E e) { synchronized (mutex) { return ns.floor(e); } } public E ceiling(E e) { synchronized (mutex) { return ns.ceiling(e); } } public E higher(E e) { synchronized (mutex) { return ns.higher(e); } } public E pollFirst() { synchronized (mutex) { return ns.pollFirst(); } } public E pollLast() { synchronized (mutex) { return ns.pollLast(); } } public NavigableSet descendingSet() { synchronized (mutex) { return new SynchronizedNavigableSet<>(ns.descendingSet(), mutex); } } public Iterator descendingIterator() { synchronized (mutex) { return descendingSet().iterator(); } } public NavigableSet subSet(E fromElement, E toElement) { synchronized (mutex) { return new SynchronizedNavigableSet<>(ns.subSet(fromElement, true, toElement, false), mutex); } } public NavigableSet headSet(E toElement) { synchronized (mutex) { return new SynchronizedNavigableSet<>(ns.headSet(toElement, false), mutex); } } public NavigableSet tailSet(E fromElement) { synchronized (mutex) { return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, true), mutex); } } public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { synchronized (mutex) { return new SynchronizedNavigableSet<>(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), mutex); } } public NavigableSet headSet(E toElement, boolean inclusive) { synchronized (mutex) { return new SynchronizedNavigableSet<>(ns.headSet(toElement, inclusive), mutex); } } public NavigableSet tailSet(E fromElement, boolean inclusive) { synchronized (mutex) { return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive), mutex); } } } static public class MethodMaker { public ClassGen cg; public MethodGen mg; public InstructionList il = new InstructionList(); public ConstantPoolGen cp; public InstructionFactory factory; public int frameSize; final public MethodMaker setVerboseAdd(boolean verboseAdd) { return verboseAdd(verboseAdd); } public MethodMaker verboseAdd(boolean verboseAdd) { this.verboseAdd = verboseAdd; return this; } final public boolean getVerboseAdd() { return verboseAdd(); } public boolean verboseAdd() { return verboseAdd; } public boolean verboseAdd = false; public boolean classConstantWorkaround = false; public MethodMaker(ClassMaker classMaker, Class returnType, String methodName, Class... argumentTypes) { this(classMaker.cg, returnType, methodName, argumentTypes); } public MethodMaker(ClassGen cg, Class returnType, String methodName, Class... argumentTypes) { this(cg, Const.ACC_PUBLIC, returnType, methodName, argumentTypes); } public MethodMaker(ClassGen cg, short modifiers, Class returnType, String methodName, Class... argumentTypes) { this.cg = cg; cp = cg.getConstantPool(); factory = new InstructionFactory(cg); org.apache.bcel.generic.Type[] argTypes = wrapTypes(argumentTypes); mg = new MethodGen(modifiers, wrapType(returnType), argTypes, null, methodName, cg.getClassName(), il, cp); frameSize = l(argTypes) + 1; } static public org.apache.bcel.generic.Type[] wrapTypes(Class[] classes) { org.apache.bcel.generic.Type[] types = new org.apache.bcel.generic.Type[l(classes)]; for (int i = 0; i < l(classes); i++) types[i] = wrapType(classes[i]); return types; } static public org.apache.bcel.generic.Type wrapType(Class c) { return classToBCELType(c); } public int newLocalVar() { return frameSize++; } public MethodMaker newObject(Class c, Class... argTypes) { il.append(factory.createNew(className(c))); il.append(InstructionConst.DUP); Constructor ctor = findConstructor_precise_onTypes(c, argTypes); il.append(factory.createInvoke(className(c), "", org.apache.bcel.generic.Type.VOID, wrapTypes(ctor.getParameterTypes()), Const.INVOKESPECIAL)); return this; } public MethodMaker dup() { il.append(InstructionConst.DUP); return this; } public MethodMaker astore(int var) { il.append(new ASTORE(var)); return this; } public MethodMaker aload(int var) { il.append(new ALOAD(var)); return this; } public MethodMaker stringConstant(String s) { il.append(new PUSH(cp, s)); return this; } public MethodMaker classConstant(Class c) { if (classConstantWorkaround) { stringConstant(c.getName()); invokeStatic(Class.class, Class.class, "forName", String.class); } else { var ldc = new LDC(classRef(c)); assertEquals("classConstant", ldc.getValue(cp), wrapType(c)); il.append(ldc); } return this; } final public MethodMaker intConst(int i) { return intConstant(i); } public MethodMaker intConstant(int i) { if (i >= -1 && i <= 5) return add(new ICONST(i)); if (i == (byte) i) return add(new BIPUSH((byte) i)); if (i == (short) i) return add(new SIPUSH((short) i)); return add(new LDC(cp.addInteger(i))); } final public MethodMaker doubleConst(double d) { return doubleConstant(d); } public MethodMaker doubleConstant(double d) { return add(new LDC2_W(cp.addDouble(d))); } public MethodMaker boolConstant(boolean b) { return intConstant(b ? 1 : 0); } public MethodMaker invokeVirtual(Class c, Class returnType, String methodName, Class... argTypes) { Method m = findNonStaticMethod_precise_onTypes(c, methodName, argTypes); if (m == null) throw fail("Method not found: " + className(c) + "." + formatFunctionCall(methodName, argTypes) + " returning " + className(returnType)); il.append(factory.createInvoke(className(c), methodName, wrapType(m.getReturnType()), wrapTypes(m.getParameterTypes()), Const.INVOKEVIRTUAL)); return this; } public MethodMaker invokeInterface(Class c, Class returnType, String methodName, Class... argTypes) { Method m = mostApplicableMethod_onTypes(filter(nonDefaultInterfaceMethods(c), _m -> _m.getName().equals(methodName)), argTypes); if (m == null) throw fail("Method not found: " + className(c) + "." + formatFunctionCall(methodName, argTypes) + " returning " + className(returnType)); il.append(factory.createInvoke(className(c), methodName, wrapType(m.getReturnType()), wrapTypes(m.getParameterTypes()), Const.INVOKEINTERFACE)); return this; } public MethodMaker invokeStatic(Class c, Class returnType, String methodName, Class... argTypes) { Method m = findMethod_precise_onTypes(c, methodName, argTypes); if (m == null) throw fail("Method not found: " + className(c) + "." + formatFunctionCall(methodName, argTypes) + " returning " + className(returnType)); il.append(factory.createInvoke(className(c), methodName, wrapType(m.getReturnType()), wrapTypes(m.getParameterTypes()), Const.INVOKESTATIC)); return this; } public MethodMaker areturn() { il.append(InstructionConst.ARETURN); return this; } public MethodMaker _return() { il.append(InstructionConst.RETURN); return this; } public MethodMaker add(Instruction i) { il.append(i); if (verboseAdd) print("> " + i); return this; } public A addAndReturn(A i) { add(i); return i; } public MethodMaker add(BranchInstruction i) { il.append(i); if (verboseAdd) print("> " + i); return this; } public A addAndReturn(A i) { add(i); return i; } public void done() { mg.stripAttributes(true); mg.setMaxStack(); mg.setMaxLocals(); cg.addMethod(mg.getMethod()); } public JVMStackCellType convertToObject(JVMStackCellType stackTop) { if (stackTop == JVMStackCellType.objValue) { } else if (stackTop == JVMStackCellType.intValue) invokeStatic(Integer.class, Integer.class, "valueOf", int.class); else if (stackTop == JVMStackCellType.doubleValue) invokeStatic(Double.class, Double.class, "valueOf", double.class); else if (stackTop == JVMStackCellType.none) add(new ACONST_NULL()); else throw fail("TODO: add conversion for stack cell type: " + stackTop); return JVMStackCellType.objValue; } public void discardStackTop(JVMStackCellType stackTop) { if (stackTop == JVMStackCellType.none) { } else if (stackTop == JVMStackCellType.doubleValue || stackTop == JVMStackCellType.longValue) add(new POP2()); else add(new POP()); } public int classRef(Class c) { return cp.addClass((ObjectType) wrapType(assertNotNull(c))); } public MethodMaker checkCast(Class c) { return add(new CHECKCAST(classRef(c))); } public MethodMaker loadNull() { return add(new ACONST_NULL()); } public InstructionHandle here() { return il.append(new NOP()); } public GOTO forwardGoto() { return addAndReturn(new GOTO(null)); } public void returnWithType(JVMStackCellType stackTop) { if (stackTop == JVMStackCellType.objValue) areturn(); else if (stackTop == JVMStackCellType.intValue) add(new IRETURN()); else if (stackTop == JVMStackCellType.doubleValue) add(new DRETURN()); else if (stackTop == JVMStackCellType.none) _return(); else throw fail("TODO: add return for stack cell type: " + stackTop); } public void getStaticField(String className, String fieldName, Class type) { il.append(factory.createGetStatic(className, fieldName, wrapType(type))); } } static public class FixedVarContext extends VarContext { public String[] names; public Object[] values; public FixedVarContext() { } public FixedVarContext(String[] names) { this(null, names); this.names = names; } public FixedVarContext(VarContext parent, String[] names) { super(parent); this.names = names; if (names != null) values = new Object[names.length]; } public int indexOfVar(String name) { return indexOfInSortedArray(names, name); } public int indexOfVarMandatory(String name) { int idx = indexOfVar(name); if (idx < 0) throw fail("Variable not found: " + name + ", known: " + joinWithComma(names)); return idx; } public Object get(int idx) { return values[idx]; } public Object get(String name) { int idx = indexOfVar(name); if (idx >= 0) return values[idx]; if (parent != null) return parent.get(name); return null; } public void set(int idx, Object value) { values[idx] = value; } public void set(String name, Object value) { int idx = indexOfVar(name); if (idx >= 0) values[idx] = value; else throw fail("Variable " + name + " not defined in context"); } public AutoCloseable tempSet(String name, Object value) { int idx = indexOfVar(name); if (idx >= 0) { Object old = values[idx]; values[idx] = value; return () -> values[idx] = old; } else throw fail("Variable " + name + " not defined in context"); } public void unset(String name) { set(name, null); } public Map varMap() { Map map = new HashMap(); int n = l(names); for (int i = 0; i < n; i++) map.put(names[i], values[i]); return map; } } static public interface Htmlable { default public String headStuff() { return ""; } public String html(); } public enum JVMStackCellType { none, objValue, intValue, longValue, floatValue, doubleValue } static public class FlexibleVarContext extends VarContext { public Map vars; public FlexibleVarContext() { } public FlexibleVarContext(VarContext parent) { super(parent); } public Object get(String name) { if (containsKey(vars, name)) return mapGet(vars, name); if (parent != null) return parent.get(name); return null; } public void set(String name, Object value) { vars = putOrCreateSyncMap(vars, name, value); } public AutoCloseable tempSet(String name, Object value) { initMap(); return main.tempPut(vars, name, value); } public void unset(String name) { remove(vars, name); } public Map varMap() { return vars; } final public void initMap() { makeThreadSafe(); } public void makeThreadSafe() { if (vars == null) vars = syncHashMap(); } } static public class LASToByteCode implements IFieldsToList { public MethodMaker m; public LASToByteCode() { } public LASToByteCode(MethodMaker m) { this.m = m; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + m + ")"; } public Object[] _fieldsToList() { return new Object[] { m }; } public boolean callPing = true; final public LASToByteCode setIVarContext(int iVarContext) { return iVarContext(iVarContext); } public LASToByteCode iVarContext(int iVarContext) { this.iVarContext = iVarContext; return this; } final public int getIVarContext() { return iVarContext(); } public int iVarContext() { return iVarContext; } public int iVarContext = -1; public GazelleV_LeftArrowScript.Script returnableScript; final public LASToByteCode setPostConversion(IF1 postConversion) { return postConversion(postConversion); } public LASToByteCode postConversion(IF1 postConversion) { this.postConversion = postConversion; return this; } final public IF1 getPostConversion() { return postConversion(); } public IF1 postConversion() { return postConversion; } public IF1 postConversion; public JVMStackCellType compileScript(GazelleV_LeftArrowScript.Script script) { returnableScript = script; var stackTop = compile(script); if (postConversion != null) stackTop = postConversion.get(stackTop); return stackTop; } public void compileToObject(GazelleV_LeftArrowScript.Evaluable code) { m.convertToObject(compile(code)); } public JVMStackCellType compile(GazelleV_LeftArrowScript.Evaluable code) { if (code instanceof GazelleV_LeftArrowScript.Const) { Object o = ((GazelleV_LeftArrowScript.Const) code).value; if (o == null) { m.add(new ACONST_NULL()); return JVMStackCellType.objValue; } else if (o instanceof String) { m.stringConstant((String) o); return JVMStackCellType.objValue; } else if (o instanceof Integer) { m.intConstant((Integer) o); return JVMStackCellType.intValue; } else if (o instanceof Double) { m.doubleConstant((Double) o); return JVMStackCellType.doubleValue; } else if (o instanceof Class) { m.classConstant((Class) o); return JVMStackCellType.objValue; } else if (o instanceof Boolean) { m.boolConstant((Boolean) o); return JVMStackCellType.intValue; } else throw fail("Can't compile const value: " + toStringWithClass(o)); } else if (code instanceof GazelleV_LeftArrowScript.Script) { var stackTop = JVMStackCellType.none; for (var step : ((GazelleV_LeftArrowScript.Script) code).steps) { if (stackTop != JVMStackCellType.none) m.add(new POP()); stackTop = compile(step); } return stackTop; } else if (code instanceof GazelleV_LeftArrowScript.CallMethod) { compileToObject(((GazelleV_LeftArrowScript.CallMethod) code).target); m.stringConstant(((GazelleV_LeftArrowScript.CallMethod) code).methodName); argumentsAsArray(((GazelleV_LeftArrowScript.CallMethod) code).args); m.invokeStatic(main.class, Object.class, "call", Object.class, String.class, Object[].class); return JVMStackCellType.objValue; } else if (code instanceof GazelleV_LeftArrowScript.CallMethodOrGetField) { compileToObject(((GazelleV_LeftArrowScript.CallMethodOrGetField) code).target); m.stringConstant(((GazelleV_LeftArrowScript.CallMethodOrGetField) code).name); m.invokeStatic(main.class, Object.class, "preciseGetOrCallMethod", Object.class, String.class); return JVMStackCellType.objValue; } else if (code instanceof GazelleV_LeftArrowScript.SetField) { compileToObject(((GazelleV_LeftArrowScript.SetField) code).target); m.stringConstant(((GazelleV_LeftArrowScript.SetField) code).name); compileToObject(((GazelleV_LeftArrowScript.SetField) code).expr); m.invokeStatic(main.class, Object.class, "set", Object.class, String.class, Object.class); return JVMStackCellType.none; } else if (code instanceof GazelleV_LeftArrowScript.NewObject) { m.classConstant(((GazelleV_LeftArrowScript.NewObject) code).c); argumentsAsArray(((GazelleV_LeftArrowScript.NewObject) code).args); m.invokeStatic(main.class, Object.class, "nuObject", Class.class, Object[].class); return JVMStackCellType.objValue; } else if (code instanceof GazelleV_LeftArrowScript.Assignment) { compileToObject(((GazelleV_LeftArrowScript.Assignment) code).expression); m.astore(iTemp()); loadVarContext(); m.stringConstant(((GazelleV_LeftArrowScript.Assignment) code).var); m.aload(iTemp()); m.invokeVirtual(VarContext.class, void.class, "set", String.class, Object.class); m.aload(iTemp()); return JVMStackCellType.objValue; } else if (code instanceof GazelleV_LeftArrowScript.While) { var loopStart = m.il.append(new NOP()); BranchInstruction branch1 = null; if (callPing) { m.invokeStatic(main.class, boolean.class, "ping"); branch1 = new IFEQ(null); m.add(branch1); } compileToBool(((GazelleV_LeftArrowScript.While) code).condition); var branch2 = new IFEQ(null); m.add(branch2); m.discardStackTop(compile(((GazelleV_LeftArrowScript.While) code).body)); m.add(new GOTO(loopStart)); var loopEnd = m.il.append(new NOP()); { if (branch1 != null) branch1.setTarget(loopEnd); } branch2.setTarget(loopEnd); return JVMStackCellType.none; } else if (code instanceof GazelleV_LeftArrowScript.IfThen) { compileToBool(((GazelleV_LeftArrowScript.IfThen) code).condition); var branch1 = new IFEQ(null); m.add(branch1); var stackTop = compile(((GazelleV_LeftArrowScript.IfThen) code).body); if (stackTop == JVMStackCellType.none) { branch1.setTarget(m.here()); return stackTop; } else { m.convertToObject(stackTop); var jumpToEnd = m.forwardGoto(); branch1.setTarget(m.here()); m.loadNull(); jumpToEnd.setTarget(m.here()); return JVMStackCellType.objValue; } } else if (code instanceof GazelleV_LeftArrowScript.GetVar) { return compileGetVar((GazelleV_LeftArrowScript.GetVar) code); } else if (code instanceof GazelleV_LeftArrowScript.ReturnFromScript) { if (((GazelleV_LeftArrowScript.ReturnFromScript) code).script != returnableScript) throw fail("Can only return from current script"); var stackTop = compile(((GazelleV_LeftArrowScript.ReturnFromScript) code).value); if (postConversion != null) stackTop = postConversion.get(stackTop); m.returnWithType(stackTop); return JVMStackCellType.none; } throw fail("Can't compile yet: " + className(code)); } public void argumentsAsArray(GazelleV_LeftArrowScript.Evaluable[] args) { int n = l(args); m.intConst(n); m.add(new ANEWARRAY(m.classRef(Object.class))); for (int iArg = 0; iArg < n; iArg++) { m.dup(); m.intConst(iArg); compileToObject(args[iArg]); m.add(new AASTORE()); } } public void loadVarContext() { assertTrue("Need VarContext", iVarContext >= 0); m.aload(iVarContext); } public Integer iTemp_cache; public int iTemp() { if (iTemp_cache == null) iTemp_cache = iTemp_load(); return iTemp_cache; } public Integer iTemp_load() { return m.newLocalVar(); } public void compileToBool(GazelleV_LeftArrowScript.Evaluable condition) { var stackTop = compile(condition); if (stackTop == JVMStackCellType.objValue) { m.checkCast(Boolean.class); m.invokeVirtual(Boolean.class, boolean.class, "booleanValue"); } else if (stackTop == JVMStackCellType.intValue) { } else throw fail("Can't convert to bool: " + stackTop); } public JVMStackCellType compileGetVar(GazelleV_LeftArrowScript.GetVar code) { loadVarContext(); m.stringConstant(code.var); m.invokeVirtual(VarContext.class, Object.class, "get", String.class); return JVMStackCellType.objValue; } } static public interface IMultiSet { public int add(A key); public int get(A key); } static public class SynchronizedSortedSet extends SynchronizedSet implements SortedSet { public SynchronizedSortedSet() { } @java.io.Serial static final public long serialVersionUID = 8695801310862127406L; @SuppressWarnings("serial") public SortedSet ss; public SynchronizedSortedSet(SortedSet s) { super(s); ss = s; } public SynchronizedSortedSet(SortedSet s, Object mutex) { super(s, mutex); ss = s; } public Comparator comparator() { synchronized (mutex) { return ss.comparator(); } } public SortedSet subSet(E fromElement, E toElement) { synchronized (mutex) { return new SynchronizedSortedSet<>(ss.subSet(fromElement, toElement), mutex); } } public SortedSet headSet(E toElement) { synchronized (mutex) { return new SynchronizedSortedSet<>(ss.headSet(toElement), mutex); } } public SortedSet tailSet(E fromElement) { synchronized (mutex) { return new SynchronizedSortedSet<>(ss.tailSet(fromElement), mutex); } } public E first() { synchronized (mutex) { return ss.first(); } } public E last() { synchronized (mutex) { return ss.last(); } } } abstract static public class VarContext { final public VarContext getParent() { return parent(); } public VarContext parent() { return parent; } public VarContext parent; public VarContext() { } public VarContext(VarContext parent) { this.parent = parent; } abstract public Object get(String name); final public void put(String name, Object value) { set(name, value); } abstract public void set(String name, Object value); final public AutoCloseable tempPut(String name, Object value) { return tempSet(name, value); } abstract public AutoCloseable tempSet(String name, Object value); abstract public void unset(String name); abstract public Map varMap(); public void printMe() { pnl(varMap()); print("parent", parent); } final public VarContext setExitFromScript(Object exitFromScript) { return exitFromScript(exitFromScript); } public VarContext exitFromScript(Object exitFromScript) { this.exitFromScript = exitFromScript; return this; } final public Object getExitFromScript() { return exitFromScript(); } public Object exitFromScript() { return exitFromScript; } public Object exitFromScript; final public VarContext setReturnValue(Object returnValue) { return returnValue(returnValue); } public VarContext returnValue(Object returnValue) { this.returnValue = returnValue; return this; } final public Object getReturnValue() { return returnValue(); } public Object returnValue() { return returnValue; } public Object returnValue; public boolean exiting() { ping(); return exitFromScript != null; } } static public class LineAndColumn implements IFieldsToList { static final public String _fieldOrder = "line col getLineText"; public int line; public int col; public LineAndColumn() { } public LineAndColumn(int line, int col) { this.col = col; this.line = line; } public boolean equals(Object o) { if (!(o instanceof LineAndColumn)) return false; LineAndColumn __1 = (LineAndColumn) o; return line == __1.line && col == __1.col; } public int hashCode() { int h = -1128952231; h = boostHashCombine(h, _hashCode(line)); h = boostHashCombine(h, _hashCode(col)); return h; } public Object[] _fieldsToList() { return new Object[] { line, col }; } transient public IF1 getLineText; public String getLineText(int line) { return getLineText != null ? getLineText.get(line) : getLineText_base(line); } final public String getLineText_fallback(IF1 _f, int line) { return _f != null ? _f.get(line) : getLineText_base(line); } public String getLineText_base(int line) { return null; } public String toString() { return "Line " + n2(line) + ", col " + n2(col); } } static public class FailedRule extends RuleWithParams { public List satisfiedConditions; public Exp remainingCondition; public FailedRule() { } public FailedRule(IfThen rule, VarMatches matches, Exp remainingCondition) { this.remainingCondition = remainingCondition; this.matches = matches; this.rule = rule; } public FailedRule(IfThen rule, VarMatches matches, List satisfiedConditions, Exp remainingCondition) { this.remainingCondition = remainingCondition; this.satisfiedConditions = satisfiedConditions; this.matches = matches; this.rule = rule; } } static public class RuleWithParams implements IFieldsToList { static final public String _fieldOrder = "rule matches"; public IfThen rule; public VarMatches matches; public RuleWithParams() { } public RuleWithParams(IfThen rule, VarMatches matches) { this.matches = matches; this.rule = rule; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + rule + ", " + matches + ")"; } public boolean equals(Object o) { if (!(o instanceof RuleWithParams)) return false; RuleWithParams __7 = (RuleWithParams) o; return eq(rule, __7.rule) && eq(matches, __7.matches); } public int hashCode() { int h = 1254104616; h = boostHashCombine(h, _hashCode(rule)); h = boostHashCombine(h, _hashCode(matches)); return h; } public Object[] _fieldsToList() { return new Object[] { rule, matches }; } public String ruleID() { return rule.globalID; } } static public class IfThen implements IFieldsToList { static final public String _fieldOrder = "in out globalID options originalText"; public Exp in; public Exp out; public IfThen() { } public IfThen(Exp in, Exp out) { this.out = out; this.in = in; } public boolean equals(Object o) { if (!(o instanceof IfThen)) return false; IfThen __8 = (IfThen) o; return eq(in, __8.in) && eq(out, __8.out); } public int hashCode() { int h = -2108234502; h = boostHashCombine(h, _hashCode(in)); h = boostHashCombine(h, _hashCode(out)); return h; } public Object[] _fieldsToList() { return new Object[] { in, out }; } public String globalID; public Set options; public String originalText; public String text() { Collection opt = options; if (nempty(globalID)) opt = concatLists(ll("id: " + globalID), opt); return (nempty(opt) ? "[" + joinWithComma(opt) + "] " : "") + (in == null ? "" : in.text() + "\n => ") + nlLogic_text(out); } public String toString() { return text(); } } abstract static public class Exp { abstract public String text(); public String toString() { return text(); } } static public class Func extends Exp implements IFieldsToList { public String name; public Exp arg; public Func() { } public Func(String name, Exp arg) { this.arg = arg; this.name = name; } public boolean equals(Object o) { if (!(o instanceof Func)) return false; Func __0 = (Func) o; return eq(name, __0.name) && eq(arg, __0.arg); } public int hashCode() { int h = 2201316; h = boostHashCombine(h, _hashCode(name)); h = boostHashCombine(h, _hashCode(arg)); return h; } public Object[] _fieldsToList() { return new Object[] { name, arg }; } public List options; public Func(String name, List options, Exp arg) { this.arg = arg; this.options = options; this.name = name; } public String text() { return name + (empty(options) ? "" : "[" + joinWithComma(options) + "]") + "(" + arg.text() + ")"; } public String argText() { return nlLogic_text(arg); } } static public class And extends Exp implements IFieldsToList { public Exp a; public Exp b; public And() { } public And(Exp a, Exp b) { this.b = b; this.a = a; } public boolean equals(Object o) { if (!(o instanceof And)) return false; And __1 = (And) o; return eq(a, __1.a) && eq(b, __1.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 String text() { return a.text() + "\n && " + b.text(); } } static public class ExpNot extends Exp implements IFieldsToList { public Exp a; public ExpNot() { } public ExpNot(Exp a) { this.a = a; } public boolean equals(Object o) { if (!(o instanceof ExpNot)) return false; ExpNot __2 = (ExpNot) o; return eq(a, __2.a); } public int hashCode() { int h = 2089649046; h = boostHashCombine(h, _hashCode(a)); return h; } public Object[] _fieldsToList() { return new Object[] { a }; } public String text() { return "!" + a.text(); } } abstract static public class Literal extends Exp { } static public class Sentence extends Literal implements IFieldsToList { public List tok; public Sentence() { } public Sentence(List tok) { this.tok = tok; } public boolean equals(Object o) { if (!(o instanceof Sentence)) return false; Sentence __3 = (Sentence) o; return eq(tok, __3.tok); } public int hashCode() { int h = 1327381123; h = boostHashCombine(h, _hashCode(tok)); return h; } public Object[] _fieldsToList() { return new Object[] { tok }; } public String text() { return join(tok); } } static public class Sentence2 extends Literal implements IFieldsToList { public String text; public Sentence2() { } public Sentence2(String text) { this.text = text; } public boolean equals(Object o) { if (!(o instanceof Sentence2)) return false; Sentence2 __4 = (Sentence2) o; return eq(text, __4.text); } public int hashCode() { int h = -1800858097; h = boostHashCombine(h, _hashCode(text)); return h; } public Object[] _fieldsToList() { return new Object[] { text }; } public String text() { return text; } } static public class Eq extends Exp implements IFieldsToList { public Exp left; public Exp right; public Eq() { } public Eq(Exp left, Exp right) { this.right = right; this.left = left; } public boolean equals(Object o) { if (!(o instanceof Eq)) return false; Eq __5 = (Eq) o; return eq(left, __5.left) && eq(right, __5.right); } public int hashCode() { int h = 2252; h = boostHashCombine(h, _hashCode(left)); h = boostHashCombine(h, _hashCode(right)); return h; } public Object[] _fieldsToList() { return new Object[] { left, right }; } public String text() { return left.text() + " = " + right.text(); } } static public class ClassMaker { final public String getClassName() { return className(); } public String className() { return className; } public String className; public ClassGen cg; public JavaClass baked; public InMemoryClassLoader classLoader; public Class loadedClass; final public ClassMaker setPrintDisassembly(boolean printDisassembly) { return printDisassembly(printDisassembly); } public ClassMaker printDisassembly(boolean printDisassembly) { this.printDisassembly = printDisassembly; return this; } final public boolean getPrintDisassembly() { return printDisassembly(); } public boolean printDisassembly() { return printDisassembly; } public boolean printDisassembly = false; public ClassMaker(String className) { this.className = className; setClassGen(new ClassGen(className, "java.lang.Object", null, Const.ACC_PUBLIC, null)); } public ClassMaker(Class interfaceToImplement) { className = randomClassName(); setClassGen(new ClassGen(className, "java.lang.Object", null, Const.ACC_PUBLIC, new String[] { main.className(interfaceToImplement) })); addDefaultConstructor(); } public void addDefaultConstructor() { cg.addEmptyConstructor(Const.ACC_PUBLIC); } public void setClassGen(ClassGen cg) { this.cg = cg; cg.setMajor(50); cg.setMinor(0); } public JavaClass bake() { if (baked == null) { baked = cg.getJavaClass(); if (printDisassembly) printClassWithMethods(); } return baked; } public void printClassWithMethods() { print_tabToSingleSpace(bake()); for (var method : baked.getMethods()) { print_tabToSingleSpace("\n" + method); print_tabToSingleSpace(method.getCode()); } } public byte[] getBytes_cache; final public byte[] getBytes() { if (getBytes_cache == null) getBytes_cache = getBytes_load(); return getBytes_cache; } final public byte[] getBytes_load() { return toBytes(); } public byte[] toBytes() { return bake().getBytes(); } public Class load() { if (loadedClass == null) { var bytes = toBytes(); classLoader = new InMemoryClassLoader(myClassLoader()); loadedClass = (Class) classLoader.defineAClass(className, bytes); } return loadedClass; } public A newInstance() { return main.newInstance(load()); } public void addField(FieldGen fg) { cg.addField(fg.getField()); } public ConstantPoolGen getConstantPool() { return cg.getConstantPool(); } } static public class OrError extends Var { public Object error; public OrError() { } public OrError(A value) { super(value); } public OrError(boolean dummy, Object error) { this.error = error; assertNotNull(error); } public boolean ok() { return error == null; } public Object error() { return error; } static public OrError ok(B a) { return new OrError(a); } static public OrError error(Object error) { return new OrError(true, error); } public String toString() { return ok() ? super.toString() : str(error); } } public interface IVStack { default public void call(VStack.Computable f) { push(f); } public void push(VStack.Computable f); default public void _return() { _return(null); } public void _return(Object value); public Object subResult(); } abstract static public class Sleeping implements AutoCloseable, IFieldsToList { public Timestamp targetTime; public Runnable action; public Sleeping() { } public Sleeping(Timestamp targetTime, Runnable action) { this.action = action; this.targetTime = targetTime; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + targetTime + ", " + action + ")"; } public Object[] _fieldsToList() { return new Object[] { targetTime, action }; } public long remainingMS() { return targetTime.minus(tsNow()); } } static public class HasTokenRangeWithSrc implements IHasTokenRangeWithSrc { public TokenRangeWithSrc src; public void setTokenRangeWithSrc(TokenRangeWithSrc src) { this.src = src; } public TokenRangeWithSrc tokenRangeWithSrc() { return src; } } static public class MultiSleeper extends RestartableCountdown implements ISleeper_v2 { public TreeMultiMap entries = new TreeMultiMap(); public void check() { var time = nextWakeUpTime(); var action = firstValue(entries); setTargetTime(time == null ? 0 : time.sysTime(), new Runnable() { public void run() { try { List toCall; synchronized (MultiSleeper.this) { toCall = entries.get(time); entries.remove(time); } check(); pcallFAll(toCall); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "List toCall;\r\n synchronized(MultiSleeper.this) {\r\n toCa..."; } }); } synchronized public void removeEntry(Timestamp targetTime, Runnable action) { entries.remove(targetTime, action); } synchronized public Timestamp nextWakeUpTime() { return firstKey(entries); } public synchronized Sleeping doLater(Timestamp targetTime, Runnable r) { if (r == null || targetTime == null) return null; targetTime = max(targetTime, tsNow()); entries.put(targetTime, r); check(); return new Sleeping(targetTime, r) { public void close() { try { removeEntry(targetTime, r); } catch (Exception __e) { throw rethrow(__e); } } }; } } static public class ListAndIndex implements IFieldsToList { static final public String _fieldOrder = "list idx"; public List list; public int idx; public ListAndIndex() { } public ListAndIndex(List list, int idx) { this.idx = idx; this.list = list; } public boolean equals(Object o) { if (!(o instanceof ListAndIndex)) return false; ListAndIndex __1 = (ListAndIndex) o; return eq(list, __1.list) && idx == __1.idx; } public int hashCode() { int h = 276903961; h = boostHashCombine(h, _hashCode(list)); h = boostHashCombine(h, _hashCode(idx)); return h; } public Object[] _fieldsToList() { return new Object[] { list, idx }; } public boolean atEnd() { return idx >= l(list); } public A get() { return _get(list, idx); } public int size() { return l(list); } public String toString() { return subList(list, 0, idx) + ", then " + subList(list, idx); } public ListAndIndex plus(int ofs) { return new ListAndIndex(list, idx + ofs); } public ListAndIndex minus(int ofs) { return new ListAndIndex(list, idx - ofs); } public List list() { return list; } final public int idx() { return index(); } public int index() { return idx; } public ListAndIndex mapIdx(IF1_IntToInt f) { return new ListAndIndex(list, f.get(idx)); } } static public class TokenRange extends IntRange { public TokenRange() { } public TokenRange(int start, int end) { this.end = end; this.start = start; } } static public interface Steppable { public boolean step(); } static public class InMemoryClassLoader extends ClassLoader { final public InMemoryClassLoader setRememberClassBytes(boolean rememberClassBytes) { return rememberClassBytes(rememberClassBytes); } public InMemoryClassLoader rememberClassBytes(boolean rememberClassBytes) { this.rememberClassBytes = rememberClassBytes; return this; } final public boolean getRememberClassBytes() { return rememberClassBytes(); } public boolean rememberClassBytes() { return rememberClassBytes; } transient public boolean rememberClassBytes = false; transient public Map classBytes = syncMap(); public InMemoryClassLoader(ClassLoader parent) { super(parent); } public Class defineAClass(String name, byte[] bytes) { Class c = defineClass(name, bytes, 0, bytes.length); if (rememberClassBytes) classBytes.put(c, bytes); return c; } public byte[] getClassBytes(Class c) { return classBytes.get(c); } } static public class RestartableCountdown implements AutoCloseable { public java.util.Timer timer; public long targetTime; public long totalSleepTime; synchronized public void setTargetTime(long targetTime, Runnable action) { if (targetTime <= 0) stop(); else if (targetTime != this.targetTime) { start(targetTime - sysNow(), action); this.targetTime = targetTime; } } synchronized public void start(long delayMS, Object action) { stop(); if (delayMS <= 0) { startThread(new Runnable() { public void run() { try { callF(action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(action);"; } }); } else { totalSleepTime += delayMS; timer = doLater_daemon(delayMS, action); targetTime = sysNow() + delayMS; } } public void start(double delaySeconds, Object action) { start(toMS(delaySeconds), action); } synchronized public void stop() { cancelTimer(timer); timer = null; targetTime = 0; } public void close() { stop(); } } static public class VarMatches extends WrappedMap { public VarMatches() { super(new LinkedHashMap()); } public VarMatches(Map map) { this(); main.putAll(this, map); } } static public interface IF1_IntToInt { public int get(int i); } static public class WrappedMap extends AbstractMap { public Map map; public WrappedMap() { } public WrappedMap(Map map) { this.map = map; } public B get(Object key) { return map.get(key); } public B put(A key, B value) { return map.put(key, value); } public boolean containsKey(Object key) { return map.containsKey(key); } public Set> entrySet() { return map.entrySet(); } } static public Object preciseGetOrCallMethod(Object object, String name) { if (object == null) return null; if (canCallWithVarargs(object, name)) return call(object, name); return _get(object, name); } static public boolean bareDBMode_on = false; static public void bareDBMode() { bareDBMode(null); } static public void bareDBMode(Integer autoSaveInterval) { bareDBMode_on = true; conceptsAndBot(autoSaveInterval); } static public A newObject(Class c, Object... args) { return (A) nuObject(c, args); } static public Object newObject(String className, Object... args) { return nuObject(className, args); } 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 remove(BitSet bs, int i) { bs.clear(i); } static public Set emptySet() { return new HashSet(); } static public A getAndClear(IVar v) { A a = v.get(); v.set(null); return 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.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(IMultiMap map) { return map == null ? null : first(map.keySet()); } static public BetterThreadLocal pingSource_tl_var = new BetterThreadLocal() { @Override public PingSource initialValue() { return ping_v3_pingSourceMaker().get(); } }; static public BetterThreadLocal pingSource_tl() { return pingSource_tl_var; } 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 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 int _hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static public NavigableMap synchroTreeMap() { return synchroNavigableMap(new TreeMap()); } static public boolean hasConcept(Class c, Object... params) { return hasConcept(db_mainConcepts(), c, params); } static public boolean hasConcept(Concepts cc, Class c, Object... params) { return findConceptWhere(cc, c, params) != null; } static public Object load(String varName) { readLocally(varName); return get(mc(), varName); } static public Object load(String progID, String varName) { readLocally(progID, varName); return get(mc(), varName); } static public void clearConcepts() { db_mainConcepts().clearConcepts(); } static public void clearConcepts(Concepts concepts) { concepts.clearConcepts(); } static public Map unstructureMap(String s) { return (Map) unstructure(s); } static public Map unstructureMap(String text, boolean allDynamic, Object classFinder) { return (Map) unstructure(text, allDynamic, classFinder); } static public boolean exceptionMessageContains(Throwable e, String s) { return cic(getInnerMessage(e), s); } static public void printShortException(Throwable e) { print(exceptionToStringShort(e)); } static public void printShortException(String s, Throwable e) { print(s, exceptionToStringShort(e)); } static public Object unstructureGZFile(File f) { return unstructureGZFile(f, null); } static public Object unstructureGZFile(File f, IF1 classFinder) { try { if (!fileExists(f)) return null; BufferedReader reader = utf8BufferedReader(gzInputStream(f)); return unstructure_tok(javaTokC_noMLS_onReader(reader), false, classFinder); } catch (Exception __e) { throw rethrow(__e); } } static public File conceptsFile(String progID) { return getProgramFile(progID, conceptsFileName()); } static public File conceptsFile() { return conceptsFile(dbProgramID()); } static public File conceptsFile(Concepts concepts) { return concepts.conceptsFile(); } static public IF1 toIF1(final Object f) { if (f == null) return null; if (f instanceof IF1) return (IF1) f; if (isString(f)) { throw fail("callF_legacy"); } return new IF1() { public Object get(Object a) { return callF(f, a); } }; } static public int done_minPrint = 10; static public long done(long startTime, String desc) { long time = now() - startTime; if (time >= done_minPrint) print(desc + " [" + time + " ms]"); return time; } static public long done(String desc, long startTime) { return done(startTime, desc); } static public long done(long startTime) { return done(startTime, ""); } static public RemoteDB connectToDBOpt(String dbNameOrID) { try { return new RemoteDB(dbNameOrID); } catch (Throwable __e) { return null; } } 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 String dynShortName(Object o) { return shortDynamicClassName(o); } static public A lastKey(SortedMap map) { return empty(map) ? null : map.lastKey(); } static public File conceptsDir() { return conceptsDir(db_mainConcepts()); } static public File conceptsDir(Concepts cc) { return cc.conceptsDir(); } static public File conceptsDir(String subName) { return conceptsDir(db_mainConcepts(), subName); } static public File conceptsDir(Concepts cc, String subName) { return newFile(conceptsDir(cc), subName); } static public void callRunnableWithWrapper(Object wrapper, Runnable r) { if (wrapper == null) callF(r); else callF(wrapper, r); } static public List callFAll(Collection l, Object... args) { return callF_all(l, args); } static public long saveGZStructureToFile(String file, Object o) { return saveGZStructureToFile(getProgramFile(file), o); } static public long saveGZStructureToFile(File file, Object o) { return saveGZStructureToFile(file, o, new structure_Data()); } static public long saveGZStructureToFile(File file, Object o, structure_Data data) { try { File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); File tempFile = tempFileFor(file); if (tempFile.exists()) try { String saveName = tempFile.getPath() + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); CountingOutputStream cos; try { GZIPOutputStream gos = new GZIPOutputStream(fileOutputStream); cos = new CountingOutputStream(gos); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(cos, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); structureToPrintWriter(o, printWriter, data); printWriter.close(); gos.close(); fileOutputStream.close(); } catch (Throwable e) { fileOutputStream.close(); tempFile.delete(); throw rethrow(e); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + file.getPath()); if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); return cos.getFilePointer(); } catch (Exception __e) { throw rethrow(__e); } } 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 String javaTokWordWrap(String s) { return javaTokWordWrap(120, s); } static public String javaTokWordWrap(int cols, String s) { int col = 0; List tok = javaTok(s); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && col >= cols && !containsNewLine(t)) tok.set(i, t = rtrimSpaces(t) + "\n"); int idx = t.lastIndexOf('\n'); if (idx >= 0) col = l(t) - (idx + 1); else col += l(t); } return join(tok); } static public String fileName(File f) { return f == null ? null : f.getName(); } static public int roundDownTo_rev(int x, int n) { return roundDownTo(n, x); } static public long roundDownTo_rev(long x, long n) { return roundDownTo(n, x); } static public int minutes() { return minutes(java.util.Calendar.getInstance()); } static public int minutes(java.util.Calendar c) { return c.get(java.util.Calendar.MINUTE); } static public long toK(long l) { return (l + 1023) / 1024; } static public Collection allConcepts() { return db_mainConcepts().allConcepts(); } static public Collection allConcepts(Concepts concepts) { return concepts.allConcepts(); } static public FixedRateTimer doEvery_daemon(long delay, final Object r) { return doEvery_daemon(defaultTimerName(), delay, r); } static public FixedRateTimer doEvery_daemon(String timerName, long delay, final Object r) { return doEvery_daemon(timerName, delay, delay, r); } static public FixedRateTimer doEvery_daemon(long delay, long firstDelay, final Object r) { return doEvery_daemon(defaultTimerName(), delay, firstDelay, r); } static public FixedRateTimer doEvery_daemon(String timerName, long delay, long firstDelay, final Object r) { FixedRateTimer timer = new FixedRateTimer(true); timer.scheduleAtFixedRate(smartTimerTask(r, timer, delay), firstDelay, delay); return timer; } static public FixedRateTimer doEvery_daemon(double delaySeconds, final Object r) { return doEvery_daemon(toMS(delaySeconds), r); } static public void sleepInCleanUp(long ms) { try { if (ms < 0) return; Thread.sleep(ms); } catch (Exception __e) { throw rethrow(__e); } } 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_raw(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) { printStackTrace(__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) { printStackTrace(__e); } setOpt_raw(c, "cleaningUp_flag", false); if (c instanceof Class && ((Class) c).getName().equals("main")) retireClassLoader(((Class) c).getClassLoader()); } static public void cleanUp(Collection l) { if (l == null) return; for (Object c : l) cleanUp(c); l.clear(); } static public A firstOfType(Collection c, Class type) { for (Object x : c) if (isInstanceX(type, x)) return (A) x; return null; } static public List conceptsOfType(String type) { return db_mainConcepts().conceptsOfType(type); } static public List concatLists_conservative(List a, List b) { if (empty(a)) return b; if (empty(b)) return a; return concatLists(a, b); } static public List concatLists_conservative(Collection a, Collection b) { if (empty(a) && b instanceof List) return ((List) b); if (empty(b) && a instanceof List) return ((List) a); return concatLists(a, b); } static public List filterByType(Iterable c, Class type) { List l = new ArrayList(); if (c != null) for (Object x : c) if (isInstanceX(type, x)) l.add((A) x); return l; } static public List filterByType(Object[] c, Class type) { return filterByType(asList(c), type); } static public List filterByType(Class type, Iterable c) { return filterByType(c, type); } static public List filterByDynamicType(Collection c, String type) { List l = new ArrayList(); for (A x : c) if (eq(dynamicClassName(x), type)) l.add(x); return l; } static public boolean hasType(Collection c, Class type) { for (Object x : c) if (isInstanceX(type, x)) return true; return false; } static public A findBackRef(Concept c, Class type) { for (Concept.Ref r : c.backRefs) if (instanceOf(r.concept(), type)) return (A) r.concept(); return null; } static public A findBackRef(Class type, Concept c) { return findBackRef(c, type); } static public void mapRemove(Map map, A key) { if (map != null && key != null) map.remove(key); } static public B firstValue(Map map) { return first(values(map)); } static public B firstValue(MultiSetMap map) { return map == null ? null : first(firstValue(map.data)); } static public B firstValue(MultiMap map) { return map == null ? null : first(firstValue(map.data)); } 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 loadConceptsStructure(String progID) { return loadTextFilePossiblyGZipped(getProgramFile(progID, "concepts.structure")); } static public String loadConceptsStructure() { return loadConceptsStructure(dbProgramID()); } 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 boolean containsKey(Map map, A key) { return map != null && map.containsKey(key); } static public boolean syncRemove(Collection c, A b) { if (c == null) return false; synchronized (collectionMutex(c)) { return c.remove(b); } } static public A syncRemove(List l, int idx) { if (l == null) return null; synchronized (collectionMutex(l)) { return l.remove(idx); } } static public B syncRemove(Map map, A key) { return map == null ? null : map.remove(key); } static public List syncAddOrCreate(List l, A a) { if (l == null) l = syncList(); l.add(a); return l; } 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 int identityHashCode(Object o) { return System.identityHashCode(o); } static public String shortDynamicClassName(Object o) { if (o instanceof DynamicObject && ((DynamicObject) o).className != null) return ((DynamicObject) o).className; return shortClassName(o); } static public boolean dynamicObjectIsLoading() { return isUnstructuring(); } static public void assertIsInstance(Class type, Object o) { if (!isInstance(type, o)) throw fail(_getClass(o) + " is not a subclass of " + type); } static public void assertIsInstance(Object o, Class type) { assertIsInstance(type, o); } static public boolean has(String a, String b, String c) { return false; } static public boolean has(T3 t) { return false; } 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 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 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 List addDyn_quickSync(List l, A a) { if (l == null) l = new ArrayList(); syncAdd(l, a); return l; } static public List removeDyn_quickSync(List l, A a) { if (l == null) return null; synchronized (collectionMutex(l)) { l.remove(a); return empty(l) ? null : l; } } static public void crenameField_noOverwrite(Concept c, String oldField, String newField) { if (c == null || eq(oldField, newField)) return; Object value = cget(c, oldField); if (newField != null && cget(c, newField) == null) cset(c, newField, value); cset(c, oldField, null); } 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 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 String divUnlessEmpty(String s, Object... params) { return empty(s) ? "" : div(s, params); } static public String hInlineSearchForm(String query, String action) { return hInlineSearchForm("q", query, action); } static public String hInlineSearchForm(String queryField, String query, String action) { return hform(hinputfield(queryField, query, "style", "width: 75px") + " " + hsubmit("Search"), "style", "display: inline", "action", action); } static public String joinWithVBar(Iterable l) { return join(" | ", l); } static public String joinWithVBar(String... l) { return joinWithVBar(asList(l)); } static public List keysDeprefixNemptyValue(Map map, String prefix) { List l = new ArrayList(); for (String s : keys(map)) if (startsWith(s, prefix) && nempty(map.get(s))) l.add(s.substring(l(prefix))); return l; } static public String hhiddenStuff(String secretHTML) { String id = aGlobalID(); String js = "document.getElementById(" + jsQuote(id) + ").innerHTML = " + jsQuote(secretHTML) + "; return false;"; return span(ahref("#", "show", "onclick", js), "id", id); } static public String yesNo_short(boolean b) { return b ? "yes" : "no"; } static public String htmlEncode_nlToBr_withIndents(String s) { return nlToBr_withIndents(htmlEncode(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 > List sortByTransformedMapKey_alphaNum(IF1 transform, Iterable c, B key) { List l = cloneList(c); sort(l, (a, b) -> cmpAlphaNum(transform.get(mapGet(a, key)), transform.get(mapGet(b, key)))); return l; } static public List lazyMap(final Object f, final List l) { return lazilyMap(f, l); } static public List lazyMap(List l, IF1 f) { return lazilyMap(f, l); } static public List lazyMap(IF1 f, List l) { return lazilyMap(f, l); } static public Map mapMinusKeys(Map map, A... keys) { return mapMinusKeys(map, asList(keys)); } static public Map mapMinusKeys(Map map, Collection keys) { if (empty(keys) || empty(map)) return map; keys = asSet(keys); Map m2 = similarEmptyMap(map); for (Map.Entry __0 : _entrySet(map)) { A key = __0.getKey(); B val = __0.getValue(); if (!keys.contains(key)) m2.put(key, val); } return m2; } static public Map mapMinusKeys(Collection keys, Map map) { return mapMinusKeys(map, keys); } 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 Map mapToMap(IF1> f, Iterable l) { Map map = new HashMap(); for (A o : unnullForIteration(l)) { Pair p = callF(f, o); map.put(p.a, p.b); } return map; } static public Map mapToMap(Iterable l, IF1> f) { return mapToMap(f, l); } static public Map mapToMap(Map m, IF2> f) { return mapMapToMap(f, m); } static public Map mapToMap(IF2> f, Map m) { return mapMapToMap(f, m); } static public B mapPut_returnValue(Map map, A key, B value) { mapPut(map, key, value); return value; } static public String aname(String anchor, Object contents, Object... params) { return tag("a", contents, concatArrays(new Object[] { "name", anchor }, params)); } static public String addParamsToURL(String url, Map params) { return appendQueryToURL(url, params); } static public String addParamsToURL(String url, Object... data) { return appendQueryToURL(url, data); } static public 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 List subListOrFull(List l, IntRange r) { return r == null ? l : subList(l, r.start, r.end); } static public String span_title(String title, Object contents) { return spanTitle(title, contents); } static public String unicode_downOrUpPointingTriangle(boolean down) { return down ? unicode_downPointingTriangle() : unicode_upPointingTriangle(); } static public Object[] litobjectarray(Object... l) { return litObjectArray(l); } static public String htmldecode_dropTagsAndComments(String html) { return htmldecode(dropTagsAndHTMLComments(html)); } static public String htmlTable2_noHtmlEncode(Object data, Object... __) { return htmlTable2(data, paramsPlus(__, "htmlEncode", false)); } static public String hCheckBoxMultiSelect_v2(Object... __) { boolean verbose = boolPar("verbose", __); return hscript(replaceDollarVars("\r\n var lastChecked;\r\n\r\n $(document).ready(function() {\r\n console.log(\"document ready\");\r\n $(\"input[type=checkbox]\").click(function(e) {\r\n var verbose = $verbose;\r\n var cls = this.className;\r\n if (verbose) console.log(\"cls=\" + cls);\r\n if (!cls) return;\r\n \r\n if (!lastChecked || lastChecked.className != cls) {\r\n lastChecked = this;\r\n return;\r\n }\r\n \r\n var $chkboxes = $('input[type=checkbox].' + cls);\r\n \r\n if (e.shiftKey) {\r\n var start = $chkboxes.index(this);\r\n var end = $chkboxes.index(lastChecked);\r\n\r\n // change checkboxes, trigger their change event in case there are handlers installed\r\n $chkboxes.slice(Math.min(start, end), Math.max(start,end)+1).prop('checked', lastChecked.checked)\r\n .each(function(idx, chkbox) {\r\n chkbox.dispatchEvent(new Event('change'));\r\n });\r\n }\r\n \r\n lastChecked = this;\r\n });\r\n });\r\n ", "verbose", verbose)); } static public String lines_rtrim(Collection lines) { return rtrim_fromLines(lines); } static public Map putKeysFirst(Map map, Object... keys) { Map m2 = litorderedmap(); Map remaining = cloneMap(map); for (Object key : keys) { if (remaining.containsKey(key)) { m2.put(key, remaining.get(key)); remaining.remove(key); } } m2.putAll(remaining); return m2; } static public Map putKeysFirst(List keys, Map map) { return putKeysFirst(map, toObjectArray(keys)); } 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 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 hinputfield(String name, Object... params) { return htextinput(name, params); } static public String htableRaw_valignTop(List data, Object... params) { return htableRaw2(data, asList(params), ll(), ll("valign", "top")); } static public String htextarea(String text, Object... params) { params = html_massageAutofocusParam(params); return hopeningTag("textarea", params) + htmlencode2(text) + ""; } static public String htrickcheckboxWithText(String name, String text, boolean checked, Object... params) { String id = randomID(); return hhidden(name, checked ? "1" : "0") + hcheckbox(null, checked, paramsPlus(params, "id", id, "onclick", "this.previousElementSibling.value=this.checked ? 1 : 0")) + " " + hlabelFor(id, htmlEncode2(text)); } static public String htrickcheckboxWithText(String name, String text) { return htrickcheckboxWithText(name, text, false); } 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 String jquery_submitFormOnCtrlEnter() { return "if ((event.keyCode == 10 || event.keyCode == 13) && event.ctrlKey) $(this).closest('form').submit();"; } static public String htextfield(String name, Object... params) { return htextinput(name, params); } static public Map subMapStartingWith_dropPrefix(Map map, String prefix) { if (map == null) return null; Map map2 = new HashMap(); for (Map.Entry __0 : _entrySet(map)) { String key = __0.getKey(); T value = __0.getValue(); if (startsWith(key, prefix)) map2.put(substring(key, l(prefix)), value); } return map2; } static public Map joinMaps(Map map1, Map map2) { if (empty(map2)) return map1; if (empty(map1)) return map2; Map map3 = cloneMap(map1); putAll(map3, map2); return map3; } static public void listPut(List l, int i, A a, A emptyElement) { listSet(l, i, a, emptyElement); } static public void listPut(List l, int i, A a) { listSet(l, i, a); } 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 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 List itemPlus(A a, Collection l) { return itemPlusList(a, l); } static public List tok_identifiersOnly(String s) { return tok_identifiersInOrder(s); } static public String p_vbar(String... items) { return p_vbar(asList(items)); } static public String p_vbar(Collection items, Object... __) { return pUnlessEmpty(joinNemptiesWithVBar(items), __); } static public String hbuttonOnClick_noSubmit(String text, String onClick, Object... params) { return hfulltag("button", text, paramsPlus(params, "onclick", onClick, "type", "button")); } static public String firstToUpper(String s) { if (empty(s)) return s; return Character.toUpperCase(s.charAt(0)) + s.substring(1); } static public String htmlDecode_dropTags(String html) { return htmldecode_dropAllTags(html); } static public Object getVarOpt(Object o) { return o instanceof IF0 ? ((IF0) o).get() : o; } static public String joinNemptiesWithVBar(String... strings) { return joinNempties(" | ", strings); } static public String joinNemptiesWithVBar(Collection strings) { return joinNempties(" | ", strings); } 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 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 String hselect_list(String name, Collection entries, Object... params) { return hselect_list(entries, paramsPlus_skipFirst(params, "name", name)); } static public String hselect_list(Collection entries, Object... params) { StringBuilder buf = new StringBuilder(); String selected = null; if (odd(l(params))) { selected = str(first(params)); params = dropFirst(params); } int i = indexOf(params, "allowEmpty"); if (even(i)) { buf.append("\n"); params[i] = params[i + 1] = null; } if (nempty(entries)) for (String k : entries) { String value = k; boolean isSelected = eq(selected, k); buf.append(hfulltag("option", htmlencode(str(or(value, ""))), "value", k, "selected", isSelected ? html_valueLessParam() : null)).append("\n"); } return hfulltag("select", buf, params) + "\n"; } 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 hoption(String text) { return tag("option", htmlEncode2(text)); } static public List llNempties(String... a) { ArrayList l = new ArrayList(a.length); if (a != null) for (String x : a) if (nempty(x)) l.add(x); return l; } static public String unicode_DEL() { return unicodeFromCodePoint(0x2421); } static public String ahrefWithConfirm(String msg, String url, Object contents, Object... params) { return ahref(url, contents, paramsPlus(params, "onClick", "return confirm(" + jsQuote(msg) + ");")); } 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 List keysList(Map map) { return cloneListSynchronizingOn(keys(map), map); } static public List keysList(MultiSet ms) { return ms == null ? null : keysList(ms.map); } static public String dropPrefixOrNull(String prefix, String s) { return s != null && s.startsWith(prefix) ? s.substring(l(prefix)) : null; } static public List regexpGroups(String pat, String s) { return regexpFirstGroups(pat, s); } 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 joinNemptiesWithColon(String... strings) { return joinNempties(": ", strings); } static public String joinNemptiesWithColon(Collection strings) { return joinNempties(": ", strings); } static public String commaCombine(Object... l) { return joinNemptiesWithComma(flattenCollectionsAndArrays(ll(l))); } public static boolean isWindows() { return System.getProperty("os.name").contains("Windows"); } static public long stopTiming_defaultMin = 10; static public long startTiming_startTime; static public void startTiming() { startTiming_startTime = now(); } static public void stopTiming() { stopTiming(null); } static public void stopTiming(String text) { stopTiming(text, stopTiming_defaultMin); } static public void stopTiming(String text, long minToPrint) { long time = now() - startTiming_startTime; if (time >= minToPrint) { text = or2(text, "Time: "); print(text + time + " ms"); } } static public double sqrt(double x) { return Math.sqrt(x); } static public Pt ptMinus(Pt a, Pt b) { if (b == null) return a; return new Pt(a.x - b.x, a.y - b.y); } static public UnsupportedOperationException unsupportedOperation() { throw new UnsupportedOperationException(); } static public double infinity() { return positiveInfinity(); } static public FileInputStream fileInputStream(File path) { try { return newFileInputStream(path); } catch (Exception __e) { throw rethrow(__e); } } static public FileInputStream fileInputStream(String path) { try { return newFileInputStream(path); } catch (Exception __e) { throw rethrow(__e); } } static public File assertFileExists(File f) { return assertExists(f); } static public A floorKey(NavigableMap map, A key) { if (map == null) return null; return map.floorKey(key); } static public Map.Entry higherEntry(NavigableMap map, A key) { return map == null ? null : map.higherEntry(key); } static public Map.Entry lastEntry(NavigableMap map) { return map == null ? null : map.lastEntry(); } static public SortedMap subMap(SortedMap map, A fromKey, A toKey) { return map == null ? null : map.subMap(fromKey, toKey); } static public MultiSetMap generalizedCIMultiSetMap() { MultiSetMap mm = new MultiSetMap(); mm.data = generalizedCIMap(); return mm; } static public ListIterator listIterator(List l) { return l == null ? emptyListIterator() : l.listIterator(); } static public boolean classIsExportedTo(Class c, java.lang.Module destModule) { if (c == null || destModule == null) return false; java.lang.Module srcModule = c.getModule(); String packageName = c.getPackageName(); return srcModule.isExported(packageName, destModule); } static public Set allInterfacesImplementedBy(Object o) { return allInterfacesImplementedBy(_getClass(o)); } 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 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 List quoteAll(String[] l) { return quoteAll(asList(l)); } static public List quoteAll(Collection l) { List x = new ArrayList(); for (String s : l) x.add(quote(s)); return x; } static public boolean arraysEqual(Object[] a, Object[] b) { if (a.length != b.length) return false; for (int i = 0; i < a.length; i++) if (neq(a[i], b[i])) return false; return true; } static public Object metaGet(IMeta o, Object key) { return metaMapGet(o, key); } static public Object metaGet(Object o, Object key) { return metaMapGet(o, key); } static public Object metaGet(String key, IMeta o) { return metaMapGet(o, key); } static public Object metaGet(String key, Object o) { return metaMapGet(o, key); } static public Object metaMapGet(IMeta o, Object key) { return o == null ? null : o.metaGet(key); } static public Object metaMapGet(Object o, Object key) { return metaMapGet(toIMeta(o), key); } static public void metaPut(IMeta o, Object key, Object value) { metaMapPut(o, key, value); } static public void metaPut(Object o, Object key, Object value) { metaMapPut(o, key, value); } static public Map convertObjectMetaToMap(IMeta o) { return convertObjectMetaToMap(o, () -> makeObjectMetaMap()); } static public Map convertObjectMetaToMap(IMeta o, IF0 createEmptyMap) { if (o == null) return null; Object meta = o._getMeta(); if (meta instanceof Map) return ((Map) meta); var mutex = tempMetaMutex(o); try { var actualMutex = mutex.get(); synchronized (actualMutex) { meta = o._getMeta(); if (meta instanceof Map) return ((Map) meta); Map map = createEmptyMap.get(); if (meta != null) map.put("previousMeta", meta); o._setMeta(map); return map; } } finally { _close(mutex); } } static public void syncMapPutOrRemove(Map map, A key, B value) { syncMapPut2(map, key, value); } static public String humanizeShortName(Object o) { return humanizeLabel(shortName(o)); } static public A postProcess(Object f, A a) { return callPostProcessor(f, a); } static public A postProcess(IF1 f, A a) { return callPostProcessor(f, a); } static public 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 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 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 List sortedByConceptIDDesc(Collection c) { return sortedByCalculatedFieldDesc(__96 -> conceptID(__96), c); } static public Map conceptToMap_gen_withNullValues(Object c) { Map map = litorderedmap("id", str(getLong(c, "id"))); for (String field : conceptFields_gen(c)) map.put(field, getOpt(c, field)); return map; } static public List nonStaticNonTransientFieldObjectsOfType(Class type, Object o) { return filter(nonStaticNonTransientFieldObjects(o), f -> eq(f.getType(), type)); } static public B lastValue(NavigableMap map) { if (map == null) return null; Map.Entry entry = map.lastEntry(); return entry == null ? null : entry.getValue(); } static public void removeLastKey(SortedMap map) { if (nempty(map)) map.remove(lastKey(map)); } static public List valuesAsList(Map map) { return valuesList(map); } static public List cloneKeys(Map map) { return cloneList(keys(map)); } static public String optCastString(Object o) { return optCastToString(o); } static public boolean isSingleLine(String s) { return !containsNewLine(s); } static public boolean isUntrimmed(String s) { return neq(s, trim(s)); } static public boolean englishStringToBool(String s) { return swicOneOf(s, "y", "t", "1"); } static public Map cgetAll_cloneLists(Concept c, Collection fields) { return mapToValues(fields, f -> cloneIfList(cget(c, f))); } static public int cSmartSet(Concept c, Object... values) { try { if (c == null) return 0; warnIfOddCount(values = expandParams(c.getClass(), values)); int changes = 0; for (int i = 0; i + 1 < l(values); i += 2) if (_cSmartSetField(c, (String) values[i], values[i + 1])) ++changes; return changes; } catch (Exception __e) { throw rethrow(__e); } } static public int cSmartSet_withConverter_pcall(Concept c, Object... values) { return cSmartSet_withConverter_pcall(false, c, values); } static public int cSmartSet_withConverter_pcall(boolean verbose, Concept c, Object... values) { return cSmartSet_withConverter_pcall(verbose, new DefaultValueConverterForField(), c, values); } static public int cSmartSet_withConverter_pcall(ValueConverterForField converter, Concept c, Object... values) { return cSmartSet_withConverter_pcall(false, converter, c, values); } static public int cSmartSet_withConverter_pcall(boolean verbose, ValueConverterForField converter, Concept c, Object... values) { try { if (c == null) return 0; warnIfOddCount(values = unrollAndExpandParams(c.getClass(), values)); int changes = 0; for (int i = 0; i + 1 < l(values); i += 2) { try { if (cSmartSetField_withConverter(c, (String) values[i], values[i + 1], converter, verbose)) ++changes; } catch (Throwable __e) { printStackTrace(__e); } } return changes; } catch (Exception __e) { throw rethrow(__e); } } static public boolean hasField(Object o, String field) { return findField2(o, field) != null; } static public Concept _getConcept(long id) { return getConcept(id); } static public Concept _getConcept(Concepts concepts, long id) { return getConcept(concepts, id); } static public A _getConcept(Class cc, long id) { return getConcept(cc, id); } static public A _getConcept(Concepts concepts, Class cc, long id) { return getConcept(concepts, cc, id); } 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 Map orderedMapPutOrCreate(Map map, A key, B value) { if (key != null && value != null) { if (map == null) map = new LinkedHashMap(); map.put(key, value); } return map; } static public A trueFalseNull(Boolean b, A onTrue, A onFalse, A onNull) { return b == null ? onNull : b.booleanValue() ? onTrue : onFalse; } static public String firstWhereFirstLongIs(Collection l, long i) { return firstThat(l, s -> parseFirstLong(s) == i); } static public boolean hasBackRefs(Concept c) { return c != null && syncNempty(c.backRefs); } static public Class getTypeArgumentAsClass(Type type) { if (type instanceof ParameterizedType) return typeToClass(first(((ParameterizedType) type).getActualTypeArguments())); return null; } static public Type genericFieldType(Object o, String field) { Field f = getField(o, field); return f == null ? null : f.getGenericType(); } static public List scoredSearch(String query, Iterable data) { Map scores = new HashMap(); List searchTerms = scoredSearch_prepare(query); if (empty(searchTerms)) return asList(data); for (String s : data) { int score = scoredSearch_score(s, searchTerms); if (score != 0) scores.put(s, score); } return keysSortedByValuesDesc(scores); } static public long parseFirstLong(String s) { return parseLong(jextract("", s)); } static public Map putOrCreate(Map map, A key, B value) { if (map == null) map = new HashMap(); map.put(key, value); return map; } static public String formatLocalDateWithSeconds(long time) { return localDateWithSeconds(time); } static public String formatLocalDateWithSeconds() { return localDateWithSeconds(); } static public BigInteger plus(BigInteger a, BigInteger b) { return a.add(b); } static public BigInteger plus(BigInteger a, long b) { return a.add(bigint(b)); } static public long plus(long a, long b) { return a + b; } static public int plus(int a, int b) { return a + b; } static public float plus(float a, float b) { return a + b; } static public double plus(double a, double b) { return a + b; } static public long clockTimeToSystemTime(long now) { return now == 0 ? 0 : now + clockToSysTimeDiff(); } static public List minus(Collection a, Object... b) { Set set = asSet(b); List l = new ArrayList(); for (Object s : unnull(a)) if (!set.contains(s)) l.add(s); return l; } static public BigInteger minus(BigInteger a, BigInteger b) { return a.subtract(b); } static public Complex minus(Complex c) { return c == null ? null : complex(-c.re(), -c.im()); } static public int minus(int a, int b) { return a - b; } static public double minus(double a, double b) { return a - b; } static public Set createOrAddToSyncLinkedHashSet(Set set, A a) { if (set == null) set = syncLinkedHashSet(); set.add(a); return set; } static public A pcallF_typed(F0 f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { printStackTrace(__e); } return null; } static public B pcallF_typed(F1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { printStackTrace(__e); } return null; } static public void pcallF_typed(VF1 f, A a) { try { { if (f != null) f.get(a); } } catch (Throwable __e) { printStackTrace(__e); } } static public void pcallF_typed(IVF1 f, A a) { try { { if (f != null) f.get(a); } } catch (Throwable __e) { printStackTrace(__e); } } static public void pcallF_typed(IVF2 f, A a, B b) { try { { if (f != null) f.get(a, b); } } catch (Throwable __e) { printStackTrace(__e); } } static public Object pcallF_typed(Runnable r) { try { { if (r != null) r.run(); } } catch (Throwable __e) { printStackTrace(__e); } return null; } static public A pcallF_typed(IF0 f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { printStackTrace(__e); } return null; } static public B pcallF_typed(IF1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { printStackTrace(__e); } return null; } static public void replaceLast(List l, A a) { replaceLastElement(l, a); } static public A[] toTypedArray(Class type, Iterable c) { return toArray(c, type); } static public String pnlToLines(String prefix, Iterable l) { return pnlToString(prefix, l); } static public String pnlToLines(Iterable l) { return pnlToString(l); } static public String pnlToLines(A[] l) { return pnlToString(l); } static public String pnlToLines(Map map) { return pnlToString(map); } static public String pnlToLines(MultiMap map) { return pnlToString(map); } static public String formatRecordVars(String recordName, Object... params) { return renderRecordVars(recordName, params); } 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(() -> { 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(() -> { if (!setText_opt || neq(callOpt(c, "getText"), s)) call(c, "setText", s); }); } return c; } static public RuntimeException rethrowAndAppendToMessage(Throwable t, String msg) { String haveMsg = t.getMessage(); if (empty(msg) || endsWith(haveMsg, " " + msg)) throw rethrow(t); throw new RuntimeException(joinWithSpace(t.getMessage(), msg), t); } static public String squareBracketed(String s) { return "[" + s + "]"; } static public AutoCloseable tempRestoreMap(Map map) { if (map == null) return null; var cloned = cloneMap(map); return () -> copyMap(cloned, map); } static public boolean is(String a, String b) { return false; } static public void printVars(Object... params) { printVars_str(params); } static public void scaffoldCalled(Object obj, Object function, Object... args) { printShortenedFunctionCall(200, (obj == null ? "" : shorten(20, str(obj)) + " :: ") + function, args); } static public int parseHexInt(String s) { return hexToInt(s); } static public int intFromBinary(String s) { return Integer.parseInt(s, 2); } static public boolean hasStaticMethodNamed(Class c, String method) { if (c == null) return false; var methods = getMethodCache(c).cache.get(method); if (methods != null) for (var m : methods) if (isStaticMethod(m)) return true; return false; } static public boolean isInterface(Class c) { return c != null && c.isInterface(); } static public boolean isStaticField(Field f) { return (f.getModifiers() & Modifier.STATIC) != 0; } static public List constructorsWithNumberOfArguments(Class c, int n) { return filter(getDeclaredConstructors_cached(c), con -> l(con.getParameterTypes()) == n); } static public A[] toArrayOrNull(Class type, Collection c) { if (empty(c)) return null; return toArray(type, c); } static public Map parsePrimitiveType_map = litmap("int", int.class, "char", char.class, "byte", byte.class, "short", short.class, "long", long.class, "float", float.class, "double", double.class, "bool", boolean.class); static public Class parsePrimitiveType(String s) { return parsePrimitiveType_map.get(s); } 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) { if (c == null) return false; return getMethodCache(c).cache.containsKey(method); } static public Map mapWithSingleValue(Iterable l, B b) { HashMap map = new HashMap(); if (l != null) for (A a : l) map.put(a, b); return map; } static public AutoCloseable tempMapPutAll(Map map, Map toAdd) { if (map != null && nempty(toAdd)) { List> toRestore = new ArrayList(); for (var __0 : _entrySet(toAdd)) { var key = __0.getKey(); var value = __0.getValue(); if (key != null && value != null) { B old = map.put(key, value); if (!eq(old, value)) toRestore.add(pair(key, old)); } } return () -> { for (var p : toRestore) mapPutOrRemove(map, p.a, p.b); }; } return null; } static public AutoCloseable tempAdd(Collection l, A a) { if (l == null || l.contains(a)) return null; l.add(a); return new tempAdd_undo(l, a); } static public class tempAdd_undo implements AutoCloseable, IFieldsToList { public Collection l; public A a; public tempAdd_undo() { } public tempAdd_undo(Collection l, A a) { this.a = a; this.l = l; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + l + ", " + a + ")"; } public Object[] _fieldsToList() { return new Object[] { l, a }; } public void close() { try { l.remove(a); } catch (Exception __e) { throw rethrow(__e); } } } static public AutoCloseable tempAdd(Container a, Component b) { if (a == null || b == null) return null; { return swing(() -> { if (b.getParent() == a) return null; a.add(b); return () -> { swing(() -> { if (b.getParent() == a) removeFromParent(b); }); }; }); } } static public TreeSet mapToTreeSet(Object f, Iterable l) { TreeSet x = new TreeSet(); if (l != null) for (Object o : l) x.add(callF(f, o)); return x; } static public TreeSet mapToTreeSet(IF1 f, Iterable l) { TreeSet x = new TreeSet(); if (l != null) for (var o : l) x.add(f.get(o)); return x; } static public TreeSet mapToTreeSet(Iterable l, IF1 f) { return mapToTreeSet(f, l); } static public boolean isAnonymousClass(Class c) { return isAnonymousClassName(className(c)); } static public String longestPrefixInTreeSet(String s, TreeSet set) { return longestPrefixInNavigableSet(s, set); } static public Map javaxClassShortcuts_cache; static public Map javaxClassShortcuts() { if (javaxClassShortcuts_cache == null) javaxClassShortcuts_cache = javaxClassShortcuts_load(); return javaxClassShortcuts_cache; } static public Map javaxClassShortcuts_load() { return litmap("O", "Object", "S", "String", "L", "List", "Cl", "Collection"); } static public List standardImports_fullyImportedPackages() { return endingWith_dropSuffix(standardImports(), ".*"); } static public boolean scaffoldingEnabled(Object o) { return metaGet(o, "scaffolding") != null; } static public File getBytecodePathForClass(Object o) { return getBytecodePathForClass(_getClass(o)); } static public File getBytecodePathForClass(Class c) { try { return c == null ? null : new File(c.getProtectionDomain().getCodeSource().getLocation().toURI()); } catch (Exception __e) { throw rethrow(__e); } } static public int hashOfLong(long l) { return Long.hashCode(l); } 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 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 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 int hashCodeFor(Object a) { return a == null ? 0 : a.hashCode(); } 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 LinkedHashMap cloneLinkedHashMap(Map map) { return map == null ? new LinkedHashMap() : new LinkedHashMap(map); } static public List> pwt_topDogs(Iterable> l) { List> topDogs = new ArrayList(); for (ParsedWithTokens p : unnullForIteration(l)) for (int i = p.iStart; i < p.iRemaining; i += 2) listPut(topDogs, i, pwt_winner(_get(topDogs, i), p)); return uniquify(nonNulls(topDogs)); } static public List> pwt_filterByType(Class type, Iterable l) { return (List) filter(l, p -> isInstance(type, p.get())); } static public List> pwt_initial(int maxTokens, String s) { return pwt_initial(s, maxTokens); } static public List> pwt_initial(String s, int maxTokens) { return pwt_initial(javaTok(s), maxTokens); } static public List> pwt_initial(List tok, int maxTokens) { return concatMap(lai_codeTokens(tok), lai -> pwt_followingTokens(1, maxTokens, lai)); } static public List> pwt_initial(int maxTokens, List tok) { return pwt_initial(tok, maxTokens); } static public List> pwt_transform(IF1 f, Iterable> l) { return mapNonNulls(p -> { B b = f.get(p.get()); return b == null ? null : p.withValue(b); }, l); } static public ParsedWithTokens pwt_combine(A value, ParsedWithTokens p1, ParsedWithTokens p2) { assertSame(p1.tok, p2.tok); return new ParsedWithTokens(value, p1.tok, min(p1.iStart, p2.iStart), max(p1.iRemaining, p2.iRemaining)); } static public ParsedWithTokens pwt_combine(ParsedWithTokens p1, ParsedWithTokens p2) { return pwt_combine(p1.get(), p1, p2); } static public List> pwt_combine(Iterable> l1, Iterable> l2, IF2 f) { List> out = new ArrayList(); for (ParsedWithTokens a : l1) for (ParsedWithTokens b : pwt_toTheRightOf(l2, a)) out.add(pwt_combine(f.get(a.get(), b.get()), a, b)); return out; } static public List> pwt_combine(Iterable> l1, Iterable> l2, Iterable> l3, IF3 f) { List> out = new ArrayList(); for (ParsedWithTokens a : l1) for (ParsedWithTokens b : pwt_toTheRightOf(l2, a)) for (ParsedWithTokens c : pwt_toTheRightOf(l3, b)) out.add(pwt_combine(f.get(a.get(), b.get(), c.get()), a, c)); return out; } static public List> pwt_filter(IF1 f, Iterable> l) { return filter(p -> f.get(p.get()), l); } static public String weekday() { return get(englishWeekdays(), dayOfWeek_nr() - 1); } static public IterableIterator> pwt_toTheRightOf(Iterable> l, ParsedWithTokens b) { return filterI(iterator(l), p -> { return p.iStart == (b.iRemaining | 1); }); } static public boolean between(long x, long min, long max) { return isBetween(x, min, max); } static public boolean between(double x, double min, double max) { return isBetween(x, min, max); } static public IterableIterator> pwt_toTheLeftOf(Iterable> l, ParsedWithTokens b) { return filterI(iterator(l), p -> { return (p.iRemaining | 1) == (b.iStart | 1); }); } static public IterableIterator itIt(IterableIterator it) { if (it == null) return emptyItIt(); return it; } static public IterableIterator itIt(Iterator it) { if (it == null) return emptyItIt(); if (it instanceof IterableIterator) return ((IterableIterator) it); return new IterableIterator() { public boolean hasNext() { return it.hasNext(); } public A next() { return it.next(); } }; } static public IterableIterator itIt(Iterable l) { if (l == null) return emptyItIt(); if (l instanceof IterableIterator) return ((IterableIterator) l); Iterator it = l.iterator(); if (it instanceof IterableIterator) return ((IterableIterator) it); return new IterableIterator() { public boolean hasNext() { return it.hasNext(); } public A next() { return it.next(); } }; } static public int parseEnglishWeekday(String s) { return indexOfIC(englishWeekdays(), s) + 1; } static public Map parseEnglishMonthName_cache; static public int parseEnglishMonthName(String s) { if (parseEnglishMonthName_cache == null) parseEnglishMonthName_cache = listIndexCI(englishMonthNames()); return or(parseEnglishMonthName_cache.get(s), -1) + 1; } static public IterableIterator> pwt_precedingTokens(int minTokens, int maxTokens, ListAndIndex tok) { int remaining = countPrecedingTokens(tok); int iStart = tok.idx; return countIterator_inclusive(min(minTokens, remaining), min(maxTokens, remaining), n -> pwt_raw(tok.list, iStart - n * 2, iStart - 1)); } static public IterableIterator> pwt_followingTokens(int minTokens, int maxTokens, ListAndIndex tok) { int remaining = countRemainingTokens(tok); int iStart = tok.idx | 1; return countIterator_inclusive(min(minTokens, remaining), min(maxTokens, remaining), n -> pwt_raw(tok.list, iStart, iStart + n * 2 - 1)); } static public List syncList() { return synchroList(); } static public List syncList(List l) { return synchroList(l); } static public void cancelAndInterruptThread(Thread t) { if (t == null) return; cancelThread(t); t.interrupt(); } static public String loadPageWithTimeout(long timeout, String url) { return loadPageWithTimeout(url, timeout); } static public String loadPageWithTimeout(String url, long timeout) { try { ping(); url = loadPage_preprocess(url); print("Loading with timeout: " + hideCredentials(url)); URL _url = new URL(url); return loadPage(setURLConnectionTimeouts(_url.openConnection(), timeout), _url); } catch (Exception __e) { throw rethrow(__e); } } static public String loadPageWithTimeout(String url, double timeoutSeconds) { return loadPageWithTimeout(url, toMS(timeoutSeconds)); } static public String loadPageWithTimeout(double timeoutSeconds, String url) { return loadPageWithTimeout(url, timeoutSeconds); } static public A printWithIndent(A o) { return printIndent(o); } static public A printWithIndent(String indent, A o) { return printIndent(indent, o); } static public void printWithIndent(int indent, Object o) { printIndent(indent, o); } static public List webBotTester_extractMsgs(String html) { List out = new ArrayList(); List> msgs = findContainerTagWithClass(htmlTok(html), "span", "chat_msg_item"); for (List tokMsg : msgs) { WebChatBotMsg msg = new WebChatBotMsg(); msg.fullHTML = trimJoin(tokMsg); List tokMsg2 = dropFirstTwoAndLastTwo(tokMsg); for (List srSpan : findContainerTagWithClass(tokMsg2, "span", "sr-only")) setAllToEmptyString(dropFirstAndLast2(srSpan)); msg.fromUser = tagHasClass(tokMsg, "chat_msg_item_user"); msg.msgHTML = trimJoin(tokMsg2); msg.msgText = trim(htmldecode_dropAllTags(msg.msgHTML)); out.add(msg); } return out; } static public List getHTMLComments(String html) { return getHTMLComments(htmlTok(html)); } static public List getHTMLComments(List tok) { List l = new ArrayList(); for (int idx = 0; idx < l(tok); idx += 2) { String t = tok.get(idx); int i = 0; while ((i = indexOf(t, "", i + 4); l.add(substring(t, i + 4, j)); i = j + 3; } } return l; } static public int parseFirstIntOrMinus1(String s) { return parseIntOrMinus1(jextract("", s)); } static public int parseFirstIntOrMinus1(Iterable l) { return parseIntOrMinus1(firstIntegerString(l)); } static public String doPostWithTimeout(Map urlParameters, String url, int timeout) { return doPostWithTimeout(makePostData(urlParameters), url, timeout); } static public String doPostWithTimeout(String urlParameters, String url, int timeout) { try { URL _url = new URL(url); return doPost(urlParameters, setURLConnectionTimeouts(_url.openConnection(), timeout), _url); } catch (Exception __e) { throw rethrow(__e); } } static public int toMS_int(double seconds) { return toInt_checked((long) (seconds * 1000)); } static public void waitUntil(int interval, IF0 condition) { if (condition == null) return; while (!condition.get()) sleep(interval); } static public boolean waitUntil(int interval, double timeout, IF0 condition) { if (condition == null) return false; long start = sysNow(); while (sysNow() < start + toMS(timeout)) if (condition.get()) return true; else sleep(interval); return false; } static public Class typeToClass(Type type) { if (type == null) return null; if (type instanceof Class) return ((Class) type); if (type instanceof ParameterizedType) return optCast(Class.class, ((ParameterizedType) type).getRawType()); return null; } static public void assertSame(Object a, Object b) { assertSame("", a, b); } static public void assertSame(String msg, Object a, Object b) { if (a != b) throw fail(joinNemptiesWithColon(msg, a + " != " + b + " (" + identityHash(a) + "/" + identityHash(b) + ")")); } static public void assertSame(IF0 msg, Object a, Object b) { if (a != b) throw fail(joinNemptiesWithColon(msg.get(), a + " != " + b + " (" + identityHash(a) + "/" + identityHash(b) + ")")); } static public LineAndColumn tokenToLineAndColumn(ListAndIndex ptr) { return ptr == null ? null : tokenToLineAndColumn(ptr.list(), ptr.idx()); } static public LineAndColumn tokenToLineAndColumn(List tok, int tokenIndex) { int line = 1, col = 1; tokenIndex = min(tokenIndex, l(tok)); for (int i = 0; i < tokenIndex; i++) { String t = tok.get(i); int n = l(t); for (int j = 0; j < n; j++) if (t.charAt(j) == '\n') { ++line; col = 1; } else ++col; } return new LineAndColumn(line, col); } static public double fileAgeInSeconds(File f) { return f == null ? -1 : msToSeconds(now() - fileModificationTime(f)); } static public String nSeconds(long n) { return n2(n, "second"); } static public String nSeconds(Collection l) { return nSeconds(l(l)); } static public boolean deleteFile(File file) { return file != null && file.delete(); } static public Path toPath(File f) { return f == null ? null : f.toPath(); } static public void printExceptionShort(Throwable e) { printExceptionShort("", e); } static public void printExceptionShort(String prefix, Throwable e) { print(prefix, exceptionToStringShort(e)); } static public File saveTextFileWithoutTemp(File file, String contents) { try { mkdirsForFile(file); var fileOutputStream = newFileOutputStream(file); try { var outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8"); var printWriter = new PrintWriter(outputStreamWriter); printWriter.print(unnull(contents)); printWriter.close(); return file; } finally { _close(fileOutputStream); } } catch (Exception __e) { throw rethrow(__e); } } 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 touchExistingFile(File file) { try { if (file == null) return; java.nio.file.Files.setLastModifiedTime(toPath(file), java.nio.file.attribute.FileTime.from(java.time.Instant.now())); } catch (Exception __e) { throw rethrow(__e); } } static public String resolve(String host) { return hostToIP(host); } static public int indexOfInSortedArray(A[] array, A a) { return array == null ? -1 : Arrays.binarySearch(array, a); } static public List sortedKeys(Map map) { return sorted(keys(map)); } static public List sortedKeys(Object map) { return sorted(keys(map)); } static public List sortedKeys(MultiSet ms) { return sorted(keys(ms)); } static public List sortedKeys(MultiMap mm) { return sorted(keys(mm)); } static public File byteCodePathForClass(Class c) { if (c == null) return null; ClassLoader cl = getClassLoader(c); Collection files = (Collection) (getOpt(cl, "files")); if (files != null) { String name = c.getName().replace('.', '/') + ".class"; for (File location : files) if (dirOrZipContainsPath(location, name)) return location; throw fail(name + " not found in: " + files); } return null; } static public File byteCodePathForClass(Object o) { return byteCodePathForClass(_getClass(o)); } static public List itemPlusList(A a, Collection l) { return concatLists(ll(a), l); } static public List endingWith_dropSuffix(Collection l, String suffix) { List out = new ArrayList(); for (String s : unnullForIteration(l)) if (endsWith(s, suffix)) out.add(dropLast(l(suffix), s)); return out; } static public List endingWith_dropSuffix(String suffix, Collection l) { return endingWith_dropSuffix(l, suffix); } static public List standardImports_cache; static public List standardImports() { if (standardImports_cache == null) standardImports_cache = standardImports_load(); return standardImports_cache; } static public List standardImports_load() { return ll("java.util.*", "java.util.zip.*", "java.util.List", "java.util.regex.*", "java.util.concurrent.*", "java.util.concurrent.atomic.*", "java.util.concurrent.locks.*", "java.util.function.*", "javax.swing.*", "javax.swing.event.*", "javax.swing.text.*", "javax.swing.table.*", "java.io.*", "java.net.*", "java.lang.reflect.*", "java.lang.ref.*", "java.lang.management.*", "java.security.*", "java.security.spec.*", "java.awt.*", "java.awt.event.*", "java.awt.image.*", "java.awt.geom.*", "javax.imageio.*", "java.math.*", "java.time.Duration"); } static public List classNamesInJarOrDir(File dir) { return classNamesInJarOrDir(dir, ""); } static public List classNamesInJarOrDir(File dir, String prefixInJar) { List classes = new ArrayList(); if (dir == null) { } else if (dir.isDirectory()) { for (File f : listFiles(dir)) { String s = f.getName(); if (s.endsWith(".class")) classes.add(dropSuffix(".class", s)); } } else if (dir.isFile()) { try { JarFile jarFile = new JarFile(dir); try { Enumeration e = jarFile.entries(); while (e.hasMoreElements()) { JarEntry je = e.nextElement(); if (je.isDirectory() || je.getName().startsWith("META-INF/") || !je.getName().endsWith(".class")) continue; String className = dropSuffix(".class", je.getName()); className = dropPrefixOrNull(prefixInJar, className); if (className == null) continue; if (className.contains("-")) continue; className = className.replace('/', '.'); classes.add(className); } } finally { jarFile.close(); } } catch (Throwable __e) { printStackTrace(__e); } } return classes; } static public List classNamesInLoadedJigsawModules() { return concatMap(loadedJigsawModuleNames(), moduleName -> classNamesInJigsawModule(moduleName)); } static volatile public int numberOfCores_value; static public int numberOfCores() { if (numberOfCores_value == 0) numberOfCores_value = Runtime.getRuntime().availableProcessors(); return numberOfCores_value; } static public int random(int n) { return random(n, defaultRandomGenerator()); } static public int random(int n, Random r) { return random(r, n); } static public int random(Random r, int n) { return n <= 0 ? 0 : getRandomizer(r).nextInt(n); } static public double random(double max) { return random() * max; } static public double random() { return defaultRandomGenerator().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 Chain chainPlus(Chain chain, A a) { return new Chain(a, chain); } static public Chain chainPlus(Chain chain, A... l) { for (A a : unnullForIteration(l)) chain = chainPlus(chain, a); return chain; } static public ReverseChain chainPlus(ReverseChain chain, A a) { return new ReverseChain(chain, a); } static public ReverseChain chainPlus(ReverseChain chain, A... l) { for (A a : unnullForIteration(l)) chain = chainPlus(chain, a); return chain; } static public AppendableChain chainPlus(AppendableChain chain, A a) { if (chain == null) return new AppendableChain(a); chain.add(a); return chain; } static public AppendableChain chainPlus(AppendableChain chain, A... l) { for (A a : unnullForIteration(l)) chain = chainPlus(chain, a); return chain; } static public void syncNotifyAll(Object o) { if (o != null) synchronized (o) { o.notifyAll(); } } static public Type getRawType(Type t) { if (t instanceof ParameterizedType) return ((ParameterizedType) t).getRawType(); return t; } 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 org.apache.bcel.generic.Type typeToBCELType(Type t) { return classToBCELType(getRawTypeClass(t)); } static public String typeToVMSignature(Type t) { Class c = getRawTypeClass(t); if (t instanceof ParameterizedType) { List args = map(__97 -> getRawTypeClass(__97), ((ParameterizedType) t).getActualTypeArguments()); if (nempty(args)) return classNameToByteCodeFormat(c) + "<" + joinMap(args, arg -> classNameToByteCodeFormat(arg) + ";") + ">;"; } return classNameToByteCodeFormat(c) + ";"; } static public org.apache.bcel.generic.Type classToBCELType(Class c) { if (c == null) return null; if (isPrimitiveType(c)) { if (c == byte.class) return org.apache.bcel.generic.Type.BYTE; if (c == char.class) return org.apache.bcel.generic.Type.BYTE; if (c == short.class) return org.apache.bcel.generic.Type.BYTE; if (c == int.class) return org.apache.bcel.generic.Type.INT; if (c == long.class) return org.apache.bcel.generic.Type.LONG; if (c == double.class) return org.apache.bcel.generic.Type.DOUBLE; if (c == void.class) return org.apache.bcel.generic.Type.VOID; if (c == boolean.class) return org.apache.bcel.generic.Type.BOOLEAN; throw fail("TODO: classToBCELType " + c); } if (isArrayType(c)) { int dimensions = 0; while (c.isArray()) { ++dimensions; c = c.componentType(); } return new ArrayType(classToBCELType(c), dimensions); } return new ObjectType(className(c)); } static public Object[] repArray(Object a, int n) { return arrayrep(a, n); } static public A[] repArray(Class type, A a, int n) { return arrayrep(type, a, n); } static public void register(Concept c) { registerConcept(c); } 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 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 replaceDollarVars(String s, Object... params) { if (empty(params)) return s; Map vars = mapKeys(__98 -> dropDollarPrefix(__98), (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 linesLL(Object... x) { return lines(ll(x)); } static public long stepAll(Steppable s) { long steps = 0; if (s != null) { var pingSource = pingSource(); while (true) { ping(pingSource); if (s.step()) ++steps; else break; } } return steps; } static public A nextToLast(List l) { return get(l, l(l) - 2); } static public boolean eqOrEqic(boolean caseInsensitive, String a, String b) { return caseInsensitive ? eqic(a, b) : eq(a, b); } static public boolean containsLineBreak(String s) { return containsNewLine(s); } 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 Map> toMap(MultiMap m) { return multiMapToMap(m); } static public String plural(String s) { return getPlural(s); } static public RuntimeException unimplemented() { throw fail("TODO"); } static public RuntimeException unimplemented(String msg) { throw fail("TODO: " + msg); } static public RuntimeException unimplemented(Object obj) { throw fail("TODO: implement method in " + className(obj)); } static public String spanTitle(String title, Object contents) { return empty(title) ? str(contents) : span(contents, "title", title); } static public String humanizeLabel(String s) { return humanizeFormLabel(s); } static public String h1_title(String s) { return htitle_h1(s); } 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 htmlEncode_nlToBr(String s) { return nlToBr(htmlEncode2(s)); } static public String pUnlessEmpty(String s, Object... __) { return empty(s) ? "" : p(s, __); } static public long waitForBotStartUp_timeoutSeconds = 60; static public String waitForBotStartUp(String botName) { for (int i = 0; i < waitForBotStartUp_timeoutSeconds; i++) { sleepSeconds(i == 0 ? 0 : 1); String addr = getBotAddress(botName); if (addr != null) return addr; } throw fail("Bot not found: " + quote(botName)); } static public Object rpc(String botName, String method, Object... args) { return unstructure_matchOK2OrFail(sendToLocalBot(botName, rpc_makeCall(method, args))); } static public Object rpc(DialogIO bot, String method, Object... args) { return unstructure_matchOK2OrFail(bot.ask(rpc_makeCall(method, args))); } static public String rpc_makeCall(String method, Object... args) { if (empty(args)) return "call " + method; return format("call *", concatLists((List) ll(method), asList(args))); } static public void close(AutoCloseable c) { _close(c); } static public Boolean not(Boolean b) { return b == null ? null : !b; } static public boolean step(Steppable steppable) { return steppable == null ? null : steppable.step(); } static public Timestamp tsNow() { return new Timestamp(); } static public int seconds() { return seconds(java.util.Calendar.getInstance()); } static public int seconds(java.util.Calendar c) { return c.get(java.util.Calendar.SECOND); } static public String joinNemptiesWithComma(Object... strings) { return joinNempties(", ", strings); } static public String joinNemptiesWithComma(Iterable strings) { return joinNempties(", ", strings); } static public long incAtomicLong(AtomicLong l) { return l.incrementAndGet(); } static public PingSource pingSource() { return pingSource_tl().get(); } static public PingSource pingSource(Thread thread) { return pingSource_tl().get(thread); } static public boolean preciseNuObject_debug = false; static public A preciseNuObject(Class c, Object... args) { try { Constructor[] methods = getDeclaredConstructors_cached(c); if (methods.length == 0) throw fail(c + " doesn't define any constructors"); return preciseNuObject(methods, args); } catch (Exception __e) { throw rethrow(__e); } } static public A preciseNuObject(Constructor[] methods, Object... args) { try { Constructor best = null; int bestScore = Integer.MAX_VALUE; boolean widening = false; if (preciseNuObject_debug) printVars("preciseNuObject", "c", first(methods).getDeclaringClass(), "methods", l(methods)); for (var m : methods) { int score = methodApplicabilityScore_withPrimitiveWidening(m, args); if (score == 0) return (A) m.newInstance(args); if (preciseNuObject_debug) print("Method score: " + m + " " + score); if (abs(score) < bestScore) { best = m; bestScore = abs(score); widening = score < 0; } } if (best != null) if (widening) return (A) invokeConstructorWithWidening(best, args); else return (A) best.newInstance(args); methodSearch: for (var m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return (A) m.newInstance(newArgs); } var c = first(methods).getDeclaringClass(); throw fail("No matching constructor found: " + formatFunctionCall(c, map(__99 -> _getClass(__99), args))); } catch (Exception __e) { throw rethrow(__e); } } static public Object[] mapToArrayOrNull(A[] l, IF1 f) { if (l == null) return null; int n = l.length; if (n == 0) return null; Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = f.get(l[i]); return array; } static public Object[] mapToArrayOrNull(IF1 f, A[] l) { return mapToArrayOrNull(l, f); } static public Object[] mapToArrayOrNull(IF1 f, Collection l) { int n = l(l); if (n == 0) return null; 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[] mapToArrayOrNull(Collection l, IF1 f) { return mapToArrayOrNull(l, f); } static public String formatFunctionCall(String fname, Object... args) { return formatFunctionCall((Object) fname, args); } static public String formatFunctionCall(Object fname, Object... args) { return fname + "(" + joinWithComma(allToString(args)) + ")"; } static public String formatFunctionCall(String fname, Iterable args) { return formatFunctionCall((Object) fname, args); } static public String formatFunctionCall(Object fname, Iterable args) { return formatFunctionCall(fname, toObjectArray(args)); } static public String strOrClassName(Object o) { if (o instanceof Class) return className((Class) o); return str(o); } static public String toStringWithClass(Object o) { return o == null ? null : className(o) + " - " + o; } static public boolean newPreciseCall_debug = false; static public Object newPreciseCall(Object o, String method, Object... args) { try { if (o == null) return null; boolean staticCall = o instanceof Class; Class c = staticCall ? (Class) o : o.getClass(); Object target = staticCall ? null : o; _MethodCache cache = callOpt_getCache(c); List methods = cache.cache.get(method); Method best = null; int bestScore = Integer.MAX_VALUE; boolean widening = false; if (newPreciseCall_debug) printVars("newPreciseCall", "method", method, "staticCall", staticCall, "c", c, "methods", l(methods)); if (methods != null) for (Method m : methods) { if (staticCall && !isStaticMethod(m)) continue; int score = methodApplicabilityScore_withPrimitiveWidening(m, args); if (score == 0) return invokeMethod(m, target, args); if (newPreciseCall_debug) print("Method score: " + m + " " + score); if (abs(score) < bestScore) { best = m; bestScore = abs(score); widening = score < 0; } } if (best != null) if (widening) return invokeMethodWithWidening(best, target, args); else return invokeMethod(best, target, args); return callWithVarargs(o, method, args); } catch (Exception __e) { throw rethrow(__e); } } static public List findMethodsNamed_cached(Object obj, String method) { return findMethodsNamed_cached(_getClass(obj), method); } static public List findMethodsNamed_cached(Class c, String method) { if (c == null) return null; return getMethodCache(c).cache.get(method); } static public Pair findMethod_withPrimitiveWidening_onTypes(Object o, String method, Class... argTypes) { try { Lowest best = new Lowest(); boolean widening = false; 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))) continue; } int score = methodApplicabilityScore_withPrimitiveWidening_onTypes(m, argTypes); if (abs(score) < Integer.MAX_VALUE) { best.put(m, abs(score)); widening = score < 0; } } return pair(best.get(), widening); } if (o == null) return null; _MethodCache cache = callOpt_getCache(o.getClass()); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) { int score = methodApplicabilityScore_withPrimitiveWidening_onTypes(m, argTypes); if (abs(score) < Integer.MAX_VALUE) { best.put(m, abs(score)); widening = score < 0; } } return pair(best.get(), widening); } catch (Exception __e) { throw rethrow(__e); } } static public Method findSingleInterfaceMethodOrFail(Class intrface) { Method m = findSingleInterfaceMethod(intrface); if (m == null) throw fail(intrface + " is not a single method interface"); return m; } static public A proxyFromInvocationHandler(Class intrface, InvocationHandler handler) { return (A) java.lang.reflect.Proxy.newProxyInstance(intrface.getClassLoader(), new Class[] { intrface }, handler); } static public Object handleObjectMethodsInProxyInvocationHandler(Object invocationHandler, Method implementedMethod, Method method, Object proxy, Object[] actualArgs) { String name = method.getName(); if (name.equals("hashCode")) return invocationHandler.hashCode(); if (name.equals("equals")) return proxy == actualArgs[0]; if (name.equals("toString")) return invocationHandler.toString(); throw fail("No handler for method " + method + " (only have " + implementedMethod + ")"); } static public Object[] concatMethodArgs(Object[] args1, Object[] args2) { int n1, n2; if (args1 == null || (n1 = args1.length) == 0) return args2; if (args2 == null || (n2 = args2.length) == 0) return args1; Object[] args = new Object[n1 + n2]; for (int i = 0; i < n1; i++) args[i] = args1[i]; for (int i = 0; i < n2; i++) args[n1 + i] = args2[i]; return args; } static public Object invokeMethodWithWidening(Method m, Object o, Object... args) { try { try { Class[] types = m.getParameterTypes(); int n = types.length; Object[] args2 = new Object[n]; for (int i = 0; i < n; i++) args2[i] = convertPrimitiveIfNecessary(args[i], types[i]); return m.invoke(o, args2); } 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 Iterator iterator_gen(Object o) { if (o == null) return emptyItIt(); if (o instanceof Iterator) return ((Iterator) o); if (o instanceof Iterable) return ((Iterable) o).iterator(); if (o instanceof Object[]) return arrayIterator((Object[]) o); throw fail("Not iterable: " + className(o)); } static public class mapI_It extends IterableIterator { public Object f; public Iterator i; public mapI_It() { } public mapI_It(Object f, Iterator i) { this.i = i; this.f = f; } public boolean hasNext() { return i.hasNext(); } public Object next() { return callF(f, i.next()); } public String toString() { return formatFunctionCall("mapI", f, i); } } static public IterableIterator mapI(final Object f, final Iterator i) { return new mapI_It(f, i); } static public IterableIterator mapI(IterableIterator i, Object f) { return mapI((Iterator) i, f); } static public IterableIterator mapI(Object f, IterableIterator i) { return mapI((Iterator) i, f); } static public IterableIterator mapI(Iterator i, Object f) { return mapI(f, i); } static public IterableIterator mapI(Iterable i, IF1 f) { return new MapI(f, iterator(i)); } static public IterableIterator mapI(Iterator i, IF1 f) { return new MapI(f, i); } static public IterableIterator mapI(IterableIterator i, IF1 f) { return new MapI(f, i); } static public IterableIterator mapI(IF1 f, Iterable i) { return new MapI(f, iterator(i)); } static public IterableIterator mapI(Iterable i, Object f) { return mapI(f, i.iterator()); } static public IterableIterator mapI(Object f, Iterable i) { return mapI(i, f); } static public > IterableIterator nestedIterator(Iterable c, final F1 makeInnerIterator) { return nestedIterator(iterator(c), makeInnerIterator); } static public > IterableIterator nestedIterator(Iterable c, IF1 makeInnerIterator) { return nestedIterator(iterator(c), makeInnerIterator); } static public > IterableIterator nestedIterator(IterableIterator c, IF1 makeInnerIterator) { return nestedIterator((Iterator) c, makeInnerIterator); } static public > IterableIterator nestedIterator(Iterator it1, IF1 makeInnerIterator) { if (it1 == null || !it1.hasNext()) return emptyItIt(); return iff(new F0() { public A a; public Iterator innerIterator; { nextOuter(); } public void nextOuter() { a = it1.next(); innerIterator = makeInnerIterator.get(a); } public Object get() { while (true) { ping(); if (innerIterator != null && innerIterator.hasNext()) return innerIterator.next(); if (!it1.hasNext()) return endMarker(); nextOuter(); } } }); } static public > IterableIterator nestedIterator(final Iterator it1, F1 makeInnerIterator) { if (it1 == null || !it1.hasNext()) return emptyItIt(); return iff(new F0() { public A a; public Iterator innerIterator; { nextOuter(); } public void nextOuter() { a = it1.next(); innerIterator = makeInnerIterator.get(a); } public Object get() { while (true) { ping(); if (innerIterator != null && innerIterator.hasNext()) return innerIterator.next(); if (!it1.hasNext()) return endMarker(); nextOuter(); } } }); } static public > IterableIterator nestedIterator(IF1 makeInnerIterator, Iterator it1) { return nestedIterator(it1, makeInnerIterator); } static public > IterableIterator nestedIterator(IF1 makeInnerIterator, Collection l) { return nestedIterator(l, makeInnerIterator); } static public String struct(Object o) { return structure(o); } static public String struct(Object o, structure_Data data) { return structure(o, data); } static public List structTok(String s) { return javaTok_noMLS(s); } static public String shortName(Object o) { return shortClassName(o); } static public String indentStructureString(String s) { return indentStructureString(100, s); } static public String indentStructureString(int levels, String s) { if (s == null) return null; return new StructureStringIndenter().levels(levels).get(s); } static public int getWidth(Component c) { return c == null ? 0 : (int) swingCall(c, "getWidth"); } static public int getHeight(Component c) { return c == null ? 0 : (int) swingCall(c, "getHeight"); } 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 long longMul(long a, long b) { return a * b; } static public double floor(double d) { return Math.floor(d); } static public Constructor findConstructor_precise_onTypes(Class c, Class... argTypes) { try { List ctors = constructorsWithNumberOfArguments(c, l(argTypes)); Lowest best = new Lowest(); if (ctors != null) for (Constructor ctor : ctors) { int score = methodApplicabilityScore_onTypes(ctor, argTypes); if (score < Integer.MAX_VALUE) best.put(ctor, score); } return best.get(); } catch (Exception __e) { throw rethrow(__e); } } static public Method findNonStaticMethod_precise_onTypes(Object o, String method, Class... argTypes) { try { Class c = _getClass(o); if (c == null) return null; _MethodCache cache = callOpt_getCache(c); List methods = cache.cache.get(method); Lowest best = new Lowest(); if (methods != null) for (Method m : methods) { { if (isStaticMethod(m)) continue; } int score = methodApplicabilityScore_onTypes(m, argTypes); if (score < Integer.MAX_VALUE) best.put(m, score); } return best.get(); } catch (Exception __e) { throw rethrow(__e); } } static public Method mostApplicableMethod_onTypes(Iterable methods, Class... argTypes) { Lowest best = new Lowest(); if (methods != null) for (Method m : methods) { int score = methodApplicabilityScore_onTypes(m, argTypes); if (score < Integer.MAX_VALUE) best.put(m, score); } return best.get(); } static public Map nonDefaultInterfaceMethods_cache = newDangerousWeakHashMap(); static public Method[] nonDefaultInterfaceMethods(Class c) { Method[] methods; synchronized (nonDefaultInterfaceMethods_cache) { methods = nonDefaultInterfaceMethods_cache.get(c); if (methods == null) nonDefaultInterfaceMethods_cache.put(c, methods = toTypedArray(Method.class, findNonDefaultInterfaceMethods(c))); } return methods; } static public Method findMethod_precise_onTypes(Object o, String method, Class... argTypes) { try { if (o instanceof Class) { _MethodCache cache = callOpt_getCache((Class) o); List methods = cache.cache.get(method); Lowest best = new Lowest(); if (methods != null) for (Method m : methods) { { if (!(isStaticMethod(m))) continue; } int score = methodApplicabilityScore_onTypes(m, argTypes); if (score < Integer.MAX_VALUE) best.put(m, score); } return best.get(); } if (o == null) return null; _MethodCache cache = callOpt_getCache(o.getClass()); List methods = cache.cache.get(method); Lowest best = new Lowest(); if (methods != null) for (Method m : methods) { int score = methodApplicabilityScore_onTypes(m, argTypes); if (score < Integer.MAX_VALUE) best.put(m, score); } return best.get(); } catch (Exception __e) { throw rethrow(__e); } } static public AutoCloseable tempSet(Object o, final String field, Object value) { return tempSetField(o, field, value); } static public Map putOrCreateSyncMap(Map map, A key, B value) { if (map == null) map = syncHashMap(); map.put(key, value); return map; } static public AutoCloseable tempPut(Map map, A key, B value) { if (map != null) { boolean wasContained = map.containsKey(key); B old = map.put(key, value); return () -> { if (wasContained) map.put(key, old); else map.remove(key); }; } return null; } 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 String nlLogic_text(Exp e) { return e == null ? null : e.text(); } static public String nlLogic_text(IfThen r) { return r == null ? null : r.text(); } static public AtomicLong randomClassName_counter = new AtomicLong(); static public String randomClassName() { return "UserCode" + inc(randomClassName_counter); } static public A print_tabToSingleSpace(A o) { print(tabToSingleSpace(str(o))); return o; } static public ClassLoader myClassLoader() { return _getClass(mc()).getClassLoader(); } static public A newInstance(Class c, Object... args) { return nuObject(c, args); } static public Object newInstance(String className, Object... args) { return nuObject(className, args); } static public String ok(Object o) { return format("ok *", o); } 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 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) { printStackTrace(__e); } } } static public boolean canCallWithVarargs(Object o, String method, Object... args) { if (o == null) return false; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); if (cache.findStaticMethod(method, args) != null) return true; List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs() && isStaticMethod(m))) continue; } if (massageArgsForVarArgsCall(m, args) != null) return true; } } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); if (cache.findMethod(method, args) != null) return true; List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } if (massageArgsForVarArgsCall(m, args) != null) return true; } } return false; } static public int lKeys(MultiMap mm) { return mm == null ? 0 : mm.keysSize(); } static public IF0 ping_v3_pingSourceMaker_cache; static public IF0 ping_v3_pingSourceMaker() { if (ping_v3_pingSourceMaker_cache == null) ping_v3_pingSourceMaker_cache = ping_v3_pingSourceMaker_load(); return ping_v3_pingSourceMaker_cache; } static public IF0 ping_v3_pingSourceMaker_load() { return or((IF0) vm_generalMap_get("ping_v3_pingSourceMaker"), () -> null); } 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 String dropNumberPrefix(String s) { return dropFirst(s, indexOfNonDigit(s)); } static public void readLocally(String progID, String varNames) { readLocally2(mc(), progID, varNames); } static public void readLocally(String varNames) { readLocally2(mc(), programID(), varNames); } static public void readLocally2(Object obj, String varNames) { readLocally2(obj, programID(), varNames); } static public int readLocally_stringLength; static public ThreadLocal readLocally2_allDynamic = new ThreadLocal(); static public ThreadLocal readLocally2_classFinder = new ThreadLocal(); static public void readLocally2(Object obj, String progID, String varNames) { try { boolean allDynamic = isTrue(getAndClearThreadLocal(readLocally2_allDynamic)); for (String variableName : javaTokC(varNames)) { File textFile = new File(programDir(progID), variableName + ".text"); String value = loadTextFile(textFile); if (value != null) set(main.class, variableName, value); else { File structureFile = new File(programDir(progID), variableName + ".structure"); value = loadTextFile(structureFile); if (value == null) { File structureGZFile = new File(programDir(progID), variableName + ".structure.gz"); if (!structureGZFile.isFile()) return; InputStream fis = new FileInputStream(structureGZFile); try { GZIPInputStream gis = newGZIPInputStream(fis); InputStreamReader reader = new InputStreamReader(gis, "UTF-8"); BufferedReader bufferedReader = new BufferedReader(reader); Object o = unstructure_tok(javaTokC_noMLS_onReader(bufferedReader), allDynamic, readLocally2_classFinder.get()); readLocally_set(obj, variableName, o); return; } finally { _close(fis); } } readLocally_stringLength = l(value); if (nempty(value)) readLocally_set(obj, variableName, unstructure(value, allDynamic, readLocally2_classFinder.get())); } } } catch (Exception __e) { throw rethrow(__e); } } static public void readLocally_set(Object c, String varName, Object value) { Object oldValue = get(c, varName); if (oldValue instanceof List && !(oldValue instanceof ArrayList) && value != null) { value = synchroList((List) value); } set(c, varName, value); } static public String conceptsFileName() { return "concepts.structure.gz"; } static public String dbProgramID() { return getDBProgramID(); } static public boolean isString(Object o) { return o instanceof String; } static public List callF_all(Collection l, Object... args) { return map(l, f -> callF(f, args)); } static public File tempFileFor(File f) { return new File(f.getPath() + "_temp"); } static public double toM_double(long l) { return l / (1024 * 1024.0); } static public boolean containsNewLine(String s) { return contains(s, '\n'); } public static String rtrimSpaces(String s) { if (s == null) return null; int i = s.length(); while (i > 0 && " \t".indexOf(s.charAt(i - 1)) >= 0) --i; return i < s.length() ? s.substring(0, i) : s; } static public String defaultTimerName_name; static public String defaultTimerName() { if (defaultTimerName_name == null) defaultTimerName_name = "A timer by " + programID(); return defaultTimerName_name; } 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 void close_pcall(AutoCloseable c) { if (c != null) { try { c.close(); } catch (Throwable __e) { printStackTrace(__e); } } } static public void preCleanUp(Object c) { if (c instanceof Collection) { for (Object o : ((Collection) c)) preCleanUp(o); return; } callOpt(c, "licensed_off"); setOpt_raw(c, "ping_anyActions", true); setOpt_raw(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) { printStackTrace(__e); } return null; } static public void interruptThreads(Collection threads) { for (Thread t : unnull(threads)) interruptThread(t); } static public void interruptThreads(Class mainClass) { interruptThreads(registeredThreads(mainClass)); } static public void retireClassLoader(ClassLoader cl) { if (isJavaXClassLoader(cl)) setOptAll(cl, "retired", true, "retiredMarker", new DefunctClassLoader()); } static public String dynamicClassName(Object o) { if (o instanceof DynamicObject && ((DynamicObject) o).className != null) return "main$" + ((DynamicObject) o).className; return className(o); } 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 String loadTextFilePossiblyGZipped(String fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static public String loadTextFilePossiblyGZipped(String fileName, String defaultContents) { File gz = new File(fileName + ".gz"); return gz.exists() ? loadGZTextFile(gz) : loadTextFile(fileName, defaultContents); } static public String loadTextFilePossiblyGZipped(File fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static public String loadTextFilePossiblyGZipped(File fileName, String defaultContents) { return loadTextFilePossiblyGZipped(fileName.getPath(), defaultContents); } static public boolean isUnstructuring() { return isTrue(getTL(dynamicObjectIsLoading_threadLocal())); } 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 String hform(Object contents, Object... params) { return htag("form", contents, params); } 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 String htmlEncode(String s) { return htmlencode(s); } static public int cmpAlphaNum(String a, String b) { return alphaNumComparator().compare(a, b); } static public List lazilyMap(IF1 f, List l) { return lazyMap((Object) f, l); } static public List lazilyMap(final Object f, final List l) { return new RandomAccessAbstractList() { final public int size = l(l); public HashMap data = new HashMap(); public int size() { return size; } public Object get(int i) { if (data.containsKey(i)) return data.get(i); Object o = callF(f, l.get(i)); data.put(i, o); return o; } }; } 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 Map mapMapToMap(IF2> f, Map m) { if (m == null) return null; Map map = similarEmptyMap(m); for (Map.Entry e : m.entrySet()) { Pair p = f.get(e.getKey(), e.getValue()); map.put(p.a, p.b); } return map; } static public Map mapMapToMap(Map m, IF2> f) { return mapMapToMap(f, m); } 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 String unicode_downPointingTriangle() { return charToString(0x25BC); } static public String unicode_upPointingTriangle() { return charToString(0x25B2); } static public Object[] litObjectArray(Object... l) { return l; } static public List dropTagsAndHTMLComments(List tok) { return dropHTMLComments(dropTags(tok)); } static public String dropTagsAndHTMLComments(String html) { return join(dropTagsAndHTMLComments(htmlTok(html))); } 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) { printStackTrace(__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 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 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 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 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 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 String stringIfTrue(boolean b, String s) { return b ? s : ""; } static public List tok_identifiersInOrder(String s) { return filter(__100 -> isIdentifier(__100), javaTokC(s)); } static public List tok_identifiersInOrder(List tok) { return filter(__101 -> isIdentifier(__101), codeTokens(tok)); } 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 String hstyle(Object contents) { return hcss(contents); } static public String unicode_smallDownPointingTriangle() { return charToString(0x25BE); } 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 ArrayList cloneListSynchronizingOn(Collection l, Object mutex) { if (l == null) return new ArrayList(); synchronized (mutex) { return new ArrayList(l); } } static public List regexpFirstGroups(String pat, String s) { if (s == null) return null; Matcher m = regexp(pat, s); return m.find() ? regexpGetGroups(m) : null; } static public List flattenCollectionsAndArrays(Iterable a) { List l = new ArrayList(); for (Object x : a) if (x instanceof Collection) l.addAll(flattenCollectionsAndArrays((Collection) x)); else if (x instanceof Object[]) l.addAll(flattenCollectionsAndArrays(asList((Object[]) x))); else l.add(x); return l; } static public double positiveInfinity() { return Double.POSITIVE_INFINITY; } static public File assertExists(File f) { if (!fileExists(f)) throw fail("File not found: " + f); return f; } static public TreeMap generalizedCIMap() { return new TreeMap(generalizedCIComparator()); } static public ListIterator emptyListIterator() { return Collections.emptyListIterator(); } static public IMeta toIMeta(Object o) { return initIMeta(o); } static public Map makeObjectMetaMap() { return new CompactHashMap(); } static public IAutoCloseableF0 tempMetaMutex(IMeta o) { return o == null ? null : o._tempMetaMutex(); } static public void syncMapPut2(Map map, A key, B value) { if (map != null && key != null) synchronized (collectionMutex(map)) { if (value != null) map.put(key, value); else map.remove(key); } } static public A callPostProcessor(Object f, A a) { return f == null ? a : (A) callF(f, a); } static public A callPostProcessor(IF1 f, A a) { return f == null ? a : f.get(a); } static public 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 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 long getLong(Object o, String field) { return toLong(getOpt(o, field)); } static public long getLong(String field, Object o) { return getLong(o, field); } static public String[] conceptFields_gen_drop = { "className", "fieldValues", "id", "created", "_modified", "refs", "backRefs", "_concepts" }; static public Set conceptFields_gen(Object c) { return setMinus(mergeTreeSets(allNonStaticNonTransientFields(c), keys((Map) getOpt_raw(c, "fieldValues"))), conceptFields_gen_drop); } static public Set conceptFields_gen(Class c) { return setMinus(allNonStaticNonTransientFields(c), conceptFields_gen_drop); } static public List nonStaticNonTransientFieldObjects(Object o) { if (o == null) return null; List fields = new ArrayList(); Class _c = _getClass(o); do { for (Field f : _c.getDeclaredFields()) if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) fields.add(makeAccessible(f)); _c = _c.getSuperclass(); } while (_c != null); return fields; } static public List valuesList(Map map) { return cloneListSynchronizingOn(values(map), map); } static public List valuesList(MultiMap mm) { return mm == null ? emptyList() : concatLists(values(mm.data)); } static public String optCastToString(Object o) { return o instanceof String ? (String) o : null; } static public boolean swicOneOf(String s, String... l) { for (String x : l) if (swic(s, x)) return true; return false; } static public boolean swicOneOf(String s, Matches m, String... l) { for (String x : l) if (swic(s, x, m)) return true; return false; } 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 Object cloneIfList(Object o) { return o instanceof List ? cloneList((List) o) : o; } static public boolean _cSmartSetField(Concept c, String field, Object value) { try { Field f = setOpt_findField(c.getClass(), field); if (f != null && value != null) { Class actualType = f.getType(); Class type = primitiveToBoxedTypeOpt(actualType); if (type == Integer.class && !(value instanceof Integer)) { if (!setField_trueIfChanged(f, c, toInt(trimIfString(value)))) return false; if (!isTransient(f)) c.change(); return true; } if (type == Boolean.class && value instanceof String) if (actualType == Boolean.class && eq(value, "")) return _csetField(c, field, null); else return _csetField(c, field, eqicOneOf((String) value, "1", "true", "yes")); } return _csetField(c, field, value); } catch (Exception __e) { throw rethrow(__e); } } static public Object[] unrollAndExpandParams(Class c, Object[] params) { return expandParams(c, unrollParams(params)); } static public boolean cSmartSetField_withConverter(Concept c, String field, Object value) { return cSmartSetField_withConverter(c, field, value, false); } static public boolean cSmartSetField_withConverter(Concept c, String field, Object value, boolean verbose) { return cSmartSetField_withConverter(c, field, value, new DefaultValueConverterForField(), verbose); } static public boolean cSmartSetField_withConverter(Concept c, String field, Object value, ValueConverterForField converter) { return cSmartSetField_withConverter(c, field, value, converter, false); } static public boolean cSmartSetField_withConverter(Concept c, String field, Object value, ValueConverterForField converter, boolean verbose) { try { Field f = setOpt_findField(c.getClass(), field); if (f != null) { if (verbose) print("cSmartSetField_withConverter: setting " + f + " = " + value); if (converter != null && value != null) { OrError result = converter.convertValue(c, f, value); if (result == null) throw fail("Unknown conversion " + className(value) + " => " + f); if (!result.ok()) throw fail("Unknown conversion " + className(value) + " => " + f + ": " + result.error()); value = result.get(); } if (verbose) print("cSmartSetField_withConverter: converted value=" + value); if (value instanceof List && f.getType() == Concept.RefL.class) { Concept.RefL l = (Concept.RefL) (f.get(c)); if (verbose) print("cSmartSetField_withConverter: RefL=" + l); l.replaceWithList((List) value); if (verbose) print("cSmartSetField_withConverter: backrefs=" + c.backRefs); return true; } if (value instanceof Concept && f.getType() == Concept.Ref.class) return ((Concept.Ref) f.get(c)).set((Concept) value); } return _csetField(c, field, value); } catch (Exception __e) { throw rethrow(__e); } } static public Field findField2(Object o, String field) { Class c = o.getClass(); HashMap map; synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } if (map == getOpt_special) { if (o instanceof Class) return findField2_findStaticField((Class) o, field); } return map.get(field); } static public Field findField2_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static public boolean eqicOrEq(Object a, Object b) { return a instanceof String && b instanceof String ? eqic((String) a, (String) b) : eq(a, b); } static public boolean syncNempty(Collection l) { return !syncEmpty(l); } static public List scoredSearch_prepare(String query) { return map(__102 -> replacePlusWithSpace(__102), splitAtSpace(query)); } 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 List keysSortedByValuesDesc(final Map map) { List l = new ArrayList(map.keySet()); sort(l, mapComparatorDesc(map)); return l; } 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 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 long clockToSysTimeDiff() { return sysNow() - now(); } static public Complex complex(double re, double im) { return new Complex(re, im); } static public Complex complex(double re) { return new Complex(re, 0.0); } static public Complex complex(double[] reIm) { if (empty(reIm)) return null; if (l(reIm) != 2) throw fail("Need 2 doubles to make complex number"); return complex(reIm[0], reIm[1]); } static public Set syncLinkedHashSet() { return synchroLinkedHashSet(); } static public void replaceLastElement(List l, A a) { if (nempty(l)) l.set(l(l) - 1, a); } 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 renderRecordVars(String recordName, Object... params) { List l = new ArrayList(); int i = 0; for (; i + 1 < l(params); i += 2) l.add(params[i] + "=" + params[i + 1]); return formatFunctionCall(recordName, l); } 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 void copyMap(Map a, Map b) { if (a == null || b == null) return; b.clear(); b.putAll(a); } static public void printShortenedFunctionCall(Object fname, Object... args) { printShortenedFunctionCall(100, fname, args); } static public void printShortenedFunctionCall(int len, Object fname, Object... args) { print(shorten(len, formatFunctionCall(fname, args))); } static public int hexToInt(String s) { return Integer.parseInt(s, 16); } static public _MethodCache getMethodCache(Class c) { return callOpt_getCache(c); } static public void removeFromParent(final Component c) { if (c != null) { swing(() -> { Container cc = c.getParent(); if (cc != null) { cc.remove(c); revalidate(cc); } }); } } 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 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 int hashMap_internalHash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } 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 Throwable innerException(Throwable e) { return getInnerException(e); } 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 ParsedWithTokens pwt_winner(ParsedWithTokens a, ParsedWithTokens b) { return a == null ? b : b == null ? a : a.length() >= b.length() ? a : b; } static public List uniquify(Collection l) { return uniquifyList(l); } 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> lai_codeTokens(List tok) { return map(codeTokenIndices(tok), i -> new ListAndIndex(tok, i)); } static public List mapNonNulls(Iterable l, Object f) { return mapNonNulls(f, l); } static public List mapNonNulls(Object f, Iterable l) { List x = new ArrayList(); if (l != null) for (Object o : l) addIfNotNull(x, callF(f, o)); return x; } static public List mapNonNulls(Object f, Object[] l) { List x = new ArrayList(); if (l != null) for (Object o : l) addIfNotNull(x, callF(f, o)); return x; } static public List mapNonNulls(Iterable l, F1 f) { return mapNonNulls(f, l); } static public List mapNonNulls(F1 f, Iterable l) { List x = new ArrayList(); if (l != null) for (Object o : l) addIfNotNull(x, callF(f, o)); return x; } static public List mapNonNulls(A[] l, IF1 f) { return mapNonNulls(f, l); } static public List mapNonNulls(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) addIfNotNull(x, f.get(o)); return x; } static public List mapNonNulls(IF1 f, Iterable l) { return mapNonNulls(l, f); } static public IterableIterator filterI(Iterator it, F1 f) { return filterIterator(it, f); } static public IterableIterator filterI(Iterator it, IF1 f) { return filterIterator(it, f); } static public IterableIterator filterI(F1 f, Iterator it) { return filterIterator(f, it); } static public IterableIterator filterI(IF1 f, Iterator it) { return filterIterator(f, it); } static public IterableIterator filterI(IF1 f, Iterable it) { return filterIterator(f, iterator(it)); } static public boolean isBetween(long x, long min, long max) { return x >= min && x <= max; } static public boolean isBetween(double x, double min, double max) { return x >= min && x <= max; } static public IterableIterator emptyItIt() { return emptyIterableIterator(); } 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 indexOfIC(a, b, 0); } static public int indexOfIC(String[] 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 Map listIndexCI(List l) { Map map = ciMap(); for (int i = 0; i < l(l); i++) map.put(l.get(i), i); return map; } static public List englishMonthNames() { return englishMonthName_data; } static public int countPrecedingTokens(ListAndIndex l) { return l == null ? 0 : l.idx / 2; } static public IterableIterator countIterator_inclusive(final int a, final int b) { return countIterator_exclusive(a, b + 1); } static public IterableIterator countIterator_inclusive(int a, int b, IF1 f) { return countIterator_inclusive(a, b, 1, f); } static public IterableIterator countIterator_inclusive(int a, int b, int step, IF1 f) { return countIterator_inclusive_step(a, b, 1, f); } static public IterableIterator countIterator_inclusive(double a, double b, double step, IF1 f) { return countIterator_inclusive_step(a, b, step, f); } static public ParsedWithTokens pwt_raw(List tok, int iStart, int iEnd) { return new ParsedWithTokens(joinSubList(tok, iStart, iEnd), tok, iStart, iEnd); } static public int countRemainingTokens(ListAndIndex l) { return l == null ? 0 : (l.size() - l.idx) / 2; } static public void cancelThread(Thread t) { if (t == null) return; ping(); synchronized (ping_actions) { ping_actions.put(t, "cancelled"); ping_anyActions = true; } } 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 List> findContainerTagWithClass(List tok, String tag, String className) { return filter(findContainerTag(tok, tag), t -> tagHasClass(t, className)); } static public List> findContainerTagWithClass(String html, String tag, String className) { return findContainerTagWithClass(htmlTok(html), tag, className); } static public List dropFirstTwoAndLastTwo(List l) { return dropFirstAndLast(2, l); } static public void setAllToEmptyString(List l) { for (int i = 0; i < l(l); i++) l.set(i, ""); } static public List dropFirstAndLast2(int n, List l) { return dropFirstAndLast_noNewList(n, l); } static public List dropFirstAndLast2(List l) { return dropFirstAndLast_noNewList(l); } static public boolean tagHasClass(List tok, String className) { String c = tagParam(tok, "class"); return cic(splitAtSpace(c), className); } static public boolean tagHasClass(String tag, String className) { String c = tagParam(tag, "class"); return cic(splitAtSpace(c), className); } static public int parseIntOrMinus1(String s) { return empty(s) ? -1 : Integer.parseInt(s); } static public String firstIntegerString(Iterable c) { Iterator it = c.iterator(); while (it.hasNext()) { String s = it.next(); if (isInteger(s)) return s; } return null; } static public 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 int toInt_checked(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static public int identityHash(Object o) { return identityHashCode(o); } static public double msToSeconds(long ms) { return toSeconds(ms); } static public double msToSeconds(double ms) { return toSeconds(ms); } static public long fileModificationTime(File f) { return f == null ? 0 : f.lastModified(); } static public String hostToIP(String host) { try { for (InetAddress a : InetAddress.getAllByName(host)) { String ip = a.getHostAddress(); if (isIPv4(ip)) return ip; } throw fail("No IP address found for " + host); } catch (Exception __e) { throw rethrow(__e); } } 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 ClassLoader getClassLoader(Object o) { return o == null ? null : _getClass(o).getClassLoader(); } static public boolean dirOrZipContainsPath(File location, String subPath) { try { if (location.isDirectory()) { return new File(location, subPath).exists(); } else if (location.isFile()) { return zipFileContains_falseOnError(location, subPath); } return false; } catch (Exception __e) { throw rethrow(__e); } } static public List loadedJigsawModuleNames() { var moduleLayer = ModuleLayer.boot(); var modules = moduleLayer.modules(); return map(modules, mod -> mod.getName()); } static public List classNamesInJigsawModule(String moduleName) { return classNamesInJigsawModule(moduleName, javaHome()); } static public List classNamesInJigsawModule(String moduleName, File javaHome) { return classNamesInJarOrDir(jigsawModuleFile(moduleName, javaHome), "classes/"); } static public Random getRandomizer(Random r) { return r != null ? r : defaultRandomGenerator(); } static public A oneOf(List l) { if (empty(l)) return null; int n = l.size(); return n == 1 ? first(l) : l.get(defaultRandomizer().nextInt(n)); } static public char oneOf(String s) { return empty(s) ? '?' : s.charAt(random(l(s))); } static public A oneOf(A... 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 Class getRawTypeClass(Type t) { if (t instanceof ParameterizedType) return (Class) ((ParameterizedType) t).getRawType(); return (Class) t; } static public String classNameToByteCodeFormat(String className) { return "L" + className.replace('.', '/'); } static public String classNameToByteCodeFormat(Class c) { return classNameToByteCodeFormat(className(c)); } 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(A[] l, IF1 f) { return joinMap(f, l); } static public String joinMap(IF1 f, Iterable l) { return join(map(f, l)); } static public String joinMap(IF1 f, A[] l) { return join(map(f, l)); } static public String joinMap(String separator, Map map, IF2 f) { return join(separator, map(map, f)); } static public boolean isPrimitiveType(Class c) { return c != null && c.isPrimitive(); } static public Object[] arrayrep(Object a, int n) { Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = a; return array; } static public A[] arrayrep(Class type, A a, int n) { A[] array = newArray(type, n); for (int i = 0; i < n; i++) array[i] = a; return array; } 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 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 String joinNemptiesWithSemicolon(String... strings) { return joinNempties("; ", strings); } static public String joinNemptiesWithSemicolon(Collection strings) { return joinNempties("; ", strings); } 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 Map> multiMapToMap(MultiMap m) { return m == null ? null : m.data; } 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 String htitle_h1(String s) { return htitle_noEncode(dropTags(s)) + h1(s); } static public String getBotAddress(String bot) { List l = fullBotScan(bot); return empty(l) ? null : first(l).address; } static public Object unstructure_matchOK2OrFail(String s) { if (swic(s, "ok ")) return unstructure_startingAtIndex(s, 3); else throw fail(s); } static public String sendToLocalBot(String bot, String text, Object... args) { text = format3(text, args); DialogIO channel = findBot(bot); try { if (channel == null) throw fail(quote(bot) + " not found"); try { channel.readLine(); print(bot + "> " + shorten(text, 80)); channel.sendLine(text); String s = channel.readLine(); print(bot + "< " + shorten(s, 80)); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static public String sendToLocalBot(int port, String text, Object... args) { text = format3(text, args); DialogIO channel = talkTo(port); try { try { channel.readLine(); print(port + "> " + shorten(text, 80)); channel.sendLine(text); String s = channel.readLine(); print(port + "< " + shorten(s, 80)); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static public int methodApplicabilityScore_withPrimitiveWidening(Executable m, Object[] args) { Class[] types = m.getParameterTypes(); if (types.length != l(args)) return Integer.MAX_VALUE; int score = 0; boolean widenings = false; for (int i = 0; i < types.length; i++) { Object a = args[i]; Class c = types[i]; if (a == null) { if (c.isPrimitive()) return Integer.MAX_VALUE; } else { Class t = a.getClass(); int s = typeConversionScoreWithUnboxing(t, c); if (s == Integer.MAX_VALUE) return Integer.MAX_VALUE; if (s < 0) widenings = true; score += abs(s); } } return widenings ? -score : score; } static public Object invokeConstructorWithWidening(Constructor m, Object... args) { try { try { Class[] types = m.getParameterTypes(); int n = types.length; Object[] args2 = new Object[n]; for (int i = 0; i < n; i++) args2[i] = convertPrimitiveIfNecessary(args[i], types[i]); return m.newInstance(args2); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(e.getMessage() + " - was calling: " + m + ", args: " + joinWithSpace(classNames(args))); } } catch (Exception __e) { throw rethrow(__e); } } static public Object callWithVarargs(Object o, String method, Object... args) { return call_withVarargs(o, method, args); } static public int methodApplicabilityScore_withPrimitiveWidening_onTypes(Executable m, Class[] argTypes) { Class[] types = m.getParameterTypes(); if (types.length != l(argTypes)) return Integer.MAX_VALUE; int score = 0; boolean widenings = false; for (int i = 0; i < types.length; i++) { Class t = argTypes[i]; Class c = types[i]; int s = typeConversionScoreWithUnboxing(t, c); if (s == Integer.MAX_VALUE) return Integer.MAX_VALUE; if (s < 0) widenings = true; score += abs(s); } return widenings ? -score : score; } static public Method findSingleInterfaceMethod(Class intrface) { return singletonOpt(findNonDefaultInterfaceMethods(intrface)); } static public Object convertPrimitiveIfNecessary(Object o, Class b) { if (b.isPrimitive()) { if (o instanceof Character) { char x = (char) (((Character) o)); if (b == int.class) return Integer.valueOf(x); if (b == long.class) return Long.valueOf(x); if (b == float.class) return Float.valueOf(x); if (b == double.class) return Double.valueOf(x); } else if (o instanceof Number) { if (b == char.class) return Character.valueOf((char) ((Number) o).intValue()); if (b == short.class) return ((Number) o).shortValue(); if (b == int.class) return ((Number) o).intValue(); if (b == long.class) return ((Number) o).longValue(); if (b == float.class) return ((Number) o).floatValue(); } } return o; } static public IterableIterator arrayIterator(A[] l) { return l == null ? null : new IterableIterator() { public int i = 0; public boolean hasNext() { return i < l.length; } public A next() { return l[i++]; } }; } 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 Object swingCall(final Object o, final String method, final Object... args) { return swing(new F0() { public Object get() { try { return call(o, method, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "return call(o, method, args);"; } }); } static public int methodApplicabilityScore_onTypes(Method m, Class[] argTypes) { return methodApplicabilityScore_onTypes((Executable) m, argTypes); } static public int methodApplicabilityScore_onTypes(Executable m, Class[] argTypes) { Class[] types = m.getParameterTypes(); if (types.length != argTypes.length) return Integer.MAX_VALUE; int score = 0; for (int i = 0; i < types.length; i++) { Class a = argTypes[i]; Class c = types[i]; if (c == a) { } else if (isSubclassOf(a, c)) ++score; else return Integer.MAX_VALUE; } return score; } static public List findNonDefaultInterfaceMethods(Class intrface) { if (!isInterface(intrface)) return null; List l = new ArrayList(); _MethodCache cache = getMethodCache(intrface); Class c = intrface; do { for (Method m : c.getDeclaredMethods()) if (m.getDeclaringClass() != Object.class && !m.isDefault() && !isStaticMethod(m)) l.add(m); c = c.getSuperclass(); } while (c != null); return l; } static public AutoCloseable tempSetField(Object o, String field, Object value) { final Object oldValue = get(o, field); set(o, field, value); return () -> set(o, field, oldValue); } static public AutoCloseable tempSetField(ISetAndGet gs, A value) { if (gs == null) return null; A oldValue = gs.get(); gs.set(value); return () -> gs.set(oldValue); } static public AutoCloseable tempSetField(A value, ISetAndGet gs) { return tempSetField(gs, value); } 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 int inc(AtomicInteger i) { return incAtomicInt(i); } static public int inc(AtomicInteger i, int delta) { return incAtomicInt(i, delta); } static public long inc(AtomicLong l) { return incAtomicLong(l); } static public long inc(AtomicLong l, long b) { return l.addAndGet(b); } static public int inc(IntVar v) { synchronized (v) { int val = v.get() + 1; v.set(val); return val; } } static public int inc(int i) { return i + 1; } static public long inc(long l) { return l + 1; } static public String tabToSingleSpace(String s) { return replace(s, '\t', ' '); } static public List englishMonthName_data = ll("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); static public String englishMonthName(int nr) { return get(englishMonthName_data, nr - 1); } 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 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 AutoCloseable tempActivity(Object r) { return null; } static public long fixTimestamp(long timestamp) { return timestamp > now() ? 0 : timestamp; } 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 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 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) { printStackTrace(__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 String loadGZTextFile(File file) { try { if (!file.isFile()) return null; ping(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream fis = new FileInputStream(file); try { GZIPInputStream gis = newGZIPInputStream(fis); byte[] buffer = new byte[1024]; int len; while ((len = gis.read(buffer)) != -1) baos.write(buffer, 0, len); baos.close(); return fromUtf8(baos.toByteArray()); } finally { _close(fis); } } catch (Exception __e) { throw rethrow(__e); } } static public Object getTL(Object o, String name) { return getThreadLocal(o, name); } static public A getTL(ThreadLocal tl) { return getThreadLocal(tl); } static public A getTL(ThreadLocal tl, A defaultValue) { return getThreadLocal(tl, defaultValue); } static public AlphanumComparator alphaNumComparator_instance; static public Comparator alphaNumComparator() { if (alphaNumComparator_instance == null) alphaNumComparator_instance = new AlphanumComparator(); return alphaNumComparator_instance; } 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 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 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 padList(List l, int w) { return padList(l, w, null); } static public List padList(List l, int w, A a) { if (l(l) >= w) return l; List x = cloneList(l); while (l(x) < w) x.add(a); return x; } static public A getOrKeep(Map map, A a) { if (map == null) return a; A v = map.get(a); return v != null ? v : a; } static public 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 htd(Object contents, Object... params) { return htag("td", contents, params); } static public List codeTokens(List tok) { return codeTokensOnly(tok); } static public List regexpGetGroups(Matcher matcher) { int n = matcher.groupCount(); List l = new ArrayList(); for (int i = 1; i <= n; i++) l.add(matcher.group(i)); return l; } static public List regexpGetGroups(String pat, String s) { Matcher m = regexpMatcher(pat, s); if (m.find()) return regexpGetGroups(m); return null; } 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 Collection concatCollections_conservative(Collection a, Collection b) { if (empty(a)) return b; if (empty(b)) return a; return concatLists(a, b); } static public Set setMinus(Set set, Object... stuff) { Set s2 = cloneSet(set); for (Object o : stuff) s2.remove(o); return s2; } static public Set mergeTreeSets(Collection... l) { TreeSet set = new TreeSet(); for (Collection o : l) if (o != null) set.addAll(o); return set; } 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 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 Class primitiveToBoxedTypeOpt(Class type) { return or(primitiveToBoxedType(type), type); } static public boolean setField_trueIfChanged(Field f, Object o, Object value) { try { if (eq(f.get(o), value)) return false; f.set(o, value); return true; } catch (Exception __e) { throw rethrow(__e); } } static public Object trimIfString(Object o) { return o instanceof String ? trim((String) o) : o; } static public boolean syncEmpty(Collection l) { if (l == null) return true; synchronized (l) { return l.isEmpty(); } } static public String replacePlusWithSpace(String s) { return replace(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 Set synchroLinkedHashSet() { return synchronizedSet(new CompactLinkedHashSet()); } static public String hijackPrint(Runnable r) { StringBuilder buf = new StringBuilder(); Object old = interceptPrintInThisThread(new F1() { public Boolean get(String s) { buf.append(s); return false; } }); try { { if (r != null) r.run(); } return str(buf); } finally { interceptPrintInThisThread(old); } } static public boolean containsNewLines(String s) { return containsNewLine(s); } static public String jlabel_textAsHTML_center(String text) { return "
" + replace(htmlencode2(text), "\n", "
") + "
"; } 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 Map weakHashMap() { return newWeakHashMap(); } static public int hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static public int hashCode(long l) { return Long.hashCode(l); } static public int hashCode(double d) { return Double.hashCode(d); } 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 IterableIterator codeTokenIndices(List tok) { return countIterator_exclusive_step(1, l(tok) & ~1, 2); } static public IterableIterator filterIterator(final Iterator it, final F1 f) { if (it == null) return null; return iff(new F0() { public Object get() { try { while (it.hasNext()) { A a = it.next(); if (callF(f, a)) return a; } return endMarker(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "while (it.hasNext()) {\r\n A a = it.next();\r\n if (callF(f, a))\r\n ..."; } }); } static public IterableIterator filterIterator(final Iterator it, final IF1 f) { if (it == null) return null; return iff(new F0() { public Object get() { try { while (it.hasNext()) { A a = it.next(); if (callF(f, a)) return a; } return endMarker(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "while (it.hasNext()) {\r\n A a = it.next();\r\n if (callF(f, a))\r\n ..."; } }); } static public IterableIterator filterIterator(final F1 f, final Iterator it) { return filterIterator(it, f); } static public IterableIterator filterIterator(Collection l, IF1 f) { if (l == null) return null; Iterator it = iterator(l); return iff(new F0() { public Object get() { try { while (it.hasNext()) { A a = it.next(); if (f.get(a)) return a; } return endMarker(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "while (it.hasNext()) {\r\n A a = it.next();\r\n if (f.get(a))\r\n ..."; } }); } static public IterableIterator filterIterator(IF1 f, Iterator it) { return filterIterator(it, f); } static public IterableIterator emptyIterableIterator_instance = new IterableIterator() { public Object next() { throw fail(); } public boolean hasNext() { return false; } }; static public IterableIterator emptyIterableIterator() { return emptyIterableIterator_instance; } static public IterableIterator countIterator_exclusive(int b) { return countIterator_exclusive(0, b); } static public IterableIterator countIterator_exclusive(int a, int b) { return new IterableIterator() { public int i = a; public boolean hasNext() { return i < b; } public Integer next() { return i++; } }; } static public IterableIterator countIterator_exclusive(int b, IF1 f) { return countIterator_exclusive(0, b, f); } static public IterableIterator countIterator_exclusive(int a, int b, IF1 f) { return mapI_if1(f, countIterator_exclusive(a, b)); } static public IterableIterator countIterator_inclusive_step(int a, final int b, int step) { assertTrue("step > 0", step > 0); return new IterableIterator() { public int i = a; public boolean hasNext() { return i <= b; } public Integer next() { var j = i; i += step; return j; } }; } static public IterableIterator countIterator_inclusive_step(double a, double b, double step) { assertTrue("step > 0", step > 0); return new IterableIterator() { public double i = a; public boolean hasNext() { return i <= b; } public Double next() { var j = i; i += step; return j; } }; } static public IterableIterator countIterator_inclusive_step(double a, double b, double step, IF1 f) { return mapI_if1(f, countIterator_inclusive_step(a, b, step)); } static public IterableIterator countIterator_inclusive_step(int a, int b, int step, IF1 f) { return mapI_if1(f, countIterator_inclusive_step(a, b, step)); } static public List dropFirstAndLast_noNewList(int n, List l) { return subList(l, n, l(l) - n); } static public List dropFirstAndLast_noNewList(List l) { return dropFirstAndLast_noNewList(1, l); } static public String tagParam(String tag, String key) { return getHtmlTagParameter(tag, key); } static public String tagParam(List tok, String key) { return getHtmlTagParameter(second(tok), key); } static public int lUtf8(String s) { return l(utf8(s)); } static public String loadPage_utf8(URL url) { return loadPage_utf8(url.toString()); } static public String loadPage_utf8(String url) { AutoCloseable __1 = tempSetTL(loadPage_charset, "UTF-8"); try { return loadPage(url); } finally { _close(__1); } } static public String loadPage_utf8(URLConnection con, URL url, boolean addHeaders) throws IOException { AutoCloseable __2 = tempSetTL(loadPage_charset, "UTF-8"); try { return loadPage(con, url, addHeaders); } finally { _close(__2); } } static public boolean isIPv4(String s) { return s != null && l(javaTokC(s)) == 7 && jfind(javaTok(s), "...") == 1; } 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 boolean zipFileContains_falseOnError(File inZip, String fileName) { try { return zipFileContains(inZip, fileName); } catch (Throwable e) { return false; } } static public File javaHome() { return envJavaHome(); } static public File javaHome(String sub) { return newFile(envJavaHome(), sub); } static public File jigsawModuleFile(String moduleName) { return jigsawModuleFile(moduleName, javaHome()); } static public File jigsawModuleFile(String moduleName, File javaHome) { return new File(javaHome, "jmods/" + moduleName + ".jmod"); } static public Random defaultRandomizer() { return defaultRandomGenerator(); } static public A listGet(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static public A[] newArray(Class c, int n) { return typedArray(c, n); } 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 boolean containsSpace(String s) { return containsSpaces(s); } static public List replaceElementsUsingMap(Iterable l, final Map map) { return map(l, new F1() { public A get(A a) { try { return getOrKeep(map, a); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getOrKeep(map, a)"; } }); } static public List splitCamelCase(String s) { return ai_splitCamelCase(s); } static public String htitle_noEncode(String title) { return tag("title", title); } static public class ScannedBot implements IFieldsToList { static final public String _fieldOrder = "helloString address"; public String helloString; public String address; public ScannedBot() { } public ScannedBot(String helloString, String address) { this.address = address; this.helloString = helloString; } public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + helloString + ", " + address + ")"; } public boolean equals(Object o) { if (!(o instanceof ScannedBot)) return false; ScannedBot __1 = (ScannedBot) o; return eq(helloString, __1.helloString) && eq(address, __1.address); } public int hashCode() { int h = 1660478935; h = boostHashCombine(h, _hashCode(helloString)); h = boostHashCombine(h, _hashCode(address)); return h; } public Object[] _fieldsToList() { return new Object[] { helloString, address }; } } static public List fullBotScan() { return fullBotScan(""); } static public List fullBotScan(String searchPattern) { List bots = new ArrayList(); for (ProgramScan.Program p : quickBotScan()) { String botName = firstPartOfHelloString(p.helloString); boolean isVM = startsWithIgnoreCase(p.helloString, "This is a JavaX VM."); boolean shouldRecurse = swic(botName, "Multi-Port") || isVM; if (swic(botName, searchPattern)) bots.add(new ScannedBot(botName, "" + p.port)); if (shouldRecurse) try { Map subBots = (Map) unstructure(sendToLocalBotQuietly(p.port, "list bots")); for (Number vport : subBots.keySet()) { botName = subBots.get(vport); if (swic(botName, searchPattern)) bots.add(new ScannedBot(botName, p.port + "/" + vport)); } } catch (Exception e) { e.printStackTrace(); } } return bots; } static public Object unstructure_startingAtIndex(String s, int i) { return unstructure_tok(javaTokC_noMLS_iterator(s, i), false, null); } static public int typeConversionScoreWithUnboxing(Class a, Class b) { int score = typeConversionScore(a, b); if (score == 0 || score == 1) return score; Class aPrim = boxedToPrimitiveType(a); if (aPrim != null) { int score2 = typeConversionScore(aPrim, b); if (score2 == 0) return 1; else if (score2 != Integer.MAX_VALUE) return score2; } return score; } static public A singletonOpt(Collection l) { return l(l) == 1 ? first(l) : null; } static public A singletonOpt(A[] l) { return l(l) == 1 ? first(l) : null; } static public boolean isSubclassOf(Class a, Class b) { return isSubclass(a, b); } static public List wrapAsList(A[] a) { return wrapArrayAsList(a); } static public int incAtomicInt(AtomicInteger i) { return i.incrementAndGet(); } static public int incAtomicInt(AtomicInteger i, int delta) { return i.addAndGet(delta); } 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 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 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 ThreadLocal threadLocalWithDefault(A defaultValue) { return new ThreadLocal() { public A initialValue() { return defaultValue; } }; } 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 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 Set cloneSet(Collection set) { if (set == null) return new HashSet(); synchronized (collectionMutex(set)) { Set s = similarEmptySet(set); s.addAll(set); return s; } } 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 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 IterableIterator countIterator_exclusive_step(final int a, final int b, final int step) { assertTrue("step > 0", step > 0); return new IterableIterator() { public int i = a; public boolean hasNext() { return i < b; } public Integer next() { var j = i; i += step; return j; } }; } static public IterableIterator countIterator_exclusive_step(double a, double b, double step) { assertTrue("step > 0", step > 0); return new IterableIterator() { public double i = a; public boolean hasNext() { return i < b; } public Double next() { var j = i; i += step; return j; } }; } static public IterableIterator countIterator_exclusive_step(double a, double b, double step, IF1 f) { return mapI_if1(f, countIterator_exclusive_step(a, b, step)); } static public class mapI_if1_It extends IterableIterator { public IF1 f; public Iterator i; public mapI_if1_It() { } public mapI_if1_It(IF1 f, Iterator i) { this.i = i; this.f = f; } public boolean hasNext() { return i.hasNext(); } public B next() { return f.get(i.next()); } public String toString() { return formatFunctionCall("mapI_if1", f, i); } } static public IterableIterator mapI_if1(IF1 f, Iterable i) { return new mapI_if1_It(f, i.iterator()); } static public IterableIterator mapI_if1(Iterable i, IF1 f) { return mapI_if1(f, i); } static public String getHtmlTagParameter(String tag, String key) { return getHtmlTagParameters(tag).get(key); } static public boolean zipFileContains(File inZip, String fileName) { try { ZipFile zip = new ZipFile(inZip); try { return zipFileContains(zip, fileName); } finally { zip.close(); } } catch (Exception __e) { throw rethrow(__e); } } static public boolean zipFileContains(ZipFile zip, String fileName) { try { return zip.getEntry(fileName) != null; } catch (Exception __e) { throw rethrow(__e); } } static public File envJavaHome() { return newFile(System.getProperty("java.home")); } static public A[] typedArray(Class c, int n) { return (A[]) Array.newInstance(c, n); } 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 int typeConversionScore(Class a, Class b) { if (a == b) return 0; if (b.isPrimitive()) { if (a.isPrimitive()) { if (b == boolean.class) return Integer.MAX_VALUE; if (b == byte.class) return Integer.MAX_VALUE; if (b == char.class) return a == byte.class ? -2 : Integer.MAX_VALUE; if (b == short.class) return a == byte.class ? -2 : Integer.MAX_VALUE; if (b == int.class) return a == byte.class || a == char.class || a == short.class ? -2 : Integer.MAX_VALUE; if (b == long.class) return a == byte.class || a == char.class || a == short.class || a == int.class ? -2 : Integer.MAX_VALUE; if (b == float.class) return a == byte.class || a == char.class || a == short.class || a == int.class ? -2 : Integer.MAX_VALUE; return a != boolean.class ? -2 : Integer.MAX_VALUE; } else { return primitiveToBoxedType(b) == a ? 1 : Integer.MAX_VALUE; } } else { if (a.isPrimitive()) return primitiveToBoxedType(a) == b ? 1 : Integer.MAX_VALUE; if (!b.isAssignableFrom(a)) return Integer.MAX_VALUE; if (a.isInterface() || b.isInterface()) return 1; return subclassDistance(a, b); } } static public Class boxedToPrimitiveType(Class type) { if (type == Boolean.class) return boolean.class; if (type == Integer.class) return int.class; if (type == Long.class) return long.class; if (type == Float.class) return float.class; if (type == Short.class) return short.class; if (type == Character.class) return char.class; if (type == Byte.class) return byte.class; if (type == Double.class) return double.class; return null; } static public boolean isSubclass(Class a, Class b) { return a != null && b != null && b.isAssignableFrom(a); } static public List wrapArrayAsList(A[] a) { return a == null ? null : Arrays.asList(a); } static public String getStackTrace2(Throwable e) { return hideCredentials(getStackTrace(unwrapTrivialExceptionWraps(e)) + replacePrefix("java.lang.RuntimeException: ", "FAIL: ", hideCredentials(str(innerException2(e)))) + "\n"); } static public boolean isStringStartingWith(Object o, String prefix) { return o instanceof String && ((String) o).startsWith(prefix); } static public boolean getHtmlTagParameters_debug = false; static public Map getHtmlTagParameters(String tag) { if (empty(tag)) return null; List tok = codeTokens(tok_joinMinusIdentifiers(htmlFineTok(tag))); if (getHtmlTagParameters_debug) printStruct(tok); assertEquals("<", tok.get(0)); int i = 1; if (eq(tok.get(1), "/")) ++i; String name = tok.get(i++); if (!isMinusIdentifier(name)) throw fail(tag + " (" + name + ")"); Map map = new HashMap(); while (i < l(tok)) { String t = tok.get(i); if (eqOneOf(t, "/", ">")) break; if (!isMinusIdentifier(t)) throw fail(tag + " (" + t + ")"); ++i; String value = "1"; if (eq(tok.get(i), "=")) { ++i; value = htmlunquote(tok.get(i++)); } map.put(t, value); } return map; } static public boolean isAllUpperCase(String s) { return hasLettersAllUpperCase(s); } static public boolean isUpperCaseLetter(char c) { return Character.isUpperCase(c); } static public int subclassDistance(Class a, Class b) { int n = 0; while (a != b) { a = a.getSuperclass(); if (a == null) return Integer.MAX_VALUE; ++n; } return n; } 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 Throwable innerException2(Throwable e) { if (e == null) return null; while (empty(e.getMessage()) && e.getCause() != null) e = e.getCause(); return e; } static public List tok_joinMinusIdentifiers(List tok) { for (int i = 1; i + 4 < l(tok); i += 2) if (isMinusIdentifier(get(tok, i)) && eq(get(tok, i + 2), "-") && isIdentifier(get(tok, i + 4))) { replaceSublist(tok, i, i + 5, ll(join(subList(tok, i, i + 5)))); i -= 2; } return tok; } static public List htmlFineTok(String s) { List tok = 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 break; } tok.add(quickSubstring(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) { 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 ++j; tok.add(quickSubstring(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static public boolean isMinusIdentifier(String s) { if (empty(s)) return false; if (!Character.isJavaIdentifierStart(s.charAt(0)) && !s.startsWith("-")) return false; for (int i = 1; i < s.length(); i++) if (!Character.isJavaIdentifierPart(s.charAt(i)) && s.charAt(i) != '-') return false; return true; } static public String htmlunquote(String s) { if (s.startsWith("'") && s.endsWith("'") && s.length() >= 2 || s.startsWith("\"") && s.endsWith("\"") && s.length() >= 2) s = s.substring(1, s.length() - 1); return htmldecode(s); } static public boolean hasLettersAllUpperCase(String s) { return hasLetters(s) && !containsLowerCase(s); } 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 boolean isLowerCase(char c) { return Character.isLowerCase(c); } static public class Chain implements Iterable { public A element; public Chain next; public int size; public Chain() { } public Chain(A element) { this.element = element; size = 1; } public Chain(A element, Chain next) { this.next = next; this.element = element; size = next != null ? next.size + 1 : 1; } public String toString() { return str(toList()); } public ArrayList toList() { ArrayList l = emptyList(size); Chain c = this; while (c != null) { l.add(c.element); c = c.next; } return l; } public Iterator iterator() { return toList().iterator(); } } static public class StructureStringIndenter { final public StructureStringIndenter setLevels(int levels) { return levels(levels); } public StructureStringIndenter levels(int levels) { this.levels = levels; return this; } final public int getLevels() { return levels(); } public int levels() { return levels; } public int levels = 100; final public StructureStringIndenter setInlineChars(int inlineChars) { return inlineChars(inlineChars); } public StructureStringIndenter inlineChars(int inlineChars) { this.inlineChars = inlineChars; return this; } final public int getInlineChars() { return inlineChars(); } public int inlineChars() { return inlineChars; } public int inlineChars = 40; final public StructureStringIndenter setVerbose(boolean verbose) { return verbose(verbose); } public StructureStringIndenter verbose(boolean verbose) { this.verbose = verbose; return this; } final public boolean getVerbose() { return verbose(); } public boolean verbose() { return verbose; } public boolean verbose = false; public List tok; public Map bracketMap; public String get(String s) { if (s == null) return null; tok = javaTokForStructure(s); int n = l(tok); bracketMap = getBracketMap(tok, __1 -> isOpeningBracket(__1), __2 -> isClosingBracket(__2)); int levels = clampToInt(this.levels * 2L); StringBuilder buf = new StringBuilder(); int indent = 0; for (int i = 0; i < n; i++) { String t = tok.get(i); if (isOpeningBracket(t)) { Integer j = or(bracketMap.get(i), n); if (j != null && !tokenRangeLongerThanNChars(tok, i + 1, j + 1, inlineChars)) { buf.append(joinSubList(tok, i, j + 1)); i = j; } else { if (verbose) print("Bracket part longer than " + inlineChars + " chars: " + quote(shortenJoinSubList(inlineChars, tok, i, j + 1))); 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 class CompactHashMap extends CompactAbstractMap { final static public int INITIAL_SIZE = 3; final static public double LOAD_FACTOR = 0.6; final static public Object nullObject = new Object(); final static public Object deletedObject = new Object(); public int elements; public int freecells; public Object[] table; public CompactHashMap() { this(INITIAL_SIZE); } public CompactHashMap(int size) { table = new Object[(size == 0 ? 1 : size) * 2]; elements = 0; freecells = tableSize(); } public CompactHashMap(Map map) { this(0); if (map != null) putAll(map); } public synchronized int size() { return elements; } public synchronized boolean isEmpty() { return elements == 0; } public synchronized void clear() { elements = 0; for (int ix = 0; ix < tableSize(); ix++) { key(ix, null); value(ix, null); } freecells = tableSize(); } public synchronized boolean containsKey(Object k) { return key(findKeyIndex(k)) != null; } public synchronized boolean containsValue(Object v) { if (v == null) v = (V) nullObject; for (int ix = 0; ix < tableSize(); ix++) if (value(ix) != null && value(ix).equals(v)) return true; return false; } public synchronized Set> entrySet() { return new EntrySet(); } public synchronized V remove(Object k) { int index = findKeyIndex(k); if (key(index) != null) { V v = value(index); key(index, deletedObject); value(index, deletedObject); elements--; return v; } else return null; } public synchronized V put(K k, V v) { if (k == null) k = (K) nullObject; int hash = k.hashCode(); int index = (hash & 0x7FFFFFFF) % tableSize(); int offset = 1; int deletedix = -1; while (key(index) != null && !(key(index).hashCode() == hash && key(index).equals(k))) { if (key(index) == deletedObject) deletedix = index; index = ((index + offset) & 0x7FFFFFFF) % tableSize(); offset = offset * 2 + 1; if (offset == -1) offset = 2; } if (key(index) == null) { if (deletedix != -1) index = deletedix; else freecells--; elements++; key(index, k); value(index, v); if (1 - (freecells / (double) tableSize()) > LOAD_FACTOR) rehash(tableSize() * 2 + 1); return null; } else { V oldv = value(index); value(index, v); return oldv; } } public void rehash(int newCapacity) { int oldCapacity = tableSize(); Object[] newTable = new Object[newCapacity * 2]; for (int ix = 0; ix < oldCapacity; ix++) { Object k = key(ix); if (k == null || k == deletedObject) continue; int hash = k.hashCode(); int index = (hash & 0x7FFFFFFF) % newCapacity; int offset = 1; while (newTable[index * 2] != null) { index = ((index + offset) & 0x7FFFFFFF) % newCapacity; offset = offset * 2 + 1; if (offset == -1) offset = 2; } newTable[index * 2] = k; newTable[index * 2 + 1] = value(ix); } table = newTable; freecells = tableSize() - elements; } public synchronized V get(Object k) { return value(findKeyIndex(k)); } public synchronized Collection values() { return new ValueCollection(); } public synchronized Set keySet() { return new KeySet(); } final public int findKeyIndex(Object k) { if (k == null) k = nullObject; int hash = k.hashCode(); int index = (hash & 0x7FFFFFFF) % tableSize(); int offset = 1; while (key(index) != null && !(key(index).hashCode() == hash && key(index).equals(k))) { index = ((index + offset) & 0x7FFFFFFF) % tableSize(); offset = offset * 2 + 1; if (offset == -1) offset = 2; } return index; } public class KeySet extends AbstractSet { public int size() { synchronized (CompactHashMap.this) { return elements; } } public boolean contains(Object k) { synchronized (CompactHashMap.this) { return containsKey(k); } } public Iterator iterator() { synchronized (CompactHashMap.this) { return new KeyIterator(); } } } public class KeyIterator implements Iterator { public int ix; public KeyIterator() { synchronized (CompactHashMap.this) { for (; ix < tableSize(); ix++) if (value(ix) != null && key(ix) != deletedObject) break; } } public boolean hasNext() { synchronized (CompactHashMap.this) { return ix < tableSize(); } } public void remove() { throw new UnsupportedOperationException("Collection is read-only"); } public K next() { synchronized (CompactHashMap.this) { if (ix >= tableSize()) throw new NoSuchElementException(); K key = (K) key(ix++); for (; ix < tableSize(); ix++) if (key(ix) != null && key(ix) != deletedObject) break; return key; } } } public class EntrySet extends AbstractSet> { public int size() { synchronized (CompactHashMap.this) { return elements; } } public boolean contains(Object o) { synchronized (CompactHashMap.this) { if (o instanceof Map.Entry) { Object key = ((Map.Entry) o).getKey(); if (!containsKey((Map.Entry) o)) return false; return eq(((Map.Entry) o).getValue(), get(key)); } return false; } } public Iterator> iterator() { return new EntryIterator(); } } public class EntryIterator implements Iterator> { public int ix; public EntryIterator() { synchronized (CompactHashMap.this) { for (; ix < tableSize(); ix++) if (value(ix) != null && key(ix) != deletedObject) break; } } public boolean hasNext() { synchronized (CompactHashMap.this) { return ix < tableSize(); } } public void remove() { throw new UnsupportedOperationException("Collection is read-only"); } public Map.Entry next() { synchronized (CompactHashMap.this) { if (ix >= tableSize()) throw new NoSuchElementException(); K key = key(ix); V val = value(ix); ++ix; for (; ix < tableSize(); ix++) if (key(ix) != null && key(ix) != deletedObject) break; return simpleMapEntry(key, val); } } } public class ValueCollection extends AbstractCollection { public int size() { synchronized (CompactHashMap.this) { return elements; } } public Iterator iterator() { return new ValueIterator(); } public boolean contains(Object v) { return containsValue(v); } } public class ValueIterator implements Iterator { public int ix; public ValueIterator() { synchronized (CompactHashMap.this) { for (; ix < table.length / 2; ix++) if (value(ix) != null && value(ix) != deletedObject) break; } } public boolean hasNext() { synchronized (CompactHashMap.this) { return ix < tableSize(); } } public void remove() { throw new UnsupportedOperationException("Collection is read-only"); } public V next() { synchronized (CompactHashMap.this) { if (ix >= tableSize()) throw new NoSuchElementException(); V value = (V) value(ix++); for (; ix < tableSize(); ix++) if (value(ix) != null && value(ix) != deletedObject) break; return value; } } } public K key(int i) { return (K) table[i * 2]; } public void key(int i, Object key) { table[i * 2] = key; } public V value(int i) { return (V) table[i * 2 + 1]; } public void value(int i, Object value) { table[i * 2 + 1] = value; } public int tableSize() { return table.length / 2; } } static public class DefunctClassLoader { } static public class JS implements IF0, Htmlable { 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); } public String html() { return hjs(code); } } static public class MapI extends IterableIterator { public IF1 f; public Iterator it; public MapI(IF1 f, Iterator it) { this.it = it; this.f = f; } public boolean hasNext() { return it.hasNext(); } public B next() { return f.get(it.next()); } } static public interface ISetAndGet extends ISetter, IF0 { } abstract static public class RandomAccessAbstractList extends AbstractList implements RandomAccess { } static public class IntVar { public int a; public synchronized void set(int v) { if (v != a) { a = v; notifyAll(); } } public synchronized int get() { return a; } synchronized public int waitForValue(int x) { try { while (a != x) wait(); return a; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return str(this.get()); } } static public interface MakesBufferedImage extends WidthAndHeight { public BufferedImage getBufferedImage(); public default void drawAt(Graphics2D g, int x, int y) { g.drawImage(getBufferedImage(), x, y, null); } } 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(A 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(A o) { return (TreeSet) index.get(o); } } static public class Complex implements IFieldsToList { static final public String _fieldOrder = "re im"; public double re; public double im; public Complex() { } public Complex(double re, double im) { this.im = im; this.re = re; } public boolean equals(Object o) { if (!(o instanceof Complex)) return false; Complex __1 = (Complex) o; return re == __1.re && im == __1.im; } public int hashCode() { int h = -1679819632; h = boostHashCombine(h, _hashCode(re)); h = boostHashCombine(h, _hashCode(im)); return h; } public Object[] _fieldsToList() { return new Object[] { re, im }; } public double abs() { return sqrt(re * re + im * im); } public double re() { return re; } public double im() { return im; } final public double angle() { return phase(); } public double phase() { return Math.atan2(im, re); } public double fracAngle() { return fracNonNeg(angle() / twoPi()); } public String toString() { if (im != 0) return re == 0 ? im + "i" : re + plusPrefixUnlessMinus(str(im)) + "i"; else return str(re); } } static public class CancelPoint implements AutoCloseable { volatile public boolean closed = false; public void close() { closed = true; } } static public class CountingOutputStream extends FilterOutputStream { public long counter; public CountingOutputStream(OutputStream out) { super(out); } @Override public void write(int b) throws IOException { ++counter; out.write(b); } @Override public void write(byte[] b) throws IOException { counter += b.length; out.write(b, 0, b.length); } @Override public void write(byte[] b, int off, int len) throws IOException { if (len == 0) return; counter += len; out.write(b, off, len); } public long getFilePointer() { return counter; } } static public class DefaultValueConverterForField implements ValueConverterForField { public OrError convertValue(Object object, Field field, Object value) { Class actualType = field.getType(); Class type = primitiveToBoxedTypeOpt(actualType); if (isInstance(type, value)) return new OrError(value); if (type == Integer.class && !(value instanceof Integer)) return new OrError(toInt(trimIfString(value))); if (type == Double.class && !(value instanceof Double)) return new OrError(toDouble(trimIfString(value))); if (type == Boolean.class && value instanceof String) if (actualType == Boolean.class && eq(value, "")) return new OrError(null); else return new OrError(eqicOneOf((String) value, "1", "true", "yes")); return new OrError(value); } } static public class CancelToCancelPoint extends QuickException { public CancelPoint cp; public CancelToCancelPoint(CancelPoint cp) { this.cp = cp; } } static public class BetterThreadLocal { public Map map = newWeakHashMap(); public BetterThreadLocal() { } public BetterThreadLocal(A value) { set(value); } public boolean isSet() { return map.containsKey(currentThread()); } public A get() { if (map.containsKey(currentThread())) return map.get(currentThread()); A value = initialValue(); set(value); return value; } public A get(Thread thread) { return thread == null ? null : map.get(thread); } public void set(A a) { map.put(currentThread(), a); } public A initialValue() { return null; } } 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 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 ReverseChain implements Iterable { public A element; public ReverseChain prev; public int size; public ReverseChain() { } public ReverseChain(ReverseChain prev, A element) { this.element = element; this.prev = prev; if (prev == null) size = 1; else { prev.check(); size = prev.size + 1; } } public void check() { if (size < 1) throw fail("You called the ReverseChain default constructor. Don't do that"); } public String toString() { return str(toList()); } public ArrayList toList() { check(); ArrayList l = emptyList(size); for (int i = 0; i < size; i++) l.add(null); int i = size; ReverseChain c = this; while (c != null) { l.set(--i, c.element); c = c.prev; } return l; } public Iterator iterator() { return toList().iterator(); } } static public interface IF3 { public D get(A a, B b, C c); } 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 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() { try { cancel(); } catch (Exception __e) { throw rethrow(__e); } } } static public class T3 { public A a; public B b; public C c; public T3() { } public T3(A a, B b, C c) { this.c = c; this.b = b; this.a = a; } public T3(T3 t) { a = t.a; b = t.b; c = t.c; } public int hashCode() { return _hashCode(a) + 2 * _hashCode(b) - 4 * _hashCode(c); } public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof T3)) return false; T3 t = (T3) o; return eq(a, t.a) && eq(b, t.b) && eq(c, t.c); } public String toString() { return "(" + quoteBorderless(a) + ", " + quoteBorderless(b) + ", " + quoteBorderless(c) + ")"; } } static public class QuickException extends RuntimeException { public Throwable fillInStackTrace() { return this; } public QuickException() { } public QuickException(Throwable e) { super(e); } public QuickException(String msg) { super(msg); } public QuickException(String msg, Throwable e) { super(msg, e); } } static public interface IContentsIndexedList2 extends List { public TreeSet indicesOf_treeSetOfHasIndex(A o); } abstract static public class CompactAbstractMap implements Map { public int size() { return entrySet().size(); } public boolean isEmpty() { return size() == 0; } public boolean containsValue(Object value) { Iterator> i = entrySet().iterator(); if (value == null) { while (i.hasNext()) { Entry e = i.next(); if (e.getValue() == null) return true; } } else { while (i.hasNext()) { Entry e = i.next(); if (value.equals(e.getValue())) return true; } } return false; } public boolean containsKey(Object key) { Iterator> i = entrySet().iterator(); if (key == null) { while (i.hasNext()) { Entry e = i.next(); if (e.getKey() == null) return true; } } else { while (i.hasNext()) { Entry e = i.next(); if (key.equals(e.getKey())) return true; } } return false; } public V get(Object key) { Iterator> i = entrySet().iterator(); if (key == null) { while (i.hasNext()) { Entry e = i.next(); if (e.getKey() == null) return e.getValue(); } } else { while (i.hasNext()) { Entry e = i.next(); if (key.equals(e.getKey())) return e.getValue(); } } return null; } public V put(K key, V value) { throw new UnsupportedOperationException(); } public V remove(Object key) { Iterator> i = entrySet().iterator(); Entry correctEntry = null; if (key == null) { while (correctEntry == null && i.hasNext()) { Entry e = i.next(); if (e.getKey() == null) correctEntry = e; } } else { while (correctEntry == null && i.hasNext()) { Entry e = i.next(); if (key.equals(e.getKey())) correctEntry = e; } } V oldValue = null; if (correctEntry != null) { oldValue = correctEntry.getValue(); i.remove(); } return oldValue; } public void putAll(Map m) { for (Entry e : m.entrySet()) put(e.getKey(), e.getValue()); } public void clear() { entrySet().clear(); } public Set keySet() { return new AbstractSet() { public Iterator iterator() { return new Iterator() { public Iterator> i = entrySet().iterator(); public boolean hasNext() { return i.hasNext(); } public K next() { return i.next().getKey(); } public void remove() { i.remove(); } }; } public int size() { return CompactAbstractMap.this.size(); } public boolean isEmpty() { return CompactAbstractMap.this.isEmpty(); } public void clear() { CompactAbstractMap.this.clear(); } public boolean contains(Object k) { return CompactAbstractMap.this.containsKey(k); } }; } public Collection values() { return new AbstractCollection() { public Iterator iterator() { return new Iterator() { public Iterator> i = entrySet().iterator(); public boolean hasNext() { return i.hasNext(); } public V next() { return i.next().getValue(); } public void remove() { i.remove(); } }; } public int size() { return CompactAbstractMap.this.size(); } public boolean isEmpty() { return CompactAbstractMap.this.isEmpty(); } public void clear() { CompactAbstractMap.this.clear(); } public boolean contains(Object v) { return CompactAbstractMap.this.containsValue(v); } }; } public abstract Set> entrySet(); public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Map)) return false; Map m = (Map) o; if (m.size() != size()) return false; try { for (Entry e : entrySet()) { K key = e.getKey(); V value = e.getValue(); if (value == null) { if (!(m.get(key) == null && m.containsKey(key))) return false; } else { if (!value.equals(m.get(key))) return false; } } } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; } return true; } public int hashCode() { int h = 0; for (Entry entry : entrySet()) h += entry.hashCode(); return h; } public String toString() { Iterator> i = entrySet().iterator(); if (!i.hasNext()) return "{}"; StringBuilder sb = new StringBuilder(); sb.append('{'); for (; ; ) { Entry e = i.next(); K key = e.getKey(); V value = e.getValue(); sb.append(key == this ? "(this Map)" : key); sb.append('='); sb.append(value == this ? "(this Map)" : value); if (!i.hasNext()) return sb.append('}').toString(); sb.append(',').append(' '); } } public Object clone() throws CloneNotSupportedException { CompactAbstractMap result = (CompactAbstractMap) super.clone(); return result; } public static class SimpleEntry implements Entry, java.io.Serializable { @java.io.Serial static final public long serialVersionUID = -8499721149061103585L; @SuppressWarnings("serial") final public K key; @SuppressWarnings("serial") public V value; public SimpleEntry(K key, V value) { this.key = key; this.value = value; } public SimpleEntry(Entry entry) { this.key = entry.getKey(); this.value = entry.getValue(); } public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { V oldValue = this.value; this.value = value; return oldValue; } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Entry e = (Entry) o; return eq(key, e.getKey()) && eq(value, e.getValue()); } public int hashCode() { return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } public String toString() { return key + "=" + value; } } public static class SimpleImmutableEntry implements Entry, java.io.Serializable { @java.io.Serial static final public long serialVersionUID = 7138329143949025153L; @SuppressWarnings("serial") final public K key; @SuppressWarnings("serial") final public V value; public SimpleImmutableEntry(K key, V value) { this.key = key; this.value = value; } public SimpleImmutableEntry(Entry entry) { this.key = entry.getKey(); this.value = entry.getValue(); } public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { throw new UnsupportedOperationException(); } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Entry e = (Entry) o; return eq(key, e.getKey()) && eq(value, e.getValue()); } public int hashCode() { return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } public String toString() { return key + "=" + value; } } } 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(A o); } 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; } final public int get() { return idx; } } static public Map getBracketMap(List tok) { return getBracketMap(tok, getBracketMap_opening, getBracketMap_closing); } static public Map getBracketMap(List tok, Collection opening, Collection closing) { return getBracketMap(tok, opening, closing, 0, l(tok)); } static public Map getBracketMap(List tok, Collection opening, Collection closing, int from, int to) { TreeMap map = new TreeMap(); List stack = new ArrayList(); for (int i = from | 1; i < to; i += 2) { Object t = tok.get(i); if (opening.contains(t)) stack.add(i); else if (closing.contains(t)) if (!empty(stack)) map.put(liftLast(stack), i); } return map; } static public Map getBracketMap(List tok, IF1 opening, IF1 closing) { return getBracketMap(tok, opening, closing, 0, l(tok)); } static public Map getBracketMap(List tok, IF1 opening, IF1 closing, int from, int to) { TreeMap map = new TreeMap(); List stack = new ArrayList(); for (int i = from | 1; i < to; i += 2) { String t = tok.get(i); if (opening.get(t)) stack.add(i); else if (closing.get(t)) if (!empty(stack)) map.put(liftLast(stack), i); } return map; } static public Set getBracketMap_opening = lithashset("{", "("); static public Set getBracketMap_closing = lithashset("}", ")"); static public boolean isOpeningBracket(String s) { return eqOneOf(s, "(", "{", "["); } static public boolean isClosingBracket(String s) { return eqOneOf(s, ")", "}", "]"); } static public int clampToInt(long l) { return (int) clamp(l, Integer.MIN_VALUE, Integer.MAX_VALUE); } static public boolean tokenRangeLongerThanNChars(List tok, int iStart, int iEnd, int maxChars) { int nChars = 0, n = l(tok); iStart = Math.max(0, iStart); iEnd = Math.min(n, iEnd); for (int i = iStart; i < iEnd; i++) { nChars += l(tok.get(i)); if (nChars > maxChars) return true; } return false; } static public String shortenJoinSubList(int max, List l, int i, int j) { return shortenJoin(max, subList(l, i, j)); } static public String shortenJoinSubList(int max, List l, int i) { return shortenJoin(max, subList(l, i)); } static public String spaces(int n) { return rep(' ', n); } static public Value value(A a) { return new Value(a); } static public Map.Entry simpleMapEntry(A key, B value) { return new Map.Entry() { public A getKey() { return key; } public B getValue() { return value; } public B setValue(B newValue) { throw unimplemented(); } }; } static public String jsDollarVars(String s, Object... __) { return replaceDollarVars_js(s, __); } static public Set addToSet_create(Set set, A a) { return createOrAddToSet(set, a); } static public double fracNonNeg(double d) { return frac_nonNeg(d); } static public double twoPi() { return Math.PI * 2; } static public String plusPrefixUnlessMinus(String s) { return startsWith(s, "-") ? s : "+" + s; } 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 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 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 String quoteBorderless(Object o) { if (o == null) return "null"; return quoteBorderless(str(o)); } static public String quoteBorderless(String s) { if (s == null) return "null"; StringBuilder out = new StringBuilder((int) (l(s) * 1.5)); quoteBorderless_impl(s, out); return out.toString(); } static public void quoteBorderless_impl(String s, StringBuilder out) { int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') out.append('\\').append(c); else if (c == '\r') out.append("\\r"); else if (c == '\n') out.append("\\n"); else out.append(c); } } 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 String shortenJoin(int max, Iterable l) { StringBuilder buf = new StringBuilder(); for (String s : unnullForIteration(l)) { buf.append(s); if (l(buf) > max) break; } return shorten(max, str(buf)); } static public String replaceDollarVars_js(String s, Object... __) { Map vars = paramsToMap_withNulls(__); if (empty(vars)) return s; var vars2 = mapKeys(__107 -> dropDollarPrefix(__107), vars); return replaceDollarVars_dyn(s, var -> { if (!vars2.containsKey(var)) return null; Object value = vars2.get(var); return jsonEncode_extended(value); }); } static public Set createOrAddToSet(Set set, A a) { if (set == null) set = new HashSet(); set.add(a); return set; } static public Set createOrAddToSet(Set set, A... l) { for (A a : unnullForIteration(l)) set = createOrAddToSet(set, a); return set; } static public double frac_nonNeg(double d) { return mod(d, 1); } static public Set newWeakHashSet() { return synchroWeakHashSet(); } 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 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 int mod(int n, int m) { return (n % m + m) % m; } static public long mod(long n, long m) { return (n % m + m) % m; } static public BigInteger mod(BigInteger n, int m) { return n.mod(bigint(m)); } static public double mod(double n, double m) { return (n % m + m) % m; } static public Set synchroWeakHashSet() { return Collections.newSetFromMap((Map) newWeakHashMap()); } static public class Value implements IF0, IFieldsToList { public A value; public Value() { } public Value(A value) { this.value = value; } public boolean equals(Object o) { if (!(o instanceof Value)) return false; Value __1 = (Value) o; return eq(value, __1.value); } public int hashCode() { int h = 82420049; h = boostHashCombine(h, _hashCode(value)); return h; } public Object[] _fieldsToList() { return new Object[] { value }; } public A get() { return value; } public String toString() { return str(get()); } } }