We love to revamp! Created a set of listener interfaces which are used

with distributed objects rather than having a single handleEvent() by
which all subscribers are forced to hear about all events. Now one
subscribes separately and then adds onesself as any of a few types of
listener once they have access to the subscribed object reference.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@439 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-10-12 00:03:03 +00:00
parent de8d9dabd1
commit 804505890f
34 changed files with 534 additions and 323 deletions
@@ -0,0 +1,23 @@
//
// $Id: AttributeChangeListener.java,v 1.1 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
/**
* Implemented by entites which wish to hear about attribute changes that
* take place for a particular distributed object.
*
* @see DObject#addListener
*/
public interface AttributeChangeListener
{
/**
* Called when an attribute changed event has been dispatched on an
* object. This will be called <em>after</em> the event has been
* applied to the object. So fetching the attribute during this call
* will provide the new value for the attribute.
*
* @param event The event that was dispatched on the object.
*/
public void attributeChanged (AttributeChangedEvent event);
}
@@ -1,5 +1,5 @@
//
// $Id: AttributeChangedEvent.java,v 1.9 2001/10/11 04:07:52 mdb Exp $
// $Id: AttributeChangedEvent.java,v 1.10 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -121,11 +121,13 @@ public class AttributeChangedEvent extends TypedEvent
return true;
}
// documentation inherited
public short getType ()
{
return TYPE;
}
// documentation inherited
public void writeTo (DataOutputStream out)
throws IOException
{
@@ -134,6 +136,7 @@ public class AttributeChangedEvent extends TypedEvent
ValueMarshaller.writeTo(out, _value);
}
// documentation inherited
public void readFrom (DataInputStream in)
throws IOException
{
@@ -142,6 +145,15 @@ public class AttributeChangedEvent extends TypedEvent
_value = ValueMarshaller.readFrom(in);
}
// documentation inherited
protected void notifyListener (Object listener)
{
if (listener instanceof AttributeChangeListener) {
((AttributeChangeListener)listener).attributeChanged(this);
}
}
// documentation inherited
protected void toString (StringBuffer buf)
{
buf.append("CHANGE:");
@@ -1,5 +1,5 @@
//
// $Id: DEvent.java,v 1.6 2001/10/11 04:07:52 mdb Exp $
// $Id: DEvent.java,v 1.7 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -63,6 +63,18 @@ public abstract class DEvent
_toid = targetOid;
}
/**
* Events with associated listener interfaces should implement this
* function and notify the supplied listener if it implements their
* event listening interface. For example, the {@link
* AttributeChangedEvent} will notify listeners that implement
* {@AttributeChangeListener}.
*/
protected void notifyListener (Object listener)
{
// the default is to do nothing
}
/**
* Constructs and returns a string representation of this event.
*/
@@ -1,5 +1,5 @@
//
// $Id: DObject.java,v 1.27 2001/10/11 04:07:52 mdb Exp $
// $Id: DObject.java,v 1.28 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -99,7 +99,7 @@ public class DObject
* instead to ensure that everything is done on the proper thread.
* This function can only safely be called directly when you know you
* are operating on the omgr thread (you are in the middle of a call
* to <code>objectAvailable</code> or <code>handleEvent</code>).
* to <code>objectAvailable</code> or to a listener callback).
*
* @see DObjectManager#subscribeToObject
*/
@@ -118,7 +118,7 @@ public class DObject
* instead to ensure that everything is done on the proper thread.
* This function can only safely be called directly when you know you
* are operating on the omgr thread (you are in the middle of a call
* to <code>objectAvailable</code> or <code>handleEvent</code>).
* to <code>objectAvailable</code> or to a listener callback).
*
* @see DObjectManager#unsubscribeFromObject
*/
@@ -135,6 +135,38 @@ public class DObject
}
}
/**
* Adds an event listener to this object. The listener will be
* notified when any events are dispatched on this object that match
* their particular listener interface.
*
* @param listener the listener to be added.
*
* @see EventListener
* @see AttributeChangeListener
* @see SetListener
* @see OidListListener
*/
public void addListener (Object listener)
{
// only add the listener if they're not already there
Object[] els = ListUtil.testAndAdd(_listeners, listener);
if (els != null) {
_listeners = els;
}
}
/**
* Removes an event listener from this object. The listener will no
* longer be notified when events are dispatched on this object.
*
* @param listener the listener to be removed.
*/
public void removeListener (Object listener)
{
ListUtil.clear(_listeners, listener);
}
/**
* At times, an entity on the server may need to ensure that events it
* has queued up have made it through the event queue and are applied
@@ -257,36 +289,33 @@ public class DObject
*
* @param event the event that was just applied.
*/
public void notifySubscribers (DEvent event)
public void notifyListeners (DEvent event)
{
// Log.info("Dispatching event to " + _scount +
// " subscribers: " + event);
// iterate over the listener list, performing the necessary
// notifications
int llength = _listeners.length;
for (int i = 0; i < llength; i++) {
Object listener = _listeners[i];
// nothing to do if we've no subscribers
if (_subs == null) {
return;
}
// otherwise iterate over the subscribers array and notify
int slength = _subs.length;
for (int i = 0; i < slength; i++) {
Subscriber sub = (Subscriber)_subs[i];
// skip empty spots
if (sub == null) {
// skip empty slots
if (listener == null) {
continue;
}
// notify the subscriber
if (!sub.handleEvent(event, this)) {
// if they return false, we need to remove them from the
// subscriber list
_subs[i] = null;
try {
// do any event specific notifications
event.notifyListener(listener);
// if we just removed our last subscriber, we need to let
// the omgr know about it
if (--_scount == 0) {
_mgr.removedLastSubscriber(this);
// and notify them if they are listening for all events
if (listener instanceof EventListener) {
((EventListener)listener).eventReceived(event);
}
} catch (Exception e) {
Log.warning("Listener choked during notification " +
"[listener=" + listener +
", event=" + event + "].");
Log.logStackTrace(e);
}
}
}
@@ -469,6 +498,9 @@ public class DObject
/** Our subscribers list. */
protected Object[] _subs;
/** Our event listeners list. */
protected Object[] _listeners;
/** Our subscriber count. */
protected int _scount;
}
@@ -1,5 +1,5 @@
//
// $Id: EntryAddedEvent.java,v 1.4 2001/10/11 04:07:52 mdb Exp $
// $Id: EntryAddedEvent.java,v 1.5 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -89,11 +89,13 @@ public class ElementAddedEvent extends TypedEvent
return true;
}
// documentation inherited
public short getType ()
{
return TYPE;
}
// documentation inherited
public void writeTo (DataOutputStream out)
throws IOException
{
@@ -102,6 +104,7 @@ public class ElementAddedEvent extends TypedEvent
ElementUtil.flatten(out, _elem);
}
// documentation inherited
public void readFrom (DataInputStream in)
throws IOException
{
@@ -116,6 +119,15 @@ public class ElementAddedEvent extends TypedEvent
in.readFully(_bytes, 0, bcount);
}
// documentation inherited
protected void notifyListener (Object listener)
{
if (listener instanceof SetListener) {
((SetListener)listener).elementAdded(this);
}
}
// documentation inherited
protected void toString (StringBuffer buf)
{
buf.append("ELADD:");
@@ -1,5 +1,5 @@
//
// $Id: EntryRemovedEvent.java,v 1.5 2001/10/11 04:07:52 mdb Exp $
// $Id: EntryRemovedEvent.java,v 1.6 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -77,11 +77,13 @@ public class ElementRemovedEvent extends TypedEvent
}
// documentation inherited
public short getType ()
{
return TYPE;
}
// documentation inherited
public void writeTo (DataOutputStream out)
throws IOException
{
@@ -90,6 +92,7 @@ public class ElementRemovedEvent extends TypedEvent
ValueMarshaller.writeTo(out, _key);
}
// documentation inherited
public void readFrom (DataInputStream in)
throws IOException
{
@@ -98,6 +101,15 @@ public class ElementRemovedEvent extends TypedEvent
_key = ValueMarshaller.readFrom(in);
}
// documentation inherited
protected void notifyListener (Object listener)
{
if (listener instanceof SetListener) {
((SetListener)listener).elementRemoved(this);
}
}
// documentation inherited
protected void toString (StringBuffer buf)
{
buf.append("ELREM:");
@@ -1,5 +1,5 @@
//
// $Id: EntryUpdatedEvent.java,v 1.2 2001/10/11 04:07:52 mdb Exp $
// $Id: EntryUpdatedEvent.java,v 1.3 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -95,11 +95,13 @@ public class ElementUpdatedEvent extends TypedEvent
return true;
}
// documentation inherited
public short getType ()
{
return TYPE;
}
// documentation inherited
public void writeTo (DataOutputStream out)
throws IOException
{
@@ -108,6 +110,7 @@ public class ElementUpdatedEvent extends TypedEvent
ElementUtil.flatten(out, _elem);
}
// documentation inherited
public void readFrom (DataInputStream in)
throws IOException
{
@@ -122,6 +125,15 @@ public class ElementUpdatedEvent extends TypedEvent
in.readFully(_bytes, 0, bcount);
}
// documentation inherited
protected void notifyListener (Object listener)
{
if (listener instanceof SetListener) {
((SetListener)listener).elementUpdated(this);
}
}
// documentation inherited
protected void toString (StringBuffer buf)
{
buf.append("ELUPD:");
@@ -0,0 +1,25 @@
//
// $Id: EventListener.java,v 1.1 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
/**
* Implemented by entites which wish to hear about all events being
* dispatched on a particular distributed object.
*
* @see DObject#addListener
*/
public interface EventListener
{
/**
* Called when any event has been dispatched on an object. The event
* will be of the derived class that corresponds to the kind of event
* that occurred on the object. This will be called <em>after</em> the
* event has been applied to the object. So fetching an attribute upon
* receiving an attribute changed event will provide the new value for
* the attribute.
*
* @param event The event that was dispatched on the object.
*/
public void eventReceived (DEvent event);
}
@@ -1,5 +1,5 @@
//
// $Id: MessageEvent.java,v 1.6 2001/10/11 04:07:52 mdb Exp $
// $Id: MessageEvent.java,v 1.7 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -86,11 +86,13 @@ public class MessageEvent extends TypedEvent
return true;
}
// documentation inherited
public short getType ()
{
return TYPE;
}
// documentation inherited
public void writeTo (DataOutputStream out)
throws IOException
{
@@ -106,6 +108,7 @@ public class MessageEvent extends TypedEvent
}
}
// documentation inherited
public void readFrom (DataInputStream in)
throws IOException
{
@@ -120,6 +123,15 @@ public class MessageEvent extends TypedEvent
}
}
// documentation inherited
protected void notifyListener (Object listener)
{
if (listener instanceof MessageListener) {
((MessageListener)listener).messageReceived(this);
}
}
// documentation inherited
protected void toString (StringBuffer buf)
{
buf.append("MSG:");
@@ -0,0 +1,20 @@
//
// $Id: MessageListener.java,v 1.1 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
/**
* Implemented by entites which wish to hear about message events that are
* dispatched on a particular distributed object.
*
* @see DObject#addListener
*/
public interface MessageListener
{
/**
* Called when an message event has been dispatched on an object.
*
* @param event The event that was dispatched on the object.
*/
public void messageReceived (MessageEvent event);
}
@@ -1,5 +1,5 @@
//
// $Id: ObjectAddedEvent.java,v 1.5 2001/10/11 04:07:52 mdb Exp $
// $Id: ObjectAddedEvent.java,v 1.6 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -73,11 +73,13 @@ public class ObjectAddedEvent extends TypedEvent
return true;
}
// documentation inherited
public short getType ()
{
return TYPE;
}
// documentation inherited
public void writeTo (DataOutputStream out)
throws IOException
{
@@ -86,6 +88,7 @@ public class ObjectAddedEvent extends TypedEvent
out.writeInt(_oid);
}
// documentation inherited
public void readFrom (DataInputStream in)
throws IOException
{
@@ -94,6 +97,15 @@ public class ObjectAddedEvent extends TypedEvent
_oid = in.readInt();
}
// documentation inherited
protected void notifyListener (Object listener)
{
if (listener instanceof OidListListener) {
((OidListListener)listener).objectAdded(this);
}
}
// documentation inherited
protected void toString (StringBuffer buf)
{
buf.append("OBJADD:");
@@ -1,5 +1,5 @@
//
// $Id: ObjectRemovedEvent.java,v 1.5 2001/10/11 04:07:52 mdb Exp $
// $Id: ObjectRemovedEvent.java,v 1.6 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -74,11 +74,13 @@ public class ObjectRemovedEvent extends TypedEvent
return true;
}
// documentation inherited
public short getType ()
{
return TYPE;
}
// documentation inherited
public void writeTo (DataOutputStream out)
throws IOException
{
@@ -87,6 +89,7 @@ public class ObjectRemovedEvent extends TypedEvent
out.writeInt(_oid);
}
// documentation inherited
public void readFrom (DataInputStream in)
throws IOException
{
@@ -95,6 +98,15 @@ public class ObjectRemovedEvent extends TypedEvent
_oid = in.readInt();
}
// documentation inherited
protected void notifyListener (Object listener)
{
if (listener instanceof OidListListener) {
((OidListListener)listener).objectRemoved(this);
}
}
// documentation inherited
protected void toString (StringBuffer buf)
{
buf.append("OBJREM:");
@@ -0,0 +1,31 @@
//
// $Id: OidListListener.java,v 1.1 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
/**
* Implemented by entites which wish to hear about changes that occur to
* oid list attributes of a particular distributed object.
*
* @see DObject#addListener
*/
public interface OidListListener
{
/**
* Called when an object added event has been dispatched on an
* object. This will be called <em>after</em> the event has been
* applied to the object.
*
* @param event The event that was dispatched on the object.
*/
public void objectAdded (ObjectAddedEvent event);
/**
* Called when an object removed event has been dispatched on an
* object. This will be called <em>after</em> the event has been
* applied to the object.
*
* @param event The event that was dispatched on the object.
*/
public void objectRemoved (ObjectRemovedEvent event);
}
@@ -0,0 +1,40 @@
//
// $Id: SetListener.java,v 1.1 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
/**
* Implemented by entites which wish to hear about changes that occur to
* set attributes of a particular distributed object.
*
* @see DObject#addListener
*/
public interface SetListener
{
/**
* Called when an element added event has been dispatched on an
* object. This will be called <em>after</em> the event has been
* applied to the object.
*
* @param event The event that was dispatched on the object.
*/
public void elementAdded (ElementAddedEvent event);
/**
* Called when an element updated event has been dispatched on an
* object. This will be called <em>after</em> the event has been
* applied to the object.
*
* @param event The event that was dispatched on the object.
*/
public void elementUpdated (ElementUpdatedEvent event);
/**
* Called when an element removed event has been dispatched on an
* object. This will be called <em>after</em> the event has been
* applied to the object.
*
* @param event The event that was dispatched on the object.
*/
public void elementRemoved (ElementRemovedEvent event);
}
@@ -1,5 +1,5 @@
//
// $Id: Subscriber.java,v 1.6 2001/10/11 04:07:52 mdb Exp $
// $Id: Subscriber.java,v 1.7 2001/10/12 00:03:03 mdb Exp $
package com.threerings.presents.dobj;
@@ -10,16 +10,24 @@ package com.threerings.presents.dobj;
* registering as a subscriber to an object, an entity can react to
* changes made to an object and ensure that their object is kept up to
* date.
*
* <p> To actually receive callbacks when events are dispatched on a
* distributed object, an entity should register itself as a listener on
* the object once it has received its object reference.
*
* @see EventListener
* @see AttributeChangeListener
* @see SetListener
* @see OidListListener
*/
public interface Subscriber
{
/**
* Called when a subscription request has succeeded and the object is
* available. If the object was requested for subscription, the
* subscriber will subsequently receive notifications via
* <code>handleEvent</code>. If the object was requested as a one-time
* read-only copy, these updates will not occur and the subscriber
* should not attempt to modify the object.
* subscriber can subsequently receive notifications by registering
* itself as a listener of some sort (see {@link
* DObject#addListener}).
*
* @see DObjectManager#subscribeToObject
*/
@@ -33,23 +41,4 @@ public interface Subscriber
* @see DObjectManager#subscribeToObject
*/
public void requestFailed (int oid, ObjectAccessException cause);
/**
* Called when an event has been dispatched on an object. The event
* will be of the derived class that corresponds to the kind of event
* that occurred on the object. <code>handleEvent</code> will be
* called <em>after</em> the event has been applied to the object. So
* fetching an attribute upon receiving an attribute changed event
* will provide the new value for the attribute.
*
* <p> A subscriber should return true from <code>handleEvent</code>
* unless they wish their subscription to be terminated.
*
* @param event The event dispatched on the object.
* @param target The object on which the event was dispatched.
*
* @return true if the subscriber wishes to remain subscribed to the
* target object, false if they do not.
*/
public boolean handleEvent (DEvent event, DObject target);
}