1 package org.apache.beehive.controls.runtime.bean; 2 3 20 21 import java.io.File ; 22 import java.lang.annotation.Annotation ; 23 import java.lang.reflect.Method ; 24 import java.net.MalformedURLException ; 25 import java.net.URI ; 26 import java.net.URL ; 27 import java.text.ParseException ; 28 import java.text.SimpleDateFormat ; 29 import java.util.ArrayList ; 30 import java.util.Collection ; 31 import java.util.Date ; 32 import java.util.Iterator ; 33 import java.util.Map ; 34 import java.util.Map.Entry; 35 36 import org.apache.beehive.controls.api.bean.AnnotationMemberTypes; 37 import org.apache.beehive.controls.api.bean.AnnotationConstraints.MembershipRule; 38 import org.apache.beehive.controls.api.bean.AnnotationConstraints.MembershipRuleValues; 39 import org.apache.beehive.controls.api.properties.PropertyKey; 40 import org.apache.beehive.controls.api.properties.PropertySet; 41 42 52 public class AnnotationConstraintValidator 53 { 54 55 public AnnotationConstraintValidator() 56 { 57 super(); 58 } 59 60 74 public static void validate(PropertyKey key, Object value) 75 throws IllegalArgumentException 76 { 77 validate(key.getAnnotations(), value); 78 } 79 80 86 public static void validateMembership(Annotation propertySet) 87 { 88 Class c = propertySet.annotationType(); 89 MembershipRule rule = (MembershipRule) c 90 .getAnnotation(MembershipRule.class); 91 if (rule == null) 92 return; 93 MembershipRuleValues ruleValue = rule.value(); 94 String [] memberNames = rule.memberNames(); 95 Method [] members = getMembers(c, memberNames); 96 int i = getNumOfMembersSet(propertySet, members); 97 if (ruleValue == MembershipRuleValues.ALL_IF_ANY) 98 { 99 if (i != 0 && i != members.length) 100 throw new IllegalArgumentException ("The membership rule on " + propertySet.toString() + 101 " is not satisfied. Either all members must be set or none is set"); 102 } 103 else if (ruleValue == MembershipRuleValues.EXACTLY_ONE) 104 { 105 if (i != 1) 106 throw new IllegalArgumentException ("The membership rule on " + propertySet.toString() + 107 " is not satisfied. Exactly one member must be set"); 108 } 109 else if (ruleValue == MembershipRuleValues.AT_LEAST_ONE) 110 { 111 if (i < 1) 112 throw new IllegalArgumentException ("The membership rule on " + propertySet.toString() + 113 " is not satisfied. At least one member must be set"); 114 } 115 else if (ruleValue == MembershipRuleValues.AT_MOST_ONE) 116 { 117 if (i > 1) 118 throw new IllegalArgumentException ("The membership rule on " + propertySet.toString() + 119 " is not satisfied. At most one member may be set"); 120 } 121 } 122 123 private static Method [] getMembers(Class <? extends Annotation > c, String [] memberNames) 124 { 125 Method [] methods = null; 126 if (memberNames == null || memberNames.length == 0) 127 { 128 methods = c.getDeclaredMethods(); 129 } 130 else 131 { 132 methods = new Method [memberNames.length]; 133 for (int i = 0; i < memberNames.length; i++) 134 { 135 try 136 { 137 methods[i] = c.getMethod(memberNames[i], (Class []) null); 138 } 139 catch (Exception e) 140 { 141 } 143 } 144 } 145 return methods; 146 } 147 148 private static int getNumOfMembersSet(Annotation propertySet, 149 Method [] members) 150 { 151 int num = 0; 152 for (Method m : members) 153 { 154 Class returnType = m.getReturnType(); 155 Object o = null; 156 try 157 { 158 o = m.invoke(propertySet, (Object []) null); 159 } 160 catch (Exception e) 161 { 162 throw new RuntimeException (e); 164 } 165 166 if ((returnType == String .class && !((String ) o) 167 .equals(AnnotationMemberTypes.OPTIONAL_STRING)) 168 || (returnType == int.class && ((Integer ) o).intValue() != AnnotationMemberTypes.OPTIONAL_INT) 169 || (returnType == short.class && ((Short ) o) 170 .shortValue() != AnnotationMemberTypes.OPTIONAL_SHORT) 171 || (returnType == long.class && ((Long ) o).longValue() != AnnotationMemberTypes.OPTIONAL_LONG) 172 || (returnType == float.class && ((Float ) o) 173 .floatValue() != AnnotationMemberTypes.OPTIONAL_FLOAT) 174 || (returnType == double.class && ((Double ) o) 175 .doubleValue() != AnnotationMemberTypes.OPTIONAL_DOUBLE) 176 || (returnType == char.class && ((Character ) o) 177 .charValue() != AnnotationMemberTypes.OPTIONAL_CHAR) 178 || (returnType == byte.class && ((Byte ) o).byteValue() != AnnotationMemberTypes.OPTIONAL_BYTE) 179 || (returnType == boolean.class && !((Boolean ) o) 180 .booleanValue())) 181 num++; 182 } 183 return num; 184 } 185 186 protected static synchronized void validate(Annotation [] annotations, 187 Object value) throws IllegalArgumentException 188 { 189 190 boolean optional = false; 195 for (Annotation a : annotations) 196 { 197 if (a instanceof AnnotationMemberTypes.Optional) 198 { 199 optional = true; 200 break; 201 } 202 } 203 204 for (Annotation a : annotations) 205 { 206 if (a instanceof AnnotationMemberTypes.Text) 207 validateText((AnnotationMemberTypes.Text) a, value, optional); 208 else if (a instanceof AnnotationMemberTypes.Decimal) 209 validateDecimal((AnnotationMemberTypes.Decimal) a, value, 210 optional); 211 else if (a instanceof AnnotationMemberTypes.Int) 212 validateInt((AnnotationMemberTypes.Int) a, value, optional); 213 else if (a instanceof AnnotationMemberTypes.Date) 214 validateDate((AnnotationMemberTypes.Date) a, value, optional); 215 else if (a instanceof AnnotationMemberTypes.FilePath) 216 validateFilePath((AnnotationMemberTypes.FilePath) a, value, 217 optional); 218 else if (a instanceof AnnotationMemberTypes.JndiName) 219 validateJndiName((AnnotationMemberTypes.JndiName) a, value, 220 optional); 221 else if (a instanceof AnnotationMemberTypes.QName) 222 validateQName((AnnotationMemberTypes.QName) a, value, optional); 223 else if (a instanceof AnnotationMemberTypes.URI) 224 validateURI((AnnotationMemberTypes.URI) a, value, optional); 225 else if (a instanceof AnnotationMemberTypes.URL) 226 validateURL((AnnotationMemberTypes.URL) a, value, optional); 227 else if (a instanceof AnnotationMemberTypes.URN) 228 validateURN((AnnotationMemberTypes.URN) a, value, optional); 229 else if (a instanceof AnnotationMemberTypes.XML) 230 validateXML((AnnotationMemberTypes.XML) a, value, optional); 231 } 232 } 233 234 private static void validateXML(AnnotationMemberTypes.XML a, Object value, 235 boolean optional) 236 { 237 } 238 239 private static void validateURN(AnnotationMemberTypes.URN a, Object value, 240 boolean optional) 241 { 242 if (optional 243 && (value == null || value 244 .equals(AnnotationMemberTypes.OPTIONAL_STRING))) 245 return; 246 247 if (!(value instanceof String )) 248 { 249 error("The value, " 250 + value 251 + ", assigned to an URN property must be of type java.lang.String."); 252 } 253 254 URI.create((String ) value); 255 } 256 257 private static void validateURL(AnnotationMemberTypes.URL a, Object value, 258 boolean optional) 259 { 260 if (optional 261 && (value == null || value 262 .equals(AnnotationMemberTypes.OPTIONAL_STRING))) 263 return; 264 265 if (!(value instanceof String )) 266 { 267 error("The value, " 268 + value 269 + ", assigned to an URL property must be of type java.lang.String."); 270 } 271 272 try 273 { 274 new URL ((String ) value); 275 } 276 catch (MalformedURLException mue) 277 { 278 error("The value, " + value 279 + ", assigned to the URL property is a malformed URL.", mue); 280 } 281 } 282 283 private static void validateURI(AnnotationMemberTypes.URI a, Object value, 284 boolean optional) 285 { 286 if (optional 287 && (value == null || value 288 .equals(AnnotationMemberTypes.OPTIONAL_STRING))) 289 return; 290 291 if (!(value instanceof String )) 292 { 293 error("The value, " 294 + value 295 + ", assigned to an URI property must be of type java.lang.String."); 296 } 297 298 URI.create((String ) value); 299 } 300 301 private static void validateQName(AnnotationMemberTypes.QName a, 302 Object value, boolean optional) 303 { 304 } 305 306 private static void validateJndiName(AnnotationMemberTypes.JndiName a, 307 Object value, boolean optional) 308 { 309 } 310 311 private static void validateFilePath(AnnotationMemberTypes.FilePath a, 312 Object value, boolean optional) 313 { 314 if (optional 315 && (value == null || value 316 .equals(AnnotationMemberTypes.OPTIONAL_STRING))) 317 return; 318 319 if (!(value instanceof String )) 320 { 321 error("The value, " 322 + value 323 + ", assigned to a FilePath property must be of type java.lang.String."); 324 } 325 326 337 } 338 339 private static void validateDate(AnnotationMemberTypes.Date a, 340 Object value, boolean optional) 341 { 342 if (optional 343 && (value == null || value 344 .equals(AnnotationMemberTypes.OPTIONAL_STRING))) 345 return; 346 347 if (!(value instanceof String )) 348 { 349 error("The value, " 350 + value 351 + ", assigned to a date property must be of type java.lang.String."); 352 } 353 354 try 355 { 356 String format = a.format(); 357 358 Date date = parseDate(format , (String ) value); 359 360 String minValue = a.minValue(); 361 if (minValue != null && minValue.length() > 0) 362 { 363 Date minDate = parseDate(format, a.minValue()); 364 if (minDate.compareTo(date) > 0) 365 { 366 error("The date, " 367 + value 368 + ", assigned to a date property is earlier than the earliest date allowed: " 369 + minValue); 370 } 371 } 372 String maxValue = a.maxValue(); 373 if (maxValue != null && maxValue.length() > 0) 374 { 375 Date maxDate = parseDate(format, a.maxValue()); 376 if (maxDate.compareTo(date) < 0) 377 { 378 error("The date, " 379 + value 380 + ", assigned to a date property is later than the latest date allowed: " 381 + maxValue); 382 } 383 } 384 } 385 catch (ParseException pe) 386 { 387 error("Value assigned to a date property is not in the specified format."); 388 } 389 390 } 391 392 public static Date parseDate(String format, String value) throws ParseException 393 { 394 SimpleDateFormat sdFormat = new SimpleDateFormat (format); 395 sdFormat.setLenient(false); 396 return sdFormat.parse(value); 397 } 398 399 403 private static void validateInt(AnnotationMemberTypes.Int a, Object value, 404 boolean optional) 405 { 406 if (optional 407 && (value == null || 408 value.equals(AnnotationMemberTypes.OPTIONAL_STRING) || 409 value.equals(AnnotationMemberTypes.OPTIONAL_INT))) 410 return; 411 412 int intValue = 0; 413 414 if (value instanceof String ) 415 { 416 try 417 { 418 intValue = Integer.parseInt((String ) value); 419 } 420 catch (NumberFormatException nfe) 421 { 422 error("The value ," 423 + value 424 + ", assigned to an int property does not represent an integer."); 425 } 426 } 427 else if (value instanceof Integer ) 428 { 429 intValue = ((Integer ) value).intValue(); 430 } 431 else 432 { 433 error("The value, " 434 + value 435 + ", assigned to an int property must be of type java.lang.String or int."); 436 } 437 438 if (intValue < a.minValue()) 439 error("The value, " 440 + intValue 441 + ", assigned to an int property is less than the minimum value allowed: " 442 + a.minValue() + "."); 443 else if (intValue > a.maxValue()) 444 error("The value, " 445 + intValue 446 + ", assigned to an int property exeeds the maximum value allowed: " 447 + a.maxValue() + "."); 448 } 449 450 private static void validateDecimal(AnnotationMemberTypes.Decimal a, 451 Object value, boolean optional) 452 { 453 if (optional 454 && (value == null || 455 value.equals(AnnotationMemberTypes.OPTIONAL_STRING) || 456 value.equals(AnnotationMemberTypes.OPTIONAL_FLOAT) || 457 value.equals(AnnotationMemberTypes.OPTIONAL_DOUBLE))) 458 return; 459 460 double doubleValue = 0; 461 String doubleString = null; 462 463 if (value instanceof String ) 464 { 465 doubleValue = Double.parseDouble((String )value); 466 doubleString = (String )value; 467 } 468 else if (value instanceof Float ) 469 { 470 doubleValue = ((Float )value).doubleValue(); 471 doubleString = ((Float )value).toString(); 472 } 473 else if (value instanceof Double ) 474 { 475 doubleValue = ((Double )value).doubleValue(); 476 doubleString = ((Double )value).toString(); 477 } 478 else 479 { 480 error("The value, " 481 + value 482 + ", assigned to a decimal property must be of type float, double, or java.lang.String."); 483 } 484 485 if (doubleValue < a.minValue()) 486 error("The value, " 487 + doubleValue 488 + ", assigned to a decimal property is less than the the minimum value allowed: " 489 + a.minValue() + "."); 490 491 if (doubleValue > a.maxValue()) 492 error("The value, " 493 + doubleValue 494 + ", assigned to a decimal property exceeds the maximum value allowed: " 495 + a.maxValue() + "."); 496 497 int decimalPos = doubleString.indexOf('.'); 498 499 if (decimalPos == -1) 500 return; 501 502 if (doubleString.length() - decimalPos - 1 > a.places()) 503 error("The decimal places in the value, " + doubleString 504 + ", assigned to a decimal property exceeds " + a.places() 505 + ", the number of decimal places allowed."); 506 507 } 508 509 private static void validateText(AnnotationMemberTypes.Text a, 510 Object value, boolean optional) 511 { 512 if (optional 513 && (value == null || value 514 .equals(AnnotationMemberTypes.OPTIONAL_STRING))) 515 return; 516 517 if (!(value instanceof String )) 518 error("The value, " 519 + value 520 + ", assigned to a text property must be of type java.lang.String."); 521 522 String str = (String ) value; 523 if (str.length() > a.maxLength()) 524 error("The value, " 525 + str 526 + ", assigned to a text property exceeds the maximum length allowed: " 527 + a.maxLength()); 528 529 if (a.isLong()) 530 { 531 try 532 { 533 Long.parseLong(str); 534 } 535 catch (NumberFormatException nfe) 536 { 537 error("The value, " 538 + str 539 + ", assigned to a text property with a long number constraint does not represent a long number."); 540 } 541 } 542 543 } 544 545 private static void error(String message) 546 { 547 error(message, null); 548 } 549 550 private static void error(String message, Throwable t) 551 { 552 throw new IllegalArgumentException (message, t); 553 } 554 555 } 556 | Popular Tags |