1
2
3
4
5
6
7 package org.mule.context.notification;
8
9 import org.mule.api.context.notification.ServerNotification;
10 import org.mule.api.context.notification.BlockingServerEvent;
11
12 import java.util.Set;
13 import java.util.HashSet;
14 import java.util.LinkedList;
15 import java.util.Iterator;
16
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 class Node implements RestrictedNode
34 {
35
36
37 public static final int SUCCESS = 0;
38 public static final int FAILURE = 1;
39 public static final int EMPTY = 2;
40
41
42 private Class clazz = null;
43 private int action;
44 private String id;
45 private boolean isIdDefined = false;
46 private boolean nodeOk = false;
47
48 protected final transient Log logger = LogFactory.getLog(this.getClass());
49
50
51 private Set parallel = new HashSet();
52
53 private LinkedList serial = new LinkedList();
54
55 public Node(Class clazz, int action, String id)
56 {
57 this(clazz, action);
58 this.id = id;
59 isIdDefined = true;
60 }
61
62 public Node(Class clazz, int action)
63 {
64 this.clazz = clazz;
65 this.action = action;
66 }
67
68 public Node()
69 {
70 nodeOk = true;
71 }
72
73 public Node parallel(RestrictedNode node)
74 {
75 if (null != node.getNotificationClass() &&
76 BlockingServerEvent.class.isAssignableFrom(node.getNotificationClass()))
77 {
78 logger.warn("Registered blocking event as parallel: " + node);
79 }
80 parallel.add(node);
81 return this;
82 }
83
84
85
86
87
88 public Node parallelSynch(RestrictedNode node)
89 {
90 if (null != node.getNotificationClass() &&
91 !BlockingServerEvent.class.isAssignableFrom(node.getNotificationClass()))
92 {
93 throw new IllegalStateException("Node " + node + " is not a synch event");
94 }
95 parallel.add(node);
96 return this;
97 }
98
99 public RestrictedNode serial(RestrictedNode node)
100 {
101 if (null != node.getNotificationClass() &&
102 !BlockingServerEvent.class.isAssignableFrom(node.getNotificationClass()))
103 {
104 logger.warn("Registered non-blocking event as serial: " + node);
105 }
106 serial.addLast(node);
107 return this;
108 }
109
110
111
112
113
114 public int match(ServerNotification notification)
115 {
116
117 if (!nodeOk)
118 {
119 if (testLocal(notification))
120 {
121 nodeOk = true;
122 return SUCCESS;
123 }
124 else
125 {
126 return FAILURE;
127 }
128 }
129
130
131 if (parallel.size() > 0)
132 {
133 for (Iterator children = parallel.iterator(); children.hasNext();)
134 {
135 Node child = (Node) children.next();
136 switch (child.match(notification))
137 {
138 case SUCCESS:
139 return SUCCESS;
140 case EMPTY:
141 children.remove();
142 break;
143 case FAILURE:
144 break;
145 default:
146 throw new IllegalStateException("Bad return from child");
147 }
148 }
149 }
150
151
152 if (parallel.size() > 0)
153 {
154 return FAILURE;
155 }
156
157
158 if (serial.size() > 0)
159 {
160 for (Iterator children = serial.iterator(); children.hasNext();)
161 {
162 Node child = (Node) children.next();
163 switch (child.match(notification))
164 {
165 case SUCCESS:
166 return SUCCESS;
167 case EMPTY:
168 children.remove();
169 break;
170 case FAILURE:
171 return FAILURE;
172 default:
173 throw new IllegalStateException("Bad return from child");
174 }
175 }
176
177 }
178
179 if (serial.size() > 0)
180 {
181 return FAILURE;
182 }
183 else
184 {
185 return EMPTY;
186 }
187 }
188
189 private boolean testLocal(ServerNotification notification)
190 {
191 return clazz.equals(notification.getClass())
192 && action == notification.getAction()
193 && (!isIdDefined ||
194 (null == id && null == notification.getResourceIdentifier()) ||
195 (null != id && id.equals(notification.getResourceIdentifier())));
196 }
197
198 public boolean contains(Class clazz, int action)
199 {
200 if (null != this.clazz && this.clazz.equals(clazz) && this.action == action)
201 {
202 return true;
203 }
204 for (Iterator children = parallel.iterator(); children.hasNext();)
205 {
206 if (((RestrictedNode) children.next()).contains(clazz, action))
207 {
208 return true;
209 }
210 }
211 for (Iterator children = serial.iterator(); children.hasNext();)
212 {
213 if (((RestrictedNode) children.next()).contains(clazz, action))
214 {
215 return true;
216 }
217 }
218 return false;
219 }
220
221 public RestrictedNode getAnyRemaining()
222 {
223 if (! nodeOk)
224 {
225 return this;
226 }
227 for (Iterator children = parallel.iterator(); children.hasNext();)
228 {
229 RestrictedNode any = ((RestrictedNode) children.next()).getAnyRemaining();
230 if (null != any)
231 {
232 return any;
233 }
234 }
235 for (Iterator children = serial.iterator(); children.hasNext();)
236 {
237 RestrictedNode any = ((RestrictedNode) children.next()).getAnyRemaining();
238 if (null != any)
239 {
240 return any;
241 }
242 }
243 return null;
244 }
245
246 public boolean isExhausted()
247 {
248 return null == getAnyRemaining();
249 }
250
251 public Class getNotificationClass()
252 {
253 return clazz;
254 }
255
256 public String toString()
257 {
258 return clazz + ": " + action + (isIdDefined ? ": " + id : "");
259 }
260
261 }