View Javadoc
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