bval-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject [bval] 36/50: [maven-release-plugin] copy for tag 0.4
Date Mon, 10 Jun 2019 05:02:30 GMT
This is an automated email from the ASF dual-hosted git repository.

rmannibucau pushed a commit to tag 0.4
in repository https://gitbox.apache.org/repos/asf/bval.git

commit 07a351b0f50f0688bdae70361b18ca24ead24552
Author: mbenson <mbenson@13f79535-47bb-0310-9956-ffa450edef68>
AuthorDate: Mon Apr 9 17:27:17 2012 +0000

    [maven-release-plugin]  copy for tag 0.4
    
    git-svn-id: http://svn.apache.org/repos/asf/bval/tags/0.4@1311345 13f79535-47bb-0310-9956-ffa450edef68
---
 trunk/CHANGES.txt                                  | 214 ++++++
 trunk/LICENSE                                      | 203 +++++
 trunk/NOTICE                                       |  14 +
 trunk/README.txt                                   |  66 ++
 trunk/bundle/pom.xml                               | 114 +++
 .../src/main/appended-resources/META-INF/NOTICE.vm |  26 +
 trunk/bval-core/pom.xml                            | 159 ++++
 .../src/main/appended-resources/META-INF/NOTICE.vm |  25 +
 .../org/apache/bval/BeanValidationContext.java     | 331 +++++++++
 .../main/java/org/apache/bval/BeanValidator.java   | 280 +++++++
 .../main/java/org/apache/bval/DynamicMetaBean.java |  49 ++
 .../apache/bval/IntrospectorMetaBeanFactory.java   | 109 +++
 .../main/java/org/apache/bval/MetaBeanBuilder.java | 136 ++++
 .../main/java/org/apache/bval/MetaBeanCache.java   | 113 +++
 .../main/java/org/apache/bval/MetaBeanFactory.java |  32 +
 .../main/java/org/apache/bval/MetaBeanFinder.java  |  41 ++
 .../main/java/org/apache/bval/MetaBeanManager.java | 143 ++++
 .../org/apache/bval/MetaBeanManagerFactory.java    |  46 ++
 .../src/main/java/org/apache/bval/Validate.java    |  41 ++
 .../java/org/apache/bval/ValidationResults.java    | 211 ++++++
 .../main/java/org/apache/bval/model/DynaType.java  |  31 +
 .../java/org/apache/bval/model/DynaTypeEnum.java   | 122 +++
 .../main/java/org/apache/bval/model/Features.java  | 114 +++
 .../org/apache/bval/model/FeaturesCapable.java     | 219 ++++++
 .../main/java/org/apache/bval/model/MetaBean.java  | 246 +++++++
 .../java/org/apache/bval/model/MetaProperty.java   | 175 +++++
 .../java/org/apache/bval/model/Validation.java     |  30 +
 .../org/apache/bval/model/ValidationContext.java   | 135 ++++
 .../org/apache/bval/model/ValidationListener.java  | 101 +++
 .../apache/bval/routines/EMailValidationUtils.java |  74 ++
 .../java/org/apache/bval/util/AccessStrategy.java  |  58 ++
 .../java/org/apache/bval/util/BValVersion.java     | 195 +++++
 .../java/org/apache/bval/util/FieldAccess.java     | 113 +++
 .../java/org/apache/bval/util/IndexedAccess.java   | 120 +++
 .../java/org/apache/bval/util/KeyedAccess.java     | 121 +++
 .../java/org/apache/bval/util/MethodAccess.java    | 155 ++++
 .../org/apache/bval/util/PrivilegedActions.java    | 189 +++++
 .../java/org/apache/bval/util/PropertyAccess.java  | 218 ++++++
 .../org/apache/bval/util/ValidationHelper.java     | 236 ++++++
 .../org/apache/bval/ValidationResultsTest.java     |  60 ++
 .../java/org/apache/bval/model/ExampleEnum.java    |  27 +
 .../org/apache/bval/model/MetaPropertyTest.java    |  51 ++
 trunk/bval-core/src/test/resources/log4j.xml       |  41 ++
 trunk/bval-extras/pom.xml                          | 105 +++
 .../extras/constraints/checkdigit/ABANumber.java   |  54 ++
 .../constraints/checkdigit/ABANumberValidator.java |  70 ++
 .../bval/extras/constraints/checkdigit/CUSIP.java  |  54 ++
 .../constraints/checkdigit/CUSIPValidator.java     |  86 +++
 .../bval/extras/constraints/checkdigit/EAN13.java  |  54 ++
 .../constraints/checkdigit/EAN13Validator.java     |  69 ++
 .../bval/extras/constraints/checkdigit/IBAN.java   |  54 ++
 .../constraints/checkdigit/IBANValidator.java      |  81 ++
 .../bval/extras/constraints/checkdigit/ISBN10.java |  54 ++
 .../constraints/checkdigit/ISBN10Validator.java    |  81 ++
 .../bval/extras/constraints/checkdigit/Luhn.java   |  54 ++
 .../constraints/checkdigit/LuhnValidator.java      |  65 ++
 .../constraints/checkdigit/ModulusValidator.java   | 140 ++++
 .../bval/extras/constraints/checkdigit/Sedol.java  |  54 ++
 .../constraints/checkdigit/SedolValidator.java     |  75 ++
 .../extras/constraints/checkdigit/Verhoeff.java    |  54 ++
 .../constraints/checkdigit/VerhoeffValidator.java  |  90 +++
 .../constraints/checkdigit/package-info.java       |  23 +
 .../constraints/creditcard/AmericanExpress.java    |  59 ++
 .../bval/extras/constraints/creditcard/Diners.java |  59 ++
 .../extras/constraints/creditcard/Discover.java    |  59 ++
 .../extras/constraints/creditcard/Mastercard.java  |  59 ++
 .../bval/extras/constraints/creditcard/Visa.java   |  59 ++
 .../constraints/creditcard/package-info.java       |  23 +
 .../bval/extras/constraints/file/Directory.java    |  51 ++
 .../constraints/file/DirectoryValidator.java       |  46 ++
 .../bval/extras/constraints/file/NotDirectory.java |  51 ++
 .../constraints/file/NotDirectoryValidator.java    |  46 ++
 .../bval/extras/constraints/file/Symlink.java      |  51 ++
 .../extras/constraints/file/SymlinkValidator.java  |  75 ++
 .../bval/extras/constraints/file/package-info.java |  21 +
 .../apache/bval/extras/constraints/net/Domain.java |  53 ++
 .../extras/constraints/net/DomainValidator.java    | 463 ++++++++++++
 .../bval/extras/constraints/net/InetAddress.java   |  51 ++
 .../constraints/net/InetAddressValidator.java      |  56 ++
 .../bval/extras/constraints/net/package-info.java  |  21 +
 .../bval/extras/constraints/package-info.java      |  23 +
 .../checkdigit/ABANumberValidatorTest.java         |  45 ++
 .../checkdigit/AbstractCheckDigitTest.java         | 190 +++++
 .../constraints/checkdigit/CUSIPValidatorTest.java |  51 ++
 .../checkdigit/EAN13CheckDigitTest.java            |  43 ++
 .../constraints/checkdigit/IBANCheckDigitTest.java | 149 ++++
 .../checkdigit/ISBN10CheckDigitTest.java           |  43 ++
 .../constraints/checkdigit/LuhnCheckDigitTest.java |  57 ++
 .../checkdigit/SedolCheckDigitTest.java            |  54 ++
 .../checkdigit/VerhoeffCheckDigitTest.java         |  55 ++
 .../constraints/net/DomainValidatorTest.java       | 152 ++++
 .../constraints/net/InetAddressValidatorTest.java  |  93 +++
 trunk/bval-guice/pom.xml                           | 120 +++
 .../bval/guice/ConfigurationStateProvider.java     |  83 +++
 .../GuiceAwareConstraintValidatorFactory.java      |  49 ++
 .../main/java/org/apache/bval/guice/Validate.java  |  72 ++
 .../bval/guice/ValidateMethodInterceptor.java      | 181 +++++
 .../org/apache/bval/guice/ValidationModule.java    |  64 ++
 .../bval/guice/ValidatorFactoryProvider.java       |  49 ++
 .../org/apache/bval/guice/ValidatorProvider.java   |  50 ++
 .../java/org/apache/bval/guice/package-info.java   |  23 +
 .../test/java/org/apache/bval/guice/Country.java   |  77 ++
 .../org/apache/bval/guice/DummyCountryDao.java     |  55 ++
 .../java/org/apache/bval/guice/DummyException.java |  36 +
 .../bval/guice/GuiceAwareValidationTestCase.java   |  95 +++
 .../test/java/org/apache/bval/guice/Insert.java    |  28 +
 .../test/java/org/apache/bval/guice/Update.java    |  28 +
 trunk/bval-json/pom.xml                            |  86 +++
 .../src/main/appended-resources/META-INF/NOTICE.vm |  25 +
 .../java/org/apache/bval/json/JSONGenerator.java   |  79 ++
 .../org/apache/bval/json/bean-infos-json.ftl       |  85 +++
 .../org/apache/bval/json/JSONGeneratorTest.java    | 104 +++
 trunk/bval-jsr303/pom.xml                          | 226 ++++++
 .../src/main/appended-resources/META-INF/NOTICE.vm |  26 +
 .../bval/constraints/AssertFalseValidator.java     |  37 +
 .../bval/constraints/AssertTrueValidator.java      |  37 +
 .../constraints/DecimalMaxValidatorForNumber.java  |  53 ++
 .../constraints/DecimalMaxValidatorForString.java  |  54 ++
 .../constraints/DecimalMinValidatorForNumber.java  |  53 ++
 .../constraints/DecimalMinValidatorForString.java  |  56 ++
 .../bval/constraints/DigitsValidatorForNumber.java |  85 +++
 .../bval/constraints/DigitsValidatorForString.java |  93 +++
 .../java/org/apache/bval/constraints/Email.java    |  49 ++
 .../apache/bval/constraints/EmailValidator.java    |  39 +
 .../constraints/FutureValidatorForCalendar.java    |  47 ++
 .../bval/constraints/FutureValidatorForDate.java   |  46 ++
 .../bval/constraints/MaxValidatorForNumber.java    |  50 ++
 .../bval/constraints/MaxValidatorForString.java    |  48 ++
 .../bval/constraints/MinValidatorForNumber.java    |  50 ++
 .../bval/constraints/MinValidatorForString.java    |  48 ++
 .../java/org/apache/bval/constraints/NotEmpty.java |  48 ++
 .../apache/bval/constraints/NotEmptyValidator.java |  56 ++
 .../NotEmptyValidatorForCollection.java            |  36 +
 .../bval/constraints/NotEmptyValidatorForMap.java  |  36 +
 .../constraints/NotEmptyValidatorForString.java    |  35 +
 .../apache/bval/constraints/NotNullValidator.java  |  34 +
 .../org/apache/bval/constraints/NullValidator.java |  37 +
 .../bval/constraints/PastValidatorForCalendar.java |  47 ++
 .../bval/constraints/PastValidatorForDate.java     |  46 ++
 .../apache/bval/constraints/PatternValidator.java  |  51 ++
 .../org/apache/bval/constraints/SizeValidator.java |  44 ++
 .../SizeValidatorForArrayOfBoolean.java            |  45 ++
 .../constraints/SizeValidatorForArrayOfByte.java   |  45 ++
 .../constraints/SizeValidatorForArrayOfChar.java   |  45 ++
 .../constraints/SizeValidatorForArrayOfDouble.java |  45 ++
 .../constraints/SizeValidatorForArrayOfFloat.java  |  45 ++
 .../constraints/SizeValidatorForArrayOfInt.java    |  45 ++
 .../constraints/SizeValidatorForArrayOfLong.java   |  45 ++
 .../constraints/SizeValidatorForArrayOfObject.java |  46 ++
 .../constraints/SizeValidatorForArrayOfShort.java  |  45 ++
 .../constraints/SizeValidatorForCollection.java    |  47 ++
 .../bval/constraints/SizeValidatorForMap.java      |  46 ++
 .../bval/constraints/SizeValidatorForString.java   |  44 ++
 .../bval/jsr303/AnnotationConstraintBuilder.java   | 276 +++++++
 .../apache/bval/jsr303/AnnotationProcessor.java    | 450 ++++++++++++
 .../apache/bval/jsr303/ApacheFactoryContext.java   | 306 ++++++++
 .../bval/jsr303/ApacheValidationProvider.java      | 130 ++++
 .../bval/jsr303/ApacheValidatorConfiguration.java  |  91 +++
 .../apache/bval/jsr303/ApacheValidatorFactory.java | 390 ++++++++++
 .../org/apache/bval/jsr303/AppendValidation.java   |  32 +
 .../bval/jsr303/AppendValidationToBuilder.java     |  89 +++
 .../apache/bval/jsr303/AppendValidationToMeta.java |  43 ++
 .../apache/bval/jsr303/BaseAppendValidation.java   |  80 ++
 .../org/apache/bval/jsr303/BeanDescriptorImpl.java | 136 ++++
 .../bval/jsr303/CascadingPropertyValidator.java    |  69 ++
 .../org/apache/bval/jsr303/ClassValidator.java     | 817 +++++++++++++++++++++
 .../org/apache/bval/jsr303/ConfigurationImpl.java  | 340 +++++++++
 .../jsr303/ConstraintAnnotationAttributes.java     | 268 +++++++
 .../org/apache/bval/jsr303/ConstraintCached.java   |  64 ++
 .../org/apache/bval/jsr303/ConstraintDefaults.java | 131 ++++
 .../bval/jsr303/ConstraintDescriptorImpl.java      | 132 ++++
 .../apache/bval/jsr303/ConstraintFinderImpl.java   | 162 ++++
 .../apache/bval/jsr303/ConstraintValidation.java   | 381 ++++++++++
 .../bval/jsr303/ConstraintValidationListener.java  | 175 +++++
 .../jsr303/ConstraintValidatorContextImpl.java     | 160 ++++
 .../bval/jsr303/ConstraintValidatorIdentity.java   | 134 ++++
 .../bval/jsr303/ConstraintViolationImpl.java       | 241 ++++++
 .../jsr303/DefaultConstraintValidatorFactory.java  |  50 ++
 .../bval/jsr303/DefaultMessageInterpolator.java    | 323 ++++++++
 .../jsr303/DefaultValidationProviderResolver.java  |  98 +++
 .../apache/bval/jsr303/ElementDescriptorImpl.java  | 141 ++++
 .../org/apache/bval/jsr303/GraphBeanIdentity.java  | 133 ++++
 .../apache/bval/jsr303/GroupValidationContext.java | 122 +++
 .../bval/jsr303/GroupValidationContextImpl.java    | 291 ++++++++
 .../jsr303/IncompatiblePropertyValueException.java |  69 ++
 .../org/apache/bval/jsr303/Jsr303Features.java     |  61 ++
 .../apache/bval/jsr303/Jsr303MetaBeanFactory.java  | 317 ++++++++
 .../apache/bval/jsr303/PropertyDescriptorImpl.java |  83 +++
 .../bval/jsr303/UnknownPropertyException.java      |  67 ++
 .../jsr303/extensions/AppendValidationToList.java  |  55 ++
 .../jsr303/extensions/ConstructorDescriptor.java   |  38 +
 .../extensions/ConstructorDescriptorImpl.java      |  74 ++
 .../jsr303/extensions/MethodBeanDescriptor.java    |  55 ++
 .../extensions/MethodBeanDescriptorImpl.java       | 131 ++++
 .../bval/jsr303/extensions/MethodDescriptor.java   |  39 +
 .../jsr303/extensions/MethodDescriptorImpl.java    |  84 +++
 .../bval/jsr303/extensions/MethodValidator.java    | 119 +++
 .../jsr303/extensions/MethodValidatorImpl.java     | 309 ++++++++
 .../extensions/MethodValidatorMetaBeanFactory.java | 175 +++++
 .../bval/jsr303/extensions/ParameterAccess.java    |  80 ++
 .../jsr303/extensions/ParameterDescriptor.java     |  39 +
 .../jsr303/extensions/ParameterDescriptorImpl.java |  79 ++
 .../jsr303/extensions/ProcedureDescriptor.java     |  45 ++
 .../bval/jsr303/extensions/ReturnAccess.java       |  76 ++
 .../java/org/apache/bval/jsr303/groups/Group.java  |  85 +++
 .../java/org/apache/bval/jsr303/groups/Groups.java | 117 +++
 .../apache/bval/jsr303/groups/GroupsComputer.java  | 143 ++++
 .../bval/jsr303/resolver/CachingRelevant.java      |  33 +
 .../resolver/CachingTraversableResolver.java       | 192 +++++
 .../resolver/DefaultTraversableResolver.java       | 123 ++++
 .../jsr303/resolver/JPATraversableResolver.java    |  53 ++
 .../jsr303/resolver/SimpleTraversableResolver.java |  56 ++
 .../org/apache/bval/jsr303/util/ClassHelper.java   |  82 +++
 .../jsr303/util/ConstraintDefinitionValidator.java |  79 ++
 .../bval/jsr303/util/EnumerationConverter.java     |  75 ++
 .../java/org/apache/bval/jsr303/util/IOUtils.java  |  53 ++
 .../util/NodeBuilderCustomizableContextImpl.java   |  80 ++
 .../jsr303/util/NodeBuilderDefinedContextImpl.java |  64 ++
 .../bval/jsr303/util/NodeContextBuilderImpl.java   |  91 +++
 .../java/org/apache/bval/jsr303/util/NodeImpl.java | 223 ++++++
 .../java/org/apache/bval/jsr303/util/PathImpl.java | 322 ++++++++
 .../apache/bval/jsr303/util/PathNavigation.java    | 327 +++++++++
 .../org/apache/bval/jsr303/util/SecureActions.java | 151 ++++
 .../jsr303/util/ValidationContextTraversal.java    | 204 +++++
 .../apache/bval/jsr303/xml/AnnotationIgnores.java  | 149 ++++
 .../apache/bval/jsr303/xml/AnnotationProxy.java    | 130 ++++
 .../bval/jsr303/xml/AnnotationProxyBuilder.java    | 202 +++++
 .../org/apache/bval/jsr303/xml/MetaConstraint.java | 112 +++
 .../bval/jsr303/xml/ValidationMappingParser.java   | 568 ++++++++++++++
 .../apache/bval/jsr303/xml/ValidationParser.java   | 286 ++++++++
 .../javax.validation.spi.ValidationProvider        |  17 +
 .../bval/jsr303/DefaultConstraints.properties      |  53 ++
 .../bval/jsr303/ValidationMessages.properties      |  37 +
 .../bval/jsr303/ValidationMessages_de.properties   |  37 +
 .../bval/jsr303/ValidationMessages_en.properties   |  20 +
 .../bval/jsr303/ValidationMessages_es.properties   |  37 +
 .../bval/jsr303/ValidationMessages_it.properties   |  37 +
 .../src/main/xjb/binding-customization.xjb         |  32 +
 .../src/main/xsd/validation-configuration-1.0.xsd  |  45 ++
 .../src/main/xsd/validation-mapping-1.0.xsd        | 171 +++++
 .../bval/constraints/AssertFalseValidatorTest.java |  61 ++
 .../bval/constraints/AssertTrueValidatorTest.java  |  61 ++
 .../bval/constraints/AuthorAddressKnown.java       |  75 ++
 .../org/apache/bval/constraints/CompanyEmail.java  |  67 ++
 .../constraints/DecimalMinMaxValidatorsTest.java   |  63 ++
 .../bval/constraints/DigitsValidatorTest.java      |  87 +++
 .../bval/constraints/EmailValidatorTest.java       |  98 +++
 .../org/apache/bval/constraints/FrenchZipCode.java |  60 ++
 .../bval/constraints/FrenchZipcodeValidator.java   |  35 +
 .../bval/constraints/HasStringValidator.java       |  39 +
 .../java/org/apache/bval/constraints/HasValue.java |  43 ++
 .../constraints/MinMaxValidatorsForNumberTest.java |  69 ++
 .../bval/constraints/NotNullValidatorTest.java     |  59 ++
 .../apache/bval/constraints/NullValidatorTest.java |  59 ++
 .../java/org/apache/bval/constraints/Password.java |  49 ++
 .../bval/constraints/ZipCodeCityCoherence.java     |  41 ++
 .../constraints/ZipCodeCityCoherenceValidator.java |  52 ++
 .../org/apache/bval/jsr303/BeanDescriptorTest.java | 235 ++++++
 .../java/org/apache/bval/jsr303/BootstrapTest.java | 184 +++++
 .../apache/bval/jsr303/CircularReferencesTest.java | 116 +++
 .../bval/jsr303/ComposedConstraintsTest.java       | 133 ++++
 .../bval/jsr303/ConstraintCompositionTest.java     | 306 ++++++++
 .../bval/jsr303/ConstraintDefinitionsTest.java     | 322 ++++++++
 .../jsr303/ConstraintValidatorContextTest.java     | 114 +++
 .../CustomConstraintValidatorFactoryTest.java      | 104 +++
 .../bval/jsr303/CustomValidatorFactoryTest.java    | 118 +++
 .../jsr303/DefaultMessageInterpolatorTest.java     | 148 ++++
 .../apache/bval/jsr303/ExceptionsContractTest.java | 270 +++++++
 .../test/java/org/apache/bval/jsr303/FooTest.java  |  66 ++
 .../java/org/apache/bval/jsr303/Jsr303Test.java    | 273 +++++++
 .../java/org/apache/bval/jsr303/PayloadTest.java   | 117 +++
 .../org/apache/bval/jsr303/TckReproducerTest.java  | 115 +++
 .../org/apache/bval/jsr303/ValidationTest.java     | 722 ++++++++++++++++++
 .../bval/jsr303/ValidatorResolutionTest.java       | 110 +++
 .../jsr303/example/AccessTestBusinessObject.java   |  73 ++
 .../example/AccessTestBusinessObjectSub.java       |  57 ++
 .../org/apache/bval/jsr303/example/Address.java    | 100 +++
 .../org/apache/bval/jsr303/example/Author.java     |  72 ++
 .../java/org/apache/bval/jsr303/example/Book.java  |  83 +++
 .../bval/jsr303/example/BusinessAddress.java       |  37 +
 .../apache/bval/jsr303/example/CompanyAddress.java |  40 +
 .../org/apache/bval/jsr303/example/Continent.java  |  40 +
 .../org/apache/bval/jsr303/example/Country.java    |  56 ++
 .../org/apache/bval/jsr303/example/Customer.java   |  86 +++
 .../org/apache/bval/jsr303/example/Employee.java   |  51 ++
 .../org/apache/bval/jsr303/example/Engine.java     |  32 +
 .../java/org/apache/bval/jsr303/example/First.java |  25 +
 .../apache/bval/jsr303/example/FrenchAddress.java  |  45 ++
 .../bval/jsr303/example/IllustratedBook.java       |  41 ++
 .../java/org/apache/bval/jsr303/example/Last.java  |  25 +
 .../org/apache/bval/jsr303/example/Library.java    |  73 ++
 .../apache/bval/jsr303/example/MaxTestEntity.java  |  70 ++
 .../bval/jsr303/example/NoValidatorTestEntity.java |  31 +
 .../org/apache/bval/jsr303/example/Person.java     |  31 +
 .../apache/bval/jsr303/example/PreferredGuest.java |  34 +
 .../apache/bval/jsr303/example/RecursiveFoo.java   |  43 ++
 .../org/apache/bval/jsr303/example/Second.java     |  25 +
 .../apache/bval/jsr303/example/SizeTestEntity.java |  56 ++
 .../bval/jsr303/example/XmlEntitySampleBean.java   |  53 ++
 .../bval/jsr303/example/ZipCodeCityCarrier.java    |  27 +
 .../jsr303/extensions/ExampleMethodService.java    |  69 ++
 .../jsr303/extensions/MethodValidatorImplTest.java | 289 ++++++++
 .../org/apache/bval/jsr303/groups/Billable.java    |  26 +
 .../bval/jsr303/groups/BillableCreditCard.java     |  25 +
 .../apache/bval/jsr303/groups/BillableUser.java    |  61 ++
 .../apache/bval/jsr303/groups/BuyInOneClick.java   |  26 +
 .../jsr303/groups/CollectionValidationTest.java    | 198 +++++
 .../bval/jsr303/groups/CyclicGroupSequence.java    |  28 +
 .../bval/jsr303/groups/CyclicGroupSequence1.java   |  28 +
 .../bval/jsr303/groups/CyclicGroupSequence2.java   |  29 +
 .../jsr303/groups/DefaultGroupSequenceTest.java    | 150 ++++
 .../org/apache/bval/jsr303/groups/GClass1.java     |  26 +
 .../org/apache/bval/jsr303/groups/GClass2.java     |  28 +
 .../org/apache/bval/jsr303/groups/GClass3.java     |  28 +
 .../org/apache/bval/jsr303/groups/GInterface1.java |  29 +
 .../jsr303/groups/GroupSequenceIsolationTest.java  | 166 +++++
 .../bval/jsr303/groups/GroupSequenceTest.java      | 211 ++++++
 .../bval/jsr303/groups/GroupValidationTest.java    |  83 +++
 .../bval/jsr303/groups/GroupsComputerTest.java     | 148 ++++
 .../bval/jsr303/groups/implicit/Auditable.java     |  33 +
 .../groups/implicit/ImplicitGroupingTest.java      |  62 ++
 .../apache/bval/jsr303/groups/implicit/Order.java  |  76 ++
 .../jsr303/groups/inheritance/BillableUser.java    |  64 ++
 .../jsr303/groups/inheritance/BuyInOneClick.java   |  31 +
 .../groups/inheritance/GroupInheritanceTest.java   |  56 ++
 .../bval/jsr303/groups/redefining/Address.java     |  84 +++
 .../InvalidRedefinedDefaultGroupAddress.java       |  46 ++
 .../redefining/RedefiningDefaultGroupTest.java     | 103 +++
 .../jsr303/util/EnumerationConverterTestCase.java  |  50 ++
 .../org/apache/bval/jsr303/util/PathImplTest.java  | 210 ++++++
 .../org/apache/bval/jsr303/util/TestUtils.java     | 113 +++
 .../jsr303/xml/TestConstraintValidatorFactory.java |  27 +
 .../bval/jsr303/xml/TestMessageInterpolator.java   |  27 +
 .../bval/jsr303/xml/ValidationParserTest.java      | 102 +++
 .../test/resources/ValidationMessages.properties   |  26 +
 trunk/bval-jsr303/src/test/resources/java.policy   |  76 ++
 .../src/test/resources/sample-constraints.xml      |  73 ++
 .../src/test/resources/sample-validation.xml       |  29 +
 trunk/bval-tck/pom.xml                             | 416 +++++++++++
 .../META-INF/jboss-test-harness.properties         |  19 +
 trunk/bval-tck/src/test/resources/jndi.properties  |  20 +
 trunk/bval-tck/src/test/resources/log4j.xml        |  57 ++
 trunk/bval-xstream/findbugs-exclude-filter.xml     |  31 +
 trunk/bval-xstream/pom.xml                         | 105 +++
 .../org/apache/bval/routines/EMailValidation.java  |  48 ++
 .../org/apache/bval/routines/NOPValidation.java    |  31 +
 .../java/org/apache/bval/routines/Reasons.java     |  31 +
 .../apache/bval/routines/StandardValidation.java   | 184 +++++
 .../java/org/apache/bval/xml/MetaBeanEnricher.java |  38 +
 .../org/apache/bval/xml/XMLFeaturesCapable.java    |  98 +++
 .../main/java/org/apache/bval/xml/XMLMapper.java   |  45 ++
 .../main/java/org/apache/bval/xml/XMLMetaBean.java | 156 ++++
 .../org/apache/bval/xml/XMLMetaBeanBuilder.java    | 178 +++++
 .../org/apache/bval/xml/XMLMetaBeanFactory.java    | 241 ++++++
 .../java/org/apache/bval/xml/XMLMetaBeanInfos.java | 134 ++++
 .../org/apache/bval/xml/XMLMetaBeanLoader.java     |  26 +
 .../org/apache/bval/xml/XMLMetaBeanManager.java    | 131 ++++
 .../apache/bval/xml/XMLMetaBeanManagerFactory.java |  62 ++
 .../org/apache/bval/xml/XMLMetaBeanReference.java  |  58 ++
 .../org/apache/bval/xml/XMLMetaBeanRegistry.java   |  35 +
 .../org/apache/bval/xml/XMLMetaBeanURLLoader.java  |  45 ++
 .../java/org/apache/bval/xml/XMLMetaElement.java   | 143 ++++
 .../java/org/apache/bval/xml/XMLMetaFeature.java   |  61 ++
 .../java/org/apache/bval/xml/XMLMetaProperty.java  | 102 +++
 .../java/org/apache/bval/xml/XMLMetaValidator.java |  77 ++
 .../apache/bval/xml/XMLMetaValidatorReference.java |  49 ++
 .../java/org/apache/bval/xml/XMLMetaValue.java     |  34 +
 .../java/org/apache/bval/example/BusinessEnum.java |  24 +
 .../org/apache/bval/example/BusinessObject.java    | 125 ++++
 .../apache/bval/example/BusinessObjectAddress.java |  49 ++
 .../bval/example/BusinessObjectBeanInfo.java       |  64 ++
 .../bval/routines/StandardValidationTest.java      | 223 ++++++
 .../org/apache/bval/xml/BeanValidatorTest.java     | 121 +++
 .../org/apache/bval/xml/XMLMetaBeanInfosTest.java  | 165 +++++
 .../apache/bval/xml/XMLMetaBeanManagerTest.java    |  93 +++
 .../apache/bval/example/test-beanInfos-custom.xml  |  31 +
 .../org/apache/bval/example/test-beanInfos.xml     |  77 ++
 trunk/pom.xml                                      | 624 ++++++++++++++++
 378 files changed, 37958 insertions(+)

diff --git a/trunk/CHANGES.txt b/trunk/CHANGES.txt
new file mode 100644
index 0000000..56144d3
--- /dev/null
+++ b/trunk/CHANGES.txt
@@ -0,0 +1,214 @@
+Apache BVal (incubating) - CHANGES.txt
+Licensed under Apache License 2.0 - http://www.apache.org/licenses/LICENSE-2.0
+--------------------------------------------------------------------------------
+
+Content
+=======
+   * Overview
+   * Disclaimer
+   * Prerequisites
+   * Documentation
+   * Getting Involved
+   * Release Notes
+
+
+Overview
+========
+This is an implementation of JSR 303 (Bean Validation), a specification of the
+Java API for Javabean validation in Java EE and Java SE.
+The technical objective is to provide a class level constraint declaration and
+validation facility for the Java application developer, as well as a constraint
+metadata repository and query API.
+
+This implementation is based on the validation framework of agimatec GmbH,
+which was contributed to the ASF under a software grant.
+
+
+Disclaimer
+==========
+Apache BVal is an effort undergoing incubation at The Apache Software
+Foundation (ASF), sponsored by the Apache Incubator PMC. Incubation is required
+of all newly accepted projects until a further review indicates that the
+infrastructure, communications, and decision making process have stabilized in a
+manner consistent with other successful ASF projects. While incubation status is
+not necessarily a reflection of the completeness or stability of the code, it
+does indicate that the project has yet to be fully endorsed by the ASF.
+
+
+Prerequisites
+=============
+You need a platform that supports Java SE 5 or later.
+
+
+Documentation
+=============
+Please refer to the project page at:
+    http://incubator.apache.org/bval/
+
+
+Getting Involved
+================
+The Apache BVal project is being built by the open source community
+for the open source community - we welcome your input and contributions!
+
+What are we looking for?
+  * Source code and fixes contributions
+  * Documentation assistance
+  * Project and feature suggestions
+  * Integration and testing with other projects
+  * Detailed and constructive feedback
+  * Articles and whitepapers
+
+How do I Contribute?
+  * To discuss BVal topics, check out the mailing lists.
+  * Bugs and other issues can be posted on the project JIRA.
+
+
+Release Notes - BVal - Version 0.4
+==================================
+
+Bug
+---
+    * [BVAL-54] - Handle Java security policies and managers
+    * [BVAL-63] - use java.util.ServiceLoader in DefaultValidationProviderResolver#getValidationProviders()
+    * [BVAL-89] - Application specific constraints and artifacts not visible by provider in OSGI-based app server
+    * [BVAL-90] - Inconsistent fraction handling of @Digits when target is a BigDecimal
+    * [BVAL-91] - Security hole in org.apache.bval.util.MethodAccess.get()
+    * [BVAL-92] - Security holes in org.apache.bval.util.PrivilegedActions
+    * [BVAL-94] - Missing SVN EOL properties
+    * [BVAL-95] - Beanvalidation with Generic-DataTypes
+    * [BVAL-96] - Use correct encoding for localization messages
+    * [BVAL-97] - More than one META-INF/validation.xml in tomcat webapp
+    * [BVAL-100] - Java2 Security AccessControlException after moving to use common-lang3
+    * [BVAL-104] - german validation messages properties are broken
+
+Improvement
+-----------
+    * [BVAL-68] - Use FindBugs to reduce coding errors
+
+Task
+----
+    * [BVAL-99] - upgrade to apache parent pom 10
+    * [BVAL-103] - switch BVal from slf4j to java.util.logging
+
+
+Release Notes for 0.3-incubating
+================================
+
+Bug
+---
+    * [BVAL-84] - CNFEX org.slf4j.impl.StaticLoggerBinder building xstream and guice
+    * [BVAL-86] - Missing DecimalMax/DecimalMin constraint messages in ValidationMessages.properties
+    * [BVAL-87] - Java 2 security violations in ClassValidator.validate
+    * [BVAL-88] - Cascaded validation adds a constraint violation for valid child property
+
+Improvement
+-----------
+    * [BVAL-60] - Use SLF4J API for logging
+    * [BVAL-85] - bval-core has no dependency on slf4j-jcl*
+
+
+Release Notes for 0.2-incubating
+================================
+
+Bug
+---
+    * [BVAL-47] - Correctly follow GroupSequence definitions when validating
+    * [BVAL-70] - Remove @Override annotations from methods implementing interfaces
+    * [BVAL-71] - Compile errors with Java SE 5
+    * [BVAL-72] - NPE when doing methodvalidation
+    * [BVAL-77] - Recent changes made the bval-xstream module required, instead of optional
+
+Improvement
+-----------
+    * [BVAL-59] - Write or reuse an scm-plugin mojo to capture the svn revision
+    * [BVAL-69] - make dependency to com.thoughtworks.xstream of bval-core optional or obsolete
+    * [BVAL-73] - Alternative way of addressing code reuse issue between the validators
+    * [BVAL-74] - Remove redundant method call from ClassValidator.validateProperty()
+    * [BVAL-75] - javadocs, compiler (generics) warnings, etc.
+    * [BVAL-76] - Correct spelling error in API:  ConstraintValidationListener.getConstaintViolations()
+    * [BVAL-78] - Avoid unsafe casting and object swapping when processing @ReportAsSingleViolation composed constraints
+    * [BVAL-79] - email validation can easily work for any CharSequence rather than String only
+
+
+Release Notes for 0.1-incubating
+================================
+
+Sub-task
+--------
+    * [BVAL-3] - Move all copyrights to NOTICE files
+    * [BVAL-4] - Rename java packages
+    * [BVAL-5] - Update builds for incubator
+    * [BVAL-7] - Setup initial structure/navigation/content in the wiki
+    * [BVAL-8] - Setup confluence autoexport template
+    * [BVAL-9] - Setup rsync cron job to copy autoexport content over to www staging area
+
+Bug
+---
+    * [BVAL-11] - After moved java packages tests don't work
+    * [BVAL-13] - ConstraintViolationImpl must be Serialziable according to JSR303 spec
+    * [BVAL-15] - @Min and @Max fail with very high values of long
+    * [BVAL-17] - PathImpl keeps a null-named first node on unindexed property paths
+    * [BVAL-18] - DefaultMessageInterpolator substitutes unexistant variables with the whole message
+    * [BVAL-19] - Several changes to pass 12 more tests
+    * [BVAL-20] - When building a MetaBean, the full tree of subclasses/interfaces must be considered
+    * [BVAL-21] - ConstraintViolations set should not have duplicates and should store ElementType and use it in equals()
+    * [BVAL-22] - Incorrect output or IOBException when interpolating messages when annotation values have $ or \
+    * [BVAL-23] - Circular dependency check produces false positives
+    * [BVAL-24] - IllegalArgumentException should be thrown when calling Validator.getConstraintsForClass() with a null class
+    * [BVAL-26] - IllegalAccessException is thrown when accesing annotation values
+    * [BVAL-27] - IllegalArgumentException should be thrown when calling BeanDescriptor.getConstraintsForProperty(null)
+    * [BVAL-28] - Property path for nodes inside iterables that do not implement List should not contain the index
+    * [BVAL-29] - Defer node creation in implementation of ConstraintViolationBuilder API
+    * [BVAL-30] - Groups from the main constraint annotation must be inherited by the composing annotations
+    * [BVAL-31] - A ConstraintDefinitionException should be thrown when the resolved validator is not compatible with the annotation type
+    * [BVAL-32] - Annotations associated with composited contraints must reflect inherited groups
+    * [BVAL-33] - Payload value must also be inherited in compositing constraints
+    * [BVAL-34] - Parameter for @Pattern message should be {regexp}
+    * [BVAL-35] - Improved support of @OverridesAttribute
+    * [BVAL-36] - Improve @ReportAsSingleValidation implementation
+    * [BVAL-37] - Ensure constraint definitions are valid
+    * [BVAL-38] - Groups and payload values must be part of the ConstraintDescriptor attributes
+    * [BVAL-39] - Implicit groups should be correctly set in constraint descriptors
+    * [BVAL-41] - Package bval artifacts as bundles
+    * [BVAL-42] - Stop group sequence validation when at least 1 violation is already reported
+    * [BVAL-43] - GroupDefinitionException must be thrown on cyclic group detection
+    * [BVAL-45] - ValidationException must be thrown when validating a bean with an annotated method which isn't a valid getter
+    * [BVAL-48] - jUnit failure during build on Windows - trunk rev 945800
+    * [BVAL-49] - ValidationException must be thrown in case ConstraintValidatorFactory returns null for a valid getInstance call
+    * [BVAL-50] - Fix TraversableResolver usage
+    * [BVAL-51] - Several fixes in ElementDescriptor and subinterfaces impls
+    * [BVAL-53] - Several fixes for XML metadata processing impl
+    * [BVAL-55] - Fix remaining TCK tests
+    * [BVAL-58] - Clean up build before release
+    * [BVAL-62] - add missing ASL headers
+    * [BVAL-64] - org.apache.bval.bundle needs a custom NOTICE file
+    * [BVAL-65] - Incubator required DISCLAIMER missing from jars
+    * [BVAL-67] - Resolve NOTICE file issues fond during RC2 vote
+
+Improvement
+-----------
+    * [BVAL-12] - Current implementation of method validation (appendix C of JSR-303) doesn't work with some constraints
+    * [BVAL-16] - Maven project to launch TCK suite
+    * [BVAL-44] - Move optional JSON code out of bval-core to a bval-json module
+    * [BVAL-46] - Create project source assembly
+    * [BVAL-52] - ValidationParser.getInputStream() should call getResourceAsStream() for TCK suite to work
+    * [BVAL-57] - Create a single apache-bval jar/bundle
+    * [BVAL-66] - Method validation parameter processing problems
+
+New Feature
+-----------
+    * [BVAL-40] - Provide a way to display the BVal version being used
+    * [BVAL-56] - make bval work with geronimo spec osgi service locator
+
+Task
+----
+    * [BVAL-2] - Initial codebase donation tasks
+    * [BVAL-6] - Setup project website
+
+Test
+----
+    * [BVAL-10] - Setup continuous builds
+
+--------------------------------------------------------------------------------
+
diff --git a/trunk/LICENSE b/trunk/LICENSE
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/trunk/LICENSE
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
diff --git a/trunk/NOTICE b/trunk/NOTICE
new file mode 100644
index 0000000..28b288f
--- /dev/null
+++ b/trunk/NOTICE
@@ -0,0 +1,14 @@
+
+Apache Incubator - BVal project
+Copyright 2010-2012 The Apache Software Foundation.
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+
+The following copyright notice(s) were affixed to portions of this code
+with which this file is now or was at one time distributed.
+
+This product includes software developed by Agimatec GmbH.
+Copyright 2007-2010 Agimatec GmbH. All rights reserved.
+
diff --git a/trunk/README.txt b/trunk/README.txt
new file mode 100644
index 0000000..5047689
--- /dev/null
+++ b/trunk/README.txt
@@ -0,0 +1,66 @@
+Apache BVal - README.txt
+Licensed under Apache License 2.0 - http://www.apache.org/licenses/LICENSE-2.0
+--------------------------------------------------------------------------------
+
+About
+=====
+This is an implementation of JSR 303 (Bean Validation), a specification of the
+Java API for Javabean validation in Java EE and Java SE.
+The technical objective is to provide a class level constraint declaration and
+validation facility for the Java application developer, as well as a constraint
+metadata repository and query API.
+
+
+Release Notes
+=============
+Please refer to the included CHANGES.txt for a complete list of new features
+available and issues resolved in this release.
+
+
+Getting Started
+===============
+Please visit the project website for the latest information:
+    http://bval.apache.org/
+
+Along with the developer mailing list archive:
+    http://mail-archives.apache.org/mod_mbox/bval-dev/
+
+
+System Requirements
+===================
+You need a platform that supports Java SE 5 or later.
+Most testing has been done with Java SE 6 on Mac OS X, Windows and Linux.
+
+
+Building
+==========================
+To build from source code:
+  - Sources require Java SE 5 or higher. (Tested with JDK 1.5.0_22 and 1.6.0_21)
+  - The project is built with Apache Maven (suggested is at least 2.2.1).
+    You need to download and install Maven from: http://maven.apache.org/
+  - Invoke maven in the root directory or a module subdirectory:
+      mvn install
+
+Checkout the Building section on the project web site for more details:
+    http://bval.apache.org/
+
+
+Support
+=======
+Any problems with this release can be reported to the user mailing list or
+opened in the Jira issue tracker.
+
+  Mailing list archive:
+    http://mail-archives.apache.org/mod_mbox/bval-user/
+
+  User mailing list:
+    user@bval.apache.org
+
+  User mailing list subscription:
+    user-subscribe@bval.apache.org
+
+  Jira:
+    https://issues.apache.org/jira/browse/BVAL/
+
+--------------------------------------------------------------------------------
+
diff --git a/trunk/bundle/pom.xml b/trunk/bundle/pom.xml
new file mode 100644
index 0000000..dd7a55b
--- /dev/null
+++ b/trunk/bundle/pom.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!--
+	Maven release plugin requires the project tag to be on a single line.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.bval</groupId>
+        <artifactId>bval-parent</artifactId>
+        <version>0.4</version>
+    </parent>
+
+    <!-- use fully qualified naming for OSGi bundles -->
+    <artifactId>org.apache.bval.bundle</artifactId>
+    <name>Apache BVal :: org.apache.bval.bundle</name>
+    <packaging>bundle</packaging>
+
+    <description>Apache BVal - Aggregate OSGi Bundle (bval-core + bval-jsr303)</description>
+
+    <dependencies>
+        <!-- JARs to include in aggregate JAR via maven-shade-plugin -->
+        <dependency>
+            <groupId>org.apache.bval</groupId>
+            <artifactId>bval-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.bval</groupId>
+            <artifactId>bval-jsr303</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <!-- OSGi Bundle Metadata -->
+                        <Main-Class>org.apache.bval.util.BValVersion</Main-Class>
+                        <Implementation-Title>Apache BVal</Implementation-Title>
+                        <Implementation-Build>${buildNumber}</Implementation-Build>
+                        <Specification-Title>JSR-303 Bean Validation</Specification-Title>
+                        <Specification-Vendor>Sun Microsystems, Inc.</Specification-Vendor>
+                        <Specification-Version>1.0</Specification-Version>
+                        <Bundle-DocURL>${project.url}</Bundle-DocURL>
+                        <Embed-Dependency>*;inline=true</Embed-Dependency>
+                        <Private-Package />
+                        <Export-Package>org.apache.bval.*</Export-Package>
+                        <Import-Package>javax.persistence.*;resolution:=optional,org.apache.bval.xml.*;resolution:=optional,*</Import-Package>
+                        <!-- geronimo spec osgi services support -->
+                        <SPI-Provider>true</SPI-Provider>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>findbugs-maven-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>apache-release</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <configuration>
+                            <skip>true</skip>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-source-plugin</artifactId>
+                        <configuration>
+                            <attach>false</attach>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
+
diff --git a/trunk/bundle/src/main/appended-resources/META-INF/NOTICE.vm b/trunk/bundle/src/main/appended-resources/META-INF/NOTICE.vm
new file mode 100644
index 0000000..05ddae6
--- /dev/null
+++ b/trunk/bundle/src/main/appended-resources/META-INF/NOTICE.vm
@@ -0,0 +1,26 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##  http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied.  See the License for the
+## specific language governing permissions and limitations
+## under the License.
+##
+
+
+The following copyright notice(s) were affixed to portions of this code
+with which this file is now or was at one time distributed.
+
+This product includes software developed by agimatec GmbH.
+Copyright 2007-2010 Agimatec GmbH. All rights reserved.
+
diff --git a/trunk/bval-core/pom.xml b/trunk/bval-core/pom.xml
new file mode 100644
index 0000000..5251d67
--- /dev/null
+++ b/trunk/bval-core/pom.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!--
+	Maven release plugin requires the project tag to be on a single line.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.bval</groupId>
+        <artifactId>bval-parent</artifactId>
+        <version>0.4</version>
+    </parent>
+
+    <artifactId>bval-core</artifactId>
+    <name>Apache BVal :: bval-core</name>
+    <packaging>jar</packaging>
+
+    <description>BVal Metadata Engine</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <!--
+                get the svn revision number and project version
+                and set it in a properties file for later retrieval
+            -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>set subversion revision</id>
+                        <phase>compile</phase>
+                        <configuration>
+                            <tasks>
+                                <echo>Version: ${project.version}</echo>
+                                <echo>Revision: ${buildNumber}</echo>
+                                <echo>Date: ${timestamp}</echo>
+                                <mkdir dir="${project.build.outputDirectory}/META-INF" />
+                                <echo file="${project.build.outputDirectory}/META-INF/org.apache.bval.revision.properties">
+# Licensed under Apache License 2.0 - http://www.apache.org/licenses/LICENSE-2.0
+project.name=Apache BVal
+project.version=${project.version}
+svn.revision=${buildNumber}
+svn.branch=${scmBranch}
+build.timestamp=${timestamp}
+                                </echo>
+                            </tasks>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- create mainClass attribute -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-jar</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                        <configuration>
+                            <archive>
+                                <manifest>
+                                   <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                                   <mainClass>org.apache.bval.util.BValVersion</mainClass>
+                                </manifest>
+                                <manifestEntries>
+                                    <Implementation-Build>${buildNumber}</Implementation-Build>
+                                </manifestEntries>
+                            </archive>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>attach-tests</id>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+        	<plugins>
+        		<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+        		<plugin>
+        			<groupId>org.eclipse.m2e</groupId>
+        			<artifactId>lifecycle-mapping</artifactId>
+        			<version>1.0.0</version>
+        			<configuration>
+        				<lifecycleMappingMetadata>
+        					<pluginExecutions>
+        						<pluginExecution>
+        							<pluginExecutionFilter>
+        								<groupId>
+        									org.apache.maven.plugins
+        								</groupId>
+        								<artifactId>
+        									maven-antrun-plugin
+        								</artifactId>
+        								<versionRange>
+        									[1.3,)
+        								</versionRange>
+        								<goals>
+        									<goal>run</goal>
+        								</goals>
+        							</pluginExecutionFilter>
+        							<action>
+        								<ignore />
+        							</action>
+        						</pluginExecution>
+        					</pluginExecutions>
+        				</lifecycleMappingMetadata>
+        			</configuration>
+        		</plugin>
+        	</plugins>
+        </pluginManagement>
+    </build>
+</project>
+
diff --git a/trunk/bval-core/src/main/appended-resources/META-INF/NOTICE.vm b/trunk/bval-core/src/main/appended-resources/META-INF/NOTICE.vm
new file mode 100644
index 0000000..9a0c1ee
--- /dev/null
+++ b/trunk/bval-core/src/main/appended-resources/META-INF/NOTICE.vm
@@ -0,0 +1,25 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##  http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied.  See the License for the
+## specific language governing permissions and limitations
+## under the License.
+##
+
+The following copyright notice(s) were affixed to portions of this code
+with which this file is now or was at one time distributed.
+
+This product includes software developed by agimatec GmbH.
+Copyright 2007-2010 Agimatec GmbH. All rights reserved.
+
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/BeanValidationContext.java b/trunk/bval-core/src/main/java/org/apache/bval/BeanValidationContext.java
new file mode 100644
index 0000000..b9b8373
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/BeanValidationContext.java
@@ -0,0 +1,331 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import org.apache.bval.model.*;
+import org.apache.bval.util.AccessStrategy;
+import org.apache.bval.util.PropertyAccess;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+/**
+ * Description: Context during validation to help the {@link org.apache.bval.model.Validation}
+ * and the {@link BeanValidator} do their jobs.
+ * Used to bundle {@link BeanValidationContext} and {@link ValidationListener}
+ * together <br/>
+ * <b>This class is NOT thread-safe: a new instance will be created for each
+ * validation
+ * processing per thread.<br/></b>
+ */
+public class BeanValidationContext<T extends ValidationListener>
+      implements ValidationContext<T> {
+    /** represent an unknown propertyValue. */
+    private static final Object UNKNOWN = new Object() {
+        public String toString() {
+            return "unknown property value";
+        };
+    };
+
+    /** metainfo of current object. */
+    private MetaBean metaBean;
+    /** current object. */
+    private Object bean;
+    /** metainfo of current property. */
+    private MetaProperty metaProperty;
+    /**
+     * cached value of current property.
+     * Cached because of potential redundant access for different Validations
+     */
+    private Object propertyValue = UNKNOWN;
+
+    /** access strategy used for previous access */
+    private AccessStrategy access;
+
+    /** set of objects already validated to avoid endless loops. */
+    @SuppressWarnings({ "rawtypes" })
+    protected Map validatedObjects;
+
+    /**
+     * true when value is fixed, so that it will NOT be dynamically
+     * determined from the annotated element or the metaProperty.
+     * <b><br>Note: When value is UNKNOWN, it will be determined THE FIRST TIME
+     * IT IS ACCESSED.</b>
+     */
+    private boolean fixed;
+
+    /** listener notified of validation constraint violations. */
+    private T listener;
+
+    /**
+     * Create a new BeanValidationContext instance.
+     * @param listener
+     */
+    @SuppressWarnings({ "rawtypes" })
+    public BeanValidationContext(T listener) {
+        this(listener, new IdentityHashMap());
+    }
+
+    /**
+     * Create a new BeanValidationContext instance.
+     * @param listener
+     * @param validatedMap
+     */
+    @SuppressWarnings({ "rawtypes" })
+    protected BeanValidationContext(T listener, Map validatedMap) {
+        this.listener = listener;
+        this.validatedObjects = validatedMap;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T getListener() {
+        return listener;
+    }
+
+    /**
+     * Set the listener.
+     * @param listener T
+     */
+    public void setListener(T listener) {
+        this.listener = listener;
+    }
+
+    /**
+     * {@inheritDoc}
+     * Here, state equates to a given bean reference.
+     */
+    @SuppressWarnings("unchecked")
+    public boolean collectValidated() {
+        return validatedObjects.put(getBean(), Boolean.TRUE) == null;
+    }
+
+    /**
+     * Learn whether a particular object has been validated.
+     * @param object
+     * @return true when the object has already been validated in this context
+     */
+    public boolean isValidated(Object object) {
+        return validatedObjects.containsKey(object);
+    }
+
+    /**
+     * Clear map of validated objects (invoke when you want to 'reuse' the
+     * context for different validations)
+     */
+    public void resetValidated() {
+        validatedObjects.clear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setBean(Object aBean, MetaBean aMetaBean) {
+        bean = aBean;
+        metaBean = aMetaBean;
+        metaProperty = null;
+        unknownValue();
+    }
+
+    /**
+     * Get the cached value or access it somehow (via field or method)<br>
+     * <b>you should prefer getPropertyValue(AccessStrategy) instead of this method</b>
+     *
+     * @return the current value of the property accessed by reflection
+     * @throws IllegalArgumentException - error accessing attribute (config error, reflection problem)
+     * @throws IllegalStateException    - when no property is currently set in the context (application logic bug)
+     */
+    public Object getPropertyValue() {
+        if (access == null) { // undefined access strategy
+            return getPropertyValue(
+                  new PropertyAccess(bean.getClass(), metaProperty.getName()));
+        } else {
+            return getPropertyValue(access);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * Caches retrieved value.
+     */
+    public Object getPropertyValue(AccessStrategy access)
+          throws IllegalArgumentException, IllegalStateException {
+        if (propertyValue == UNKNOWN || (this.access != access && !fixed)) {
+            propertyValue = access.get(bean);
+            this.access = access;
+        }
+        return propertyValue;
+    }
+
+    /**
+     * Convenience method to access metaProperty.name
+     *
+     * @return null or the name of the current property
+     */
+    public String getPropertyName() {
+        return metaProperty == null ? null : metaProperty.getName();
+    }
+
+    /**
+     * Set the current property value.
+     * @param propertyValue
+     */
+    public void setPropertyValue(Object propertyValue) {
+        this.propertyValue = propertyValue;
+    }
+
+    /**
+     * Set the property value, fixed.
+     * @param value
+     */
+    public void setFixedValue(Object value) {
+        setPropertyValue(value);
+        setFixed(true);
+    }
+
+    /**
+     * Learn whether the current property value is "fixed."
+     * @return boolean
+     */
+    public boolean isFixed() {
+        return fixed;
+    }
+
+    /**
+     * Potentially declare the current property value as being "fixed."
+     * If <code>true</code>, the context will reuse any not-<code>UNKNOWN</code>
+     * propertyValue regardless of the {@link AccessStrategy} by which it is requested.
+     * @param fixed
+     */
+    public void setFixed(boolean fixed) {
+        this.fixed = fixed;
+    }
+
+    /**
+     * Depending on whether we have a metaProperty or not,
+     * this returns the metaProperty or otherwise the metaBean.
+     * This is used to have a simple way to request features
+     * in the Validation for both bean- and property-level validations.
+     *
+     * @return something that is capable to deliver features
+     */
+    public FeaturesCapable getMeta() {
+        return (metaProperty == null) ? metaBean : metaProperty;
+    }
+
+    /**
+     * Drop cached value, marking the internal cachedValue as <code>UNKNOWN</code>.
+     * This forces the BeanValidationContext to recompute the value
+     * the next time it is accessed.
+     * Use this method inside tests or when the propertyValue has been
+     * changed during validation.
+     */
+    public void unknownValue() {
+        propertyValue = UNKNOWN;
+        access = null;
+        fixed = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MetaBean getMetaBean() {
+        return metaBean;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object getBean() {
+        return bean;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MetaProperty getMetaProperty() {
+        return metaProperty;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setMetaBean(MetaBean metaBean) {
+        this.metaBean = metaBean;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setBean(Object bean) {
+        this.bean = bean;
+        unknownValue();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setMetaProperty(MetaProperty metaProperty) {
+        this.metaProperty = metaProperty;
+        unknownValue();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return "BeanValidationContext{ bean=" + bean + ", metaProperty=" + metaProperty +
+              ", propertyValue=" + propertyValue + '}';
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void moveDown(MetaProperty prop, AccessStrategy access) {
+        setBean(getPropertyValue(access), prop.getMetaBean());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void moveUp(Object bean, MetaBean aMetaBean) {
+        setBean(bean, aMetaBean); // reset context state
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCurrentIndex(Integer index) {
+        // do nothing
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCurrentKey(Object key) {
+        // do nothing
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public AccessStrategy getAccess() {
+        return this.access;
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/BeanValidator.java b/trunk/bval-core/src/main/java/org/apache/bval/BeanValidator.java
new file mode 100644
index 0000000..175e657
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/BeanValidator.java
@@ -0,0 +1,280 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Collection;
+
+import org.apache.bval.model.Features;
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.MetaProperty;
+import org.apache.bval.model.ValidationContext;
+import org.apache.bval.model.ValidationListener;
+import org.apache.bval.util.AccessStrategy;
+import org.apache.bval.util.PropertyAccess;
+import org.apache.bval.util.ValidationHelper;
+
+// TODO: centralize treatMapsLikeBeans
+
+/**
+ * Description: Top-Level API-class to validate objects or object-trees. You can
+ * invoke, extend or utilize this class if you need other ways to integrate
+ * validation in your application.
+ * <p/>
+ * This class supports cyclic object graphs by keeping track of validated
+ * instances in the validation context.<br/>
+ */
+public class BeanValidator<T extends ValidationListener> {
+    private final MetaBeanFinder metaBeanFinder;
+
+    /**
+     * Create a new BeanValidator instance. Convenience constructor. Use the
+     * global instance of MetaBeanManagerFactory.getFinder().
+     */
+    public BeanValidator() {
+        this(MetaBeanManagerFactory.getFinder());
+    }
+
+    /**
+     * Create a new BeanValidator instance.
+     * 
+     * @param metaBeanFinder
+     */
+    public BeanValidator(MetaBeanFinder metaBeanFinder) {
+        this.metaBeanFinder = metaBeanFinder;
+    }
+
+    /**
+     * Convenience API. validate a root object with all related objects with its
+     * default metaBean definition.
+     * 
+     * @param bean
+     * @return results - validation results found
+     */
+    public T validate(Object bean) {
+        MetaBean metaBean = getMetaBeanFinder().findForClass(bean.getClass());
+        return validate(bean, metaBean);
+    }
+
+    /**
+     * Convenience API. validate a root object with all related objects
+     * according to the metaBean.
+     * 
+     * @param bean
+     *            - a single bean or a collection of beans (that share the same
+     *            metaBean!)
+     * @param metaBean
+     * @return results - validation results found
+     */
+    public T validate(Object bean, MetaBean metaBean) {
+        ValidationContext<T> context = createContext();
+        context.setBean(bean, metaBean);
+        ValidationHelper.validateContext(context, new BeanValidatorCallback(context), treatMapsLikeBeans);
+        return context.getListener();
+    }
+
+    /**
+     * Validate the method parameters based on @Validate annotations.
+     * Requirements: Parameter, that are to be validated must be annotated with @Validate
+     * 
+     * @param method
+     *            - a method
+     * @param parameters
+     *            - the parameters suitable to the method
+     * @return a validation result or null when there was nothing to validate
+     * @see Validate
+     */
+    public T validateCall(Method method, Object[] parameters) {
+        if (parameters.length > 0) {
+            // shortcut (for performance!)
+            Annotation[][] annotations = method.getParameterAnnotations();
+            ValidationContext<T> context = null;
+            for (int i = 0; i < parameters.length; i++) {
+                for (Annotation anno : annotations[i]) {
+                    if (anno instanceof Validate) {
+                        if (context == null)
+                            context = createContext();
+                        if (determineMetaBean((Validate) anno, parameters[i], context)) {
+                            ValidationHelper.validateContext(context, new BeanValidatorCallback(context),
+                                treatMapsLikeBeans);
+                            break; // next parameter
+                        }
+                    }
+                }
+            }
+            return context != null ? context.getListener() : null;
+        }
+        return null;
+    }
+
+    /**
+     * Determine the metabean for the given object.
+     * 
+     * @param <VL>
+     * @param validate
+     * @param parameter
+     * @param context
+     * @return true when validation should happen, false to skip it
+     */
+    protected <VL extends ValidationListener> boolean determineMetaBean(Validate validate, Object parameter,
+        ValidationContext<VL> context) {
+        if (validate.value().length() == 0) {
+            if (parameter == null)
+                return false;
+            Class<?> beanClass;
+            if (parameter instanceof Collection<?>) { // do not validate empty
+                                                      // collection
+                Collection<?> coll = ((Collection<?>) parameter);
+                if (coll.isEmpty())
+                    return false;
+                beanClass = coll.iterator().next().getClass(); // get first
+                                                               // object
+            } else if (parameter.getClass().isArray()) {
+                beanClass = parameter.getClass().getComponentType();
+            } else {
+                beanClass = parameter.getClass();
+            }
+            context.setBean(parameter, getMetaBeanFinder().findForClass(beanClass));
+        } else {
+            context.setBean(parameter, getMetaBeanFinder().findForId(validate.value()));
+        }
+        return true;
+    }
+
+    /**
+     * factory method - overwrite in subclasses
+     * 
+     * @return ValidationListener of the proper type
+     */
+    @SuppressWarnings("unchecked")
+    protected T createResults() {
+        return (T) new ValidationResults();
+    }
+
+    /**
+     * factory method - overwrite in subclasses
+     * 
+     * @return ValidationContext parameterized with our listener type
+     */
+    protected ValidationContext<T> createContext() {
+        return new BeanValidationContext<T>(createResults());
+    }
+
+    /**
+     * Convenience API. validate a single property.
+     * 
+     * @param bean
+     *            - the root object
+     * @param metaProperty
+     *            - metadata for the property
+     * @return validation results
+     */
+    public T validateProperty(Object bean, MetaProperty metaProperty) {
+        ValidationContext<T> context = createContext();
+        context.setBean(bean);
+        context.setMetaProperty(metaProperty);
+        ValidationHelper.validateProperty(context);
+        return context.getListener();
+    }
+
+    /**
+     * {@inheritDoc} internal validate a bean (=not a collection of beans) and
+     * its related beans
+     */
+    protected <VL extends ValidationListener> void validateBeanNet(ValidationContext<VL> context) {
+        if (context.collectValidated()) {
+            ValidationHelper.validateBean(context);
+            for (MetaProperty prop : context.getMetaBean().getProperties()) {
+                validateRelatedBean(context, prop);
+            }
+        }
+    }
+
+    /**
+     * Validate a property of a graph.
+     * 
+     * @param <VL>
+     * @param context
+     * @param prop
+     */
+    protected <VL extends ValidationListener> void validateRelatedBean(ValidationContext<VL> context, MetaProperty prop) {
+        AccessStrategy[] access = prop.getFeature(Features.Property.REF_CASCADE);
+        if (access == null && prop.getMetaBean() != null) { // single property
+                                                            // access strategy
+            // save old values from context
+            final Object bean = context.getBean();
+            final MetaBean mbean = context.getMetaBean();
+            // modify context state for relationship-target bean
+            context.moveDown(prop, new PropertyAccess(bean.getClass(), prop.getName()));
+            ValidationHelper.validateContext(context, new BeanValidatorCallback(context), treatMapsLikeBeans);
+            // restore old values in context
+            context.moveUp(bean, mbean);
+        } else if (access != null) { // different accesses to relation
+            // save old values from context
+            final Object bean = context.getBean();
+            final MetaBean mbean = context.getMetaBean();
+            for (AccessStrategy each : access) {
+                // modify context state for relationship-target bean
+                context.moveDown(prop, each);
+                ValidationHelper.validateContext(context, new BeanValidatorCallback(context), treatMapsLikeBeans);
+                // restore old values in context
+                context.moveUp(bean, mbean);
+            }
+        }
+    }
+
+    private boolean treatMapsLikeBeans = false;
+
+    public boolean isTreatMapsLikeBeans() {
+        return treatMapsLikeBeans;
+    }
+
+    public void setTreatMapsLikeBeans(boolean treatMapsLikeBeans) {
+        this.treatMapsLikeBeans = treatMapsLikeBeans;
+    }
+
+    /**
+     * Get the metabean finder associated with this validator.
+     * 
+     * @return a MetaBeanFinder
+     * @see org.apache.bval.MetaBeanManagerFactory#getFinder()
+     */
+    public MetaBeanFinder getMetaBeanFinder() {
+        return metaBeanFinder;
+    }
+
+    /**
+     * Dispatches a call from {@link #validate()} to
+     * {@link BeanValidator#validateBeanNet(ValidationContext)} with the current
+     * context set.
+     */
+    private class BeanValidatorCallback implements ValidationHelper.ValidateCallback {
+
+        private final ValidationContext<?> context;
+
+        public BeanValidatorCallback(ValidationContext<?> context) {
+            this.context = context;
+        }
+
+        public void validate() {
+            validateBeanNet(context);
+        }
+
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/DynamicMetaBean.java b/trunk/bval-core/src/main/java/org/apache/bval/DynamicMetaBean.java
new file mode 100644
index 0000000..c5e22df
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/DynamicMetaBean.java
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import org.apache.bval.model.MetaBean;
+
+// TODO: Reduce visibility
+
+/**
+ * Description: Dynamic {@link MetaBean} subclass.<br/>
+ */
+public final class DynamicMetaBean extends MetaBean {
+    private static final long serialVersionUID = 1L;
+
+    private final MetaBeanFinder finder;
+
+    /**
+     * Create a new DynamicMetaBean instance.
+     * @param finder
+     */
+    public DynamicMetaBean(MetaBeanFinder finder) {
+        this.finder = finder;
+    }
+
+    /**
+     * {@inheritDoc}
+     * different strategies with hints to find MetaBean of associated object can
+     * be implemented here.
+     */
+    @Override
+    public MetaBean resolveMetaBean(Object bean) {
+        return bean instanceof Class<?> ?
+                finder.findForClass((Class<?>) bean) : finder.findForClass(bean.getClass());
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/IntrospectorMetaBeanFactory.java b/trunk/bval-core/src/main/java/org/apache/bval/IntrospectorMetaBeanFactory.java
new file mode 100644
index 0000000..d0c9e48
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/IntrospectorMetaBeanFactory.java
@@ -0,0 +1,109 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.MetaProperty;
+
+import java.beans.BeanInfo;
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Enumeration;
+
+import static org.apache.bval.model.Features.Property.*;
+
+/**
+ * Description: use information from java.beans.Introspector in MetaBeans. The PropertyDescriptor can contain info about
+ * HIDDEN, PREFERRED, READONLY and other features<br/>
+ * NOTE: THIS IS AN OPTIONAL CLASS, TO ENABLE IT, SET Factory Property apache.bval.enable-introspector="true"
+ */
+public class IntrospectorMetaBeanFactory implements MetaBeanFactory {
+
+    /**
+     * {@inheritDoc}
+     */
+    public void buildMetaBean(MetaBean meta) throws Exception {
+        if (meta.getBeanClass() == null) {
+            return; // handle only, when local class exists
+        }
+        BeanInfo info = Introspector.getBeanInfo(meta.getBeanClass());
+        if (meta.getName() == null && info.getBeanDescriptor() != null) {
+            meta.setName(info.getBeanDescriptor().getName()); // (display?)name = simple class name!
+        }
+        for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
+            if (!(pd instanceof IndexedPropertyDescriptor || pd.getName().equals("class"))) {
+                MetaProperty metaProp = buildMetaProperty(pd, meta.getProperty(pd.getName()));
+                meta.putProperty(pd.getName(), metaProp);
+            }
+        }
+    }
+
+    /**
+     * Create a {@link MetaProperty} from the specified {@link PropertyDescriptor}.
+     * 
+     * @param pd
+     * @return MetaProperty
+     */
+    @Deprecated
+    protected MetaProperty buildMetaProperty(PropertyDescriptor pd) {
+        return buildMetaProperty(pd, null);
+    }
+
+    /**
+     * Create a {@link MetaProperty} from the specified {@link PropertyDescriptor}.
+     * 
+     * @param pd
+     * @param existing
+     * @return MetaProperty
+     */
+    protected MetaProperty buildMetaProperty(PropertyDescriptor pd, MetaProperty existing) {
+        MetaProperty meta = new MetaProperty();
+        meta.setName(pd.getName());
+        meta.setType(determineGenericPropertyType(pd));
+        if (pd.isHidden()) {
+            meta.putFeature(HIDDEN, Boolean.TRUE);
+        }
+        if (pd.isPreferred()) {
+            meta.putFeature(PREFERRED, Boolean.TRUE);
+        }
+        if (pd.isConstrained()) {
+            meta.putFeature(READONLY, Boolean.TRUE);
+        }
+        Enumeration<String> enumeration = pd.attributeNames();
+        while (enumeration.hasMoreElements()) {
+            String key = enumeration.nextElement();
+            Object value = pd.getValue(key);
+            meta.putFeature(key, value);
+        }
+        return meta;
+    }
+
+    private Type determineGenericPropertyType(PropertyDescriptor pd) {
+        Method m = pd.getReadMethod();
+        if (m != null) {
+            return m.getGenericReturnType();
+        }
+        m = pd.getWriteMethod();
+        if (m != null && m.getParameterTypes().length == 1) {
+            return m.getGenericParameterTypes()[0];
+        }
+        return pd.getPropertyType();
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanBuilder.java b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanBuilder.java
new file mode 100644
index 0000000..745b0fa
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanBuilder.java
@@ -0,0 +1,136 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import org.apache.bval.model.MetaBean;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.ClassUtils;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Description: internal implementation class to construct metabeans with
+ * factories<br/>
+ */
+public class MetaBeanBuilder {
+
+    private static final Logger log =  Logger.getLogger(MetaBeanBuilder.class.getName());
+
+    /**
+     * here you can install different kinds of factories to create MetaBeans
+     * from
+     */
+    private MetaBeanFactory[] factories;
+
+    /**
+     * Create a new MetaBeanBuilder instance.
+     */
+    public MetaBeanBuilder() {
+        this(new MetaBeanFactory[] { new IntrospectorMetaBeanFactory() });
+    }
+
+    /**
+     * Create a new MetaBeanBuilder instance.
+     * 
+     * @param factories
+     */
+    public MetaBeanBuilder(MetaBeanFactory[] factories) {
+        setFactories(factories);
+    }
+
+    /**
+     * Get the configured set of {@link MetaBeanFactory} objects.
+     * 
+     * @return {@link MetaBeanFactory} array
+     */
+    public MetaBeanFactory[] getFactories() {
+        return ArrayUtils.clone(factories);
+    }
+
+    /**
+     * Set the array of {@link MetaBeanFactory} instances with which to enrich
+     * {@link MetaBean}s.
+     * 
+     * @param factories
+     */
+    public void setFactories(MetaBeanFactory[] factories) {
+        this.factories = ArrayUtils.clone(factories);
+    }
+
+    /**
+     * Build a {@link MetaBean} for a given id.
+     * 
+     * @param beanInfoId
+     * @return MetaBean
+     * @throws Exception
+     *             if unable to build
+     */
+    public MetaBean buildForId(String beanInfoId) throws Exception {
+        throw new IllegalArgumentException("MetaBean " + beanInfoId + " not found");
+    }
+
+    /**
+     * Build beans for all known ids. Default implementation returns an empty
+     * map.
+     * 
+     * @return Map of String : MetaBean
+     */
+    public Map<String, MetaBean> buildAll() throws Exception {
+        return new HashMap<String, MetaBean>();
+    }
+
+    /**
+     * Find the named class.
+     * 
+     * @param className
+     * @return Class found or null
+     */
+    protected Class<?> findLocalClass(String className) {
+        if (className != null) {
+            try {
+                return ClassUtils.getClass(className);
+            } catch (ClassNotFoundException e) {
+            	log.log(Level.FINE, String.format("Class not found: %s", className), e);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Build a MetaBean for the specified class.
+     * 
+     * @param clazz
+     * @return MetaBean
+     * @throws Exception
+     */
+    public MetaBean buildForClass(Class<?> clazz) throws Exception {
+        MetaBean meta = new MetaBean();
+        if (clazz != null) { // local class here?
+            meta.setBeanClass(clazz);
+            meta.setId(clazz.getName()); // default id = full class name!
+        }
+        for (MetaBeanFactory factory : factories) {
+            factory.buildMetaBean(meta);
+        }
+        return meta;
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanCache.java b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanCache.java
new file mode 100644
index 0000000..c55bc0a
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanCache.java
@@ -0,0 +1,113 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.bval.model.MetaBean;
+
+/**
+ * Description: a cache to hold metabeans by id and by class.<br/>
+ */
+public class MetaBeanCache implements MetaBeanFinder, Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Cache keyed by id.
+     */
+    protected final ConcurrentMap<String, MetaBean> cacheById = new ConcurrentHashMap<String, MetaBean>();
+    /**
+     * Cache keyed by class.
+     */
+    protected final ConcurrentMap<Class<?>, MetaBean> cacheByClass = new ConcurrentHashMap<Class<?>, MetaBean>();
+
+    /**
+     * Create a new MetaBeanCache instance.
+     */
+    public MetaBeanCache() {
+        super();
+    }
+
+    /**
+     * Create a new MetaBeanCache instance.
+     * @param beans
+     */
+    public MetaBeanCache(Map<String, MetaBean> beans) {
+        this();
+        for (MetaBean bean : beans.values()) {
+            cache(bean);
+        }
+    }
+
+    /**
+     * Clear the cache.
+     */
+    public void clear() {
+        cacheById.clear();
+        cacheByClass.clear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MetaBean findForId(String beanInfoId) {
+        return cacheById.get(beanInfoId);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MetaBean findForClass(Class<?> clazz) {
+        return cacheByClass.get(clazz);
+    }
+
+    /**
+     * Return all cached MetaBeans by id.
+     * @return live map
+     */
+    public Map<String, MetaBean> findAll() {
+        return cacheById;
+    }
+
+    /**
+     * Cache the specified MetaBean.
+     * @param beanInfo
+     */
+    public void cache(MetaBean beanInfo) {
+        cacheById.put(beanInfo.getId(), beanInfo);
+        if (beanInfo.getBeanClass() != null &&
+                beanInfo.getId().equals(beanInfo.getBeanClass().getName())) {
+            cacheByClass.putIfAbsent(beanInfo.getBeanClass(), beanInfo);
+        }
+    }
+
+    /**
+     * Remove a single MetaBean from the cache.
+     * @param beanInfo
+     */
+    public void removeFromCache(MetaBean beanInfo) {
+        cacheById.remove(beanInfo.getId());
+        if (beanInfo.getBeanClass() != null &&
+                beanInfo.getId().equals(beanInfo.getBeanClass().getName())) {
+            cacheByClass.remove(beanInfo.getBeanClass());
+        }
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanFactory.java b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanFactory.java
new file mode 100644
index 0000000..e5a06d7
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanFactory.java
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import org.apache.bval.model.MetaBean;
+
+/**
+ * Description: interface for abstraction how to initialize a MetaBean
+ * with information from somewhere<br/>
+ */
+public interface MetaBeanFactory {
+    /**
+     * Initialize the specified {@link MetaBean}.
+     * @param metaBean
+     * @throws Exception
+     */
+    void buildMetaBean(MetaBean metaBean) throws Exception;
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanFinder.java b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanFinder.java
new file mode 100644
index 0000000..1caa97e
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanFinder.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+
+import org.apache.bval.model.MetaBean;
+
+/**
+ * Description: Interface to find BeanInfos <br/>
+ */
+public interface MetaBeanFinder {
+    /**
+     * Find a MetaBean with a certain id.
+     * @param beanInfoId - symbolic unique name of Meta Info
+     * @return BeanInfo
+     * @throws IllegalArgumentException - when MetaBean not found
+     */
+    MetaBean findForId(String beanInfoId);
+
+    /**
+     * Find the MetaBean for the specified class.
+     * @param clazz - bean class
+     * @return BeanInfo (never null)
+     */
+    MetaBean findForClass(Class<?> clazz);
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java
new file mode 100644
index 0000000..fe4797e
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java
@@ -0,0 +1,143 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.MetaProperty;
+
+import static org.apache.bval.model.Features.Property.*;
+
+/**
+ * Description: Default implementation for the interface to find, register and
+ * create MetaBeans. In most situations a single instance of this class is
+ * sufficient and you can get this instance from the
+ * {@link MetaBeanManagerFactory}. <br/>
+ */
+public class MetaBeanManager implements MetaBeanFinder {
+
+    /** MetaBean cache */
+    protected final MetaBeanCache cache = new MetaBeanCache();
+    /** MetaBean builder */
+    protected final MetaBeanBuilder builder;
+    /** Complete flag */
+    protected boolean complete = false;
+
+    /**
+     * Create a new MetaBeanManager instance.
+     */
+    public MetaBeanManager() {
+        builder = new MetaBeanBuilder();
+    }
+
+    /**
+     * Create a new MetaBeanManager instance.
+     * 
+     * @param builder
+     */
+    public MetaBeanManager(MetaBeanBuilder builder) {
+        this.builder = builder;
+    }
+
+    /**
+     * Get the builder used.
+     * 
+     * @return {@link MetaBeanBuilder}
+     */
+    public MetaBeanBuilder getBuilder() {
+        return builder;
+    }
+
+    /**
+     * Get the cache used.
+     * 
+     * @return {@link MetaBeanCache}
+     */
+    public MetaBeanCache getCache() {
+        return cache;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MetaBean findForId(String beanInfoId) {
+        MetaBean beanInfo = cache.findForId(beanInfoId);
+        if (beanInfo != null)
+            return beanInfo;
+        try {
+            beanInfo = builder.buildForId(beanInfoId);
+            cache.cache(beanInfo);
+            computeRelationships(beanInfo);
+            return beanInfo;
+        } catch (RuntimeException e) {
+            throw e; // do not wrap runtime exceptions
+        } catch (Exception e) {
+            throw new IllegalArgumentException("error creating beanInfo with id: " + beanInfoId, e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MetaBean findForClass(Class<?> clazz) {
+        if (clazz == null)
+            return null;
+        MetaBean beanInfo = cache.findForClass(clazz);
+        if (beanInfo != null)
+            return beanInfo;
+        try {
+            beanInfo = builder.buildForClass(clazz);
+            cache.cache(beanInfo);
+            computeRelationships(beanInfo);
+            return beanInfo;
+        } catch (RuntimeException e) {
+            throw e; // do not wrap runtime exceptions
+        } catch (Exception e) {
+            throw new IllegalArgumentException("error creating beanInfo for " + clazz, e);
+        }
+    }
+
+    /**
+     * Compute all known relationships for <code>beanInfo</code>. must be called
+     * AFTER cache.cache() to avoid endless loop
+     * 
+     * @param beanInfo
+     *            - the bean for which to compute relationships
+     */
+    protected void computeRelationships(MetaBean beanInfo) {
+        for (MetaProperty prop : beanInfo.getProperties()) {
+            String beanRef = (String) prop.getFeature(REF_BEAN_ID);
+            computeRelatedMetaBean(prop, beanRef);
+        }
+    }
+
+    /**
+     * Compute a single related {@link MetaBean}.
+     * 
+     * @param prop
+     * @param beanRef
+     */
+    protected void computeRelatedMetaBean(MetaProperty prop, String beanRef) {
+        Class<?> beanType = prop.getFeature(REF_BEAN_TYPE);
+        if (beanType != null) {
+            prop.setMetaBean(findForClass(beanType));
+        } else if (prop.getFeature(REF_CASCADE) != null) { // dynamic type
+                                                           // resolution:
+            prop.setMetaBean(new DynamicMetaBean(this));
+        }
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanManagerFactory.java b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanManagerFactory.java
new file mode 100644
index 0000000..f2cd8da
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/MetaBeanManagerFactory.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+/**
+ * Description: API class to hold a singleton of a {@link MetaBeanManager}
+ * that implements the finder and registry interfaces for MetaBeans<br/>
+ *
+ * @see org.apache.bval.model.MetaBean
+ * @see MetaBeanManager
+ */
+public class MetaBeanManagerFactory {
+    private static MetaBeanManager manager = new MetaBeanManager();
+
+    /**
+     * global meta bean finder.
+     * @return the singleton
+     */
+    public static MetaBeanFinder getFinder() {
+        return manager;
+    }
+
+
+    /**
+     * set global meta bean manager, that is responsible
+     * for finding, caching, xml registry and enrichment algorithm.
+     * @param finder
+     */
+    public static void setManager(MetaBeanManager finder) {
+        manager = finder;
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/Validate.java b/trunk/bval-core/src/main/java/org/apache/bval/Validate.java
new file mode 100644
index 0000000..039106d
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/Validate.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Description: Annotate an element (parameter) to be validated.
+ * <br>
+ */
+@Target({METHOD, FIELD, CONSTRUCTOR, PARAMETER})
+@Retention(RUNTIME)
+public @interface Validate {
+    /**
+     * (optional) the MetaBean.id to use
+     */
+    String value() default "";
+
+    /**
+     * to Support groups on @Valid(ate) in method/return validation
+     */
+    Class<?>[] groups() default {};
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/ValidationResults.java b/trunk/bval-core/src/main/java/org/apache/bval/ValidationResults.java
new file mode 100644
index 0000000..e9d79f0
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/ValidationResults.java
@@ -0,0 +1,211 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+
+import org.apache.bval.model.ValidationContext;
+import org.apache.bval.model.ValidationListener;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Description: Implements a contains to hold and transport validation results<br/>
+ */
+public class ValidationResults implements ValidationListener, Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Map<String, List<Error>> errorsByReason;
+    private Map<Object, Map<String, List<Error>>> errorsByOwner;
+
+
+    /**
+     * API to add an error to the validation results.
+     *
+     * @param reason       - Features from {@link org.apache.bval.model.Features.Property}
+     *                       or custom reason of validation error
+     * @param context        - context information (bean, propertyName, value, ...)
+     */
+    public <T extends ValidationListener> void addError(String reason, ValidationContext<T> context) {
+        Error error = createError(reason, context.getBean(), context.getPropertyName());
+        addError(error, context);
+    }
+
+
+     /**
+     * API to add an error to the validation results.
+     *
+     * @param error       - holding the description of reason and object to describe
+      *                     the validation error
+     * @param context     - null or the context to provide additional information
+     */
+    public <T extends ValidationListener> void addError(Error error, ValidationContext<T> context) {
+        if (errorsByReason == null) {
+            initialize();
+        }
+        addToReasonBucket(error);
+        addToOwnerBucket(error);
+    }
+
+    /**
+     * Old API to add an error to the validation results when no context is available.
+     *
+     * @param reason       - Features from {@link org.apache.bval.model.Features.Property} or custom validation reason
+     * @param bean         - (optional) owner bean or null
+     * @param propertyName - (optional) propertyName where valiation error occurred or null
+     */
+    public void addError(String reason, Object bean, String propertyName) {
+        addError(createError(reason, bean, propertyName), null);
+    }
+
+    /**
+     * Create an Error object.
+     * @param reason
+     * @param owner
+     * @param propertyName
+     * @return new {@link Error}
+     */
+    protected Error createError(String reason, Object owner, String propertyName) {
+        return new Error(reason, owner, propertyName);
+    }
+
+    /**
+     * initialize the error-buckets now when needed and
+     * not on instance creation to save memory garbage.
+     */
+    protected void initialize() {
+        errorsByReason = new LinkedHashMap<String, List<Error>>();
+        errorsByOwner = new LinkedHashMap<Object, Map<String, List<Error>>>();
+    }
+
+    /**
+     * Add an Error to the set of Errors shared by a particular "reason."
+     * @param error
+     * @see {@link Error#getReason()}
+     */
+    protected void addToReasonBucket(Error error) {
+        if (error.getReason() == null) return;
+
+        List<Error> errors = errorsByReason.get(error.getReason());
+        if (errors == null) {
+            errors = new ArrayList<Error>();
+            errorsByReason.put(error.getReason(), errors);
+        }
+        errors.add(error);
+    }
+
+    /**
+     * Add an Error to the property-keyed map of Errors maintained for this Error's owner.
+     * @param error
+     * @see {@link Error#getOwner()}
+     */
+    protected void addToOwnerBucket(Error error) {
+        if (error.getOwner() == null) return;
+
+        Map<String, List<Error>> errors = errorsByOwner.get(error.getOwner());
+        if (errors == null) {
+            errors = new HashMap<String, List<Error>>();
+            errorsByOwner.put(error.getOwner(), errors);
+        }
+        List<Error> list = errors.get(error.getPropertyName());
+        if (list == null) {
+            list = new ArrayList<Error>();
+            errors.put(error.getPropertyName(), list);
+        }
+        list.add(error);
+    }
+
+    /**
+     * Get the map of Errors by reason; 
+     * key = reason, value = list of errors for this reason
+     * @return map
+     */
+    public Map<String, List<Error>> getErrorsByReason() {
+        if (errorsByReason == null) return Collections.emptyMap();
+        return errorsByReason;
+    }
+
+    /**
+     * Get the map of Errors by owner;
+     * key = owner, value = map with:<br>
+     * &nbsp;&nbsp; key = propertyName, value = list of errors for this owner.propertyName
+     * @return map
+     */
+    public Map<Object, Map<String, List<Error>>> getErrorsByOwner() {
+        if (errorsByOwner == null) return Collections.emptyMap();
+        return errorsByOwner;
+    }
+
+    /**
+     * Learn whether these results are empty/error-free.
+     * @return true when there are NO errors in this validation result
+     */
+    public boolean isEmpty() {
+        if (errorsByReason == null ||
+              (errorsByReason.isEmpty() && errorsByOwner.isEmpty())) return true;
+        for (List<Error> list : errorsByReason.values()) {
+            if (!list.isEmpty()) return false;
+        }
+        for (Map<String, List<Error>> map : errorsByOwner.values()) {
+            for (List<Error> list : map.values()) {
+                if (!list.isEmpty()) return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Learn whether there is an Error keyed to a specified reason description.
+     * @param reason
+     * @return boolean
+     * @see {@link Error#getReason()}
+     */
+    public boolean hasErrorForReason(String reason) {
+        if (errorsByReason == null) return false;
+        List<Error> errors = errorsByReason.get(reason);
+        return errors != null && !errors.isEmpty();
+    }
+
+    /**
+     * Learn whether <code>bean</code> has any errors keyed to property <code>propertyName</code>.
+     * @param bean
+     * @param propertyName - may be null: any property is checked
+     *                     OR the name of the property to check
+     * @return boolean
+     */
+    public boolean hasError(Object bean, String propertyName) {
+        if (errorsByOwner == null) return false;
+        Map<String, List<Error>> errors = errorsByOwner.get(bean);
+        if (errors == null) return false;
+        if (propertyName != null) {
+            List<Error> list = errors.get(propertyName);
+            return list != null && !list.isEmpty();
+        } else {
+            for (List<Error> list : errors.values()) {
+                if (!list.isEmpty()) return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return "ValidationResults{" + errorsByOwner + "}";
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/DynaType.java b/trunk/bval-core/src/main/java/org/apache/bval/model/DynaType.java
new file mode 100644
index 0000000..7a89862
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/DynaType.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+import java.lang.reflect.Type;
+
+/**
+ * Description: implementation of a dynamic type. can be used inside a
+ * MetaProperty for instance-based types <br/>
+ */
+public interface DynaType extends Type {
+    /**
+     * Resolve the type indirection.
+     * @return Type
+     */
+    Type getRawType();
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/DynaTypeEnum.java b/trunk/bval-core/src/main/java/org/apache/bval/model/DynaTypeEnum.java
new file mode 100644
index 0000000..d520807
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/DynaTypeEnum.java
@@ -0,0 +1,122 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * Description: ("artificial" enum with custom values).<br/>
+ */
+public class DynaTypeEnum implements DynaType {
+    private final Class<?> enumClass;
+    private Value[] enumConstants;
+
+    /**
+     * Create a new DynaTypeEnum instance.
+     * @param enumClass
+     */
+    public DynaTypeEnum(Class<?> enumClass) {
+        this.enumClass = enumClass;
+    }
+
+    /**
+     * Create a new DynaTypeEnum instance.
+     * @param enumClass
+     * @param names
+     */
+    public DynaTypeEnum(Class<?> enumClass, String... names) {
+        this(enumClass);
+        setEnumNames(names);
+    }
+
+    /**
+     * Set the enumeration value names.
+     * @param names
+     */
+    public void setEnumNames(String[] names) {
+        enumConstants = new Value[names.length];
+        int i = 0;
+        for (String each : names) {
+            enumConstants[i++] = new Value(each);
+        }
+    }
+
+    /**
+     * Get the name of the enum class.
+     * @return String
+     */
+    public String getName() {
+        return enumClass.getName();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Class<?> getRawType() {
+        return enumClass;
+    }
+
+    /**
+     * Learn whether the referred class is, in fact, an enum class.
+     * used by freemarker-template "bean-infos-json.ftl"
+     */
+    public boolean isEnum() {
+        return enumClass.isEnum();
+    }
+
+    /**
+     * Get the emulated constants.
+     * used by freemarker-template "bean-infos-json.ftl"
+     * @return Value[]
+     */
+    public Value[] getEnumConstants() {
+        return ArrayUtils.clone(enumConstants);
+    }
+
+    /**
+     * Learn whether the wrapped class is assignable from <code>cls</code>.
+     * @param cls
+     * @return boolean
+     */
+    public boolean isAssignableFrom(Class<?> cls) {
+        return enumClass.isAssignableFrom(cls);
+    }
+
+    /**
+     * Represents a single "enum" instance (= the value).
+     */
+    public static final class Value {
+        final String name;
+
+        /**
+         * Create a new Value instance.
+         * @param name
+         */
+        Value(String name) {
+            this.name = name;
+        }
+
+        /**
+         * used by freemarker-template "bean-infos-json.ftl"
+         * @return the name of this constant
+         */
+        public String name() {
+            return name;
+        }
+
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/Features.java b/trunk/bval-core/src/main/java/org/apache/bval/model/Features.java
new file mode 100644
index 0000000..d362efa
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/Features.java
@@ -0,0 +1,114 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+/**
+ * Description: Contains key of common feature keys used by standard validators etc.
+ * This DOES NOT MEAN that the list of property- or bean-features is closed. You can
+ * put anything into the metabean as a feature and use it in your custom validators
+ * and other classes that access your metabeans.<br/>
+ *
+ * @see FeaturesCapable
+ */
+public interface Features {
+    /** Features of {@link MetaBean} */
+    public interface Bean {
+        /** INFO: String, name of the Property, that is the Primary Key */
+        String MAIN_KEY = "mainKey";
+        /** INFO: category/domain to which the metaBean belongs to */
+        String DOMAIN = "domain";
+
+        //        String DISPLAY_NAME = "displayName";
+        String UNIQUE_KEY = "uniqueKey";
+    }
+
+    /** Features of {@link MetaProperty} */
+    public interface Property {
+        /** INFO: possible Enum values */
+        String ENUM = "enum";
+        /** INFO: Boolean, TRUE if Property is a Unique Key */
+        String UNIQUE_KEY = "uniqueKey";
+        /** VALIDATION: Boolean, mandatory field? */
+        String MANDATORY = "mandatory";
+        /** VALIDATION: Integer, max. number of chars/digits / max. cardinality of a to-many relationship */
+        String MAX_LENGTH = "maxLen";
+        /** VALIDATION: Comparable (e.g. a subclass of Number), max value */
+        String MAX_VALUE = "maxValue";
+        /** VALIDATION: Integer, min. number of chars/digits / min. cardinality of a to-many relationship */
+        String MIN_LENGTH = "minLen";
+        /** VALIDATION: Comparable (e.g. a subclass of Number), min value */
+        String MIN_VALUE = "minValue";
+        /** INFO: String-representation of a default value */
+        String DEFAULT_VALUE = "defValue";
+        /** SECURITY, INFO: Boolean, is value or relationship unmodifiable */
+        String READONLY = "readonly";
+        /**
+         * SECURITY, INFO: Boolean, Field accessible?
+         * If false, the field must not be displayed, queried, changed.
+         */
+        String DENIED = "denied";
+        /** VALIDATION: String, regular expression to validate the format of input data */
+        String REG_EXP = "regExp";
+        /**
+         * VALIDATION: String, Constraint for time-information of a Date-field:
+         * {@link org.apache.bval.xml.XMLMetaValue#TIMELAG_Past}
+         * or
+         * {@link org.apache.bval.xml.XMLMetaValue#TIMELAG_Future}
+         */
+        String TIME_LAG = "timeLag";
+
+        /**
+         * INFO: Boolean, Field visible?
+         *
+         * @see java.beans.PropertyDescriptor#isHidden()
+         */
+        String HIDDEN = "hidden";
+        /**
+         * INFO: Boolean
+         *
+         * @see java.beans.PropertyDescriptor#isPreferred()
+         */
+        String PREFERRED = "preferred";
+
+        /** INFO: relationship's target metaBean.id * */
+        String REF_BEAN_ID = "refBeanId";
+
+        /**
+         * INFO: Class<br>
+         * Relationship's target metaBean.beanClass.
+         * In case of to-many relationships, this feature
+         * hold the Bean-type not the Collection-type.
+         */
+        String REF_BEAN_TYPE = "refBeanType";
+
+        /**
+         * INFO: AccessStrategy[]<br>
+         * an array of accessStrategies
+         * how validation should cascade into relationship target beans<br>
+         * null when validation should NOT cascade into relationship target
+         * beans<br>
+         * <p/>
+         * Default: {PropertyAccess(metaProperty.name)},
+         * when MetaProperty.metaBean is != null
+         */
+        String REF_CASCADE = "refCascade";
+
+        /** INFO: an array with the string names of custom java script validation functions */
+        @Deprecated // TODO RSt - I suggest to remove this and all related code
+        String JAVASCRIPT_VALIDATION_FUNCTIONS = "jsFunctions";
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/FeaturesCapable.java b/trunk/bval-core/src/main/java/org/apache/bval/model/FeaturesCapable.java
new file mode 100644
index 0000000..d495dc1
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/FeaturesCapable.java
@@ -0,0 +1,219 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * Description: abstract superclass of meta objects that support a map of
+ * features.<br/>
+ */
+public abstract class FeaturesCapable implements Serializable {
+    private static final long serialVersionUID = -4045110242904814218L;
+
+    private ConcurrentMap<String, Object> features = createFeaturesMap();
+
+    /** key = validation id, value = the validation */
+    private Validation[] validations = new Validation[0];
+
+    private volatile boolean locking;
+    private ReentrantLock lock = new ReentrantLock(true);
+
+    /**
+     * Create a new FeaturesCapable instance.
+     */
+    public FeaturesCapable() {
+        super();
+    }
+
+    /**
+     * Get the (live) map of features.
+     * 
+     * @return Map<String, Object>
+     */
+    public Map<String, Object> getFeatures() {
+        return features;
+    }
+
+    /**
+     * Set whether to optimize read operations by accessing the features map in
+     * an unsynchronized manner.
+     * 
+     * @param fast
+     */
+    public void optimizeRead(boolean fast) {
+        lock.lock();
+        try {
+            this.locking = !fast;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Get the specified feature.
+     * 
+     * @param <T>
+     * @param key
+     * @return T
+     */
+    public <T> T getFeature(String key) {
+        return getFeature(key, (T) null);
+    }
+
+    /**
+     * Get the specified feature, returning <code>defaultValue</code> if
+     * undeclared.
+     * 
+     * @param <T>
+     * @param key
+     * @param defaultValue
+     * @return T
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T getFeature(String key, T defaultValue) {
+        boolean release = acquireLockIfNeeded();
+        try {
+            return features.containsKey(key) ? (T) features.get(key) : defaultValue;
+        } finally {
+            if (release) {
+                lock.unlock();
+            }
+        }
+    }
+
+    /**
+     * Convenience method to set a particular feature value.
+     * 
+     * @param <T>
+     * @param key
+     * @param value
+     */
+    public <T> void putFeature(String key, T value) {
+        boolean release = acquireLockIfNeeded();
+        try {
+            features.put(key, value);
+        } finally {
+            if (release) {
+                lock.unlock();
+            }
+        }
+    }
+
+    /**
+     * Create a deep copy (copy receiver and copy properties).
+     * 
+     * @param <T>
+     * @return new T instance
+     */
+    public <T extends FeaturesCapable> T copy() {
+        try {
+            @SuppressWarnings("unchecked")
+            final T self = (T) clone();
+            copyInto(self);
+            return self;
+        } catch (CloneNotSupportedException e) {
+            throw new IllegalStateException("cannot clone() " + this, e);
+        }
+    }
+
+    /**
+     * Copy this {@link FeaturesCapable} into another {@link FeaturesCapable}
+     * instance.
+     * 
+     * @param <T>
+     * @param target
+     */
+    protected <T extends FeaturesCapable> void copyInto(T target) {
+        target.features = target.createFeaturesMap();
+        target.features.putAll(features);
+        if (validations != null) {
+            target.validations = validations.clone();
+        }
+    }
+
+    /**
+     * Get any validations set for this {@link FeaturesCapable}.
+     * 
+     * @return Validation array
+     */
+    public Validation[] getValidations() {
+        return ArrayUtils.clone(validations);
+    }
+
+    /**
+     * Set the validations for this {@link FeaturesCapable}.
+     * 
+     * @param validations
+     */
+    public void setValidations(Validation[] validations) {
+        this.validations = ArrayUtils.clone(validations);
+    }
+
+    /**
+     * Add a validation to this {@link FeaturesCapable}.
+     * 
+     * @param validation
+     *            to add
+     */
+    public void addValidation(Validation validation) {
+        validations = ArrayUtils.add(validations, validation);
+    }
+
+    /**
+     * Search for an equivalent validation among those configured.
+     * 
+     * @param aValidation
+     * @return true if found
+     */
+    public boolean hasValidation(Validation aValidation) {
+        if (validations == null)
+            return false;
+        for (Validation validation : validations) {
+            if (validation.equals(aValidation))
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Create a features map for this {@link FeaturesCapable} object.
+     * @return ConcurrentMap
+     */
+    protected ConcurrentMap<String, Object> createFeaturesMap() {
+        return new ConcurrentHashMap<String, Object>();
+    }
+
+    private boolean acquireLockIfNeeded() {
+        if (locking) {
+            lock.lock();
+            // double read
+            if (locking) {
+                return true;
+            }
+            lock.unlock();
+        }
+        return false;
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/MetaBean.java b/trunk/bval-core/src/main/java/org/apache/bval/model/MetaBean.java
new file mode 100644
index 0000000..05ce598
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/MetaBean.java
@@ -0,0 +1,246 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * Description: the meta description of a bean or class. the class/bean itself can have a map of features and an array
+ * of metaproperties.<br/>
+ * 
+ * @see MetaProperty
+ */
+public class MetaBean extends FeaturesCapable implements Cloneable, Features.Bean {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Comparator for managing the sorted properties array.
+     */
+    private static class PropertyNameComparator implements Comparator<Object> {
+        /** Static instance */
+        static final PropertyNameComparator INSTANCE = new PropertyNameComparator();
+
+        /**
+         * {@inheritDoc}
+         */
+        public int compare(Object o1, Object o2) {
+            return getName(o1).compareTo(getName(o2));
+        }
+
+        private String getName(Object o) {
+            if (o == null) {
+                throw new NullPointerException();
+            }
+            return o instanceof MetaProperty ? ((MetaProperty) o).getName() : String.valueOf(o);
+        }
+    }
+
+    private String id;
+    private String name;
+    private Class<?> beanClass;
+    private MetaProperty[] properties = new MetaProperty[0];
+
+    /**
+     * Get the id.
+     * 
+     * @return String
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * Set the id.
+     * 
+     * @param id
+     *            the String to set
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * Get the name.
+     * 
+     * @return String
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Set the name.
+     * 
+     * @param name
+     *            the String to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Get the beanClass.
+     * 
+     * @return Class<?>
+     */
+    public Class<?> getBeanClass() {
+        return beanClass;
+    }
+
+    /**
+     * Set the beanClass.
+     * 
+     * @param beanClass
+     *            the Class<?> to set
+     */
+    public void setBeanClass(Class<?> beanClass) {
+        this.beanClass = beanClass;
+    }
+
+    /**
+     * Get the properties.
+     * 
+     * @return MetaProperty[]
+     */
+    public MetaProperty[] getProperties() {
+        return ArrayUtils.clone(properties);
+    }
+
+    /**
+     * Set the properties.
+     * 
+     * @param properties
+     *            the MetaProperty[] to set
+     */
+    public void setProperties(MetaProperty[] properties) {
+        this.properties = ArrayUtils.clone(properties);
+        Arrays.sort(this.properties, PropertyNameComparator.INSTANCE);
+    }
+
+    /**
+     * Get the specified {@link MetaProperty}.
+     * 
+     * @param name
+     * @return MetaProperty found or <code>null</code>
+     */
+    public MetaProperty getProperty(String name) {
+        final MetaProperty[] props = properties;
+        int pos = Arrays.binarySearch(props, name, PropertyNameComparator.INSTANCE);
+        return pos < 0 ? null : props[pos];
+    }
+
+    /**
+     * Learn whether any known property is a relationship.
+     * 
+     * @see MetaProperty#isRelationship()
+     * @return true when at least one of the properties is a relationship
+     */
+    public boolean hasRelationships() {
+        for (MetaProperty p : properties) {
+            if (p.isRelationship()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Learn whether there are any known properties.
+     * 
+     * @return boolean
+     */
+    public boolean hasProperties() {
+        return properties.length > 0;
+    }
+
+    /**
+     * bidirectional - set the relationship between a MetaProperty and its parentMetaBean
+     * 
+     * @param name
+     * @param property
+     *            if <code>null</code>, remove
+     */
+    public void putProperty(String name, MetaProperty property) {
+        if (property != null) {
+            property.setParentMetaBean(this);
+        }
+        Object key = property == null ? name : property;
+        // make a local copy for consistency
+        MetaProperty[] props = properties;
+        int pos = Arrays.binarySearch(props, key, PropertyNameComparator.INSTANCE);
+        if (pos < 0) {
+            if (property == null) {
+                // store null property for unknown name == NOOP
+                return;
+            }
+            props = ArrayUtils.add(props, 0 - pos - 1, property);
+        } else {
+            if (property == null) {
+                props = ArrayUtils.remove(props, pos);
+            } else {
+                props[pos] = property;
+            }
+        }
+        this.properties = props;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return "MetaBean{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", beanClass=" + beanClass + '}';
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected <T extends FeaturesCapable> void copyInto(T target) {
+        super.copyInto(target);
+        final MetaBean copy = (MetaBean) target;
+        if (properties != null) {
+            copy.properties = properties.clone();
+            for (int i = copy.properties.length - 1; i >= 0; i--) {
+                copy.properties[i] = copy.properties[i].copy();
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * If this {@link MetaBean} is compatible with <code>bean</code>, return <code>this</code>, else <code>null</code>.
+     * </p>
+     * <p>
+     * Compatibility is satisfied in one of the following ways:
+     * <ul>
+     * <li><code>bean</code> is null</li>
+     * <li><code>bean</code> is an instance of our <code>beanClass</code></li>
+     * <li><code>bean</code> <em>is</em> our <code>beanClass</code> itself</li>
+     * </ul>
+     * </p>
+     * 
+     * @param bean
+     * @return <code>this</code> or <code>null</code>
+     */
+    public MetaBean resolveMetaBean(Object bean) {
+        return bean == null || bean == beanClass || beanClass.isInstance(bean) ? this : null;
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/MetaProperty.java b/trunk/bval-core/src/main/java/org/apache/bval/model/MetaProperty.java
new file mode 100644
index 0000000..48ddf38
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/MetaProperty.java
@@ -0,0 +1,175 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+import java.lang.reflect.Type;
+
+import org.apache.commons.lang3.reflect.TypeUtils;
+
+/**
+ * Description: the meta description of a property of a bean. It supports a map
+ * of features and multiple validations.<br/>
+ *
+ * @see Validation
+ * @see MetaBean
+ */
+public class MetaProperty extends FeaturesCapable
+      implements Cloneable, Features.Property {
+    private static final long serialVersionUID = 1L;
+
+    private String name;
+
+    private Type type;
+    private MetaBean metaBean;
+    private MetaBean parentMetaBean;
+
+    /**
+     * Create a new MetaProperty instance.
+     */
+    public MetaProperty() {
+    }
+
+    /**
+     * Get the metabean of the target bean (mainly for relationships).
+     * @return MetaBean (may be null).
+     */
+    public MetaBean getMetaBean() {
+        return metaBean;
+    }
+
+    /**
+     * Set the MetaBean of this {@link MetaProperty}.
+     * @param metaBean to set
+     */
+    public void setMetaBean(MetaBean metaBean) {
+        this.metaBean = metaBean;
+    }
+
+    /**
+     * Get the metabean that owns this property (set by MetaBean.putProperty())
+     * @return
+     */
+    public MetaBean getParentMetaBean() {
+        return parentMetaBean;
+    }
+
+    /**
+     * Set the metabean that owns this property (usually called by MetaBean.putProperty())
+     * @param parentMetaBean
+     */
+    void setParentMetaBean(MetaBean parentMetaBean) {
+        this.parentMetaBean = parentMetaBean;
+    }
+
+    /**
+     * Learn whether this property is considered a relationship.
+     * @return <code>true</code> if it has a MetaBean of its own
+     */
+    public boolean isRelationship() {
+        return metaBean != null;
+    }
+
+    /**
+     * Set the type of this property.
+     * @param type to set
+     */
+    public void setType(Type type) {
+        this.type = type;
+    }
+
+    /**
+     * Get the type of this property.
+     * @return
+     */
+    public Type getType() {
+        return type;
+    }
+
+    /**
+     * Resolve the type of this property to a class.
+     * @return Class, <code>null</code> if cannot be determined
+     */
+    public Class<?> getTypeClass() {
+        Type targetType = type instanceof DynaType ? ((DynaType) type)
+                .getRawType() : type;
+        if (targetType == null) {
+            return null;
+        }
+        Type assigningType = getParentMetaBean() == null ? null
+                : getParentMetaBean().getBeanClass();
+        return TypeUtils.getRawType(targetType, assigningType);
+    }
+
+    /**
+     * Get the name of this property.
+     * @return String
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Learn whether this property is considered mandatory.
+     * @return <code>true</code> if the <code>MANDATORY</code> feature is set to <code>true</code>.
+     * @see {@link Features.Property#MANDATORY}
+     */
+    public boolean isMandatory() {
+        return getFeature(MANDATORY, Boolean.FALSE).booleanValue();
+    }
+
+    /**
+     * Set this property as being mandatory (or not).
+     * @param mandatory
+     * @see {@link Features.Property#MANDATORY}
+     */
+    public void setMandatory(boolean mandatory) {
+        putFeature(MANDATORY, Boolean.valueOf(mandatory));
+    }
+
+    /**
+     * Get javascript validations of this property.
+     * @return String[]
+     * @deprecated
+     */
+    @Deprecated // remove this method?
+    public String[] getJavaScriptValidations() {
+        return getFeature(JAVASCRIPT_VALIDATION_FUNCTIONS);
+    }
+
+    /**
+     * Set the name of this property.
+     * @param name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MetaProperty clone() throws CloneNotSupportedException {
+        return (MetaProperty) super.clone();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return "MetaProperty{" + "name='" + name + '\'' + ", type=" + type + '}';
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/Validation.java b/trunk/bval-core/src/main/java/org/apache/bval/model/Validation.java
new file mode 100644
index 0000000..a81e731
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/Validation.java
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+/**
+ * Description: Interface for a single validation <br/>
+ */
+public interface Validation {
+    /**
+     * Perform a single validation routine.
+     * Validate the object or property according to the current ValidationContext.
+     *
+     * @param context - to access the property, value, constraints
+     */
+    <T extends ValidationListener> void validate(ValidationContext<T> context);
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/ValidationContext.java b/trunk/bval-core/src/main/java/org/apache/bval/model/ValidationContext.java
new file mode 100644
index 0000000..900444a
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/ValidationContext.java
@@ -0,0 +1,135 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+import org.apache.bval.util.AccessStrategy;
+
+/**
+ * Description: Interface of the context that holds all state information
+ * during the validation process<br/>
+ */
+public interface ValidationContext<T extends ValidationListener> {
+    /**
+     * Get the property value.
+     * @return {@link Object}
+     */
+    Object getPropertyValue();
+
+    /**
+     * Get the value by using the given access strategy.
+     * @param access
+     * @return {@link Object}
+     */
+    Object getPropertyValue(AccessStrategy access);
+
+    /**
+     * Get the property name.
+     * @return {@link String}
+     */
+    String getPropertyName();
+
+    /**
+     * Get the {@link ValidationListener}.
+     * @return T
+     */
+    T getListener();
+
+    /**
+     * Get the bean.
+     * @return {@link Object}
+     */
+    Object getBean();
+
+    /**
+     * Get the model meta-bean.
+     * @return {@link MetaBean}
+     */
+    MetaBean getMetaBean();
+
+    /**
+     * Set the model meta-bean.
+     * @param metaBean
+     */
+    void setMetaBean(MetaBean metaBean);
+
+    /**
+     * Get the model meta-property.
+     * @return {@link MetaProperty}
+     */
+    MetaProperty getMetaProperty();
+
+    /**
+     * Set the bean.
+     * @param bean
+     */
+    void setBean(Object bean);
+
+    /**
+     * Avoid recursion by recording the current state of this context as having been validated.
+     * <p/>
+     *
+     * @return true when this state had not already been recorded
+     */
+    boolean collectValidated();
+
+    /**
+     * Set the current bean/metabean.
+     * @param aBean
+     * @param aMetaBean
+     */
+    void setBean(Object aBean, MetaBean aMetaBean);
+
+    /**
+     * Set the current meta-property.
+     * @param metaProperty
+     */
+    void setMetaProperty(MetaProperty metaProperty);
+
+    /**
+     * Step deeper into association at 'prop' 
+     * @param prop
+     * @param access
+     */
+    void moveDown(MetaProperty prop, AccessStrategy access);
+
+    /**
+     * Step out from a validation of associated objects.
+     * @param bean
+     * @param metaBean
+     */
+    void moveUp(Object bean, MetaBean metaBean);
+
+    /**
+     * Set the index of the object currently validated into the context.
+     * used to create the propertyPath with [index] information for collections.
+     * @param index
+     */
+    void setCurrentIndex(Integer index);
+
+    /**
+     * set the key of the object in a map currently validated into the context.
+     * used to create the propertyPath with [key] information for maps.
+     * @param key
+     */
+    void setCurrentKey(Object key);
+
+    /**
+     * Get the current access strategy.
+     * @return {@link AccessStrategy}
+     */
+    AccessStrategy getAccess();
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/model/ValidationListener.java b/trunk/bval-core/src/main/java/org/apache/bval/model/ValidationListener.java
new file mode 100644
index 0000000..1a41deb
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/model/ValidationListener.java
@@ -0,0 +1,101 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+
+import java.io.Serializable;
+
+
+/**
+ * Description: The interface to collect errors found during validation<br/>
+ */
+public interface ValidationListener {
+    /**
+     * Simple API to add an error reason during validation.
+     * Error notification added from a {@link Validation} with context information
+     * taken from the given {@link ValidationContext}.
+     *
+     * @param reason  a constant describing the reason. This is normally the key of the
+     *                feature that was violated in the object 'owner' for property 'propertyName'
+     * @param context - contains
+     *                bean =         the object that contains the error (owner)
+     *                propertyName = the Name of the attribute that caused the error
+     */
+    <T extends ValidationListener> void addError(String reason, ValidationContext<T> context);
+
+    /** Alternative method to add a fully initialized {@link ValidationListener.Error} object. */
+    <T extends ValidationListener> void addError(Error error, ValidationContext<T> context);
+
+    /**
+     * An object holding a single validation constraint violation
+     * found during the validation process.
+     */
+    public class Error implements Serializable {
+        private static final long serialVersionUID = 1L;
+
+        /** Reason */
+        final String reason;
+        /** Owner */
+        final Object owner;
+        /** Property name*/
+        final String propertyName;
+
+        /**
+         * Create a new Error instance.
+         * @param aReason
+         * @param aOwner
+         * @param aPropertyName
+         */
+        public Error(String aReason, Object aOwner, String aPropertyName) {
+            this.reason = aReason;
+            this.owner = aOwner;
+            this.propertyName = aPropertyName;
+        }
+
+        /**
+         * Get the reason.
+         * @return String
+         */
+        public String getReason() {
+            return reason;
+        }
+
+        /**
+         * Get the owner.
+         * @return Object
+         */
+        public Object getOwner() {
+            return owner;
+        }
+
+        /**
+         * Get the propertyName.
+         * @return String
+         */
+        public String getPropertyName() {
+            return propertyName;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public String toString() {
+            return "Error{" + "reason='" + reason + '\'' + ", propertyName='" +
+                  propertyName + '\'' + '}';
+        }
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java b/trunk/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java
new file mode 100644
index 0000000..086da02
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.routines;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Description: holds the regexp to validate an email address<br>
+ * User: roman.stumm<br>
+ * Date: 17.06.2010<br>
+ * Time: 10:40:59<br>
+ */
+public class EMailValidationUtils {
+    private static String ATOM = "[^\\x00-\\x1F^\\(^\\)^\\<^\\>^\\@^\\,^\\;^\\:^\\\\^\\\"^\\.^\\[^\\]^\\s]";
+    private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*";
+    private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";
+    public static final java.util.regex.Pattern DEFAULT_EMAIL_PATTERN;
+
+    static {
+        DEFAULT_EMAIL_PATTERN =
+            java.util.regex.Pattern.compile("^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$",
+                java.util.regex.Pattern.CASE_INSENSITIVE);
+    }
+
+    /**
+     * Learn whether a given object is a valid email address.
+     * 
+     * @param value
+     *            to check
+     * @return <code>true</code> if the validation passes
+     */
+    public static boolean isValid(Object value) {
+        return isValid(value, DEFAULT_EMAIL_PATTERN);
+    }
+
+    /**
+     * Learn whether a particular value matches a given pattern per
+     * {@link Matcher#matches()}.
+     * 
+     * @param value
+     * @param aPattern
+     * @return <code>true</code> if <code>value</code> was a <code>String</code>
+     *         matching <code>aPattern</code>
+     */
+    // TODO it would seem to make sense to move or reduce the visibility of this
+    // method as it is more general than email.
+    public static boolean isValid(Object value, Pattern aPattern) {
+        if (value == null)
+            return true;
+        if (!(value instanceof CharSequence))
+            return false;
+        CharSequence seq = (CharSequence) value;
+        if (seq.length() == 0)
+            return true;
+        Matcher m = aPattern.matcher(seq);
+        return m.matches();
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/AccessStrategy.java b/trunk/bval-core/src/main/java/org/apache/bval/util/AccessStrategy.java
new file mode 100644
index 0000000..be97ebc
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/AccessStrategy.java
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Type;
+
+/**
+ * Description: abstract class to encapsulate different strategies
+ * to get the value of a Property.  This class is designed such that
+ * subclasses are intended to know internally to which property they refer,
+ * with only the particular target instance being externally required
+ * to calculate the property's value.  One intent of this design is
+ * that the notion of the very definition of a property is abstracted
+ * along with the mechanism for accessing that property.<br/>
+ */
+public abstract class AccessStrategy {
+    /**
+     * Get the value from the given instance.
+     * @param instance
+     * @return the value
+     * @throws IllegalArgumentException in case of an error
+     */
+    public abstract Object get(Object instance);
+
+    /**
+     * Get the Java program {@link ElementType} used by this {@link AccessStrategy}
+     * to determine property values.
+     * @return ElementType
+     */
+    public abstract ElementType getElementType();
+
+    /**
+     * Get the type of the property
+     * @return Type
+     */
+    public abstract Type getJavaType();
+
+    /**
+     * Get a name representative of this property.
+     * @return String
+     */
+    public abstract String getPropertyName();
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/BValVersion.java b/trunk/bval-core/src/main/java/org/apache/bval/util/BValVersion.java
new file mode 100644
index 0000000..49c0a38
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/BValVersion.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.bval.util;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ * This class contains version information for BVal.
+ * It uses Ant's filter tokens to convert the template into a java
+ * file with current information.
+ */
+public class BValVersion {
+
+    /** Project name */
+    public static final String PROJECT_NAME = "Apache BVal";
+    /** Unique id of the current project/version/revision */
+    public static final String PROJECT_ID;
+    /** Version number */
+    public static final String VERSION_NUMBER;
+    /** Major release number */
+    public static final int MAJOR_RELEASE;
+    /** Minor release number */
+    public static final int MINOR_RELEASE;
+    /** Patch/point release number */
+    public static final int PATCH_RELEASE;
+    /** Release status */
+    public static final String RELEASE_STATUS;
+    /** Version control revision number */
+    public static final String REVISION_NUMBER;
+
+    static {
+        Properties revisionProps = new Properties();
+        try {
+            InputStream in = BValVersion.class.getResourceAsStream
+                ("/META-INF/org.apache.bval.revision.properties");
+            if (in != null) {
+                try {
+                    revisionProps.load(in);
+                } finally {
+                    in.close();
+                }
+            }
+        } catch (IOException ioe) {
+        }
+
+        String vers = revisionProps.getProperty("project.version");
+        if (vers == null || "".equals(vers.trim()))
+            vers = "0.0.0";
+        VERSION_NUMBER = vers;
+
+        StringTokenizer tok = new StringTokenizer(VERSION_NUMBER, ".-");
+        int major, minor, patch;
+        try {
+            major = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0;
+        } catch (Exception e) {
+            major = 0;
+        }
+
+        try {
+            minor = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0;
+        } catch (Exception e) {
+            minor = 0;
+        }
+
+        try {
+            patch = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0;
+        } catch (Exception e) {
+            patch = 0;
+        }
+
+        String revision = revisionProps.getProperty("svn.revision");
+        if (revision == null || "".equals(revision.trim())) {
+            revision = "unknown";
+        } else {
+            tok = new StringTokenizer(revision, ":");
+            String strTok = null;
+            while (tok.hasMoreTokens()) {
+                try {
+                    strTok = tok.nextToken();
+                } catch (Exception e) {
+                }
+            }
+            if (strTok != null)
+                revision = strTok;
+        }
+
+        MAJOR_RELEASE = major;
+        MINOR_RELEASE = minor;
+        PATCH_RELEASE = patch;
+        RELEASE_STATUS = tok.hasMoreTokens() ? tok.nextToken("!") : "";
+        REVISION_NUMBER = revision;
+        PROJECT_ID = PROJECT_NAME + " " + VERSION_NUMBER + "-r" + REVISION_NUMBER;
+    }
+
+    /**
+     * Get the project version number.
+     * @return String
+     */
+    public static String getVersion() {
+        return VERSION_NUMBER;
+    }
+
+    /**
+     * Get the version control revision number.
+     * @return String
+     */
+    public static String getRevision() {
+        return REVISION_NUMBER;
+    }
+
+    /**
+     * Get the project name.
+     * @return String
+     */
+    public static String getName() {
+        return PROJECT_NAME;
+    }
+
+    /**
+     * Get the fully-qualified project id.
+     * @return String
+     */
+    public static String getID() {
+        return PROJECT_ID;
+    }
+
+    /**
+     * Main method of this class that prints the {@link #toString()} to <code>System.out</code>.
+     * @param args ignored
+     */
+    public static void main(String [] args) {
+        System.out.println(new BValVersion().toString());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        StringBuilder buf = new StringBuilder(80 * 40);
+        appendBanner(buf);
+        buf.append("\n");
+
+        appendProperty("os.name", buf).append("\n");
+        appendProperty("os.version", buf).append("\n");
+        appendProperty("os.arch", buf).append("\n\n");
+
+        appendProperty("java.version", buf).append("\n");
+        appendProperty("java.vendor", buf).append("\n\n");
+
+        buf.append("java.class.path:\n");
+        StringTokenizer tok = new StringTokenizer(
+            PrivilegedActions.getProperty("java.class.path"));
+        while (tok.hasMoreTokens()) {
+            buf.append("\t").append(tok.nextToken());
+            buf.append("\n");
+        }
+        buf.append("\n");
+
+        appendProperty("user.dir", buf).append("\n");
+        return buf.toString();
+    }
+
+    private void appendBanner(StringBuilder buf) {
+        buf.append("Project").append(": ").append(getName());
+        buf.append("\n");
+        buf.append("Version").append(": ").append(getVersion());
+        buf.append("\n");
+        buf.append("Revision").append(": ").append(getRevision());
+        buf.append("\n");
+    }
+
+    private StringBuilder appendProperty(String prop, StringBuilder buf) {
+        return buf.append(prop).append(": ").append(
+            PrivilegedActions.getProperty(prop));
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/FieldAccess.java b/trunk/bval-core/src/main/java/org/apache/bval/util/FieldAccess.java
new file mode 100644
index 0000000..9cbc31e
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/FieldAccess.java
@@ -0,0 +1,113 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Description: direct field access strategy.<br/>
+ */
+public class FieldAccess extends AccessStrategy {
+
+    private final Field field;
+
+    /**
+     * Create a new FieldAccess instance.
+     * @param field
+     */
+    public FieldAccess(final Field field) {
+        this.field = field;
+        if (!field.isAccessible()) {
+            run(new PrivilegedAction<Void>() {
+                public Void run() {
+                    field.setAccessible(true);
+                    return null;
+                }
+            });
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object get(final Object instance) {
+        try {
+            return field.get(instance);
+        } catch (IllegalAccessException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ElementType getElementType() {
+        return ElementType.FIELD;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Type getJavaType() {
+        return field.getGenericType();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getPropertyName() {
+        return field.getName();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return field.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        FieldAccess that = (FieldAccess) o;
+
+        return field.equals(that.field);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int hashCode() {
+        return field.hashCode();
+    }
+
+    private static <T> T run(PrivilegedAction<T> action) {
+        if (System.getSecurityManager() != null) {
+            return AccessController.doPrivileged(action);
+        } else {
+            return action.run();
+        }
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/IndexedAccess.java b/trunk/bval-core/src/main/java/org/apache/bval/util/IndexedAccess.java
new file mode 100644
index 0000000..315c25e
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/IndexedAccess.java
@@ -0,0 +1,120 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.reflect.TypeUtils;
+
+/**
+ * {@link AccessStrategy} to get an indexed member of an {@link Iterable} or
+ * array object.
+ */
+public class IndexedAccess extends AccessStrategy {
+    private static final TypeVariable<?> ITERABLE_TYPE = Iterable.class.getTypeParameters()[0];
+
+    /**
+     * Get the Java element type of a particular container type.
+     * 
+     * @param containerType
+     * @return Type or <code>null</code> if <code>containerType</code> is not
+     *         some type of {@link Iterable} or array
+     */
+    public static Type getJavaElementType(Type containerType) {
+        if (TypeUtils.isArrayType(containerType)) {
+            return TypeUtils.getArrayComponentType(containerType);
+        }
+        if (TypeUtils.isAssignable(containerType, Iterable.class)) {
+            Map<TypeVariable<?>, Type> typeArguments = TypeUtils.getTypeArguments(containerType, Iterable.class);
+            return typeArguments.containsKey(ITERABLE_TYPE) ? typeArguments.get(ITERABLE_TYPE) : Object.class;
+        }
+        return null;
+    }
+
+    private Type containerType;
+    private Integer index;
+
+    /**
+     * Create a new IndexedAccessStrategy instance.
+     * 
+     * @param containerType
+     * @param index
+     */
+    public IndexedAccess(Type containerType, Integer index) {
+        super();
+        this.containerType = containerType;
+        this.index = index;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Object get(Object instance) {
+        if (index == null) {
+            throw new UnsupportedOperationException("Cannot read null index");
+        }
+        if (instance != null && instance.getClass().isArray()) {
+            if (Array.getLength(instance) - index > 0) {
+                return Array.get(instance, index);
+            }
+        } else if (instance instanceof List<?>) {
+            List<?> list = (List<?>) instance;
+            if (list.size() - index > 0) {
+                return list.get(index);
+            }
+        } else if (instance instanceof Iterable<?>) {
+            int i = 0;
+            for (Object o : (Iterable<?>) instance) {
+                if (++i == index) {
+                    return o;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ElementType getElementType() {
+        return ElementType.METHOD;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Type getJavaType() {
+        return getJavaElementType(containerType);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getPropertyName() {
+        return String.format("[%d]", index);
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/KeyedAccess.java b/trunk/bval-core/src/main/java/org/apache/bval/util/KeyedAccess.java
new file mode 100644
index 0000000..6050502
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/KeyedAccess.java
@@ -0,0 +1,121 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Map;
+
+import org.apache.commons.lang3.reflect.TypeUtils;
+
+/**
+ * {@link AccessStrategy} to get a keyed value from a {@link Map}. Contains
+ * special handling when a string key is used against a container type whose key
+ * parameter is not assignable from {@link String}: against a map whose key type
+ * is an enum class, it will be interpreted as a named enum constant; other key
+ * types will be compared via {@link Object#toString()}.
+ */
+public class KeyedAccess extends AccessStrategy {
+    private static final TypeVariable<?>[] MAP_TYPEVARS = Map.class.getTypeParameters();
+
+    /**
+     * Get the Java element type of a particular container type.
+     * 
+     * @param containerType
+     * @return Type or <code>null</code> if <code>containerType</code> is not
+     *         some kind of {@link Map}
+     */
+    public static Type getJavaElementType(Type containerType) {
+        if (TypeUtils.isAssignable(containerType, Map.class)) {
+            Map<TypeVariable<?>, Type> typeArguments = TypeUtils.getTypeArguments(containerType, Map.class);
+            return typeArguments.containsKey(MAP_TYPEVARS[1]) ? typeArguments.get(MAP_TYPEVARS[1]) : Object.class;
+        }
+        return null;
+    }
+
+    private Type containerType;
+    private Object key;
+
+    /**
+     * Create a new KeyedAccess instance.
+     * 
+     * @param containerType
+     * @param key
+     */
+    public KeyedAccess(Type containerType, Object key) {
+        super();
+        this.containerType = containerType;
+        this.key = key;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Object get(Object instance) {
+        if (instance instanceof Map<?, ?>) {
+            Map<?, ?> map = (Map<?, ?>) instance;
+            Map<TypeVariable<?>, Type> typeArguments = TypeUtils.getTypeArguments(containerType, Map.class);
+            Type keyType = typeArguments.get(MAP_TYPEVARS[0]);
+            if (key == null || keyType == null || TypeUtils.isInstance(key, keyType)) {
+                return map.get(key);
+            }
+            if (key instanceof String) {
+                String name = (String) key;
+                Class<?> rawKeyType = TypeUtils.getRawType(keyType, containerType);
+                if (rawKeyType.isEnum()) {
+                    @SuppressWarnings({ "unchecked", "rawtypes" })
+                    final Object result = map.get(Enum.valueOf((Class<? extends Enum>) rawKeyType, name));
+                    return result;
+                }
+                for (Map.Entry<?, ?> e : map.entrySet()) {
+                    if (name.equals(e.getKey())) {
+                        return e.getValue();
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ElementType getElementType() {
+        return ElementType.METHOD;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Type getJavaType() {
+        Type result = getJavaElementType(containerType);
+        return result == null ? Object.class : result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getPropertyName() {
+        return String.format("[%s]", key);
+    }
+
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/MethodAccess.java b/trunk/bval-core/src/main/java/org/apache/bval/util/MethodAccess.java
new file mode 100644
index 0000000..2583fbb
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/MethodAccess.java
@@ -0,0 +1,155 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.util;
+
+import java.beans.Introspector;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Description: invoke a zero-argument method (getter)<br/>
+ */
+public class MethodAccess extends AccessStrategy {
+    private final Method method;
+    private final String propertyName;
+
+    /**
+     * Create a new MethodAccess instance.
+     * @param method
+     */
+    public MethodAccess(Method method) {
+        this(getPropertyName(method), method);
+    }
+
+    /**
+     * Create a new MethodAccess instance.
+     * @param propertyName
+     * @param method
+     */
+    public MethodAccess(String propertyName, final Method method) {
+        this.method = method;
+        this.propertyName = propertyName;
+        if (!method.isAccessible()) {
+            run( new PrivilegedAction<Void>() {
+                public Void run() {
+                    method.setAccessible(true);
+                    return null;
+                }
+            });
+        }
+    }
+
+    /**
+     * Process bean properties getter by applying the JavaBean naming conventions.
+     *
+     * @param member the member for which to get the property name.
+     * @return The bean method name with the "is" or "get" prefix stripped off, <code>null</code>
+     *         the method name id not according to the JavaBeans standard.
+     */
+    public static String getPropertyName(Method member) {
+        String name = null;
+        String methodName = member.getName();
+        if (methodName.startsWith("is")) {
+            name = Introspector.decapitalize(methodName.substring(2));
+        } /* else if ( methodName.startsWith("has")) {
+				name = Introspector.decapitalize( methodName.substring( 3 ) );
+			} */
+        // setter annotation is NOT supported in the spec
+        /*  else if (method.getName().startsWith("set") && method.getParameterTypes().length == 1) {
+           propName = Introspector.decapitalize(method.getName().substring(3));
+       } */
+        else if (methodName.startsWith("get")) {
+            name = Introspector.decapitalize(methodName.substring(3));
+        }
+        return name;
+    }
+
+    /**
+     * {@inheritDoc}
+     * normally the propertyName of the getter method, e.g.<br>
+     * method: getName() -> propertyName: name<br>
+     * method: isValid() -> propertyName: valid<br>
+     */
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object get(final Object instance) {
+        try {
+            return method.invoke(instance);
+        } catch (IllegalAccessException e) {
+            throw new IllegalArgumentException(e);
+        } catch (InvocationTargetException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ElementType getElementType() {
+        return ElementType.METHOD;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Type getJavaType() {
+        return method.getGenericReturnType();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return method.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        MethodAccess that = (MethodAccess) o;
+
+        return method.equals(that.method);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int hashCode() {
+        return method.hashCode();
+    }
+
+    private static <T> T run(PrivilegedAction<T> action) {
+        if (System.getSecurityManager() != null) {
+            return AccessController.doPrivileged(action);
+        } else {
+            return action.run();
+        }
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/PrivilegedActions.java b/trunk/bval-core/src/main/java/org/apache/bval/util/PrivilegedActions.java
new file mode 100644
index 0000000..26c0936
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/PrivilegedActions.java
@@ -0,0 +1,189 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.apache.commons.lang3.ClassUtils;
+
+/**
+ * Description: utility methods to perform actions with AccessController or without. <br/>
+ */
+public class PrivilegedActions {
+    private static String lineSeparator = null;
+    private static String pathSeparator = null;
+
+    /**
+     * Return the value of the "line.separator" system property.
+     * 
+     * Requires security policy: 
+     *   'permission java.util.PropertyPermission "read";'
+     */
+    @Deprecated // unused method - will remove in future release
+    public static final String getLineSeparator() {
+        if (lineSeparator == null) {
+            lineSeparator =
+                AccessController.doPrivileged(new PrivilegedAction<String>() {
+                    public String run() {
+                        return System.getProperty("line.separator");
+                    }
+                });
+        }
+        return lineSeparator;
+    }
+
+    /**
+     * Return the value of the "path.separator" system property.
+     * 
+     * Requires security policy:
+     *   'permission java.util.PropertyPermission "read";'
+     */
+    @Deprecated // unused method - will remove in future release
+    public static final String getPathSeparator() {
+        if (pathSeparator == null) {
+            pathSeparator =
+                AccessController.doPrivileged(new PrivilegedAction<String>() {
+                    public String run() {
+                        return System.getProperty("path.separator");
+                    }
+                });
+        }
+        return pathSeparator;
+    }
+
+    /**
+     * Perform action with AccessController.doPrivileged() if security if enabled.
+     *
+     * @param action - the action to run
+     * @return result of running the action
+     */
+    // should not be called by just anyone; do not increase access
+    private static <T> T run(PrivilegedAction<T> action) {
+        if (System.getSecurityManager() != null) {
+            return AccessController.doPrivileged(action);
+        } else {
+            return action.run();
+        }
+    }
+
+    /**
+     * Perform action with AccessController.doPrivileged() if security if enabled.
+     *
+     * @param action - the action to run
+     * @return result of running the action
+     */
+    // should not be called by just anyone; do not increase access
+    private static <T> T run(final PrivilegedExceptionAction<T> action) throws PrivilegedActionException, Exception {
+        if (System.getSecurityManager() != null) {
+            return AccessController.doPrivileged(action);
+        } else {
+            return action.run();
+        }
+    }
+
+    /**
+     * Perform AccessController.doPrivileged() action for ClassUtil.getClass()
+     * 
+     * @return Class
+     * @exception Exception
+     */
+    public static Class<?> getClass(final ClassLoader classLoader, final String className) throws Exception {
+        return run(new PrivilegedExceptionAction<Class<?>>() {
+            public Class<?> run() throws Exception {
+                return ClassUtils.getClass(classLoader, className, true);
+            }
+        });
+    }
+
+    /**
+     * Return a PrivilegedAction object for clazz.getDeclaredMethod().invoke().
+     * 
+     * Requires security policy
+     *  'permission java.lang.RuntimePermission "accessDeclaredMembers";'
+     *  'permission java.lang.reflect.ReflectPermission "suppressAccessChecks";'
+     *   
+     * @return Object
+     * @exception IllegalAccessException, InvocationTargetException
+     */
+    public static Object getAnnotationValue(final Annotation annotation, final String name)
+          throws IllegalAccessException, InvocationTargetException {
+        return run(new PrivilegedAction<Object>() {
+            public Object run() {
+                Method valueMethod;
+                try {
+                    valueMethod = annotation.annotationType().getDeclaredMethod(name);
+                } catch (NoSuchMethodException ex) {
+                    // do nothing
+                    valueMethod = null;
+                }
+                if (null != valueMethod) {
+                    try {
+                        valueMethod.setAccessible(true);
+                        return valueMethod.invoke(annotation);
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Return a PrivilegeAction object for clazz.getClassloader().
+     * 
+     * Requires security policy:
+     *   'permission java.lang.RuntimePermission "getClassLoader";'
+     *   
+     * @return Classloader
+     */
+    public static ClassLoader getClassLoader(final Class<?> clazz) {
+        return run(new PrivilegedAction<ClassLoader>() {
+            public ClassLoader run() {
+                ClassLoader cl = Thread.currentThread().getContextClassLoader();
+                if (cl == null) {
+                    cl = clazz.getClassLoader();
+                }
+                return cl;
+            }
+        });
+    }
+
+    /**
+     * Return a PrivilegeAction object for System.getProperty().
+     * 
+     * Requires security policy:
+     *   'permission java.util.PropertyPermission "read";'
+     *   
+     * @return String
+     */
+    public static final String getProperty(final String name) {
+        return run(new PrivilegedAction<String>() {
+            public String run() {
+                return System.getProperty(name);
+            }
+        });
+    }
+
+}
+
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/PropertyAccess.java b/trunk/bval-core/src/main/java/org/apache/bval/util/PropertyAccess.java
new file mode 100644
index 0000000..d79235e
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/PropertyAccess.java
@@ -0,0 +1,218 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.util;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Map;
+
+/**
+ * Description: Undefined dynamic strategy (FIELD or METHOD access) Uses PropertyUtils or tries to determine field to
+ * access the value<br/>
+ */
+public class PropertyAccess extends AccessStrategy {
+    private final Class<?> beanClass;
+    private final String propertyName;
+    private Field rememberField;
+
+    /**
+     * Create a new PropertyAccess instance.
+     * 
+     * @param clazz
+     * @param propertyName
+     */
+    public PropertyAccess(Class<?> clazz, String propertyName) {
+        this.beanClass = clazz;
+        this.propertyName = propertyName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ElementType getElementType() {
+        return rememberField != null ? ElementType.FIELD : ElementType.METHOD;
+    }
+
+    private static Object getPublicProperty(Object bean, String property) throws InvocationTargetException,
+        NoSuchMethodException, IllegalAccessException {
+        if (bean instanceof Map<?, ?>) {
+            return ((Map<?, ?>) bean).get(property);
+        } else { // supports DynaBean and standard Objects
+            return PropertyUtils.getSimpleProperty(bean, property);
+        }
+    }
+
+    /**
+     * Get a named property from <code>bean</code>.
+     * 
+     * @param bean
+     * @param propertyName
+     * @return Object found
+     * @throws InvocationTargetException
+     * @throws NoSuchMethodException
+     * @throws IllegalAccessException
+     */
+    public static Object getProperty(Object bean, String propertyName) throws InvocationTargetException,
+        NoSuchMethodException, IllegalAccessException {
+        return new PropertyAccess(bean.getClass(), propertyName).get(bean);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return "Property{" + beanClass.getName() + '.' + propertyName + '}';
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Type getJavaType() {
+        Type result = getTypeInner();
+        return result == null ? Object.class : result;
+    }
+
+    /**
+     * Learn whether this {@link PropertyAccess} references a known property.
+     * 
+     * @return boolean
+     */
+    public boolean isKnown() {
+        return getTypeInner() != null;
+    }
+
+    /**
+     * Find out what, if any, type can be calculated.
+     * 
+     * @return type found or <code>null</code>
+     */
+    private Type getTypeInner() {
+        if (rememberField != null) {
+            return rememberField.getGenericType();
+        }
+        Method readMethod = getPropertyReadMethod(propertyName, beanClass);
+        if (readMethod != null) {
+            return readMethod.getGenericReturnType();
+        }
+        Field fld = getField(propertyName, beanClass);
+        if (fld != null) {
+            cacheField(fld);
+            return rememberField.getGenericType();
+        }
+        return null;
+    }
+
+    private static Method getPropertyReadMethod(String propertyName, Class<?> beanClass) {
+        for (PropertyDescriptor each : PropertyUtils.getPropertyDescriptors(beanClass)) {
+            if (each.getName().equals(propertyName)) {
+                return each.getReadMethod();
+            }
+        }
+        return null;
+    }
+
+    private static Field getField(String propertyName, Class<?> beanClass) {
+        try { // try public field
+            return beanClass.getField(propertyName);
+        } catch (NoSuchFieldException ex2) {
+            // search for private/protected field up the hierarchy
+            Class<?> theClass = beanClass;
+            while (theClass != null) {
+                try {
+                    return theClass.getDeclaredField(propertyName);
+                } catch (NoSuchFieldException ex3) {
+                    // do nothing
+                }
+                theClass = theClass.getSuperclass();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object get(Object bean) {
+        try {
+            if (rememberField != null) { // cache field of previous access
+                return rememberField.get(bean);
+            }
+            try { // try public method
+                return getPublicProperty(bean, propertyName);
+            } catch (NoSuchMethodException ex) {
+                return getFieldValue(bean);
+            }
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new IllegalArgumentException("cannot access " + propertyName, e);
+        }
+    }
+
+    private Object getFieldValue(Object bean) throws IllegalAccessException {
+        Field field = getField(propertyName, beanClass);
+        if (field != null) {
+            cacheField(field);
+            return rememberField.get(bean);
+        }
+        throw new IllegalArgumentException("cannot access field " + propertyName);
+    }
+
+    private void cacheField(Field field) {
+        if (!field.isAccessible()) {
+            field.setAccessible(true);
+        }
+        this.rememberField = field;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        PropertyAccess that = (PropertyAccess) o;
+
+        return beanClass.equals(that.beanClass) && propertyName.equals(that.propertyName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int hashCode() {
+        int result;
+        result = beanClass.hashCode();
+        result = 31 * result + propertyName.hashCode();
+        return result;
+    }
+}
diff --git a/trunk/bval-core/src/main/java/org/apache/bval/util/ValidationHelper.java b/trunk/bval-core/src/main/java/org/apache/bval/util/ValidationHelper.java
new file mode 100644
index 0000000..35677c8
--- /dev/null
+++ b/trunk/bval-core/src/main/java/org/apache/bval/util/ValidationHelper.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.bval.util;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.bval.DynamicMetaBean;
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.MetaProperty;
+import org.apache.bval.model.Validation;
+import org.apache.bval.model.ValidationContext;
+import org.apache.bval.model.ValidationListener;
+
+
+/**
+ * Stateless helper methods used by the validators.
+ * 
+ * @author Carlos Vara
+ */
+public class ValidationHelper {
+
+    /**
+     * Interface implemented by the call-back object passed to
+     * {@link ValidationHelper#validateContext(ValidationContext, ValidateCallback, boolean)}
+     * . Its {@link #validate()} method will be called accordingly for every
+     * dispatch.
+     */
+    public static interface ValidateCallback {
+        void validate();
+    }
+
+    /**
+     * validate a complex 'bean' with related beans according to
+     * validation rules in 'metaBean'
+     * 
+     * @param context
+     *            - the context is initialized with: <br>
+     *            &nbsp;&nbsp;bean - the root object start validation at
+     *            or a collection of root objects <br>
+     *            &nbsp;&nbsp;metaBean - the meta information for the root
+     *            object(s)
+     * @param context
+     *            The current validation context.
+     */
+    static public void validateContext(ValidationContext<?> context, ValidateCallback s, boolean treatMapsLikeBeans) {
+        if (context.getBean() != null) {
+            if (!treatMapsLikeBeans && context.getBean() instanceof Map<?, ?>) {
+                validateMapInContext(context, s);
+            } else if (context.getBean() instanceof Iterable<?>) {
+                validateIterableInContext(context, s);
+            } else if (context.getBean() instanceof Object[]) {
+                validateArrayInContext(context, s);
+            } else { // to One Bean (or Map like Bean)
+                validateBeanInContext(context, s);
+            }
+        }
+    }
+
+    /**
+     * Validates a single object.
+     * 
+     * @param <VL>
+     * @param context
+     *            The validation context, its current bean must be a single
+     *            object.
+     * @param s
+     */
+    static protected <VL extends ValidationListener> void validateBeanInContext(ValidationContext<VL> context, ValidateCallback s) {
+        if (getDynamicMetaBean(context) != null) {
+            context.setMetaBean(getDynamicMetaBean(context).resolveMetaBean(context.getBean()));
+        }
+        s.validate();
+    }
+
+    /**
+     * Iterates the values of an array, setting the current context
+     * appropriately and validating each value.
+     * 
+     * @param <VL>
+     * @param context
+     *            The validation context, its current bean must be an array.
+     */
+    static protected <VL extends ValidationListener> void validateArrayInContext(ValidationContext<VL> context, ValidateCallback s) {
+        int index = 0;
+        DynamicMetaBean dyn = getDynamicMetaBean(context);
+        Object[] array = (Object[]) context.getBean();
+        MetaBean metaBean = context.getMetaBean();
+        context.setCurrentIndex(null);
+        try {
+            for (Object each : array) {
+                context.setCurrentIndex(index++);
+                if (each == null) {
+                    continue; // Null values are not validated
+                }
+                if (dyn != null) {
+                    context.setBean(each, dyn.resolveMetaBean(each));
+                } else {
+                    context.setBean(each);
+                }
+                s.validate();
+            }
+        } finally {
+            context.moveUp(array, metaBean);
+        }
+    }
+
+    /**
+     * Iterates the values of an {@link Iterable} object, setting the current
+     * context appropriately and validating each value.
+     * 
+     * @param <VL>
+     * @param context
+     *            The validation context, its current bean must implement
+     *            {@link Iterable}.
+     */
+    static protected <VL extends ValidationListener> void validateIterableInContext(ValidationContext<VL> context, ValidateCallback s) {
+
+        final boolean positional = context.getBean() instanceof List<?>;
+        int index = 0;
+        Iterable<?> iterable = (Iterable<?>) context.getBean();
+        MetaBean metaBean = context.getMetaBean();
+        context.setCurrentIndex(null);
+
+        try {
+            // jsr303 spec: Each object provided by the iterator is validated.
+            final DynamicMetaBean dyn = getDynamicMetaBean(context);
+            for (Object each : iterable) {
+                if (positional) {
+                    context.setCurrentIndex(index++);
+                }
+                if (each == null) {
+                    continue; // Null values are not validated
+                }
+                if (dyn != null) {
+                    context.setBean(each, dyn.resolveMetaBean(each));
+                } else {
+                    context.setBean(each);
+                }
+                s.validate();
+            }
+        } finally {
+            context.moveUp(iterable, metaBean);
+        }
+    }
+
+    /**
+     * Iterates the values of a {@link Map}, setting the current context
+     * appropriately and validating each value.
+     * 
+     * @param <VL>
+     * @param context
+     *            The validation context, its current bean must implement
+     *            {@link Map}.
+     */
+    static protected <VL extends ValidationListener> void validateMapInContext(ValidationContext<VL> context, ValidateCallback s) {
+        // jsr303 spec: For Map, the value of each Map.Entry is validated (key
+        // is not validated).
+        Map<?, ?> currentBean = (Map<?, ?>) context.getBean();
+        MetaBean metaBean = context.getMetaBean();
+        final DynamicMetaBean dyn = getDynamicMetaBean(context);
+        context.setCurrentKey(null);
+        try {
+            for (Map.Entry<?, ?> entry : currentBean.entrySet()) {
+                Object value = entry.getValue();
+                if (value == null) {
+                    continue;
+                }
+                context.setCurrentKey(entry.getKey());
+                if (dyn == null) {
+                    context.setBean(value);
+                } else {
+                    context.setBean(value, dyn.resolveMetaBean(value));
+                }
+                s.validate();
+            }
+        } finally {
+            context.moveUp(currentBean, metaBean);
+        }
+    }
+
+    /**
+     * @param <VL>
+     * @param context
+     *            The current validation context.
+     * @return the current {@link DynamicMetaBean} in context, or
+     *         <code>null</code> if the current meta bean is not dynamic.
+     */
+    static private <VL extends ValidationListener> DynamicMetaBean getDynamicMetaBean(ValidationContext<VL> context) {
+        return context.getMetaBean() instanceof DynamicMetaBean ? (DynamicMetaBean) context.getMetaBean() : null;
+    }
+
+
+    /**
+     * Validate a single bean only, no related beans will be validated.
+     */
+    static public <VL extends ValidationListener> void validateBean(ValidationContext<VL> context) {
+        // execute all property level validations
+        for (MetaProperty prop : context.getMetaBean().getProperties()) {
+            context.setMetaProperty(prop);
+            validateProperty(context);
+        }
+
+        // execute all bean level validations
+        context.setMetaProperty(null);
+        for (Validation validation : context.getMetaBean().getValidations()) {
+            validation.validate(context);
+        }
+    }
+
+
+    /**
+     * Validate a single property only. Performs all validations
+     * for this property.
+     */
+    static public <VL extends ValidationListener> void validateProperty(ValidationContext<VL> context) {
+        for (Validation validation : context.getMetaProperty().getValidations()) {
+            validation.validate(context);
+        }
+    }
+}
diff --git a/trunk/bval-core/src/test/java/org/apache/bval/ValidationResultsTest.java b/trunk/bval-core/src/test/java/org/apache/bval/ValidationResultsTest.java
new file mode 100644
index 0000000..e16f9de
--- /dev/null
+++ b/trunk/bval-core/src/test/java/org/apache/bval/ValidationResultsTest.java
@@ -0,0 +1,60 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.bval.model.MetaProperty;
+
+/**
+ * ValidationResults Tester.
+ */
+public class ValidationResultsTest extends TestCase {
+    private ValidationResults results;
+
+    public ValidationResultsTest(String name) {
+        super(name);
+    }
+
+    public void setUp() throws Exception {
+        super.setUp();
+        results = new ValidationResults();
+    }
+
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testValidationResults() throws Exception {
+        assertTrue(results.isEmpty());
+        BeanValidationContext<ValidationResults> ctx = new BeanValidationContext<ValidationResults>(results);
+        ctx.setBean(this);
+        ctx.setMetaProperty(new MetaProperty());
+        ctx.getMetaProperty().setName("prop");
+        results.addError("test", ctx);
+        assertFalse(results.isEmpty());
+        assertTrue(results.hasErrorForReason("test"));
+        assertTrue(results.hasError(this, "prop"));
+        assertTrue(results.hasError(this, null));
+        assertFalse(results.hasError(this, "prop2"));
+    }
+
+    public static Test suite() {
+        return new TestSuite(ValidationResultsTest.class);
+    }
+}
diff --git a/trunk/bval-core/src/test/java/org/apache/bval/model/ExampleEnum.java b/trunk/bval-core/src/test/java/org/apache/bval/model/ExampleEnum.java
new file mode 100644
index 0000000..10f87a9
--- /dev/null
+++ b/trunk/bval-core/src/test/java/org/apache/bval/model/ExampleEnum.java
@@ -0,0 +1,27 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+/**
+ * Description: <br>
+ * User: roman.stumm<br>
+ * Date: 17.06.2010<br>
+ * Time: 18:00:12<br>
+ */
+public enum ExampleEnum {
+    VALUE1, VALUE2, VALUE3
+}
diff --git a/trunk/bval-core/src/test/java/org/apache/bval/model/MetaPropertyTest.java b/trunk/bval-core/src/test/java/org/apache/bval/model/MetaPropertyTest.java
new file mode 100644
index 0000000..35b626a
--- /dev/null
+++ b/trunk/bval-core/src/test/java/org/apache/bval/model/MetaPropertyTest.java
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.model;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * MetaProperty Tester.
+ *
+ * @author <Authors name>
+ * @since <pre>02/12/2009</pre>
+ * @version 1.0
+ */
+public class MetaPropertyTest extends TestCase {
+    public MetaPropertyTest(String name) {
+        super(name);
+    }
+
+
+    public void testGetTypeClass() throws Exception {
+        MetaProperty prop = new MetaProperty();
+        prop.setType(String.class);
+        assertEquals(String.class, prop.getTypeClass());
+        assertEquals(String.class, prop.getType());
+        prop.setType(new DynaTypeEnum(ExampleEnum.class, ExampleEnum.VALUE1.name(),
+              ExampleEnum.VALUE3.name()));
+        assertEquals(ExampleEnum.class, prop.getTypeClass());
+        assertEquals(2, ((DynaTypeEnum)prop.getType()).getEnumConstants().length);
+    }
+
+
+    public static Test suite() {
+        return new TestSuite(MetaPropertyTest.class);
+    }
+}
diff --git a/trunk/bval-core/src/test/resources/log4j.xml b/trunk/bval-core/src/test/resources/log4j.xml
new file mode 100644
index 0000000..3c4bb67
--- /dev/null
+++ b/trunk/bval-core/src/test/resources/log4j.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  Log4j Configuration                                                  -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+
+  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+    <param name="Threshold" value="DEBUG"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%d %-5p %c - %m%n"/>
+    </layout>
+  </appender>
+
+  <root>
+    <appender-ref ref="CONSOLE"/>
+  </root>
+
+</log4j:configuration>
diff --git a/trunk/bval-extras/pom.xml b/trunk/bval-extras/pom.xml
new file mode 100644
index 0000000..bab695f
--- /dev/null
+++ b/trunk/bval-extras/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!--
+	Maven release plugin requires the project tag to be on a single line.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.bval</groupId>
+        <artifactId>bval-parent</artifactId>
+        <version>0.4</version>
+    </parent>
+
+    <artifactId>bval-extras</artifactId>
+    <name>Apache BVal :: bval-extras (optional)</name>
+    <packaging>bundle</packaging>
+
+    <description>BVal - non-JSR303 routines and constraints</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.bval</groupId>
+            <artifactId>org.apache.bval.bundle</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <profiles>
+        <!--
+            default profile using geronimo-validation_1.0_spec.jar
+            active when property "ri" is not present.
+        -->
+        <profile>
+            <id>geronimo</id>
+            <activation>
+                <property>
+                    <name>!ri</name>
+                </property>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.geronimo.specs</groupId>
+                    <artifactId>geronimo-validation_1.0_spec</artifactId>
+                    <!-- allow users to choose an API provider -->
+                    <scope>provided</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+        <!--
+            optional profile using javax.validation/validation-api.jar
+            from RI manually active when property "-Pri" is provided.
+        -->
+        <profile>
+            <id>ri</id>
+            <activation>
+                <property>
+                    <name>ri</name>
+                </property>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>javax.validation</groupId>
+                    <artifactId>validation-api</artifactId>
+                    <!-- allow users to choose an API provider -->
+                    <scope>provided</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+
+    <build>
+        <defaultGoal>install</defaultGoal>
+
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+    </build>
+
+</project>
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ABANumber.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ABANumber.java
new file mode 100644
index 0000000..7e48693
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ABANumber.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = ABANumberValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface ABANumber {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.checkdigit.ABANumber.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ABANumberValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ABANumberValidator.java
new file mode 100644
index 0000000..4eed858
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ABANumberValidator.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+/**
+ * Modulus 10 <b>ABA Number</b> (or <b>Routing Transit Number</b> (RTN)) Check Digit
+ * calculation/validation.
+ * <p>
+ * ABA Numbers (or Routing Transit Numbers) are a nine digit numeric code used
+ * to identify American financial institutions for things such as checks or deposits
+ * (ABA stands for the American Bankers Association).
+ * <p>
+ * Check digit calculation is based on <i>modulus 10</i> with digits being weighted
+ * based on their position (from right to left) as follows:
+ * <ul>
+ *     <li>Digits 1, 4 and & 7 are weighted 1
+ *     <li>Digits 2, 5 and & 8 are weighted 7
+ *     <li>Digits 3, 6 and & 9 are weighted 3
+ * </ul>
+ * <p>
+ * For further information see
+ *  <a href="http://en.wikipedia.org/wiki/Routing_transit_number">Wikipedia -
+ *  Routing transit number</a>.
+ */
+public final class ABANumberValidator
+    extends ModulusValidator<ABANumber> {
+
+    /** weighting given to digits depending on their right position */
+    private static final int[] POSITION_WEIGHT = new int[] {3, 1, 7};
+
+    public ABANumberValidator() {
+        super(10);
+    }
+
+    /**
+     * Calculates the <i>weighted</i> value of a character in the
+     * code at a specified position.
+     * <p>
+     * ABA Routing numbers are weighted in the following manner:
+     * <pre><code>
+     *     left position: 1  2  3  4  5  6  7  8  9
+     *            weight: 3  7  1  3  7  1  3  7  1
+     * </code></pre>
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    protected int weightedValue( int charValue, int leftPos, int rightPos )
+            throws Exception {
+        int weight = POSITION_WEIGHT[rightPos % 3];
+        return (charValue * weight);
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/CUSIP.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/CUSIP.java
new file mode 100644
index 0000000..860b7d3
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/CUSIP.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = CUSIPValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface CUSIP {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.checkdigit.CUSIP.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/CUSIPValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/CUSIPValidator.java
new file mode 100644
index 0000000..82e8c29
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/CUSIPValidator.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.Character.getNumericValue;
+
+/**
+ * Modulus 10 <b>CUSIP</b> (North American Securities)
+ * Check Digit calculation/validation.
+ * <p>
+ * CUSIP Numbers are 9 character alphanumeric codes used
+ * to identify North American Securities.
+ * <p>
+ * Check digit calculation uses the <i>Modulus 10 Double Add Double</i> technique
+ * with every second digit being weighted by 2. Alphabetic characters are
+ * converted to numbers by their position in the alphabet starting with A being 10.
+ * Weighted numbers greater than ten are treated as two separate numbers.
+ * <p>
+ *
+ * <p>
+ * See <a href="http://en.wikipedia.org/wiki/CUSIP">Wikipedia - CUSIP</a>
+ * for more details.
+ */
+public final class CUSIPValidator
+    extends ModulusValidator<CUSIP> {
+
+    /** weighting given to digits depending on their right position */
+    private static final int[] POSITION_WEIGHT = new int[] {2, 1};
+
+    public CUSIPValidator() {
+        super(10);
+    }
+
+    /**
+     * Calculates the <i>weighted</i> value of a character in the
+     * code at a specified position.
+     * <p>
+     * ABA Routing numbers are weighted in the following manner:
+     * <pre><code>
+     *     left position: 1  2  3  4  5  6  7  8  9
+     *            weight: 3  7  1  3  7  1  3  7  1
+     * </code></pre>
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    protected int weightedValue( int charValue, int leftPos, int rightPos )
+            throws Exception {
+        int weight = POSITION_WEIGHT[rightPos % 2];
+        int weightedValue = (charValue * weight);
+        return sumDigits(weightedValue);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected int toInt(char character, int leftPos, int rightPos) {
+        int charValue = getNumericValue(character);
+        if (charValue < 0 || charValue > 35) {
+            throw new IllegalArgumentException("Invalid Character["
+                                               + leftPos
+                                               + "] = '"
+                                               + charValue
+                                               + "'");
+        }
+        return charValue;
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/EAN13.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/EAN13.java
new file mode 100644
index 0000000..d72af8f
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/EAN13.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = EAN13Validator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface EAN13 {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.checkdigit.EAN13.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/EAN13Validator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/EAN13Validator.java
new file mode 100644
index 0000000..4270394
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/EAN13Validator.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+/**
+ * Modulus 10 <b>EAN-13</b> / <b>UPC</b> / <b>ISBN-13</b> Check Digit
+ * calculation/validation.
+ * <p>
+ * Check digit calculation is based on <i>modulus 10</i> with digits in
+ * an <i>odd</i> position (from right to left) being weighted 1 and <i>even</i>
+ * position digits being weighted 3.
+ * <p>
+ * For further information see:
+ * <ul>
+ *   <li>EAN-13 - see
+ *       <a href="http://en.wikipedia.org/wiki/European_Article_Number">Wikipedia -
+ *       European Article Number</a>.</li>
+ *   <li>UPC - see
+ *       <a href="http://en.wikipedia.org/wiki/Universal_Product_Code">Wikipedia -
+ *       Universal Product Code</a>.</li>
+ *   <li>ISBN-13 - see
+ *       <a href="http://en.wikipedia.org/wiki/ISBN">Wikipedia - International
+ *       Standard Book Number (ISBN)</a>.</li>
+ * </ul>
+ */
+public final class EAN13Validator
+    extends ModulusValidator<EAN13> {
+
+    /** weighting given to digits depending on their right position */
+    private static final int[] POSITION_WEIGHT = new int[] {3, 1};
+
+    public EAN13Validator() {
+        super(10);
+    }
+
+    /**
+     * <p>Calculates the <i>weighted</i> value of a character in the
+     * code at a specified position.</p>
+     *
+     * <p>For EAN-13 (from right to left) <b>odd</b> digits are weighted
+     * with a factor of <b>one</b> and <b>even</b> digits with a factor
+     * of <b>three</b>.</p>
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    protected int weightedValue( int charValue, int leftPos, int rightPos )
+            throws Exception {
+        int weight = POSITION_WEIGHT[rightPos % 2];
+        return (charValue * weight);
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/IBAN.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/IBAN.java
new file mode 100644
index 0000000..c2f33c8
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/IBAN.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = IBANValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface IBAN {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.checkdigit.IBAN.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/IBANValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/IBANValidator.java
new file mode 100644
index 0000000..e365ce1
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/IBANValidator.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.Character.getNumericValue;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * <b>IBAN</b> (International Bank Account Number) Check Digit calculation/validation.
+ * <p>
+ * This rountine is based on the ISO 7064 Mod 97,10 check digit caluclation routine.
+ * <p>
+ * The two check digit characters in a IBAN number are the third and fourth characters
+ * in the code. For <i>check digit</i> calculation/validation the first four characters are moved
+ * to the end of the code.
+ *  So <code>CCDDnnnnnnn</code> becomes <code>nnnnnnnCCDD</code> (where
+ *  <code>CC</code> is the country code and <code>DD</code> is the check digit). For
+ *  check digit calcualtion the check digit value should be set to zero (i.e.
+ *  <code>CC00nnnnnnn</code> in this example.
+ * <p>
+ * For further information see
+ *  <a href="http://en.wikipedia.org/wiki/International_Bank_Account_Number">Wikipedia -
+ *  IBAN number</a>.
+ */
+public final class IBANValidator
+    implements ConstraintValidator<IBAN, String> {
+
+    private static final long MAX = 999999999;
+
+    private static final long MODULUS = 97;
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid(String code, ConstraintValidatorContext context) {
+        if (code.length() < 5) {
+            return false;
+        }
+
+        String reformattedCode = code.substring(4) + code.substring(0, 4);
+        long total = 0;
+        for (int i = 0; i < reformattedCode.length(); i++) {
+            int charValue = getNumericValue(reformattedCode.charAt(i));
+            if (charValue < 0 || charValue > 35) {
+                return false;
+            }
+            total = (charValue > 9 ? total * 100 : total * 10) + charValue;
+            if (total > MAX) {
+                total = (total % MODULUS);
+            }
+        }
+
+        return (total % MODULUS) == 1;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void initialize( IBAN iban ) {
+        // not needed
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ISBN10.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ISBN10.java
new file mode 100644
index 0000000..31aab70
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ISBN10.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = ISBN10Validator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface ISBN10 {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.checkdigit.ISBN10.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ISBN10Validator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ISBN10Validator.java
new file mode 100644
index 0000000..cf2c133
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ISBN10Validator.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+/**
+ * Modulus 11 <b>ISBN-10</b> Check Digit calculation/validation.
+ * <p>
+ * ISBN-10 Numbers are a numeric code except for the last (check) digit
+ * which can have a value of "X".
+ * <p>
+ * Check digit calculation is based on <i>modulus 11</i> with digits being weighted
+ * based by their position, from right to left  with the first digit being weighted
+ * 1, the second 2 and so on. If the check digit is calculated as "10" it is converted
+ * to "X".
+ * <p>
+ * <b>N.B.</b> From 1st January 2007 the book industry will start to use a new 13 digit
+ * ISBN number (rather than this 10 digit ISBN number) which uses the EAN-13 / UPC
+ * (see {@link EAN13CheckDigit}) standard.
+ * <p>
+ * For further information see:
+ * <ul>
+ *   <li><a href="http://en.wikipedia.org/wiki/ISBN">Wikipedia - International
+ *       Standard Book Number (ISBN)</a>.</li>
+ *   <li><a href="http://www.isbn.org/standards/home/isbn/transition.asp">ISBN-13
+ *       Transition details</a>.</li>
+ * </ul>
+ */
+public final class ISBN10Validator
+    extends ModulusValidator<ISBN10> {
+
+    public ISBN10Validator() {
+        super(11);
+    }
+
+    /**
+     * Calculates the <i>weighted</i> value of a charcter in the
+     * code at a specified position.
+     *
+     * <p>For ISBN-10 (from right to left) digits are weighted
+     * by their position.</p>
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    protected int weightedValue( int charValue, int leftPos, int rightPos )
+            throws Exception {
+        return (charValue * rightPos);
+    }
+
+    /**
+     * <p>Convert a character at a specified position to an
+     * integer value.</p>
+     *
+     * <p>Character 'X' check digit converted to 10.</p>
+     *
+     * {@inheritDoc}
+     */
+    protected int toInt(char character, int leftPos, int rightPos) {
+        if (rightPos == 1 && character == 'X') {
+            return 10;
+        }
+        return super.toInt(character, leftPos, rightPos);
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Luhn.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Luhn.java
new file mode 100644
index 0000000..03be6ca
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Luhn.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = LuhnValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Luhn {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.checkdigit.Luhn.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/LuhnValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/LuhnValidator.java
new file mode 100644
index 0000000..030fe3c
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/LuhnValidator.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+/**
+ * Modulus 10 <b>Luhn</b> Check Digit calculation/validation.
+ * <p>
+ * Luhn check digits are used, for example, by:
+ * <ul>
+ *    <li><a href="http://en.wikipedia.org/wiki/Credit_card">Credit Card Numbers</a></li>
+ *    <li><a href="http://en.wikipedia.org/wiki/IMEI">IMEI Numbers</a> - International
+ *        Mobile Equipment Identity Numbers</li>
+ * </ul>
+ * Check digit calculation is based on <i>modulus 10</i> with digits in
+ * an <i>odd</i> position (from right to left) being weighted 1 and <i>even</i>
+ * position digits being weighted 2 (weighted values greater than 9 have 9 subtracted).
+ * <p>
+ * See <a href="http://en.wikipedia.org/wiki/Luhn_algorithm">Wikipedia</a>
+ * for more details.
+ */
+public final class LuhnValidator
+    extends ModulusValidator<Luhn> {
+
+    /** weighting given to digits depending on their right position */
+    private static final int[] POSITION_WEIGHT = new int[] {2, 1};
+
+    public LuhnValidator() {
+        super(10);
+    }
+
+    /**
+     * <p>Calculates the <i>weighted</i> value of a charcter in the
+     * code at a specified position.</p>
+     *
+     * <p>For Luhn (from right to left) <b>odd</b> digits are weighted
+     * with a factor of <b>one</b> and <b>even</b> digits with a factor
+     * of <b>two</b>. Weighted values > 9, have 9 subtracted</p>
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    protected int weightedValue( int charValue, int leftPos, int rightPos )
+            throws Exception {
+        int weight = POSITION_WEIGHT[rightPos % 2];
+        int weightedValue = (charValue * weight);
+        return (weightedValue > 9 ? (weightedValue - 9) : weightedValue);
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ModulusValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ModulusValidator.java
new file mode 100644
index 0000000..aeb7249
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/ModulusValidator.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.Character.getNumericValue;
+import static java.lang.Character.isDigit;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * Abstract <b>Modulus</b> Check digit calculation/validation.
+ * <p>
+ * Provides a <i>base</i> class for building <i>modulus</i> Check
+ * Digit routines.
+ * <p>
+ * This implementation only handles <i>numeric</i> codes, such as
+ * <b>EAN-13</b>. For <i>alphanumeric</i> codes such as <b>EAN-128</b> you
+ * will need to implement/override the <code>toInt()</code> and
+ * <code>toChar()</code> methods.
+ *
+ * @param <A>
+ */
+abstract class ModulusValidator<A extends Annotation>
+    implements ConstraintValidator<A, String> {
+
+    private final int modulus;
+
+    public ModulusValidator(int modulus) {
+        this.modulus = modulus;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final void initialize(A annotation) {
+        // not needed ATM
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid(String code, ConstraintValidatorContext context) {
+        if (code.length() == 0) {
+            return false;
+        }
+        int total = 0;
+        for (int i = 0; i < code.length(); i++) {
+            int lth = code.length();
+            int leftPos  = i + 1;
+            int rightPos = lth - i;
+            try {
+                int charValue = toInt(code.charAt(i), leftPos, rightPos);
+                total += weightedValue(charValue, leftPos, rightPos);
+            } catch (Throwable e) {
+                return false;
+            }
+        }
+        if (total == 0) {
+            return false;
+        }
+        return (total % modulus) == 0;
+    }
+
+    /**
+     * Calculates the <i>weighted</i> value of a character in the
+     * code at a specified position.
+     * <p>
+     * Some modulus routines weight the value of a character
+     * depending on its position in the code (e.g. ISBN-10), while
+     * others use different weighting factors for odd/even positions
+     * (e.g. EAN or Luhn). Implement the appropriate mechanism
+     * required by overriding this method.
+     *
+     * @param charValue The numeric value of the character
+     * @param leftPos The position of the character in the code, counting from left to right
+     * @param rightPos The position of the character in the code, counting from right to left
+     * @return The weighted value of the character
+     */
+    protected abstract int weightedValue(int charValue, int leftPos, int rightPos)
+        throws Exception;
+
+    /**
+     * Convert a character at a specified position to an integer value.
+     * <p>
+     * <b>Note:</b> this implementation only handlers numeric values
+     * For non-numeric characters, override this method to provide
+     * character-->integer conversion.
+     *
+     * @param character The character to convert
+     * @param leftPos The position of the character in the code, counting from left to right
+     * @param rightPos The positionof the character in the code, counting from right to left
+     * @return The integer value of the character
+     */
+    protected int toInt(char character, int leftPos, int rightPos) {
+        if (isDigit(character)) {
+            return getNumericValue(character);
+        }
+        throw new IllegalArgumentException("Invalid Character["
+                                           + leftPos
+                                           + "] = '"
+                                           + character
+                                           + "'");
+    }
+
+    /**
+     * Add together the individual digits in a number.
+     *
+     * @param number The number whose digits are to be added
+     * @return The sum of the digits
+     */
+    protected static int sumDigits(int number) {
+        int total = 0;
+        int todo = number;
+        while (todo > 0) {
+            total += todo % 10;
+            todo  = todo / 10;
+        }
+        return total;
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Sedol.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Sedol.java
new file mode 100644
index 0000000..2c90cb0
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Sedol.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = SedolValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Sedol {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.checkdigit.Sedol.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/SedolValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/SedolValidator.java
new file mode 100644
index 0000000..4476084
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/SedolValidator.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.Character.getNumericValue;
+
+/**
+ * Modulus 10 <b>SEDOL</b> (UK Securities) Check Digit calculation/validation.
+ * <p>
+ * SEDOL Numbers are 7 character alphanumeric codes used
+ * to identify UK Securities (SEDOL stands for Stock Exchange Daily Official List).
+ * <p>
+ * Check digit calculation is based on <i>modulus 10</i> with digits being weighted
+ * based on their position, from left to right, as follows:
+ * <p>
+ * <pre><code>
+ *      position:  1  2  3  4  5  6  7
+ *     weighting:  1  3  1  7  3  9  1
+ * </code></pre>
+ * <p>
+ * See <a href="http://en.wikipedia.org/wiki/SEDOL">Wikipedia - SEDOL</a>
+ * for more details.
+ */
+public final class SedolValidator
+    extends ModulusValidator<Sedol> {
+
+    /** weighting given to digits depending on their right position */
+    private static final int[] POSITION_WEIGHT = new int[] {1, 3, 1, 7, 3, 9, 1};
+
+    public SedolValidator() {
+        super(10);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected int weightedValue( int charValue, int leftPos, int rightPos )
+            throws Exception {
+        return (charValue * POSITION_WEIGHT[leftPos - 1]);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected int toInt( char character, int leftPos, int rightPos ) {
+        int charValue = getNumericValue(character);
+        if (charValue < 0 || charValue > 35) {
+            throw new IllegalArgumentException("Invalid Character["
+                                               + leftPos
+                                               + "] = '"
+                                               + charValue
+                                               + "'");
+        }
+        return charValue;
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Verhoeff.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Verhoeff.java
new file mode 100644
index 0000000..abdf759
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/Verhoeff.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = VerhoeffValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Verhoeff {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.checkdigit.Verhoeff.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/VerhoeffValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/VerhoeffValidator.java
new file mode 100644
index 0000000..19a9594
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/VerhoeffValidator.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static java.lang.Character.getNumericValue;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * <b>Verhoeff</b> (Dihedral) Check Digit calculation/validation.
+ * <p>
+ * Check digit calculation for numeric codes using a
+ * <a href="http://en.wikipedia.org/wiki/Dihedral_group">Dihedral Group</a>
+ * of order 10.
+ * <p>
+ * See <a href="http://en.wikipedia.org/wiki/Verhoeff_algorithm">Wikipedia
+ *  - Verhoeff algorithm</a> for more details.
+ */
+public final class VerhoeffValidator
+    implements ConstraintValidator<Verhoeff, String> {
+
+    /** D - multiplication table */
+    private static final int[][] D_TABLE = new int[][] {
+        {0,  1,  2,  3,  4,  5,  6,  7,  8,  9},
+        {1,  2,  3,  4,  0,  6,  7,  8,  9,  5},
+        {2,  3,  4,  0,  1,  7,  8,  9,  5,  6},
+        {3,  4,  0,  1,  2,  8,  9,  5,  6,  7},
+        {4,  0,  1,  2,  3,  9,  5,  6,  7,  8},
+        {5,  9,  8,  7,  6,  0,  4,  3,  2,  1},
+        {6,  5,  9,  8,  7,  1,  0,  4,  3,  2},
+        {7,  6,  5,  9,  8,  2,  1,  0,  4,  3},
+        {8,  7,  6,  5,  9,  3,  2,  1,  0,  4},
+        {9,  8,  7,  6,  5,  4,  3,  2,  1,  0}};
+
+    /** P - permutation table */
+    private static final int[][] P_TABLE = new int[][] {
+        {0,  1,  2,  3,  4,  5,  6,  7,  8,  9},
+        {1,  5,  7,  6,  2,  8,  3,  0,  9,  4},
+        {5,  8,  0,  3,  7,  9,  6,  1,  4,  2},
+        {8,  9,  1,  6,  0,  4,  3,  5,  2,  7},
+        {9,  4,  5,  3,  1,  2,  6,  8,  7,  0},
+        {4,  2,  8,  6,  5,  7,  3,  9,  0,  1},
+        {2,  7,  9,  3,  8,  0,  6,  4,  1,  5},
+        {7,  0,  4,  6,  9,  1,  3,  2,  5,  8}};
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid(String code, ConstraintValidatorContext context) {
+        if (code.length() == 0) {
+            return false;
+        }
+
+        int checksum = 0;
+        for (int i = 0; i < code.length(); i++) {
+            int idx = code.length() - (i + 1);
+            int num = getNumericValue(code.charAt(idx));
+            if (num < 0 || num > 9) {
+                return false;
+            }
+            checksum = D_TABLE[checksum][P_TABLE[i % 8][num]];
+        }
+        return checksum == 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void initialize(Verhoeff iban) {
+        // not needed
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/package-info.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/package-info.java
new file mode 100644
index 0000000..a81b2ed
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/checkdigit/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * This package contains <i>Check Digit</i> validation routines.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/AmericanExpress.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/AmericanExpress.java
new file mode 100644
index 0000000..4d340d3
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/AmericanExpress.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.creditcard;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import javax.validation.constraints.Pattern;
+
+import org.apache.bval.extras.constraints.checkdigit.Luhn;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Luhn
+@Pattern(regexp="^(3[47]\\d{13})$")
+@Constraint(validatedBy={})
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface AmericanExpress {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.creditcard.AmericanExpress.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Diners.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Diners.java
new file mode 100644
index 0000000..3f21de8
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Diners.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.creditcard;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import javax.validation.constraints.Pattern;
+
+import org.apache.bval.extras.constraints.checkdigit.Luhn;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Luhn
+@Pattern(regexp="^(30[0-5]\\d{11}|3095\\d{10}|36\\d{12}|3[8-9]\\d{12})$")
+@Constraint(validatedBy={})
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Diners {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.creditcard.Diners.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Discover.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Discover.java
new file mode 100644
index 0000000..56c3ca9
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Discover.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.creditcard;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import javax.validation.constraints.Pattern;
+
+import org.apache.bval.extras.constraints.checkdigit.Luhn;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Luhn
+@Pattern(regexp="^((6011\\d{12})|(64[4-9]\\d{13})|(65\\d{14}))$")
+@Constraint(validatedBy={})
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Discover {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.creditcard.Discover.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Mastercard.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Mastercard.java
new file mode 100644
index 0000000..cb3a627
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Mastercard.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.creditcard;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import javax.validation.constraints.Pattern;
+
+import org.apache.bval.extras.constraints.checkdigit.Luhn;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Luhn
+@Pattern(regexp="^(5[1-5]\\d{14})$")
+@Constraint(validatedBy={})
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Mastercard {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.creditcard.Mastercard.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Visa.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Visa.java
new file mode 100644
index 0000000..1ae223e
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/Visa.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.creditcard;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import javax.validation.constraints.Pattern;
+
+import org.apache.bval.extras.constraints.checkdigit.Luhn;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Luhn
+@Pattern(regexp="^(4)(\\d{12}|\\d{15})$")
+@Constraint(validatedBy={})
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Visa {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.creditcard.Visa.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/package-info.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/package-info.java
new file mode 100644
index 0000000..4d10d9e
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/creditcard/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * This package contains <i>Credit Card</i> validation routines.
+ */
+package org.apache.bval.extras.constraints.creditcard;
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/Directory.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/Directory.java
new file mode 100644
index 0000000..92abcb2
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/Directory.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.file;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = DirectoryValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Directory {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.file.Directory.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/DirectoryValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/DirectoryValidator.java
new file mode 100644
index 0000000..61eb8ed
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/DirectoryValidator.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.bval.extras.constraints.file;
+
+import java.io.File;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+
+/**
+ * Description: <br/>
+ */
+public class DirectoryValidator implements ConstraintValidator<Directory, File> {
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid(File value, ConstraintValidatorContext context) {
+        return value.exists() && value.isDirectory();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void initialize(Directory parameters) {
+        // do nothing (as long as Directory has no properties)
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/NotDirectory.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/NotDirectory.java
new file mode 100644
index 0000000..0f7deff
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/NotDirectory.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.file;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is not a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = DirectoryValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface NotDirectory {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.file.NotDirectory.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/NotDirectoryValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/NotDirectoryValidator.java
new file mode 100644
index 0000000..0b4ff97
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/NotDirectoryValidator.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.bval.extras.constraints.file;
+
+import java.io.File;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+
+/**
+ * Description: <br/>
+ */
+public class NotDirectoryValidator implements ConstraintValidator<NotDirectory, File> {
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid(File value, ConstraintValidatorContext context) {
+        return value.exists() && !value.isDirectory();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void initialize(NotDirectory parameters) {
+        // do nothing (as long as Directory has no properties)
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/Symlink.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/Symlink.java
new file mode 100644
index 0000000..006f8cd
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/Symlink.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.file;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a symbolic link<br/>
+ */
+@Documented
+@Constraint( validatedBy = SymlinkValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Symlink {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.file.Symlink.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/SymlinkValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/SymlinkValidator.java
new file mode 100644
index 0000000..3b16b2d
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/SymlinkValidator.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.bval.extras.constraints.file;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+
+/**
+ * Description: <br/>
+ */
+public class SymlinkValidator implements ConstraintValidator<Symlink, File> {
+
+    /**
+     * The Windows separator character.
+     */
+    private static final char WINDOWS_SEPARATOR = '\\';
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid(File value, ConstraintValidatorContext context) {
+        if (!value.exists()) {
+            return false;
+        }
+
+        // routine kindly borrowed from Apache Commons-IO
+
+        if (File.separatorChar == WINDOWS_SEPARATOR) {
+            return false;
+        }
+
+        try {
+            File fileInCanonicalDir = null;
+            if (value.getParent() == null) {
+                fileInCanonicalDir = value;
+            } else {
+                File canonicalDir = value.getParentFile().getCanonicalFile();
+                fileInCanonicalDir = new File(canonicalDir, value.getName());
+            }
+
+            return (!fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile()));
+        } catch (IOException e) {
+            // TODO: is it true?
+            return false;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void initialize(Symlink parameters) {
+        // do nothing (as long as Symlink has no properties)
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/package-info.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/package-info.java
new file mode 100644
index 0000000..b877ab0
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/file/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * {@link java.io.File} constraints validators.
+ */
+package org.apache.bval.extras.constraints.file;
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/Domain.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/Domain.java
new file mode 100644
index 0000000..9ff3eba
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/Domain.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.net;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = DomainValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface Domain {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.net.Domain.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+    boolean allowLocal() default false;
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/DomainValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/DomainValidator.java
new file mode 100644
index 0000000..52b3ef4
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/DomainValidator.java
@@ -0,0 +1,463 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.net;
+
+import static java.util.Arrays.asList;
+
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * <p><b>Domain name</b> validation routines.</p>
+ *
+ * <p>
+ * This validator provides methods for validating Internet domain names
+ * and top-level domains.
+ * </p>
+ *
+ * <p>Domain names are evaluated according
+ * to the standards <a href="http://www.ietf.org/rfc/rfc1034.txt">RFC1034</a>,
+ * section 3, and <a href="http://www.ietf.org/rfc/rfc1123.txt">RFC1123</a>,
+ * section 2.1. No accomodation is provided for the specialized needs of
+ * other applications; if the domain name has been URL-encoded, for example,
+ * validation will fail even though the equivalent plaintext version of the
+ * same name would have passed.
+ * </p>
+ *
+ * <p>
+ * Validation is also provided for top-level domains (TLDs) as defined and
+ * maintained by the Internet Assigned Numbers Authority (IANA):
+ * </p>
+ *
+ *   <ul>
+ *     <li>{@link #isValidInfrastructureTld} - validates infrastructure TLDs
+ *         (<code>.arpa</code>, etc.)</li>
+ *     <li>{@link #isValidGenericTld} - validates generic TLDs
+ *         (<code>.com, .org</code>, etc.)</li>
+ *     <li>{@link #isValidCountryCodeTld} - validates country code TLDs
+ *         (<code>.us, .uk, .cn</code>, etc.)</li>
+ *   </ul>
+ *
+ * <p>
+ * (<b>NOTE</b>: This class does not provide IP address lookup for domain names or
+ * methods to ensure that a given domain name matches a specific IP; see
+ * {@link java.net.InetAddress} for that functionality.)
+ * </p>
+ */
+public class DomainValidator implements ConstraintValidator<Domain, String> {
+
+    private boolean allowLocal;
+
+    // Regular expression strings for hostnames (derived from RFC2396 and RFC 1123)
+    private static final Pattern DOMAIN_LABEL = Pattern.compile("\\p{Alnum}(?>[\\p{Alnum}-]*\\p{Alnum})*");
+
+    private static final Pattern DOMAIN_NAME_REGEX = Pattern.compile("^(?:"
+                                                                     + DOMAIN_LABEL.pattern()
+                                                                     + "\\.)+(\\p{Alpha}{2,})$");
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid(String domain, ConstraintValidatorContext context) {
+        Matcher matcher = DOMAIN_NAME_REGEX.matcher(domain);
+        if (matcher.matches()) {
+            domain = matcher.group(1);
+            return isValidTld(domain);
+        } else if (allowLocal && DOMAIN_LABEL.matcher(domain).matches()) {
+           return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * IANA-defined top-level domain. Leading dots are ignored if present.
+     * The search is case-sensitive.
+     *
+     * @param tld the parameter to check for TLD status
+     * @return true if the parameter is a TLD
+     */
+    boolean isValidTld(String tld) {
+        if (allowLocal && isValidLocalTld(tld)) {
+           return true;
+        }
+
+        tld = chompLeadingDot(tld).toLowerCase();
+        return isValidInfrastructureTld(tld)
+                || isValidGenericTld(tld)
+                || isValidCountryCodeTld(tld);
+    }
+
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * IANA-defined infrastructure top-level domain. Leading dots are
+     * ignored if present. The search is case-sensitive.
+     *
+     * @param iTld the parameter to check for infrastructure TLD status
+     * @return true if the parameter is an infrastructure TLD
+     */
+    static boolean isValidInfrastructureTld(String iTld) {
+        return INFRASTRUCTURE_TLDS.contains(iTld);
+    }
+
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * IANA-defined generic top-level domain. Leading dots are ignored
+     * if present. The search is case-sensitive.
+     *
+     * @param gTld the parameter to check for generic TLD status
+     * @return true if the parameter is a generic TLD
+     */
+    static boolean isValidGenericTld(String gTld) {
+        return GENERIC_TLDS.contains(gTld);
+    }
+
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * IANA-defined country code top-level domain. Leading dots are
+     * ignored if present. The search is case-sensitive.
+     *
+     * @param ccTld the parameter to check for country code TLD status
+     * @return true if the parameter is a country code TLD
+     */
+    static boolean isValidCountryCodeTld(String ccTld) {
+        return COUNTRY_CODE_TLDS.contains(ccTld);
+    }
+
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * widely used "local" domains (localhost or localdomain). Leading dots are
+     * ignored if present. The search is case-sensitive.
+     *
+     * @param iTld the parameter to check for local TLD status
+     * @return true if the parameter is an local TLD
+     */
+    static boolean isValidLocalTld(String iTld) {
+        return LOCAL_TLDS.contains(iTld);
+    }
+
+    private static String chompLeadingDot(String str) {
+        if (str.startsWith(".")) {
+            return str.substring(1);
+        }
+        return str;
+    }
+
+    // ---------------------------------------------
+    // ----- TLDs defined by IANA
+    // ----- Authoritative and comprehensive list at:
+    // ----- http://data.iana.org/TLD/tlds-alpha-by-domain.txt
+
+    private static final List<String> INFRASTRUCTURE_TLDS = asList(
+        "arpa",               // internet infrastructure
+        "root"                // diagnostic marker for non-truncated root zone
+    );
+
+    private static final List<String> GENERIC_TLDS = asList(
+        "aero",               // air transport industry
+        "asia",               // Pan-Asia/Asia Pacific
+        "biz",                // businesses
+        "cat",                // Catalan linguistic/cultural community
+        "com",                // commercial enterprises
+        "coop",               // cooperative associations
+        "info",               // informational sites
+        "jobs",               // Human Resource managers
+        "mobi",               // mobile products and services
+        "museum",             // museums, surprisingly enough
+        "name",               // individuals' sites
+        "net",                // internet support infrastructure/business
+        "org",                // noncommercial organizations
+        "pro",                // credentialed professionals and entities
+        "tel",                // contact data for businesses and individuals
+        "travel",             // entities in the travel industry
+        "gov",                // United States Government
+        "edu",                // accredited postsecondary US education entities
+        "mil",                // United States Military
+        "int"                 // organizations established by international treaty
+    );
+
+    private static final List<String> COUNTRY_CODE_TLDS = asList(
+        "ac",                 // Ascension Island
+        "ad",                 // Andorra
+        "ae",                 // United Arab Emirates
+        "af",                 // Afghanistan
+        "ag",                 // Antigua and Barbuda
+        "ai",                 // Anguilla
+        "al",                 // Albania
+        "am",                 // Armenia
+        "an",                 // Netherlands Antilles
+        "ao",                 // Angola
+        "aq",                 // Antarctica
+        "ar",                 // Argentina
+        "as",                 // American Samoa
+        "at",                 // Austria
+        "au",                 // Australia (includes Ashmore and Cartier Islands and Coral Sea Islands)
+        "aw",                 // Aruba
+        "ax",                 // Åland
+        "az",                 // Azerbaijan
+        "ba",                 // Bosnia and Herzegovina
+        "bb",                 // Barbados
+        "bd",                 // Bangladesh
+        "be",                 // Belgium
+        "bf",                 // Burkina Faso
+        "bg",                 // Bulgaria
+        "bh",                 // Bahrain
+        "bi",                 // Burundi
+        "bj",                 // Benin
+        "bm",                 // Bermuda
+        "bn",                 // Brunei Darussalam
+        "bo",                 // Bolivia
+        "br",                 // Brazil
+        "bs",                 // Bahamas
+        "bt",                 // Bhutan
+        "bv",                 // Bouvet Island
+        "bw",                 // Botswana
+        "by",                 // Belarus
+        "bz",                 // Belize
+        "ca",                 // Canada
+        "cc",                 // Cocos (Keeling) Islands
+        "cd",                 // Democratic Republic of the Congo (formerly Zaire)
+        "cf",                 // Central African Republic
+        "cg",                 // Republic of the Congo
+        "ch",                 // Switzerland
+        "ci",                 // Côte d'Ivoire
+        "ck",                 // Cook Islands
+        "cl",                 // Chile
+        "cm",                 // Cameroon
+        "cn",                 // China, mainland
+        "co",                 // Colombia
+        "cr",                 // Costa Rica
+        "cu",                 // Cuba
+        "cv",                 // Cape Verde
+        "cx",                 // Christmas Island
+        "cy",                 // Cyprus
+        "cz",                 // Czech Republic
+        "de",                 // Germany
+        "dj",                 // Djibouti
+        "dk",                 // Denmark
+        "dm",                 // Dominica
+        "do",                 // Dominican Republic
+        "dz",                 // Algeria
+        "ec",                 // Ecuador
+        "ee",                 // Estonia
+        "eg",                 // Egypt
+        "er",                 // Eritrea
+        "es",                 // Spain
+        "et",                 // Ethiopia
+        "eu",                 // European Union
+        "fi",                 // Finland
+        "fj",                 // Fiji
+        "fk",                 // Falkland Islands
+        "fm",                 // Federated States of Micronesia
+        "fo",                 // Faroe Islands
+        "fr",                 // France
+        "ga",                 // Gabon
+        "gb",                 // Great Britain (United Kingdom)
+        "gd",                 // Grenada
+        "ge",                 // Georgia
+        "gf",                 // French Guiana
+        "gg",                 // Guernsey
+        "gh",                 // Ghana
+        "gi",                 // Gibraltar
+        "gl",                 // Greenland
+        "gm",                 // The Gambia
+        "gn",                 // Guinea
+        "gp",                 // Guadeloupe
+        "gq",                 // Equatorial Guinea
+        "gr",                 // Greece
+        "gs",                 // South Georgia and the South Sandwich Islands
+        "gt",                 // Guatemala
+        "gu",                 // Guam
+        "gw",                 // Guinea-Bissau
+        "gy",                 // Guyana
+        "hk",                 // Hong Kong
+        "hm",                 // Heard Island and McDonald Islands
+        "hn",                 // Honduras
+        "hr",                 // Croatia (Hrvatska)
+        "ht",                 // Haiti
+        "hu",                 // Hungary
+        "id",                 // Indonesia
+        "ie",                 // Ireland (Éire)
+        "il",                 // Israel
+        "im",                 // Isle of Man
+        "in",                 // India
+        "io",                 // British Indian Ocean Territory
+        "iq",                 // Iraq
+        "ir",                 // Iran
+        "is",                 // Iceland
+        "it",                 // Italy
+        "je",                 // Jersey
+        "jm",                 // Jamaica
+        "jo",                 // Jordan
+        "jp",                 // Japan
+        "ke",                 // Kenya
+        "kg",                 // Kyrgyzstan
+        "kh",                 // Cambodia (Khmer)
+        "ki",                 // Kiribati
+        "km",                 // Comoros
+        "kn",                 // Saint Kitts and Nevis
+        "kp",                 // North Korea
+        "kr",                 // South Korea
+        "kw",                 // Kuwait
+        "ky",                 // Cayman Islands
+        "kz",                 // Kazakhstan
+        "la",                 // Laos (currently being marketed as the official domain for Los Angeles)
+        "lb",                 // Lebanon
+        "lc",                 // Saint Lucia
+        "li",                 // Liechtenstein
+        "lk",                 // Sri Lanka
+        "lr",                 // Liberia
+        "ls",                 // Lesotho
+        "lt",                 // Lithuania
+        "lu",                 // Luxembourg
+        "lv",                 // Latvia
+        "ly",                 // Libya
+        "ma",                 // Morocco
+        "mc",                 // Monaco
+        "md",                 // Moldova
+        "me",                 // Montenegro
+        "mg",                 // Madagascar
+        "mh",                 // Marshall Islands
+        "mk",                 // Republic of Macedonia
+        "ml",                 // Mali
+        "mm",                 // Myanmar
+        "mn",                 // Mongolia
+        "mo",                 // Macau
+        "mp",                 // Northern Mariana Islands
+        "mq",                 // Martinique
+        "mr",                 // Mauritania
+        "ms",                 // Montserrat
+        "mt",                 // Malta
+        "mu",                 // Mauritius
+        "mv",                 // Maldives
+        "mw",                 // Malawi
+        "mx",                 // Mexico
+        "my",                 // Malaysia
+        "mz",                 // Mozambique
+        "na",                 // Namibia
+        "nc",                 // New Caledonia
+        "ne",                 // Niger
+        "nf",                 // Norfolk Island
+        "ng",                 // Nigeria
+        "ni",                 // Nicaragua
+        "nl",                 // Netherlands
+        "no",                 // Norway
+        "np",                 // Nepal
+        "nr",                 // Nauru
+        "nu",                 // Niue
+        "nz",                 // New Zealand
+        "om",                 // Oman
+        "pa",                 // Panama
+        "pe",                 // Peru
+        "pf",                 // French Polynesia With Clipperton Island
+        "pg",                 // Papua New Guinea
+        "ph",                 // Philippines
+        "pk",                 // Pakistan
+        "pl",                 // Poland
+        "pm",                 // Saint-Pierre and Miquelon
+        "pn",                 // Pitcairn Islands
+        "pr",                 // Puerto Rico
+        "ps",                 // Palestinian territories (PA-controlled West Bank and Gaza Strip)
+        "pt",                 // Portugal
+        "pw",                 // Palau
+        "py",                 // Paraguay
+        "qa",                 // Qatar
+        "re",                 // Réunion
+        "ro",                 // Romania
+        "rs",                 // Serbia
+        "ru",                 // Russia
+        "rw",                 // Rwanda
+        "sa",                 // Saudi Arabia
+        "sb",                 // Solomon Islands
+        "sc",                 // Seychelles
+        "sd",                 // Sudan
+        "se",                 // Sweden
+        "sg",                 // Singapore
+        "sh",                 // Saint Helena
+        "si",                 // Slovenia
+        "sj",                 // Svalbard and Jan Mayen Islands Not in use (Norwegian dependencies; see .no)
+        "sk",                 // Slovakia
+        "sl",                 // Sierra Leone
+        "sm",                 // San Marino
+        "sn",                 // Senegal
+        "so",                 // Somalia
+        "sr",                 // Suriname
+        "st",                 // São Tomé and Príncipe
+        "su",                 // Soviet Union (deprecated)
+        "sv",                 // El Salvador
+        "sy",                 // Syria
+        "sz",                 // Swaziland
+        "tc",                 // Turks and Caicos Islands
+        "td",                 // Chad
+        "tf",                 // French Southern and Antarctic Lands
+        "tg",                 // Togo
+        "th",                 // Thailand
+        "tj",                 // Tajikistan
+        "tk",                 // Tokelau
+        "tl",                 // East Timor (deprecated old code)
+        "tm",                 // Turkmenistan
+        "tn",                 // Tunisia
+        "to",                 // Tonga
+        "tp",                 // East Timor
+        "tr",                 // Turkey
+        "tt",                 // Trinidad and Tobago
+        "tv",                 // Tuvalu
+        "tw",                 // Taiwan, Republic of China
+        "tz",                 // Tanzania
+        "ua",                 // Ukraine
+        "ug",                 // Uganda
+        "uk",                 // United Kingdom
+        "um",                 // United States Minor Outlying Islands
+        "us",                 // United States of America
+        "uy",                 // Uruguay
+        "uz",                 // Uzbekistan
+        "va",                 // Vatican City State
+        "vc",                 // Saint Vincent and the Grenadines
+        "ve",                 // Venezuela
+        "vg",                 // British Virgin Islands
+        "vi",                 // U.S. Virgin Islands
+        "vn",                 // Vietnam
+        "vu",                 // Vanuatu
+        "wf",                 // Wallis and Futuna
+        "ws",                 // Samoa (formerly Western Samoa)
+        "ye",                 // Yemen
+        "yt",                 // Mayotte
+        "yu",                 // Serbia and Montenegro (originally Yugoslavia)
+        "za",                 // South Africa
+        "zm",                 // Zambia
+        "zw"                  // Zimbabwe
+    );
+
+    private static final List<String> LOCAL_TLDS = asList(
+       "localhost",           // RFC2606 defined
+       "localdomain"          // Also widely used as localhost.localdomain
+   );
+
+    /**
+     * {@inheritDoc}
+     */
+    public void initialize(Domain domain) {
+        allowLocal = domain.allowLocal();
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/InetAddress.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/InetAddress.java
new file mode 100644
index 0000000..4dc3bc0
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/InetAddress.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.net;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * <p>
+ * --
+ * TODO - This class is NOT part of the bean_validation spec and might disappear
+ * as soon as a final version of the specification contains a similar functionality.
+ * --
+ * </p>
+ * Description: annotation to validate a java.io.File is a directory<br/>
+ */
+@Documented
+@Constraint( validatedBy = InetAddressValidator.class )
+@Target( { FIELD, ANNOTATION_TYPE, PARAMETER } )
+@Retention( RUNTIME )
+public @interface InetAddress {
+
+    Class<?>[] groups() default {};
+
+    String message() default "{org.apache.bval.extras.constraints.net.InetAddress.message}";
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/InetAddressValidator.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/InetAddressValidator.java
new file mode 100644
index 0000000..f0896f1
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/InetAddressValidator.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.net;
+
+import java.util.regex.Pattern;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * <p><b>InetAddress</b> validation and conversion routines (<code>java.net.InetAddress</code>).</p>
+ *
+ * <p>This class provides methods to validate a candidate IP address.
+ */
+public class InetAddressValidator implements ConstraintValidator<InetAddress, String> {
+
+    private static final Pattern IPV4_PATTERN = Pattern.compile("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+                                                                + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+                                                                + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+                                                                + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid(String value, ConstraintValidatorContext context) {
+        if (!IPV4_PATTERN.matcher(value).matches()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void initialize(InetAddress parameters) {
+        // do nothing (as long as InetAddress has no properties)
+    }
+
+}
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/package-info.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/package-info.java
new file mode 100644
index 0000000..d7e7550
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/net/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * net constraints validators.
+ */
+package org.apache.bval.extras.constraints.net;
diff --git a/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/package-info.java b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/package-info.java
new file mode 100644
index 0000000..02f423c
--- /dev/null
+++ b/trunk/bval-extras/src/main/java/org/apache/bval/extras/constraints/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Contains constraints that are NOT part of the Bean Validation specification
+ * and might disappear as soon as a final version of the specification contains
+ * similar functionalities.
+ */
+package org.apache.bval.extras.constraints;
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/ABANumberValidatorTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/ABANumberValidatorTest.java
new file mode 100644
index 0000000..56d5e62
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/ABANumberValidatorTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+
+/**
+ * ABA Number Validator Test.
+ */
+public class ABANumberValidatorTest extends AbstractCheckDigitTest {
+
+    @Override
+    protected ConstraintValidator<? extends Annotation, String> getConstraint() {
+        return new ABANumberValidator();
+    }
+
+    @Override
+    protected String[] getValid() {
+        return new String[] {
+            "123456780",
+            "123123123",
+            "011000015",
+            "111000038",
+            "231381116",
+            "121181976"
+        };
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/AbstractCheckDigitTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/AbstractCheckDigitTest.java
new file mode 100644
index 0000000..36b5198
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/AbstractCheckDigitTest.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.validation.ConstraintValidator;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ */
+public abstract class AbstractCheckDigitTest {
+
+    /** Check digit routine being tested */
+    private int checkDigitLth;
+
+    /** Check digit routine being tested */
+    private ConstraintValidator<? extends Annotation, String> routine;
+
+    /** Array of valid code values */
+    private String[] valid;
+
+    /** Array of invalid code values */
+    private String[] invalid;
+
+    /** code value which sums to zero */
+    private String zeroSum;
+
+    /** Prefix for error messages */
+    private String missingMessage;
+
+    public int getCheckDigitLth() {
+        return 1;
+    }
+
+    protected abstract ConstraintValidator<? extends Annotation, String> getConstraint();
+
+    protected abstract String[] getValid();
+
+    protected String[] getInvalid() {
+        return new String[] {"12345678A"};
+    }
+
+    protected String getZeroSum() {
+        return "0000000000";
+    }
+
+    public String getMissingMessage() {
+        return "Code is missing";
+    }
+
+    @Before
+    public void setUp() {
+        checkDigitLth = getCheckDigitLth();
+        routine = getConstraint();
+        valid = getValid();
+        invalid = getInvalid();
+        zeroSum = getZeroSum();
+        missingMessage = getMissingMessage();
+    }
+
+    /**
+     * Tear Down - clears routine and valid codes.
+     */
+    @After
+    public void tearDown() {
+        valid = null;
+        routine = null;
+    }
+
+    /**
+     * Test isValid() for valid values.
+     */
+    @Test
+    public void testIsValidTrue() {
+        // test valid values
+        for (int i = 0; i < valid.length; i++) {
+            assertTrue("valid[" + i +"]: " + valid[i], routine.isValid(valid[i], null));
+        }
+    }
+
+    /**
+     * Test isValid() for invalid values.
+     */
+    @Test
+    public void testIsValidFalse() {
+        // test invalid code values
+        for (int i = 0; i < invalid.length; i++) {
+            assertFalse("invalid[" + i +"]: " + invalid[i], routine.isValid(invalid[i], null));
+        }
+
+        // test invalid check digit values
+        String[] invalidCheckDigits = createInvalidCodes(valid);
+        for (int i = 0; i < invalidCheckDigits.length; i++) {
+            assertFalse("invalid check digit[" + i +"]: " + invalidCheckDigits[i], routine.isValid(invalidCheckDigits[i], null));
+        }
+    }
+
+    /**
+     * Test missing code
+     */
+    @Test
+    public void testMissingCode() {
+        // isValid() zero length
+        assertFalse("isValid() Zero Length", routine.isValid("", null));
+    }
+
+    /**
+     * Test zero sum
+     */
+    @Test
+    public void testZeroSum() {
+        assertFalse("isValid() Zero Sum", routine.isValid(zeroSum, null));
+    }
+
+    /**
+     * Returns an array of codes with invalid check digits.
+     *
+     * @param codes Codes with valid check digits
+     * @return Codes with invalid check digits
+     */
+    protected String[] createInvalidCodes(String[] codes) {
+        List<String> list = new ArrayList<String>();
+
+        // create invalid check digit values
+        for (int i = 0; i < codes.length; i++) {
+            String code = removeCheckDigit(codes[i]);
+            String check  = checkDigit(codes[i]);
+            for (int j = 0; j < 10; j++) {
+                String curr =  "" + Character.forDigit(j, 10);
+                if (!curr.equals(check)) {
+                    list.add(code + curr);
+                }
+            }
+        }
+
+        return list.toArray(new String[list.size()]);
+    }
+
+    /**
+     * Returns a code with the Check Digit (i.e. last character) removed.
+     *
+     * @param code The code
+     * @return The code without the check digit
+     */
+    protected String removeCheckDigit(String code) {
+        if (code == null || code.length() <= checkDigitLth) {
+            return null;
+        }
+        return code.substring(0, code.length() - checkDigitLth);
+    }
+
+    /**
+     * Returns the check digit (i.e. last character) for a code.
+     *
+     * @param code The code
+     * @return The check digit
+     */
+    protected String checkDigit(String code) {
+        if (code == null || code.length() <= checkDigitLth) {
+            return "";
+        }
+        int start = code.length() - checkDigitLth;
+        return code.substring(start);
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/CUSIPValidatorTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/CUSIPValidatorTest.java
new file mode 100644
index 0000000..d522626
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/CUSIPValidatorTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+
+/**
+ * CUSIP Check Digit Test.
+ */
+public class CUSIPValidatorTest extends AbstractCheckDigitTest {
+
+    @Override
+    protected ConstraintValidator<? extends Annotation, String> getConstraint() {
+        return new CUSIPValidator();
+    }
+
+    @Override
+    protected String[] getValid() {
+        return new String[] {
+            "037833100",
+            "931142103",
+            "837649128",
+            "392690QT3",
+            "594918104",
+            "86770G101",
+            "Y8295N109",
+            "G8572F100"
+        };
+    }
+
+    @Override
+    protected String[] getInvalid() {
+        return new String[] {"0378#3100"};
+    }
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/EAN13CheckDigitTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/EAN13CheckDigitTest.java
new file mode 100644
index 0000000..80885fe
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/EAN13CheckDigitTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+
+/**
+ * EAN-13 Check Digit Test.
+ */
+public class EAN13CheckDigitTest extends AbstractCheckDigitTest {
+
+    @Override
+    protected ConstraintValidator<? extends Annotation, String> getConstraint() {
+        return new EAN13Validator();
+    }
+
+    @Override
+    protected String[] getValid() {
+        return new String[] {
+            "9780072129519",
+            "9780764558313",
+            "4025515373438",
+            "0095673400332"
+        };
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/IBANCheckDigitTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/IBANCheckDigitTest.java
new file mode 100644
index 0000000..36ed7d2
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/IBANCheckDigitTest.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.validation.ConstraintValidator;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * IVAN Check Digit Test.
+ */
+public class IBANCheckDigitTest extends AbstractCheckDigitTest {
+
+    @Override
+    public int getCheckDigitLth() {
+        return 2;
+    }
+
+    @Override
+    protected ConstraintValidator<? extends Annotation, String> getConstraint() {
+        return new IBANValidator();
+    }
+
+    @Override
+    protected String[] getValid() {
+        return new String[] {
+            "AD1200012030200359100100",
+            "AT611904300234573201",
+            "AT611904300234573201",
+            "BE68539007547034",
+            "BE62510007547061",
+            "CY17002001280000001200527600",
+            "CZ6508000000192000145399",
+            "DK5000400440116243",
+            "EE382200221020145685",
+            "FI2112345600000785",
+            "FR1420041010050500013M02606",
+            "DE89370400440532013000",
+            "GI75NWBK000000007099453",
+            "GR1601101250000000012300695",
+            "HU42117730161111101800000000",
+            "IS140159260076545510730339",
+            "IE29AIBK93115212345678",
+            "IT60X0542811101000000123456",
+            "LV80BANK0000435195001",
+            "LT121000011101001000",
+            "LU280019400644750000",
+            "NL91ABNA0417164300",
+            "NO9386011117947",
+            "PL27114020040000300201355387",
+            "PT50000201231234567890154",
+            "SK3112000000198742637541",
+            "SI56191000000123438",
+            "ES8023100001180000012345",
+            "SE3550000000054910000003",
+            "CH3900700115201849173",
+            "GB29NWBK60161331926819"
+        };
+    }
+
+    @Override
+    protected String[] getInvalid() {
+        return new String[] {"510007+47061BE63"};
+    }
+
+    @Override
+    protected String getZeroSum() {
+        return null;
+    }
+
+    @Override
+    public String getMissingMessage() {
+        return "Invalid Code length=0";
+    }
+
+    /**
+     * Test zero sum
+     */
+    @Override
+    @Test
+    @Ignore
+    public void testZeroSum() {
+        // ignore, don't run this test
+    }
+
+    @Override
+    protected String[] createInvalidCodes( String[] codes ) {
+        List<String> list = new ArrayList<String>();
+
+        // create invalid check digit values
+        for (int i = 0; i < codes.length; i++) {
+            String code = removeCheckDigit(codes[i]);
+            String check  = checkDigit(codes[i]);
+            for (int j = 0; j < 96; j++) {
+                String curr =  j > 9 ? "" + j : "0" + j;
+                if (!curr.equals(check)) {
+                    list.add(code.substring(0, 2) + curr + code.substring(4));
+                }
+            }
+        }
+
+        return list.toArray(new String[list.size()]);
+    }
+
+
+
+    /**
+     * Returns a code with the Check Digit (i.e. last character) removed.
+     *
+     * @param code The code
+     * @return The code without the check digit
+     */
+    protected String removeCheckDigit(String code) {
+        return code.substring(0, 2) + "00" + code.substring(4);
+    }
+
+    /**
+     * Returns the check digit (i.e. last character) for a code.
+     *
+     * @param code The code
+     * @return The check digit
+     */
+    protected String checkDigit(String code) {
+        if (code == null || code.length() <= getCheckDigitLth()) {
+            return "";
+        }
+       return code.substring(2, 4);
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/ISBN10CheckDigitTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/ISBN10CheckDigitTest.java
new file mode 100644
index 0000000..111d866
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/ISBN10CheckDigitTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+
+/**
+ * ISBN-10 Check Digit Test.
+ */
+public class ISBN10CheckDigitTest extends AbstractCheckDigitTest {
+
+    @Override
+    protected ConstraintValidator<? extends Annotation, String> getConstraint() {
+        return new ISBN10Validator();
+    }
+
+    @Override
+    protected String[] getValid() {
+        return new String[] {
+            "1930110995",
+            "020163385X",
+            "1932394354",
+            "1590596277"
+        };
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/LuhnCheckDigitTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/LuhnCheckDigitTest.java
new file mode 100644
index 0000000..85c8234
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/LuhnCheckDigitTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+
+/**
+ * Luhn Check Digit Test.
+ */
+public class LuhnCheckDigitTest extends AbstractCheckDigitTest {
+
+    private static final String VALID_VISA       = "4417123456789113";
+
+    private static final String VALID_SHORT_VISA = "4222222222222";
+
+    private static final String VALID_AMEX       = "378282246310005";
+
+    private static final String VALID_MASTERCARD = "5105105105105100";
+
+    private static final String VALID_DISCOVER   = "6011000990139424";
+
+    private static final String VALID_DINERS     = "30569309025904";
+
+    @Override
+    protected ConstraintValidator<? extends Annotation, String> getConstraint() {
+        return new LuhnValidator();
+    }
+
+    @Override
+    protected String[] getValid() {
+        return new String[] {
+            VALID_VISA,
+            VALID_SHORT_VISA,
+            VALID_AMEX,
+            VALID_MASTERCARD,
+            VALID_DISCOVER,
+            VALID_DINERS
+        };
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/SedolCheckDigitTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/SedolCheckDigitTest.java
new file mode 100644
index 0000000..0ebde22
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/SedolCheckDigitTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+
+/**
+ * Sedol Check Digit Test.
+ */
+public class SedolCheckDigitTest extends AbstractCheckDigitTest {
+
+    @Override
+    protected ConstraintValidator<? extends Annotation, String> getConstraint() {
+        return new SedolValidator();
+    }
+
+    @Override
+    protected String[] getValid() {
+        return new String[] {
+            "0263494",
+            "0870612",
+            "B06LQ97",
+            "3437575",
+            "B07LF55",
+        };
+    }
+
+    @Override
+    protected String[] getInvalid() {
+        return new String[] {"123#567"};
+    }
+
+    @Override
+    protected String getZeroSum() {
+        return "0000000";
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/VerhoeffCheckDigitTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/VerhoeffCheckDigitTest.java
new file mode 100644
index 0000000..2db2372
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/checkdigit/VerhoeffCheckDigitTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.checkdigit;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Verhoeff Check Digit Test.
+ */
+public class VerhoeffCheckDigitTest extends AbstractCheckDigitTest {
+
+    @Override
+    protected ConstraintValidator<? extends Annotation, String> getConstraint() {
+        return new VerhoeffValidator();
+    }
+
+    @Override
+    protected String[] getValid() {
+        return new String[] {
+            "15",
+            "1428570",
+            "12345678902"
+        };
+    }
+
+    /**
+     * Test zero sum
+     */
+    @Override
+    @Test
+    @Ignore
+    public void testZeroSum() {
+        // ignore, don't run this test
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/net/DomainValidatorTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/net/DomainValidatorTest.java
new file mode 100644
index 0000000..fcf32e4
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/net/DomainValidatorTest.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.extras.constraints.net;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.Payload;
+
+import org.apache.bval.extras.constraints.net.Domain;
+import org.apache.bval.extras.constraints.net.DomainValidator;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the DomainValidator.
+ */
+public class DomainValidatorTest {
+
+    private DomainValidator validator;
+
+    @Before
+    public void setUp() {
+        validator = new DomainValidator();
+    }
+
+    @Test
+    public void testValidDomains() {
+        assertTrue("apache.org should validate", validator.isValid("apache.org", null));
+        assertTrue("www.google.com should validate", validator.isValid("www.google.com", null));
+
+        assertTrue("test-domain.com should validate", validator.isValid("test-domain.com", null));
+        assertTrue("test---domain.com should validate", validator.isValid("test---domain.com", null));
+        assertTrue("test-d-o-m-ain.com should validate", validator.isValid("test-d-o-m-ain.com", null));
+        assertTrue("two-letter domain label should validate", validator.isValid("as.uk", null));
+
+        assertTrue("case-insensitive ApAchE.Org should validate", validator.isValid("ApAchE.Org", null));
+
+        assertTrue("single-character domain label should validate", validator.isValid("z.com", null));
+
+        assertTrue("i.have.an-example.domain.name should validate", validator.isValid("i.have.an-example.domain.name", null));
+    }
+
+    @Test
+    public void testInvalidDomains() {
+        assertFalse("bare TLD .org shouldn't validate", validator.isValid(".org", null));
+        assertFalse("domain name with spaces shouldn't validate", validator.isValid(" apache.org ", null));
+        assertFalse("domain name containing spaces shouldn't validate", validator.isValid("apa che.org", null));
+        assertFalse("domain name starting with dash shouldn't validate", validator.isValid("-testdomain.name", null));
+        assertFalse("domain name ending with dash shouldn't validate", validator.isValid("testdomain-.name", null));
+        assertFalse("domain name starting with multiple dashes shouldn't validate", validator.isValid("---c.com", null));
+        assertFalse("domain name ending with multiple dashes shouldn't validate", validator.isValid("c--.com", null));
+        assertFalse("domain name with invalid TLD shouldn't validate", validator.isValid("apache.rog", null));
+
+        assertFalse("URL shouldn't validate", validator.isValid("http://www.apache.org", null));
+        assertFalse("Empty string shouldn't validate as domain name", validator.isValid(" ", null));
+    }
+
+    @Test
+    public void testTopLevelDomains() {
+        // infrastructure TLDs
+        assertTrue(".arpa should validate as iTLD", DomainValidator.isValidInfrastructureTld("arpa"));
+        assertFalse(".com shouldn't validate as iTLD", DomainValidator.isValidInfrastructureTld("com"));
+
+        // generic TLDs
+        assertTrue(".name should validate as gTLD", DomainValidator.isValidGenericTld("name"));
+        assertFalse(".us shouldn't validate as gTLD", DomainValidator.isValidGenericTld("us"));
+
+        // country code TLDs
+        assertTrue(".uk should validate as ccTLD", DomainValidator.isValidCountryCodeTld("uk"));
+        assertFalse(".org shouldn't validate as ccTLD", DomainValidator.isValidCountryCodeTld("org"));
+
+        // case-insensitive
+        assertTrue(".COM should validate as TLD", validator.isValidTld("COM"));
+        assertTrue(".BiZ should validate as TLD", validator.isValidTld("BiZ"));
+
+        // corner cases
+        assertFalse("invalid TLD shouldn't validate", validator.isValid("nope", null));
+        assertFalse("empty string shouldn't validate as TLD", validator.isValid("", null));
+    }
+
+    @Test
+    public void testAllowLocal() {
+       DomainValidator noLocal = new DomainValidator();
+       DomainValidator allowLocal = new DomainValidator();
+       allowLocal.initialize( new Domain()
+       {
+
+            public Class<? extends Annotation> annotationType() {
+                // not needed
+                return null;
+            }
+
+            public Class<? extends Payload>[] payload() {
+                // not needed
+                return null;
+            }
+
+            public String message() {
+                // not needed
+                return null;
+            }
+
+            public Class<?>[] groups() {
+                // not needed
+                return null;
+            }
+
+            public boolean allowLocal() {
+                // enable the local
+                return true;
+            }
+        });
+
+       // Default won't allow local
+       assertFalse("localhost.localdomain should validate", noLocal.isValid("localhost.localdomain", null));
+       assertFalse("localhost should validate", noLocal.isValid("localhost", null));
+
+       // But it may be requested
+       assertTrue("localhost.localdomain should validate", allowLocal.isValid("localhost.localdomain", null));
+       assertTrue("localhost should validate", allowLocal.isValid("localhost", null));
+       assertTrue("hostname should validate", allowLocal.isValid("hostname", null));
+       assertTrue("machinename should validate", allowLocal.isValid("machinename", null));
+
+       // Check the localhost one with a few others
+       assertTrue("apache.org should validate", allowLocal.isValid("apache.org", null));
+       assertFalse("domain name with spaces shouldn't validate", allowLocal.isValid(" apache.org ", null));
+    }
+
+    @Test
+    public void testIDN() {
+       assertTrue("b\u00fccher.ch in IDN should validate", validator.isValid("www.xn--bcher-kva.ch", null));
+    }
+
+}
diff --git a/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/net/InetAddressValidatorTest.java b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/net/InetAddressValidatorTest.java
new file mode 100644
index 0000000..4703279
--- /dev/null
+++ b/trunk/bval-extras/src/test/java/org/apache/bval/extras/constraints/net/InetAddressValidatorTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.extras.constraints.net;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.bval.extras.constraints.net.InetAddressValidator;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test cases for InetAddressValidator.
+ *
+ * @version $Revision$
+ */
+public class InetAddressValidatorTest {
+
+    private InetAddressValidator validator;
+
+    @Before
+    public void setUp() {
+        validator = new InetAddressValidator();
+    }
+
+    /**
+     * Test IPs that point to real, well-known hosts (without actually looking them up).
+     */
+    @Test
+    public void testInetAddressesFromTheWild() {
+        assertTrue("www.apache.org IP should be valid",       validator.isValid("140.211.11.130", null));
+        assertTrue("www.l.google.com IP should be valid",     validator.isValid("72.14.253.103", null));
+        assertTrue("fsf.org IP should be valid",              validator.isValid("199.232.41.5", null));
+        assertTrue("appscs.ign.com IP should be valid",       validator.isValid("216.35.123.87", null));
+    }
+
+    /**
+     * Test valid and invalid IPs from each address class.
+     */
+    @Test
+    public void testInetAddressesByClass() {
+        assertTrue("class A IP should be valid",              validator.isValid("24.25.231.12", null));
+        assertFalse("illegal class A IP should be invalid",   validator.isValid("2.41.32.324", null));
+
+        assertTrue("class B IP should be valid",              validator.isValid("135.14.44.12", null));
+        assertFalse("illegal class B IP should be invalid",   validator.isValid("154.123.441.123", null));
+
+        assertTrue("class C IP should be valid",              validator.isValid("213.25.224.32", null));
+        assertFalse("illegal class C IP should be invalid",   validator.isValid("201.543.23.11", null));
+
+        assertTrue("class D IP should be valid",              validator.isValid("229.35.159.6", null));
+        assertFalse("illegal class D IP should be invalid",   validator.isValid("231.54.11.987", null));
+
+        assertTrue("class E IP should be valid",              validator.isValid("248.85.24.92", null));
+        assertFalse("illegal class E IP should be invalid",   validator.isValid("250.21.323.48", null));
+    }
+
+    /**
+     * Test reserved IPs.
+     */
+    @Test
+    public void testReservedInetAddresses() {
+        assertTrue("localhost IP should be valid",            validator.isValid("127.0.0.1", null));
+        assertTrue("broadcast IP should be valid",            validator.isValid("255.255.255.255", null));
+    }
+
+    /**
+     * Test obviously broken IPs.
+     */
+    @Test
+    public void testBrokenInetAddresses() {
+        assertFalse("IP with characters should be invalid",   validator.isValid("124.14.32.abc", null));
+        assertFalse("IP with three groups should be invalid", validator.isValid("23.64.12", null));
+        assertFalse("IP with five groups should be invalid",  validator.isValid("26.34.23.77.234", null));
+    }
+
+}
diff --git a/trunk/bval-guice/pom.xml b/trunk/bval-guice/pom.xml
new file mode 100644
index 0000000..a5bd492
--- /dev/null
+++ b/trunk/bval-guice/pom.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!--
+	Maven release plugin requires the project tag to be on a single line.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.bval</groupId>
+        <artifactId>bval-parent</artifactId>
+        <version>0.4</version>
+    </parent>
+
+    <artifactId>bval-guice</artifactId>
+    <name>Apache BVal :: bval-guice (optional)</name>
+    <packaging>bundle</packaging>
+
+    <description>BVal - Google Guice Integration</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.bval</groupId>
+            <artifactId>org.apache.bval.bundle</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>aopalliance</groupId>
+            <artifactId>aopalliance</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <profiles>
+        <!--
+            default profile using geronimo-validation_1.0_spec.jar
+            active when property "ri" is not present.
+        -->
+        <profile>
+            <id>geronimo</id>
+            <activation>
+                <property>
+                    <name>!ri</name>
+                </property>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.geronimo.specs</groupId>
+                    <artifactId>geronimo-validation_1.0_spec</artifactId>
+                    <!-- allow users to choose an API provider -->
+                    <scope>provided</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+        <!--
+            optional profile using javax.validation/validation-api.jar
+            from RI manually active when property "-Pri" is provided.
+        -->
+        <profile>
+            <id>ri</id>
+            <activation>
+                <property>
+                    <name>ri</name>
+                </property>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>javax.validation</groupId>
+                    <artifactId>validation-api</artifactId>
+                    <!-- allow users to choose an API provider -->
+                    <scope>provided</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+
+    <build>
+        <defaultGoal>install</defaultGoal>
+
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+    </build>
+
+</project>
diff --git a/trunk/bval-guice/src/main/java/org/apache/bval/guice/ConfigurationStateProvider.java b/trunk/bval-guice/src/main/java/org/apache/bval/guice/ConfigurationStateProvider.java
new file mode 100644
index 0000000..09c4db8
--- /dev/null
+++ b/trunk/bval-guice/src/main/java/org/apache/bval/guice/ConfigurationStateProvider.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.guice;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.TraversableResolver;
+import javax.validation.spi.BootstrapState;
+import javax.validation.spi.ConfigurationState;
+import javax.validation.spi.ValidationProvider;
+
+import org.apache.bval.jsr303.ConfigurationImpl;
+
+/**
+ * The {@code javax.validation.spi.ConfigurationState} provider implementation.
+ *
+ * @version $Id$
+ */
+public final class ConfigurationStateProvider implements Provider<ConfigurationState> {
+
+    @com.google.inject.Inject(optional = true)
+    private BootstrapState bootstrapState;
+
+    @Inject
+    private ValidationProvider<?> validationProvider;
+
+    @Inject
+    private TraversableResolver traversableResolver;
+
+    @Inject
+    private MessageInterpolator messageInterpolator;
+
+    @Inject
+    private ConstraintValidatorFactory constraintValidatorFactory;
+
+    public void setBootstrapState(BootstrapState bootstrapState) {
+        this.bootstrapState = bootstrapState;
+    }
+
+    public void setValidationProvider(ValidationProvider<?> validationProvider) {
+        this.validationProvider = validationProvider;
+    }
+
+    public void setTraversableResolver(TraversableResolver traversableResolver) {
+        this.traversableResolver = traversableResolver;
+    }
+
+    public void setMessageInterpolator(MessageInterpolator messageInterpolator) {
+        this.messageInterpolator = messageInterpolator;
+    }
+
+    public void setConstraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
+        this.constraintValidatorFactory = constraintValidatorFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ConfigurationState get() {
+        ConfigurationImpl configuration = new ConfigurationImpl(this.bootstrapState, this.validationProvider);
+        configuration.traversableResolver(this.traversableResolver);
+        configuration.messageInterpolator(this.messageInterpolator);
+        configuration.constraintValidatorFactory(this.constraintValidatorFactory);
+        return configuration;
+    }
+
+}
diff --git a/trunk/bval-guice/src/main/java/org/apache/bval/guice/GuiceAwareConstraintValidatorFactory.java b/trunk/bval-guice/src/main/java/org/apache/bval/guice/GuiceAwareConstraintValidatorFactory.java
new file mode 100644
index 0000000..4917b74
--- /dev/null
+++ b/trunk/bval-guice/src/main/java/org/apache/bval/guice/GuiceAwareConstraintValidatorFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.guice;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorFactory;
+
+import com.google.inject.Injector;
+
+/**
+ * {@code javax.validation.ConstraintValidatorFactory} implementation that
+ * relies on Google Guice.
+ *
+ * @version $Id$
+ */
+@Singleton
+final class GuiceAwareConstraintValidatorFactory implements ConstraintValidatorFactory {
+
+    @Inject
+    private Injector injector;
+
+    public void setInjector(Injector injector) {
+        this.injector = injector;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
+        return this.injector.getInstance(key);
+    }
+
+}
diff --git a/trunk/bval-guice/src/main/java/org/apache/bval/guice/Validate.java b/trunk/bval-guice/src/main/java/org/apache/bval/guice/Validate.java
new file mode 100644
index 0000000..d1ca823
--- /dev/null
+++ b/trunk/bval-guice/src/main/java/org/apache/bval/guice/Validate.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.guice;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.ConstraintViolationException;
+
... 30645 lines suppressed ...


Mime
View raw message