import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
import java.awt.dnd.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.DataFlavor;
import javax.swing.event.AncestorEvent;
import java.awt.datatransfer.*;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.geom.AffineTransform;
import java.awt.geom.*;
import javax.swing.event.AncestorListener;
import javax.swing.Timer;
import java.awt.geom.*;
import java.awt.font.GlyphVector;
import java.awt.geom.*;
import javax.swing.Timer;
import javax.swing.undo.UndoManager;
class main {
public static void main(final String[] args) throws Exception {
allWebs_transientOnly = true;
ai_postTransientTriple_force.set(true);
String id = aGlobalID();
assertCollectionContents(ll(), printStruct(ai_invalidatedWebs()));
// invalidate
Web web = ai_invalidateWebTransiently(id);
assertCollectionContents(ll(id), printStruct(ai_invalidatedWebs()));
// invalidate again
Web web2 = ai_invalidateWebTransiently(id);
assertCollectionContents(ll(id), printStruct(ai_invalidatedWebs()));
print("remove one");
removeTransientWeb(web);
assertCollectionContents(ll(id), printStruct(ai_invalidatedWebs()));
print("remove the other");
removeTransientWeb(web2);
assertCollectionContents(ll(), printStruct(ai_invalidatedWebs()));
print("OK");
}
static String aGlobalID() {
return randomID(16);
}
static List ll(A... a) {
return litlist(a);
}
static A printStruct(String prefix, A a) {
printStructure(prefix, a);
return a;
}
static A printStruct(A a) {
printStructure(a);
return a;
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static volatile StringBuffer print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
//static int print_maxLineLength = 0; // 0 = unset
static boolean print_silent; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal> print_byThread; // special handling by thread
static void print() {
print("");
}
// slightly overblown signature to return original object...
static A print(A o) {
ping();
if (print_silent) return o;
String s = String.valueOf(o) + "\n";
print_noNewLine(s);
return o;
}
static void print_noNewLine(String s) {
if (print_byThread != null) {
F1 f = print_byThread.get();
if (f != null)
if (isFalse(f.get(s))) return;
}
print_raw(s);
}
static void print_raw(String s) {
s = fixNewLines(s);
// TODO if (print_maxLineLength != 0)
StringBuffer loc = local_log;
StringBuffer buf = print_log;
int loc_max = print_log_max;
if (buf != loc && buf != null) {
print_append(buf, s, print_log_max);
loc_max = local_log_max;
}
if (loc != null)
print_append(loc, s, loc_max);
System.out.print(s);
}
static void print(long l) {
print(String.valueOf(l));
}
static void print(char c) {
print(String.valueOf(c));
}
static void print_append(StringBuffer buf, String s, int max) {
synchronized(buf) {
buf.append(s);
max /= 2;
if (buf.length() > max) 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);
}
}
}
// the map is: invalidated id -> invalidators
static DependentCache> ai_invalidatedWebs_cache = new DependentCache("ai_invalidatedWebs_calc", "cachedNodeIndex" /*_changeCount*/);
static Set ai_invalidatedWebs() {
return keys(ai_invalidatedWebs_cache.get());
}
static MultiMap ai_invalidatedWebs_calc() {
print("ai_invalidatedWebs_calc");
ai_onNewOrRemovedWeb("ai_invalidatedWebs_onNewWeb", "ai_invalidatedWebs_onRemovedWeb");
ai_invalidatedWebs_cache.set(new MultiMap());
Collection webs = allWebsFromCachedNodeIndex_uncached();
print("Have " + nWebs(webs));
for (Web web : webs)
ai_invalidatedWebs_onNewWeb(web);
print("calc done");
return ai_invalidatedWebs_cache.get();
}
static void ai_invalidatedWebs_onNewWeb(Web web) {
if (web.unverified) return;
Lock _lock_2 = ai_invalidatedWebs_cache.lock; lock(_lock_2); try {
Matches m = new Matches();
for (WebNode n : web_search_dollarX(webFromTriple("$X", "is", "invalid"), web))
if (web_match("Web *", n, m) && isGlobalID(m.unq(0)))
ai_invalidatedWebs_cache.get().put(m.unq(0), web.globalID);
} finally { _lock_2.unlock(); } }
static void ai_invalidatedWebs_onRemovedWeb(Web web) {
if (web.unverified) return;
Lock _lock_3 = ai_invalidatedWebs_cache.lock; lock(_lock_3); try {
Matches m = new Matches();
for (WebNode n : web_search_dollarX(webFromTriple("$X", "is", "invalid"), web))
if (web_match("Web *", n, m) && isGlobalID(m.unq(0)))
ai_invalidatedWebs_cache.get().remove(m.unq(0), web.globalID);
} finally { _lock_3.unlock(); } }
static RuntimeException asRuntimeException(Throwable t) {
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static Map _registerThread_threads = Collections.synchronizedMap(new WeakHashMap());
static Thread _registerThread(Thread t) {
_registerThread_threads.put(t, true);
return t;
}
static void _registerThread() { _registerThread(Thread.currentThread()); }
static void removeTransientWeb(Web web) {
if (!transientWebs_list.contains(web)) return;
transientWebs_list.remove(web);
onTransientWebRemoved(web);
}
static Web ai_invalidateWebTransiently(String globalID) {
return ai_postTransientTriple("Web " + globalID, "is", "invalid");
}
static Web ai_invalidateWebTransiently(Web web) {
return web == null ? null : ai_invalidateWebTransiently(web.globalID);
}
static void assertCollectionContents(Collection expected, Collection real) {
assertEquals(new HashSet(expected), new HashSet(real));
}
static String fixNewLines(String s) {
return s.replace("\r\n", "\n").replace("\r", "\n");
}
static Collection allWebsFromCachedNodeIndex_uncached() {
return nodesToWebs(values(cachedNodeIndex()));
}
static List web_search_dollarX(Web searchWeb, Web web) {
return webs_search_dollarX(searchWeb, ll(web));
}
static volatile boolean ping_pauseAll;
static int ping_sleep = 100; // poll pauseAll flag every 100
static volatile boolean ping_anyActions;
static Map ping_actions = (Map) synchroMap(newWeakHashMap());
// always returns true
static boolean ping() {
if (ping_pauseAll || ping_anyActions) ping_impl();
return true;
}
// returns true when it slept
static boolean ping_impl() { try {
if (ping_pauseAll && !isAWTThread()) {
do
Thread.sleep(ping_sleep);
while (ping_pauseAll);
return true;
}
if (ping_anyActions) {
Object action;
synchronized(ping_actions) {
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 Set keys(Map map) {
return map == null ? new HashSet() : map.keySet();
}
static Set keys(Object map) {
return keys((Map) map);
}
static Set keys(MultiMap mm) {
return mm.keySet();
}
static boolean web_match(String pat, WebNode node, Matches m) {
for (String s : web_texts(node))
if (match(pat, s, m)) return true;
return false;
}
static MultiMap cachedNodeIndex() {
return cachedNodeIndex2();
}
static void ai_onNewOrRemovedWeb(Object onNewWeb, Object onRemovedWeb) {
setAdd(postSoftwareMadeWeb_onNewWeb, onNewWeb);
onTransientWebAdded_do(onNewWeb);
onTransientWebRemoved_do(onRemovedWeb);
}
static Web webFromTriple(String a, String b, String c) {
return webFromTriple(triple(a, b, c));
}
static Web webFromTriple(T3 t) {
return webFromTriple(t, 0.2, 0.2, 0.8, 0.7);
}
static Web webFromTriple(T3 t, double x1, double y1, double x2, double y2) {
Web web = webFromTriples(t.a, t.b, t.c);
web_setPosition(first(web.nodes), x1, y1);
web_setPosition(second(web.nodes), x2, y2);
return web;
}
static ThreadLocal ai_postTransientTriple_force = new ThreadLocal();
static Web ai_postTransientTriple(T3 triple) {
if (ai_hasTriple(triple) && !isTrue(ai_postTransientTriple_force.get())) return null;
Web web = webFromTriple(triple);
addTransientWeb(web);
return web;
}
static Web ai_postTransientTriple(String a, String b, String c) {
return ai_postTransientTriple(t3(a, b, c));
}
static ArrayList litlist(A... a) {
return new ArrayList(Arrays.asList(a));
}
static void lock(Lock lock) { try {
lock.lockInterruptibly();
} catch (Exception __e) { throw rethrow(__e); } }
static void lock(Lock lock, String msg) {
print("Locking: " + msg);
lock(lock);
}
static void lock(Lock lock, String msg, long timeout) {
print("Locking: " + msg);
lockOrFail(lock, timeout);
}
static ReentrantLock lock() {
return fairLock();
}
static String nWebs(int i) {
return n(i, "web");
}
static String nWebs(Collection c) {
return n(c, "web");
}
static List onTransientWebRemoved_list = synchroList();
// f: voidfunc(Web)
static void onTransientWebRemoved_do(Object f) {
setAdd(onTransientWebRemoved_list, f);
}
static void onTransientWebRemoved(Web web) {
pcallFAll(onTransientWebRemoved_list, web);
}
static void printStructure(String prefix, Object o) {
if (endsWithLetter(prefix)) prefix += ": ";
print(prefix + structureForUser(o));
}
static void printStructure(Object o) {
print(structureForUser(o));
}
static boolean isGlobalID(String s) {
return possibleGlobalID(s);
}
static List transientWebs_list = synchroList();
static List transientWebs() {
return transientWebs_list;
}
static boolean isFalse(Object o) {
return eq(false, o);
}
static A assertEquals(Object x, A y) {
return assertEquals(null, x, y);
}
static A assertEquals(String msg, Object x, A y) {
if (!(x == null ? y == null : x.equals(y)))
throw fail((msg != null ? msg + ": " : "") + y + " != " + x);
return y;
}
static int randomID_defaultLength = 12;
static String randomID(int length) {
return makeRandomID(length);
}
static String randomID() {
return randomID(randomID_defaultLength);
}
static void lockOrFail(Lock lock, long timeout) { try {
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);
}
} catch (Exception __e) { throw rethrow(__e); } }
static Map newWeakHashMap() {
return _registerWeakMap(synchroMap(new WeakHashMap()));
}
static A second(List l) {
return get(l, 1);
}
static A second(A[] bla) {
return bla == null || bla.length <= 1 ? null : bla[1];
}
static B second(Pair p) {
return p == null ? null : p.b;
}
static B second(T3 t) {
return t == null ? null : t.b;
}
static Cache> cachedNodeIndex2_cache = new Cache("dwlw_fullNodeIndex_ci");
static boolean cachedNodeIndex2_first = true;
static FileStatus cachedNodeIndex2_status;
static MultiMap cachedNodeIndex2() {
if (cachedNodeIndex2_first) {
cachedNodeIndex2_first = false;
onWebsChanged("cachedNodeIndex2_clear");
onTransientWebAdded_do("cachedNodeIndex2_onNewWeb");
onTransientWebRemoved_do("cachedNodeIndex2_onWebRemoved");
setAdd(postSoftwareMadeWeb_onNewWeb, "cachedNodeIndex2_onNewWeb");
}
FileStatus status = conceptsFileStatus(circlesEditorDBID());
if (neq(cachedNodeIndex2_status, status)) {
cachedNodeIndex2_status = status;
cachedNodeIndex2_cache.clear();
}
return cachedNodeIndex2_cache.get();
}
static void cachedNodeIndex2_clear() {
cachedNodeIndex2_cache.clear();
}
static boolean cachedNodeIndex2_onNewWeb(Web web, Object[] params) {
return cachedNodeIndex2_onNewWeb(web);
}
static boolean cachedNodeIndex2_onNewWeb(Web web) {
Lock _lock_10 = cachedNodeIndex2_cache.lock; lock(_lock_10); try {
print("Incremental update");
ai_addWebToIndex(cachedNodeIndex2_cache.get(), web);
cachedNodeIndex2_cache.changeCount++;
return false; // don't trigger full update
} finally { _lock_10.unlock(); } }
static void cachedNodeIndex2_onWebRemoved(Web web) {
Lock _lock_11 = cachedNodeIndex2_cache.lock; lock(_lock_11); try {
print("Incremental removal");
ai_removeWebFromIndex(cachedNodeIndex2_cache.get(), web);
cachedNodeIndex2_cache.changeCount++;
} finally { _lock_11.unlock(); } }
static long cachedNodeIndex_changeCount() {
return cachedNodeIndex2_cache.changeCount;
}
static List onTransientWebAdded_list = synchroList();
// f: voidfunc(Web)
static void onTransientWebAdded_do(Object f) {
setAdd(onTransientWebAdded_list, f);
}
static void onTransientWebAdded(Web web) {
pcallFAll(onTransientWebAdded_list, web);
}
// TODO: test if android complains about this
static boolean isAWTThread() {
if (isAndroid()) return false;
if (isHeadless()) return false;
return isAWTThread_awt();
}
static boolean isAWTThread_awt() {
return SwingUtilities.isEventDispatchThread();
}
static Thread currentThread() {
return Thread.currentThread();
}
static boolean eq(Object a, Object b) {
return a == null ? b == null : a == b || a.equals(b);
}
static void addTransientWeb(Web web) {
onTransientWebAdded(web);
transientWebs_list.add(web);
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static T3 triple(A a, B b, C c) {
return new T3(a, b, c);
}
static T3 t3(A a, B b, C c) {
return new T3(a, b, c);
}
static Map synchroMap() {
return synchroHashMap();
}
static Map synchroMap(Map map) {
return Collections.synchronizedMap(map);
}
static Collection values(Map map) {
return map == null ? emptyList() : map.values();
}
static Collection values(MultiMap mm) {
return mm == null ? emptyList() : concatLists(values(mm.data));
}
static List web_texts(WebNode node) {
return node == null ? new ArrayList() : node.texts();
}
static List web_texts(Collection l) {
return map("web_text",l);
}
static List webs_search_dollarX(Web searchWeb, Collection webs) {
List < Map > mappings = new ArrayList();
for (Web web : webs)
addIfNotNull(mappings, web_matchAllPerms_x(searchWeb, web, "nodeMatch_dollarVars"));
return getFromAll(mappings, web_findNode(searchWeb, "$X"));
}
static void pcallFAll(Collection l, Object... args) {
if (l != null) for (Object f : l) pcallF(f, args);
}
static List synchroList() {
return Collections.synchronizedList(new ArrayList());
}
static List synchroList(List l) {
return Collections.synchronizedList(l);
}
static String structureForUser(Object o) {
return beautifyStructure(struct_noStringSharing(o));
}
static boolean setAdd(Collection c, A a) {
if (c.contains(a)) return false;
c.add(a);
return true;
}
static boolean endsWithLetter(String s) {
return nempty(s) && isLetter(last(s));
}
static RuntimeException rethrow(Throwable e) {
throw asRuntimeException(e);
}
static ReentrantLock fairLock() {
return new ReentrantLock(true);
}
static boolean match(String pat, String s) {
return match3(pat, s);
}
static boolean match(String pat, String s, Matches matches) {
return match3(pat, s, matches);
}
static boolean possibleGlobalID(String s) {
return l(s) == 16 && allLowerCaseCharacters(s);
}
static String makeRandomID(int length) {
Random random = new Random();
char[] id = new char[length];
for (int i = 0; i < id.length; i++)
id[i] = (char) ((int) 'a' + random.nextInt(26));
return new String(id);
}
static String n(long l, String name) {
return l + " " + trim(l == 1 ? singular(name) : getPlural(name));
}
static String n(Collection l, String name) {
return n(l(l), name);
}
static String n(Map m, String name) {
return n(l(m), name);
}
static String n(Object[] a, String name) {
return n(l(a), name);
}
static boolean isTrue(Object o) {
if (o instanceof Boolean)
return ((Boolean) o).booleanValue();
if (o == null) return false;
throw fail(getClassName(o));
}
static Web webFromTriples(String... l) {
Web web = simpleWeb();
for (int i = 0; i < l(l); i += 3) {
String a = unnull(get(l, i)), b = unnull(get(l, i+1)), c = unnull(get(l, i+2));
web_addRelation(web, a, c, b);
}
return web;
}
static Web webFromTriples(List l) {
return webFromTriples(toStringArray(l));
}
static WebNode web_setPosition(WebNode node, double x, double y) {
node.x = x;
node.y = y;
return node;
}
static boolean ai_hasTriple(String a, String b, String c) {
return ai_cache_hasTriple(a, b, c);
}
static boolean ai_hasTriple(T3 t) {
return ai_cache_hasTriple(t);
}
static List nodesToWebs(Collection nodes) {
Set webs = litorderedset();
for (WebNode node : nodes)
webs.add(node.web);
return asList(webs);
}
static Object first(Object list) {
return empty((List) list) ? null : ((List) list).get(0);
}
static A first(List list) {
return empty(list) ? null : list.get(0);
}
static A first(A[] bla) {
return bla == null || bla.length == 0 ? null : bla[0];
}
static A first(Iterable i) {
if (i == null) return null;
Iterator it = i.iterator();
return it.hasNext() ? it.next() : null;
}
static Character first(String s) { return empty(s) ? null : s.charAt(0); }
static A first(Pair p) {
return p == null ? null : p.a;
}
static List getFromAll(Collection