/** * Copyright (c) 2009 - 2010 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org> * * This file is part of org.appwork.utils.event * * This software is licensed under the Artistic License 2.0, * see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php * for details */ package org.appwork.utils.event; import java.io.File; import java.io.IOException; import java.lang.ref.WeakReference; //import java.net.URISyntaxException; //import java.net.URL; import java.util.ArrayList; import java.util.EventListener; import org.appwork.utils.IO; //import org.appwork.utils.swing.dialog.Dialog; //import org.appwork.utils.swing.dialog.DialogCanceledException; //import org.appwork.utils.swing.dialog.DialogClosedException; //import org.appwork.utils.swing.dialog.ExtFileChooserDialog; //import org.appwork.utils.swing.dialog.FileChooserSelectionMode; //import org.appwork.utils.swing.dialog.FileChooserType; /** * The Eventsenderclass is the core of the Eventsystem. it can be used to design * new Eventbroadcaster Systems easily. * * Guidelines:<br> * 1. CReate a new MyEventSender extends * org.appwork.utils.event.Eventsender<ListenerType, EventType> <br> * 2. Create MyListenerType extends java.util.EventListener<br> * 3. CReate MyEvent extends org.appwork.utils.event.SimpleEvent<CallerType, * ParameterType, TypeEnumType><br> * * <br> * TypeEnumType is usually a intern enum which defines all available eventtypes * * @author $Author: unknown$ * */ public abstract class Eventsender<ListenerType extends EventListener, EventType extends DefaultEvent> { /** * @param name * @param file * @throws IOException */ @SuppressWarnings("unused") private static void create(final String name, final File file) throws IOException { String pkg = ""; System.out.println(""); File p = file; do { if (pkg.length() > 0) { pkg = "." + pkg; } pkg = p.getName() + pkg; } while ((p = p.getParentFile()) != null && !p.getName().equals("src")); StringBuilder sb = new StringBuilder(); final String senderName = name + "EventSender"; final String eventName = name + "Event"; final String listenerName = name + "Listener"; sb.append("package " + pkg + ";\r\n\r\n"); sb.append("import org.appwork.utils.event.Eventsender;\r\n\r\n"); sb.append("public class " + senderName + " extends Eventsender<" + listenerName + ", " + eventName + "> {\r\n\r\n"); sb.append("@Override\r\n"); sb.append("protected void fireEvent(" + listenerName + " listener, " + eventName + " event) {\r\nswitch (event.getType()) {\r\n//fill\r\ndefault: System.out.println(\"Unhandled Event: \"+event); \r\n}\r\n}"); sb.append("}"); new File(file, senderName + ".java").delete(); IO.writeStringToFile(new File(file, senderName + ".java"), sb.toString()); sb = new StringBuilder(); sb.append("package " + pkg + ";\r\n\r\n"); sb.append("import java.util.EventListener;\r\n\r\n"); sb.append("public interface " + listenerName + " extends EventListener {\r\n\r\n}"); new File(file, listenerName + ".java").delete(); IO.writeStringToFile(new File(file, listenerName + ".java"), sb.toString()); sb = new StringBuilder(); sb.append("package " + pkg + ";\r\n\r\n"); sb.append("import org.appwork.utils.event.SimpleEvent;\r\n\r\n"); sb.append("public class " + eventName + " extends SimpleEvent<Object, Object, " + eventName + ".Type> {\r\n\r\n"); sb.append("public static enum Type{\r\n}\r\n"); sb.append("public " + eventName + "(Object caller, Type type, Object... parameters) {\r\n"); sb.append("super(caller, type, parameters);\r\n}\r\n"); sb.append("}"); new File(file, eventName + ".java").delete(); IO.writeStringToFile(new File(file, eventName + ".java"), sb.toString()); } // public static void main(final String[] args) throws DialogClosedException, DialogCanceledException, IOException, URISyntaxException { // final URL root = Thread.currentThread().getClass().getResource("/"); // final File rootFile = new File(root.toURI()); // final String name = Dialog.getInstance().showInputDialog("Enter Name"); // // ExtFileChooserDialog d = new ExtFileChooserDialog(0, "Choose folder", null, null); // d.setStorageID("EventSenderCReater"); // d.setFileSelectionMode(FileChooserSelectionMode.DIRECTORIES_ONLY); // // d.setType(FileChooserType.OPEN_DIALOG); // d.setMultiSelection(false); // d.setPreSelection(rootFile.getParentFile().getParentFile()); // try { // Dialog.I().showDialog(d); // } catch (DialogClosedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } catch (DialogCanceledException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // // // // Eventsender.create(name, d.getSelectedFile()); // System.exit(1); // } /** * List of registered Eventlistener */ transient volatile protected java.util.List<ListenerType> strongListeners = null; transient volatile protected java.util.List<WeakReference<ListenerType>> weakListener = null; private final Object LOCK = new Object(); /** * List of Listeners that are requested for removal * */ /** * Creates a new Eventsender Instance */ public Eventsender() { this.strongListeners = new ArrayList<ListenerType>(); this.weakListener = new ArrayList<WeakReference<ListenerType>>(); } /** * Adds a list of listeners * * @param listener */ public void addAllListener(final java.util.List<ListenerType> listener) { this.addAllListener(listener, false); } public void addAllListener(final java.util.List<ListenerType> listener, final boolean weak) { for (final ListenerType l : listener) { this.addListener(l, weak); } } public void addListener(final ListenerType t) { this.addListener(t, false); } /** * Add a single Listener * * @param listener */ public void addListener(final ListenerType t, final boolean weak) { if (t == null) { return; } synchronized (this.LOCK) { boolean added = false; if (weak == false) { /* update strong listeners */ final java.util.List<ListenerType> newStrongListener = new ArrayList<ListenerType>(this.strongListeners); if (!newStrongListener.contains(t)) { newStrongListener.add(t); } this.strongListeners = newStrongListener; } /* update weak listeners */ ListenerType l = null; final java.util.List<WeakReference<ListenerType>> newWeakListener = new ArrayList<WeakReference<ListenerType>>(this.weakListener.size()); for (final WeakReference<ListenerType> listener : this.weakListener) { if ((l = listener.get()) == null) { /* remove weak listener because it is gone */ } else if (l == t) { /* list already contains t, no need to add it again */ added = true; newWeakListener.add(listener); } else { newWeakListener.add(listener); } } if (added == false) { newWeakListener.add(new WeakReference<ListenerType>(t)); } this.weakListener = newWeakListener; } } public void cleanup() { synchronized (this.LOCK) { final java.util.List<WeakReference<ListenerType>> newWeakListener = new ArrayList<WeakReference<ListenerType>>(this.weakListener.size()); for (final WeakReference<ListenerType> listener : this.weakListener) { if (listener.get() == null) { /* weak item is gone */ continue; } else { newWeakListener.add(listener); } } this.weakListener = newWeakListener; } } public boolean containsListener(final ListenerType t) { if (t == null) { return false; } synchronized (this.LOCK) { for (final ListenerType tmp : this.strongListeners) { if (tmp == t) { return true; } } ListenerType l = null; for (final WeakReference<ListenerType> listener : this.weakListener) { if ((l = listener.get()) == null) { /* weak item is gone */ continue; } else if (l == t) { return true; } } return false; } } final public void fireEvent(final EventType event) { if (event == null) { return; } ListenerType t = null; boolean cleanup = false; final java.util.List<WeakReference<ListenerType>> listeners = this.weakListener; for (final WeakReference<ListenerType> listener : listeners) { t = listener.get(); if (t == null) { cleanup = true; continue; } this.fireEvent(t, event); } if (cleanup && listeners.size() > 0) { this.cleanup(); } } /** * Fires an Event to all registered Listeners * * @param event * @return */ final public void fireEvent(final int id, final Object... parameters) { ListenerType t = null; boolean cleanup = false; final java.util.List<WeakReference<ListenerType>> listeners = this.weakListener; for (final WeakReference<ListenerType> listener : listeners) { t = listener.get(); if (t == null) { cleanup = true; continue; } this.fireEvent(t, id, parameters); } if (cleanup && listeners.size() > 0) { this.cleanup(); } } /** * Abstract fire Event Method. * * @param listener * @param event */ protected abstract void fireEvent(ListenerType listener, EventType event); /** * * @param t * @param id * @param parameters */ protected void fireEvent(final ListenerType listener, final int id, final Object... parameters) { throw new RuntimeException("Not implemented. Overwrite org.appwork.utils.event.Eventsender.fireEvent(T, int, Object...) to use this"); } public java.util.List<ListenerType> getListener() { final java.util.List<WeakReference<ListenerType>> listeners = this.weakListener; boolean cleanup = true; final java.util.List<ListenerType> ret = new ArrayList<ListenerType>(listeners.size()); ListenerType t = null; for (final WeakReference<ListenerType> listener : listeners) { t = listener.get(); if (t != null) { ret.add(t); } else { cleanup = true; } } if (cleanup && listeners.size() > 0) { this.cleanup(); } return ret; } public boolean hasListener() { final java.util.List<WeakReference<ListenerType>> listeners = this.weakListener; for (final WeakReference<ListenerType> listener : listeners) { if (listener.get() != null) { return true; } } return false; } public void removeListener(final ListenerType t) { if (t == null) { return; } synchronized (this.LOCK) { ListenerType l = null; final java.util.List<WeakReference<ListenerType>> newWeakListener = new ArrayList<WeakReference<ListenerType>>(this.weakListener.size()); final java.util.List<ListenerType> newStrongListener = new ArrayList<ListenerType>(this.strongListeners); for (final WeakReference<ListenerType> listener : this.weakListener) { if ((l = listener.get()) == null) { /* weak item is gone */ continue; } else if (l != t) { newWeakListener.add(listener); } } /* remove strong item */ newStrongListener.remove(t); this.weakListener = newWeakListener; this.strongListeners = newStrongListener; } } }