001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.scxml;
018:
019: import java.io.Serializable;
020: import java.util.HashMap;
021: import java.util.HashSet;
022: import java.util.Iterator;
023: import java.util.Map;
024: import java.util.Set;
025:
026: import org.apache.commons.scxml.model.SCXML;
027: import org.apache.commons.scxml.model.Transition;
028: import org.apache.commons.scxml.model.TransitionTarget;
029:
030: /**
031: * The registry where SCXML listeners are recorded for nodes of
032: * interest such as the <code>SCXML</code> root,
033: * <code>TransitionTarget</code>s and <code>Transition</code>s.
034: * The notification registry keeps track of all
035: * <code>SCXMLListener</code>s attached and notifies relevant
036: * listeners of the events that interest them.
037: *
038: */
039: public final class NotificationRegistry implements Serializable {
040:
041: /**
042: * Serial version UID.
043: */
044: private static final long serialVersionUID = 1L;
045:
046: /**
047: * The Map of all listeners keyed by Observable.
048: */
049: private Map regs = new HashMap();
050:
051: /**
052: * Constructor.
053: */
054: public NotificationRegistry() {
055: super ();
056: }
057:
058: /**
059: * Register this SCXMLListener for this Observable.
060: *
061: * @param source The observable this listener wants to listen to
062: * @param lst The listener
063: */
064: synchronized void addListener(final Object source,
065: final SCXMLListener lst) {
066: Set entries = (Set) regs.get(source);
067: if (entries == null) {
068: entries = new HashSet();
069: regs.put(source, entries);
070: }
071: entries.add(lst);
072: }
073:
074: /**
075: * Deregister this SCXMLListener for this Observable.
076: *
077: * @param source The observable this listener wants to stop listening to
078: * @param lst The listener
079: */
080: synchronized void removeListener(final Object source,
081: final SCXMLListener lst) {
082: Set entries = (Set) regs.get(source);
083: if (entries != null) {
084: entries.remove(lst);
085: if (entries.size() == 0) {
086: regs.remove(source);
087: }
088: }
089: }
090:
091: /**
092: * Inform all relevant listeners that a TransitionTarget has been
093: * entered.
094: *
095: * @param observable The Observable
096: * @param state The TransitionTarget that was entered
097: */
098: public void fireOnEntry(final TransitionTarget observable,
099: final TransitionTarget state) {
100: Object source = observable;
101: fireOnEntry(source, state);
102: }
103:
104: /**
105: * Inform all relevant listeners that a TransitionTarget has been
106: * entered.
107: *
108: * @param observable The Observable
109: * @param state The TransitionTarget that was entered
110: */
111: public void fireOnEntry(final SCXML observable,
112: final TransitionTarget state) {
113: Object source = observable;
114: fireOnEntry(source, state);
115: }
116:
117: /**
118: * Inform all relevant listeners that a TransitionTarget has been
119: * entered.
120: *
121: * @param source The Observable
122: * @param state The TransitionTarget that was entered
123: */
124: private synchronized void fireOnEntry(final Object source,
125: final TransitionTarget state) {
126: Set entries = (Set) regs.get(source);
127: if (entries != null) {
128: for (Iterator iter = entries.iterator(); iter.hasNext();) {
129: SCXMLListener lst = (SCXMLListener) iter.next();
130: lst.onEntry(state);
131: }
132: }
133: }
134:
135: /**
136: * Inform all relevant listeners that a TransitionTarget has been
137: * exited.
138: *
139: * @param observable The Observable
140: * @param state The TransitionTarget that was exited
141: */
142: public void fireOnExit(final TransitionTarget observable,
143: final TransitionTarget state) {
144: Object source = observable;
145: fireOnExit(source, state);
146: }
147:
148: /**
149: * Inform all relevant listeners that a TransitionTarget has been
150: * exited.
151: *
152: * @param observable The Observable
153: * @param state The TransitionTarget that was exited
154: */
155: public void fireOnExit(final SCXML observable,
156: final TransitionTarget state) {
157: Object source = observable;
158: fireOnExit(source, state);
159: }
160:
161: /**
162: * Inform all relevant listeners that a TransitionTarget has been
163: * exited.
164: *
165: * @param source The Observable
166: * @param state The TransitionTarget that was exited
167: */
168: private synchronized void fireOnExit(final Object source,
169: final TransitionTarget state) {
170: Set entries = (Set) regs.get(source);
171: if (entries != null) {
172: for (Iterator iter = entries.iterator(); iter.hasNext();) {
173: SCXMLListener lst = (SCXMLListener) iter.next();
174: lst.onExit(state);
175: }
176: }
177: }
178:
179: /**
180: * Inform all relevant listeners of a transition that has occured.
181: *
182: * @param observable The Observable
183: * @param from The source TransitionTarget
184: * @param to The destination TransitionTarget
185: * @param transition The Transition that was taken
186: */
187: public void fireOnTransition(final Transition observable,
188: final TransitionTarget from, final TransitionTarget to,
189: final Transition transition) {
190: Object source = observable;
191: fireOnTransition(source, from, to, transition);
192: }
193:
194: /**
195: * Inform all relevant listeners of a transition that has occured.
196: *
197: * @param observable The Observable
198: * @param from The source TransitionTarget
199: * @param to The destination TransitionTarget
200: * @param transition The Transition that was taken
201: */
202: public void fireOnTransition(final SCXML observable,
203: final TransitionTarget from, final TransitionTarget to,
204: final Transition transition) {
205: Object source = observable;
206: fireOnTransition(source, from, to, transition);
207: }
208:
209: /**
210: * Inform all relevant listeners of a transition that has occured.
211: *
212: * @param source The Observable
213: * @param from The source TransitionTarget
214: * @param to The destination TransitionTarget
215: * @param transition The Transition that was taken
216: */
217: private synchronized void fireOnTransition(final Object source,
218: final TransitionTarget from, final TransitionTarget to,
219: final Transition transition) {
220: Set entries = (Set) regs.get(source);
221: if (entries != null) {
222: for (Iterator iter = entries.iterator(); iter.hasNext();) {
223: SCXMLListener lst = (SCXMLListener) iter.next();
224: lst.onTransition(from, to, transition);
225: }
226: }
227: }
228:
229: }
|