//----------------------------------------------------------------------------// // // // S e l e c t i o n S e r v i c e // // // //----------------------------------------------------------------------------// // <editor-fold defaultstate="collapsed" desc="hdr"> // // Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. // // This software is released under the GNU General Public License. // // Goto http://kenai.com/projects/audiveris to report bugs or suggestions. // //----------------------------------------------------------------------------// // </editor-fold> package omr.selection; import omr.constant.Constant; import omr.constant.ConstantSet; import org.bushe.swing.event.EventSubscriber; import org.bushe.swing.event.ThreadSafeEventService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * Class {@code SelectionService} is an OMR customized version of an * EventService as provided by the EventBus framework. * * @author Hervé Bitteur */ public class SelectionService extends ThreadSafeEventService { //~ Static fields/initializers --------------------------------------------- /** Specific application parameters */ private static final Constants constants = new Constants(); /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger( SelectionService.class); //~ Instance fields -------------------------------------------------------- /** Name of this service */ private final String name; /** Allowed events */ private final Class[] allowedEvents; //~ Constructors ----------------------------------------------------------- //------------------// // SelectionService // //------------------// /** * Creates a new SelectionService object. * * @param name a name for this service (meant for debug) * @param allowedEvents classes of events that can be published here */ public SelectionService (String name, Class[] allowedEvents) { this.name = name; this.allowedEvents = allowedEvents; // This cache is needed to be able to retrieve the last publication of // any event class setDefaultCacheSizePerClassOrTopic(1); } //~ Methods ---------------------------------------------------------------- //-----------------// // dumpSubscribers // //-----------------// public void dumpSubscribers () { logger.info("{} subscribers:", this); for (Class<?> eventClass : allowedEvents) { List<?> subscribers = getSubscribers(eventClass); if (!subscribers.isEmpty()) { UserEvent last = (UserEvent) getLastEvent(eventClass); logger.info( " {}: {}{}", eventClass.getSimpleName(), subscribers.size(), (last != null) ? (" " + last) : ""); for (Object obj : subscribers) { logger.info( " @{} {}", Integer.toHexString(obj.hashCode()), obj); } } } } //---------// // getName // //---------// public String getName () { return name; } //--------------// // getSelection // //--------------// /** * Report the current selection regarding the specified event class * * @param classe the event class we are interested in * @return the carried data, if any */ public Object getSelection (Class<? extends UserEvent> classe) { UserEvent event = (UserEvent) getLastEvent(classe); if (event == null) { return null; } else { return event.getData(); } } //---------// // publish // //---------// /** * This method is overridden just to be able to potentially check * and trace every publication. * * @param event the published event */ @Override public void publish (Object event) { logger.debug("{} published: {}", this, event); // Check whether the event may be published on this service if (!constants.checkPublishedEvents.isSet() || contains(allowedEvents, event.getClass())) { super.publish(event); } else { logger.error("Unexpected event {} published on {}", event, name); } } //-------------------// // subscribeStrongly // //-------------------// /** * Overridden to check that the subscription corresponds to a * declared class. * * @param type the observed class * @param es the subscriber * @return I don't know */ @Override public boolean subscribeStrongly (Class type, EventSubscriber es) { if (contains(allowedEvents, type)) { return super.subscribeStrongly(type, es); } else { logger.error("event class {} not available on {}", type, name); return false; } } //------------------// // subscribersCount // //------------------// /** * Convenient method to retrieve the number of subscribers on the * selection service for a specific class. * * @param classe the specific class * @return the number of subscribers found */ public int subscribersCount (Class<? extends UserEvent> classe) { return getSubscribers(classe) .size(); } //----------// // toString // //----------// @Override public String toString () { StringBuilder sb = new StringBuilder("{"); sb.append(getClass().getSimpleName()); sb.append(" ") .append(name); sb.append("}"); return sb.toString(); } @Override public boolean unsubscribe (Class cl, EventSubscriber eh) { boolean res = super.unsubscribe(cl, eh); logger.debug( "{} unsubscribe {} subscriber:{}@{} res:{}", this, cl.getName(), eh, Integer.toHexString(eh.hashCode()), res); return res; } //----------// // contains // //----------// private boolean contains (Class<?>[] classes, Class<?> classe) { for (Class<?> cl : classes) { if (cl == classe) { return true; } } return false; } //~ Inner Classes ---------------------------------------------------------- //-----------// // Constants // //-----------// private static final class Constants extends ConstantSet { //~ Instance fields ---------------------------------------------------- Constant.Boolean checkPublishedEvents = new Constant.Boolean( true, "(debug) Should we check published events?"); } }