001: /*
002: * Bossa Workflow System
003: *
004: * $Id: NotificationBus.java,v 1.7 2003/11/20 17:23:17 gdvieira Exp $
005: *
006: * Copyright (C) 2003 OpenBR Sistemas S/C Ltda.
007: *
008: * This file is part of Bossa.
009: *
010: * Bossa is free software; you can redistribute it and/or modify it
011: * under the terms of version 2 of the GNU General Public License as
012: * published by the Free Software Foundation.
013: *
014: * This program is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * General Public License for more details.
018: *
019: * You should have received a copy of the GNU General Public
020: * License along with this program; if not, write to the
021: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
022: * Boston, MA 02111-1307, USA.
023: */
024:
025: package com.bigbross.bossa.notify;
026:
027: import java.io.IOException;
028: import java.io.Serializable;
029: import java.util.ArrayList;
030: import java.util.HashMap;
031: import java.util.Iterator;
032: import java.util.List;
033: import java.util.Map;
034:
035: import com.bigbross.bossa.Bossa;
036: import com.bigbross.bossa.resource.Resource;
037: import com.bigbross.bossa.resource.ResourceManager;
038: import com.bigbross.bossa.wfnet.WFNetEvents;
039:
040: /**
041: * This class manages all event notifications inside Bossa. The events are
042: * notified to listeners registered in the bus. This registration can happen
043: * either at the bus creation or at a later time. <p>
044: *
045: * The listeners registered after the bus is created will not be preserved
046: * if this bus is serialized. Due to this behaviour, objects outside the Bossa
047: * core that are registered as listeners may lose notification of events if
048: * a failure crashes the system. <p>
049: *
050: * @author <a href="http://www.bigbross.com">BigBross Team</a>
051: */
052: public class NotificationBus implements Serializable {
053:
054: private List persistentListeners;
055:
056: private transient Map transientListeners;
057:
058: private Bossa engine;
059:
060: /**
061: * Creates a new notification bus with some persistent listeners. <p>
062: *
063: * @param engine the bossa engine this notification bus is part.
064: * @param persistentListeners a list of the persistent listeners.
065: */
066: public NotificationBus(Bossa engine, List persistentListeners) {
067: this .engine = engine;
068: this .persistentListeners = persistentListeners != null ? persistentListeners
069: : new ArrayList();
070: this .transientListeners = new HashMap();
071: }
072:
073: /**
074: * Creates a new empty notification bus. <p>
075: *
076: * @param engine the bossa engine this notification bus is part.
077: */
078: public NotificationBus(Bossa engine) {
079: this (engine, null);
080: }
081:
082: /**
083: * Returns the bossa engine this notification bus is part. <p>
084: *
085: * @return the bossa engine this notification bus is part.
086: */
087: Bossa getBossa() {
088: return engine;
089: }
090:
091: /**
092: * Registers a new listener of the notification bus. <p>
093: *
094: * @param listener the object that will act as a listener of the
095: * notification bus.
096: * @return <code>true</code> if the listener is registered,
097: * <code>false</code> if there is already a listener registered
098: * with the same id.
099: */
100: public boolean registerListener(Listener listener) {
101: if (transientListeners.containsKey(listener.getId())) {
102: return false;
103: }
104: transientListeners.put(listener.getId(), listener);
105: return true;
106: }
107:
108: /**
109: * Removes the listener from the notification bus, if present. <p>
110: *
111: * @param id the id of the listener.
112: */
113: public void removeListener(String id) {
114: transientListeners.remove(id);
115: }
116:
117: /**
118: * Informs the occurrence of an event to all registered listeners. <p>
119: *
120: * An event has an id and some attributes that are dependent on the event
121: * type. See the constructor of the <code>Event</code> class for more
122: * information. <p>
123: *
124: * @param event the event.
125: * @see com.bigbross.bossa.notify.Event#Event
126: */
127: public void notifyEvent(Event event) {
128: ResourceManager resourceManager = getBossa() != null ? getBossa()
129: .getResourceManager()
130: : null;
131: Iterator[] iterators = { persistentListeners.iterator(),
132: transientListeners.values().iterator() };
133: for (int i = 0; i < iterators.length; i++) {
134: Iterator it = iterators[i];
135: while (it.hasNext()) {
136: Listener l = (Listener) it.next();
137: singleListenerNotify(event, l, resourceManager);
138: }
139: }
140: }
141:
142: /**
143: * Informs the occurrence of an event to a single listener. <p>
144: *
145: * @param event the event.
146: * @param l the listener.
147: * @param resourceManager the resource manager with respect to will
148: * the resource filtering happen.
149: */
150: private void singleListenerNotify(Event event, Listener l,
151: ResourceManager resourceManager) {
152: if (l.interested(event.getType())) {
153: if (event.getType() == Event.WFNET_EVENT) {
154: String resourceId = (String) event.getAttributes().get(
155: WFNetEvents.ATTRIB_RESOURCE_ID);
156: Resource resource = resourceManager != null ? resourceManager
157: .getResource(resourceId)
158: : null;
159: if (resource != null && l.getResource() != null
160: && !resource.contains(l.getResource())) {
161: return;
162: }
163: }
164: try {
165: l.notifyEvent(event);
166: } catch (Exception e) {
167: /* We ignore listeners exceptions. */
168: }
169: }
170: }
171:
172: /**
173: * @see java.io.Serializable
174: */
175: private void readObject(java.io.ObjectInputStream in)
176: throws IOException, ClassNotFoundException {
177: in.defaultReadObject();
178: /* Initializes the transient listeners map to a blank map. */
179: transientListeners = new HashMap();
180: }
181: }
|