1 /*
2 * Throwables.java
3 * Created on September 17, 2003
4 *
5 * The Blues Framework - A lightweight application framework
6 * Copyright (C) 2003 Lonnie Pryor
7 * http://blues.lonniepryor.com
8 *
9 * This library is free software; you can redistribute it and/or modify it under the
10 * terms of the GNU Lesser General Public License as published by the Free Software
11 * Foundation; either version 2.1 of the License, or (at your option) any later
12 * version.
13 *
14 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
16 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License along
19 * with this library; if not, write to:
20 *
21 * The Free Software Foundation, Inc.
22 * 59 Temple Place, Suite 330
23 * Boston, MA 02111-1307 USA
24 *
25 */
26 package com.lonniepryor.blues.util;
27
28 import java.util.ArrayList;
29 import java.util.List;
30
31 /***
32 * Specification interface for identifying sets of Types. Instances of this class
33 * may be logically combined using the AND, OR, and NOT operations. Many common
34 * use-cases are supplied via static accessor methods.
35 *
36 * @author Lonnie Pryor
37 * @version $Revision: 1.1 $
38 */
39 public abstract class Throwables {
40 /*** A specification matching any not-null throwable set. */
41 private static final Throwables any = new Throwables() {
42 protected boolean evaluate (Class[] throwableTypes) {
43 return true;
44 }
45 };
46
47 /***
48 * Creates a new Throwables object.
49 */
50 protected Throwables () {
51 }
52
53 /***
54 * Returns a specification matching any not-null throwable set.
55 *
56 * @return A specification matching any not-null throwable set.
57 */
58 public static Throwables any () {
59 return any;
60 }
61
62 /***
63 * Returns a specification matching any throwable set containing an element that
64 * satisfies the supplied specification.
65 *
66 * @param specification The specification that any element in canidate throwable
67 * sets must match.
68 *
69 * @return A specification matching any throwable set containing an element that
70 * satisfies the supplied specification.
71 */
72 public static Throwables containing (final Types specification) {
73 if (specification == null)
74 throw new NullPointerException("specification");
75 return new Throwables() {
76 protected boolean evaluate (Class[] throwableTypes) {
77 return specification.isSatisifiedByAny(throwableTypes);
78 }
79 };
80 }
81
82 /***
83 * Parses a pattern string into a complete Throwables specification. Format:
84 * <pre>
85 * throwables ::= element [ "," element ]...
86 * element ::= [ "!" ] ( types | ( "(" types-expr ")" ) )
87 * </pre>
88 *
89 * @param throwablesPattern The content of the pattern.
90 *
91 * @return A Throwables specification from the supplied pattern.
92 *
93 * @throws ParseException if the pattern is invalid.
94 */
95 public static Throwables parse (String throwablesPattern) {
96 if (throwablesPattern == null)
97 throw new NullPointerException("throwablesPattern");
98 return readElement(throwablesPattern, 0);
99 }
100
101 /***
102 * Recursivly reads sequental throwables pattern elements.
103 *
104 * @param throwablesPattern The content of the pattern.
105 * @param index The index in the pattern.
106 *
107 * @return A Throwables specification from the supplied pattern.
108 *
109 * @throws ParseException if the pattern is invalid.
110 */
111 private static Throwables readElement (String throwablesPattern, int index) {
112 boolean not = false;
113 while (index < throwablesPattern.length()) {
114 if (throwablesPattern.charAt(index) == '!') {
115 if (not)
116 throw new ParseException(
117 "Illegal double NOT in '" + throwablesPattern + "'");
118 not = true;
119 } else if (!Character.isWhitespace(throwablesPattern.charAt(index)))
120 break;
121 ++index;
122 }
123 Types classSpec = null;
124 int nextComma = throwablesPattern.indexOf(',', index);
125 int elementStart = Expression.ltrim(
126 throwablesPattern, index,
127 (nextComma < 0) ? throwablesPattern.length() : nextComma);
128 int elementEnd = Expression.rtrim(
129 throwablesPattern, elementStart,
130 (nextComma < 0) ? throwablesPattern.length() : nextComma);
131 if (elementEnd == elementStart)
132 throw new ParseException("Invalid empty throwables pattern element");
133 classSpec = (throwablesPattern.charAt(elementStart) == '(')
134 ? Types.parseExpression(
135 throwablesPattern.substring(elementStart, elementEnd))
136 : Types.parse(throwablesPattern.substring(elementStart, elementEnd));
137 Throwables result = Throwables.containing(classSpec);
138 if (not)
139 result = result.not();
140
141 return (nextComma < 0) ? result
142 : result.and(
143 readElement(throwablesPattern, nextComma + 1));
144 }
145
146 /***
147 * Returns true if the supplied throwable set is not null and satisfies this
148 * specification.
149 *
150 * @param throwableTypes The throwable set to test.
151 *
152 * @return True if the supplied throwable set is not null and satisfies this
153 * specification.
154 */
155 public final boolean isSatisfiedBy (Class[] throwableTypes) {
156 return (throwableTypes != null) && evaluate(throwableTypes);
157 }
158
159 /***
160 * Returns true if the supplied throwable set satisfies this specification.
161 *
162 * @param throwableTypes The throwable set to test.
163 *
164 * @return True if the supplied throwable set satisfies this specification.
165 */
166 protected abstract boolean evaluate (Class[] throwableTypes);
167
168 /***
169 * Returns true if all of the supplied throwable sets satisfy this specification.
170 *
171 * @param all The array of throwable sets to test.
172 *
173 * @return True if all of the supplied throwable sets satisfy this specification.
174 */
175 public final boolean isSatisifiedByAll (Class[][] all) {
176 if (all == null)
177 throw new NullPointerException("all");
178 for (int i = 0; i < all.length; ++i)
179 if (!isSatisfiedBy(all[i]))
180 return false;
181 return true;
182 }
183
184 /***
185 * Returns true if any of the supplied throwable sets satisfy this specification.
186 *
187 * @param any The array of throwable sets to test.
188 *
189 * @return True if any of the supplied throwable sets satisfy this specification.
190 */
191 public final boolean isSatisifiedByAny (Class[][] any) {
192 if (any == null)
193 throw new NullPointerException("any");
194 for (int i = 0; i < any.length; ++i)
195 if (isSatisfiedBy(any[i]))
196 return true;
197 return false;
198 }
199
200 /***
201 * Selects the first throwable set that satisfies this specification from the
202 * supplied array.
203 *
204 * @param from The array of throwable sets to select from.
205 *
206 * @return The first throwable set that satisfies this specification from the
207 * supplied array.
208 */
209 public final Class[] selectFirst (Class[][] from) {
210 if (from == null)
211 throw new NullPointerException("from");
212 for (int i = 0; i < from.length; ++i)
213 if (isSatisfiedBy(from[i]))
214 return from[i];
215 return null;
216 }
217
218 /***
219 * Selects all the throwable sets that satisfy this specification from the
220 * supplied array.
221 *
222 * @param from The array of throwable sets to select from.
223 *
224 * @return All the throwable sets that satisfy this specification from the
225 * supplied array.
226 */
227 public final Class[][] selectAll (Class[][] from) {
228 if (from == null)
229 throw new NullPointerException("from");
230 List results = new ArrayList(from.length);
231 for (int i = 0; i < from.length; ++i)
232 if (isSatisfiedBy(from[i]))
233 results.add(from[i]);
234 return (Class[][])results.toArray(new Class[results.size()][]);
235 }
236
237 /***
238 * Returns a specification representing a logical AND of this specification on
239 * the left and the supplied specification on the right.
240 *
241 * @param specification The specification to AND with.
242 *
243 * @return A specification representing a logical AND of this specification on
244 * the left and the supplied specification on the right.
245 */
246 public final Throwables and (final Throwables specification) {
247 if (specification == null)
248 throw new NullPointerException("specification");
249 return new Throwables() {
250 protected boolean evaluate (Class[] throwableTypes) {
251 return Throwables.this.evaluate(throwableTypes)
252 && specification.evaluate(throwableTypes);
253 }
254 };
255 }
256
257 /***
258 * Returns a specification representing a logical OR of this specification on the
259 * left and the supplied specification on the right.
260 *
261 * @param specification The specification to OR with.
262 *
263 * @return A specification representing a logical OR of this specification on the
264 * left and the supplied specification on the right.
265 */
266 public final Throwables or (final Throwables specification) {
267 if (specification == null)
268 throw new NullPointerException("specification");
269 return new Throwables() {
270 protected boolean evaluate (Class[] throwableTypes) {
271 return Throwables.this.evaluate(throwableTypes)
272 || specification.evaluate(throwableTypes);
273 }
274 };
275 }
276
277 /***
278 * Returns a specification representing a logical NOT of this specification.
279 *
280 * @return A specification representing a logical NOT of this specification.
281 */
282 public final Throwables not () {
283 return new Throwables() {
284 protected boolean evaluate (Class[] throwableTypes) {
285 return !Throwables.this.evaluate(throwableTypes);
286 }
287 };
288 }
289 }
This page was automatically generated by Maven