/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2009 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package alma.acs.nc; import alma.ACSErrTypeCommon.wrappers.AcsJCouldntPerformActionEx; import alma.ACSErrTypeCommon.wrappers.AcsJIllegalStateEventEx; import alma.acsErrTypeLifeCycle.wrappers.AcsJEventSubscriptionEx; import alma.acsnc.EventDescription; /** * This interface provides an event subscriber * that can be implemented on top of Corba NC or DDS, in-memory for local testing, * or hopefully also on top of other technologies such as ZeroMQ. *

* Subscriber lifecycle: *

* The lifecycle is internally implemented using a state machine, see {@link #getLifecycleState()}. *

* Discussion: *

* @param The event (base) type. If all events are of the same type then that type should be used; otherwise a common * base type for all applicable events should be used, such as Object or IDLEntity. * * @author jslopez, hsommer */ public interface AcsEventSubscriber { /*===========================================*/ /* Subscription management methods */ /*===========================================*/ /** * Adds a handler that will receive events of a specific type. The event type * is determined by the value returned by calling {@link Callback#getEventType()} * on the receiver parameter. *

* Note that the same event type can only be subscribed to with one handler, * which means that another handler added for the same type will replace the previous handler. *

* The event type must be that of actual events, not of base classes. * For example, the AcsEventSubscriber could be parameterized with base type IDLEntity * and we could then add two subscriptions for events defined as IDL structs, * say AntennaStatus and TemperatureData. * If you want to subscribe to events without knowing their exact type, * use {@link #addGenericSubscription(GenericCallback)} instead. * * @param receiver The callback to use when receiving events for the specified type. * * @throws AcsJEventSubscriptionEx If there is a problem and the receiver cannot be added */ public void addSubscription(Callback receiver) throws AcsJEventSubscriptionEx; /** * Removes the subscription for a specified event type or for all events types, so that the handler previously * registered for that event type will no longer receive events. * * @param structClass * the event type to be unsubscribed. If null, then all subscriptions but the generic * subscription are removed. * * @throws AcsJEventSubscriptionEx * if the specified event type has not been previously subscribed or if the removal fails with a * technical problem. */ public void removeSubscription(Class structClass) throws AcsJEventSubscriptionEx; /** * Adds a generic handler for all types of events. * This should only be used by monitoring tools and other special applications. * For normal applications, use one or many calls to {@link #addSubscription(Callback)}, * each with a Callback object that matches exactly the subscribed event type. *

* It is possible to add a generic handler in addition to event type-specific handlers * (where the latter will get precedence). * Adding another generic handler will replace the previous generic handler. * * @param receiver The callback to use when receiving events * * @throws AcsJEventSubscriptionEx If there is a problem and the generic receiver cannot * be added */ public void addGenericSubscription(GenericCallback receiver) throws AcsJEventSubscriptionEx; /** * Removes the generic event handler, so that it will no longer receive events. * Event specific handlers may still receive events. * * @throws SubscriptionNotFoundException If a generic receiver has not been previously subscribed * @throws AcsJEventSubscriptionEx If there is any problem while unsubscribing the generic receiver */ public void removeGenericSubscription() throws AcsJEventSubscriptionEx; /*===========================================*/ /* Lifecycle methods */ /*===========================================*/ /** * Returns the lifecycle state as obtained from an internal state machine. *

* This state can be used only for debug output. * The state names may change over time and should not be used to control execution. */ public String getLifecycleState(); /** * This method must be called to actually start receiving events. * Typically it is called after the subscriptions are set up. * User may still add and remove subscriptions at any given time, though. * Also, the connection can be suspended and resumed. *

* No further invocations should be attempted on this method after one * has been already successful. Otherwise, an {@link AcsJIllegalStateEventEx} * will be thrown. *

* If this method is not called, no event will ever be received * * @throws AcsJIllegalStateEventEx If the user calls this method on an object that * is already receiving events * @throws AcsJCouldntPerformActionEx If any error happens while trying * to start receiving events */ public void startReceivingEvents() throws AcsJIllegalStateEventEx, AcsJCouldntPerformActionEx; /** * Disconnects this subscriber from the Notification Channel, and releases all * the resources associated with it. After this call, all registered handlers * will stop receiving events, and this subscriber becomes unusable. *

* Calling this method over a subscriber object that has been already disconnected * will throw an {@link AcsJIllegalStateEventEx}. *

* @throws AcsJIllegalStateEventEx If this method is called on an AcsEventSubscriber object * that has been already disconnected */ public void disconnect() throws AcsJIllegalStateEventEx, AcsJCouldntPerformActionEx; /** * Used to temporarily halt receiving events of all types. *

* If the Subscriber has been connected already (method {@link #startReceivingEvents()}, * then after calling this method, incoming events will be buffered instead of being discarded; * unexpired events will be received later, after a call to {@link #resume()}. * *

// * This call has no effect if the Subscriber is not connected, or if it is // * connected but already suspended. * * @throws AcsJIllegalStateEventEx if the subscriber is not connected to an NC. */ public void suspend() throws AcsJIllegalStateEventEx, AcsJCouldntPerformActionEx; /** * Returns true if this subscriber has been suspended. */ public boolean isSuspended(); /** * Used to reenable the Subscriber after a call to the * suspend() method. Queued events will be received after * this call, see {@link #suspend()}. * * This call has no effect if the Subscriber is not connected, or if it is * connected and already processing events. */ public void resume() throws AcsJIllegalStateEventEx, AcsJCouldntPerformActionEx; /** * User callback for received events. *

* This ACS-defined interface replaces the runtime search for the old * "Consumer#receive(...)" method that was based on Java introspection. */ public static interface Callback { /** * Event delivery, from the framework to user code. * @param eventData The event data, e.g. an IDL-defined struct. * @param eventDescrip Event meta data. */ public void receive(U eventData, EventDescription eventDescrip); /** * This method is needed for adding event-specific subscriptions * and for the type-safety of this API (based on java generics), * and should be implemented like *

		 * public Class<MyEvent> getEventType() {
		 *     return MyEvent.class;
		 * }
		 * 
*/ public Class getEventType(); } /** * Generic event callback, for use with {@link AcsEventSubscriber#addGenericSubscription(GenericCallback)}. */ public static interface GenericCallback { /** * TODO: Use T instead of Object ? */ public void receiveGeneric(Object event, EventDescription eventDescrip); } }