package nbtool.util; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import javax.swing.SwingUtilities; import nbtool.data.group.Group; import nbtool.data.log.Log; import nbtool.data.log.LogReference; import nbtool.nio.CrossServer.CrossInstance; import nbtool.nio.RobotConnection; import nbtool.util.Center.ToolEvent; public class Events { public static abstract interface EventListener{} private static abstract class SimpleForEach extends ToolEvent { private Class<? extends EventListener> eclass; public SimpleForEach(Class<? extends EventListener> eclass) { this.eclass = eclass; } @Override protected boolean canCombine() { return false; } @Override protected void combine(LinkedList<ToolEvent> others) {} @Override protected Class<? extends EventListener> listenerClass() { return eclass; } @Override protected void execute(ArrayList<EventListener> guiList, ArrayList<EventListener> centerList) { assert(Center.isCenterThread()); this.preface(); for (EventListener ce : centerList) { this.inform(ce); } final SimpleForEach sfe = this; final EventListener[] listeners = guiList.toArray(new EventListener[0]); try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { for (EventListener ge : listeners) { sfe.inform(ge); } } }); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } protected abstract void preface(); protected abstract void inform(EventListener l); } //SimpleCombine can only combine SimpleCombine events. private static abstract class SimpleCombine extends SimpleForEach { protected Object[] payload; protected SimpleCombine(Class<? extends EventListener> eclass, Object ... load ) { super(eclass); this.payload = load; } @Override protected boolean canCombine() { return true; } @Override protected abstract void combine(LinkedList<ToolEvent> others); } /* * Most of the specific EventListener sub-interfaces. */ /* NBCROSS EVENTS */ //Get functions from instance. public static interface CrossStatus extends EventListener { public void nbCrossFound(CrossInstance inst, boolean up); } public static final class GCrossStatus { public static void generate(final CrossInstance inst, final boolean up) { Center.addEvent(new SimpleForEach(CrossStatus.class){ @Override protected void preface() { Debug.event( "CrossStatus: %s %b", inst.name(), up); } @Override protected void inform(EventListener l) { ((CrossStatus) l).nbCrossFound(inst, up); } }); } } /* STREAM EVENTS */ public static interface RobotConnectionStatus extends EventListener { public void robotStatus(RobotConnection inst, boolean up); } public static final class GRobotConnectionStatus { public static void generate(final RobotConnection inst, final boolean up) { Center.addEvent(new SimpleForEach(RobotConnectionStatus.class) { @Override protected void preface() { Debug.event( "StreamIOStatus: %s %b", inst.name(), up); } @Override protected void inform(EventListener l) { ((RobotConnectionStatus) l).robotStatus(inst, up); } }); } } public static interface LogRefsFound extends EventListener { public void logRefsFound(Object source, LogReference ... found); } public static final class GLogRefsFound { public static void generate(final Object source, final LogReference ... found) { Center.addEvent(new SimpleCombine(LogRefsFound.class, source, found){ @Override protected void combine(LinkedList<ToolEvent> others) { assert(this.payload.length == 2); if (others.size() == 0) return; LogReference[] ours = (LogReference[]) payload[1]; List<LogReference> alsoFound = new ArrayList<>(); alsoFound.addAll(Arrays.asList(ours)); for (ToolEvent te : others) { assert(te instanceof SimpleCombine); LogReference[] theirs = (LogReference[]) ((SimpleCombine) te).payload[1]; alsoFound.addAll(Arrays.asList(theirs)); } Debug.info( "LogReferenceFound combined %d events with %d logs.", others.size(), alsoFound.size()); this.payload[0] = null; this.payload[1] = alsoFound.toArray(new LogReference[0]); } @Override protected void preface() { Debug.event( "LogReferenceFound..."); } @Override protected void inform(EventListener l) { LogReference[] logs = (LogReference[]) payload[1]; ((LogRefsFound) l).logRefsFound(payload[0], logs); } }); } } public static interface LogsFound extends EventListener { public void logsFound(Object source, Log ... found); } public static final class GLogsFound { public static void generate(final Object source, final Log ... found) { Center.addEvent(new SimpleCombine(LogsFound.class, source, found){ @Override protected void combine(LinkedList<ToolEvent> others) { assert(this.payload.length == 2); if (others.size() == 0) return; Log[] ours = (Log[]) payload[1]; List<Log> alsoFound = new ArrayList<>(); alsoFound.addAll(Arrays.asList(ours)); for (ToolEvent te : others) { assert(te instanceof SimpleCombine); Log[] theirs = (Log[]) ((SimpleCombine) te).payload[1]; alsoFound.addAll(Arrays.asList(theirs)); } Debug.info( "LogFound combined %d events with %d logs.", others.size(), alsoFound.size()); this.payload[0] = null; this.payload[1] = alsoFound.toArray(new Log[0]); } @Override protected void preface() { Debug.event( "LogFound..."); } @Override protected void inform(EventListener l) { Log[] logs = (Log[]) payload[1]; ((LogsFound) l).logsFound(payload[0], logs); } }); } } public static interface GroupAdded extends EventListener { public void groupAdded(Object source, Group group); } public static final class GGroupAdded { public static void generate(final Object source, final Group group) { Center.addEvent(new SimpleForEach(GroupAdded.class) { @Override protected void preface() { Debug.event( "GroupAdded from %s (%s)", source, group); } @Override protected void inform(EventListener l) { ((GroupAdded) l).groupAdded(source, group); } }); } } public static interface LogSelected extends EventListener { public void logSelected(Object source, Log first, List<Log> alsoSelected); } public static final class GLogSelected { public static void generate(Object source, Log first, List<Log> alsoSelected) { Center.addEvent(new SimpleCombine(LogSelected.class, source, first, alsoSelected){ @Override protected void combine(LinkedList<ToolEvent> others) { if (others.isEmpty()) return; /* other events can only have been posted later, so drop them. */ Debug.event( "LogSelected dropping %d others.", others.size()); if (others.isEmpty()) return; ToolEvent te = others.getLast(); assert(te instanceof SimpleCombine); SimpleCombine sc = (SimpleCombine) te; payload[0] = sc.payload[0]; payload[1] = sc.payload[1]; payload[2] = sc.payload[2]; } @Override protected void preface() { Debug.event( "LogSelected{%s}", payload[0]); } @Override protected void inform(EventListener l) { ((LogSelected) l).logSelected(payload[0], (Log) payload[1], (List<Log>) payload[2]); } }); } } public static interface GroupSelected extends EventListener { public void groupSelected(Object source, Group s); } public static final class GGroupSelected{ public static void generate(final Object source, final Group s) { Center.addEvent(new SimpleCombine(GroupSelected.class, source, s){ @Override protected void combine(LinkedList<ToolEvent> others) { if (others.isEmpty()) return; /* other events can only have been posted later, so drop them. */ Debug.event( "GroupSelected dropping %d others.", others.size()); if (others.isEmpty()) return; ToolEvent te = others.getLast(); assert(te instanceof SimpleCombine); SimpleCombine sc = (SimpleCombine) te; payload[0] = sc.payload[0]; payload[1] = sc.payload[1]; } @Override protected void preface() { Debug.event( "GroupSelected{%s}", payload[0]); } @Override protected void inform(EventListener l) { ((GroupSelected) l).groupSelected(payload[0], (Group) payload[1]); } }); } } public static interface ViewProfileSetChanged extends EventListener { //Get new profiles via ViewProfile.PROFILES public void viewProfileSetChanged(Object changer); } public static final class GViewProfileSetChanged { public static void generate(final Object source) { Center.addEvent(new SimpleCombine(ViewProfileSetChanged.class, source) { @Override protected void combine(LinkedList<ToolEvent> others) { if (others.isEmpty()) return; SimpleCombine sc = (SimpleCombine) others.getLast(); payload[0] = sc.payload[0]; } @Override protected void preface() { Debug.event( "ViewProfileSetChanged{%s}", payload[0]); } @Override protected void inform(EventListener l) { ((ViewProfileSetChanged) l).viewProfileSetChanged(payload[0]); } }); } } }