// // Copyright (c)1998-2011 Pearson Education, Inc. or its affiliate(s). // All rights reserved. // package openadk.library; import openadk.library.impl.DataObjectInputStreamImpl; /** * Encapsulates a SIF Event.<p> * * An Event is a notification to subscribing agents that a data object has been * added, changed, or deleted in the reporting application's database. In the * Schools Interoperability Framework, any agent may report SIF_Event messages for * any object, even if that agent is not the authoritative publisher of the object.<p> * * <b>Reporting SIF Events</b><p> * * To report a SIF_Event to a zone, construct an Event instance and call the * {@link openadk.library.Zone#reportEvent(Event)} method. Supply a * SIFDataObject instance and an action code to the Event constructor. You may * also call alternative forms of the <code>reportEvent</code> method that accept * SIFDataObjects and an action code as parameters. Note Events cannot be reported * to a Topic because the ADK cannot determine which of its zones should receive * the event. If you're using Topics, you must report events to the specific Zone * or Zones to which the data applies.<p> * * <b>Subscribing to SIF Events</b><p> * * To subscribe to SIF_Events for a specific object type, register a <i>Subscriber</i> * message handler with Zone or Topic instances. Call the <code>setSubscriber</code> * method repeatedly for each object type you wish to subscribe to. When the ADK * connects to a zone, it sends SIF_Subscribe messages for each object type. When a * SIF_Event message is received by the ADK, it is dispatched to your * {@linkplain openadk.library.Subscriber#onEvent(Event, Zone, MessageInfo)} * method for processing. Refer to that method for more information.<p> * * @author Eric Petersen * @since ADK 1.0 */ public class Event { /** * The data that has changed as described by the action */ protected DataObjectInputStream fData; /** * Identifies the type of SIF Data Object contained in the event */ protected ElementDef fObjType; /** * The action */ protected String fAction; /** * The zone from which this event originated */ protected Zone fZone; /** * The SIF Contexts to which this event applies */ private SIFContext[] fContexts = new SIFContext[] { SIFContext.DEFAULT }; /** * Constructs an Event object to encapsulate an inbound SIF Event. This form * of constructor is called internally by the ADK when it receives a SIF_Event * message.<p> * * @param data A DataObjectInputStream that returns SIFDataObjects, all of * which must be of the same class type * @param action Describes how the data has changed. One of the * following flags: <code>ADD</code>, <code>CHANGE</code>, or <code>DELETE</code> * @param objectType An ElementDef constant from the {@linkplain openadk.library.SIFDTD} class that * identifies the type of SIF Data Object contained in the event * @see openadk.library.EventAction */ public Event( DataObjectInputStream data, EventAction action, ElementDef objectType ) { fData = data; fObjType = objectType; switch( action ) { case ADD: fAction="Add"; break; case CHANGE: fAction="Change"; break; case DELETE: fAction="Delete"; break; default: throw new IllegalArgumentException( "Event action code " + action + " is not valid" ); } } /** * Constructs an Event object to encapsulate an inbound SIF Event. This form * of constructor is called internally by the ADK when it receives a SIF_Event * message.<p> * * @param data A DataObjectInputStream that returns SIFDataObjects, all of * which must be of the same class type * @param action Describes how the data has changed * @param objectType An ElementDef constant from the {@linkplain openadk.library.SIFDTD} class that * identifies the type of SIF Data Object contained in the event */ public Event( DataObjectInputStream data, String action, ElementDef objectType ) { fData = data; fObjType = objectType; fAction = action; } /** * Constructs an Event object to encapsulate an outbound SIF Event, which * describes one or more SIF Data Objects that have been added, changed, or * deleted by the local application. This form of constructor is called by * agents when reporting a SIF Event message to a zone.<p> * * @param data A SIFDataObject * @param action Describes how the data has changed. One of the * following flags: <code>ADD</code>, <code>CHANGE</code>, or <code>DELETE</code> * @see openadk.library.EventAction * @see openadk.library.Zone#reportEvent(Event) */ public Event( SIFDataObject data, EventAction action ) { try { fData = DataObjectInputStreamImpl.newInstance(); if( data != null ) ((DataObjectInputStreamImpl)fData).setData( new SIFDataObject[] { data } ); } catch( ADKException adke ) { throw new RuntimeException( adke.toString() ); } fObjType = data != null ? data.getElementDef() : null; switch( action ) { case ADD: fAction="Add"; break; case CHANGE: fAction="Change"; break; case DELETE: fAction="Delete"; break; default: throw new IllegalArgumentException( "Event action code " + action + " is not valid" ); } } /** * Constructs an Event object to encapsulate an outbound SIF Event, which * describes one or more SIF Data Objects that have been added, changed, or * deleted by the local application. This form of constructor is called by * agents when reporting a SIF Event message to a zone.<p> * * @param data * @param action * @param contexts */ public Event( SIFDataObject data, EventAction action, SIFContext... contexts ) { this( data, action ); setContexts( contexts ); } /** * Constructs an Event object to encapsulate an outbound SIF Event, which * describes one or more SIF Data Objects that have been added, changed, or * deleted by the local application. This form of constructor is called by * agents when reporting a SIF Event message to a zone.<p> * * @param data An array of SIFDataObjects, all of which must be of the same class type * @param action Describes how the data has changed: in SIF, this string should * be "Add", "Change", or "Delete" * * @see openadk.library.Zone#reportEvent(Event) */ public Event( SIFDataObject[] data, String action ) { try { fData = DataObjectInputStreamImpl.newInstance(); if( data != null ) ((DataObjectInputStreamImpl)fData).setData( data ); } catch( ADKException adke ) { throw new RuntimeException( adke.toString() ); } fObjType = data != null && data.length > 0 && data[0] != null ? data[0].getElementDef() : null; fAction = action; } /** * Gets the SIF Data Objects in the Event payload<p> * @return An input stream from which the agent can read the individual * SIFDataObjects contained in the event */ public DataObjectInputStream getData() { return fData; } /** * Identifies the type of SIF Data Object contained in the Event payload * @return An ElementDef constant from the {@linkplain openadk.library.SIFDTD} class that identifies the * type of SIF Data Object contained in the event. All objects in an Event * must be of the same type. */ public ElementDef getObjectType() { return fObjType; } /** * Gets the action code identifying how the data in the Event payload has changed<p> * * @return One of the action codes defined by this class. <code>UNDEFINED</code> * is returned if the ADK could not parse the value of the <code>@Action</code> * attribute specified in the SIF_Event message (call {@link #getActionString} * to inspect the actual Action attribute value) * * @see EventAction * @see #getActionString */ public EventAction getAction() { if( fAction.equalsIgnoreCase("Add") ) return EventAction.ADD; if( fAction.equalsIgnoreCase("Change") ) return EventAction.CHANGE; if( fAction.equalsIgnoreCase("Delete") ) return EventAction.DELETE; return EventAction.UNDEFINED; } /** * Gets the action string that was assigned to the <code>SIF_Event/@Action</code> attribute<p> * @return An action string (e.g. "Add", "Change", or "Delete") * @see #getAction */ public String getActionString() { return fAction; } /** * Called internally by the ADK to track the zone from which this event * originated. Note: Calling this method for outbound Events created by an agent * has no effect. * @param zone The Zone the SIF_Event message was received from */ public void setZone( Zone zone ) { fZone = zone; } /** * Gets the Zone from which an inbound event originated. * @return The Zone the SIF_Event message was received from */ public Zone getZone() { return fZone; } /** * Sets the SIF Contexts to which this event applies. If not set, the event * applies to the default SIF Context * @param contexts One or more contexts to which this event applies * @see SIFContext#DEFAULT */ public void setContexts(SIFContext... contexts) { if( contexts == null || contexts.length == 0 ) { throw new IllegalArgumentException( "Event must apply to one or more SIF Contexsts. SIFContext cannot be null" ); } this.fContexts = contexts; } /** * Gets the SIF Contexts that this event applies to. If the context has not been set, * it defaults to the SIF Default context * @return An array of SIF contexts to which this event applies * @see SIFContext#DEFAULT */ public SIFContext[] getContexts() { return fContexts; } }