├── .editorconfig ├── .gitignore ├── .maven-bintray.xml ├── .travis.yml ├── README.adoc ├── pom.xml ├── script └── travis-deploy └── src ├── main └── java │ └── cz │ └── jirutka │ └── validator │ └── collection │ ├── CommonEachValidator.java │ ├── constraints │ ├── EachAssertFalse.java │ ├── EachAssertTrue.java │ ├── EachConstraint.java │ ├── EachCreditCardNumber.java │ ├── EachDecimalMax.java │ ├── EachDecimalMin.java │ ├── EachDigits.java │ ├── EachEAN.java │ ├── EachEmail.java │ ├── EachFuture.java │ ├── EachLength.java │ ├── EachLuhnCheck.java │ ├── EachMax.java │ ├── EachMin.java │ ├── EachMod10Check.java │ ├── EachMod11Check.java │ ├── EachNotBlank.java │ ├── EachNotEmpty.java │ ├── EachNotNull.java │ ├── EachPast.java │ ├── EachPattern.java │ ├── EachRange.java │ ├── EachSafeHtml.java │ ├── EachScriptAssert.java │ ├── EachSize.java │ └── EachURL.java │ └── internal │ ├── AnnotationUtils.java │ ├── ConstraintDescriptorFactory.java │ ├── ConstraintValidatorContextUtils.java │ ├── HibernateValidatorInfo.java │ └── MessageInterpolatorContext.java └── test ├── groovy └── cz │ └── jirutka │ └── validator │ └── collection │ ├── CommonEachValidatorIT.groovy │ ├── CommonEachValidatorTest.groovy │ ├── TestUtils.groovy │ ├── constraints │ └── EachAnnotationIT.groovy │ └── internal │ ├── AnnotationUtilsTest.groovy │ └── HibernateValidatorInfoTest.groovy ├── java └── cz │ └── jirutka │ └── validator │ └── collection │ └── fixtures │ ├── EachComposite.java │ └── LegacyEachSize.java └── resources └── simplelogger.properties /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 4 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.yml] 13 | indent_size = 2 14 | 15 | [script/*] 16 | indent_size = 4 17 | indent_style = tab 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | nb-configuration.xml 3 | .idea 4 | *.iml 5 | -------------------------------------------------------------------------------- /.maven-bintray.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | jfrog-oss-snapshot-local 9 | jirutka 10 | ${env.BINTRAY_API_KEY} 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: java 3 | jdk: 4 | - openjdk7 5 | - oraclejdk8 6 | env: 7 | global: 8 | secure: "KncKGamS99AWFQNs2L4a3s65BdNvP07yD/fulNZA+tsBNVLgxsieXkRdzrA5Efxbd5PvnBJuLkYgjPFSFh4uPNwijH5PnZMsSYlnSFIbLyGAIkWx2cJeUoDXOOrbHIeRmCDS6gZjs9sUZHrVlhF9B/19txf4XUjpd/6slqdsEng=" # BINTRAY_API_KEY 9 | matrix: 10 | - HV_VERSION=4.3.2.Final 11 | - HV_VERSION=5.0.3.Final DEPLOY=yes 12 | - HV_VERSION=5.1.3.Final 13 | - HV_VERSION=5.2.5.Final 14 | - HV_VERSION=5.3.5.Final 15 | - HV_VERSION=5.4.1.Final 16 | 17 | # Cache local Maven repository 18 | cache: 19 | directories: 20 | - $HOME/.m2 21 | before_cache: 22 | - rm -Rf ~/.m2/repository/cz/jirutka/validator/validator-collection 23 | 24 | install: 25 | - mvn install -Ptest-different-hv-version -Dhv.version.test=${HV_VERSION} -DskipTests=true --batch-mode 26 | script: 27 | - mvn verify -Ptest-different-hv-version -Dhv.version.test=${HV_VERSION} --batch-mode 28 | after_success: 29 | - mvn jacoco:report coveralls:report 30 | 31 | deploy: 32 | provider: script 33 | script: script/travis-deploy 34 | skip_cleanup: true 35 | on: 36 | branch: master 37 | jdk: oraclejdk8 38 | condition: "$DEPLOY = yes" 39 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Bean Validation / Collection Validators 2 | :source-language: java 3 | :name: validator-collection 4 | :version: 2.2.0 5 | :artifact-id: {name} 6 | :group-id: cz.jirutka.validator 7 | :gh-name: jirutka/{name} 8 | :gh-branch: master 9 | :codacy-id: b77fcc2a16794c49a64ac0727ec274f7 10 | 11 | ifdef::env-github[] 12 | image:https://travis-ci.org/{gh-name}.svg?branch={gh-branch}[Build Status, link="https://travis-ci.org/{gh-name}"] 13 | image:https://coveralls.io/repos/github/{gh-name}/badge.svg?branch={gh-branch}[Coverage Status, link="https://coveralls.io/github/{gh-name}"] 14 | image:https://api.codacy.com/project/badge/grade/{codacy-id}[Code quality, link="https://www.codacy.com/app/{gh-name}"] 15 | image:https://maven-badges.herokuapp.com/maven-central/{group-id}/{artifact-id}/badge.svg[Maven Central, link="https://maven-badges.herokuapp.com/maven-central/{group-id}/{artifact-id}"] 16 | endif::env-github[] 17 | 18 | 19 | Neither http://beanvalidation.org/1.1/spec/[Bean Validation 1.1] (JSR 303/349) nor http://hibernate.org/validator/[Hibernate Validator], the reference _(and the only one…)_ implementation of it, provide simple way to validate a collection of basic types like String, Integer, Date… (i.e. validate each element of the collection). 20 | 21 | This library allows you to easily create a “pseudo constraint” (typically named as `@EachX`) for _any_ validation constraint to annotate a collection of simple types, without writing an extra validator or unnecessary wrapper classes for every collection. 22 | `EachX` constraint is supported for all standard Bean Validation constraints and Hibernate specific constraints. 23 | For example: 24 | 25 | [source] 26 | ---- 27 | @EachSize(min = 5, max = 255) 28 | Collection values; 29 | 30 | @EachFuture 31 | List dates; 32 | 33 | @EachEmail 34 | Set emails; 35 | ---- 36 | 37 | 38 | == How to create a custom constraint 39 | 40 | Every `@EachX` pseudo constraint uses the same validator, link:src/main/java/cz/jirutka/validator/collection/CommonEachValidator.java[CommonEachValidator]. 41 | To create an `@EachAwesome` for your own `@Awesome` constraint, just copy & paste the annotation class (i.e. all the attributes and boilerplate meta annotations), replace `@Constraint` annotation with `@Constraint(validatedBy = CommonEachValidator.class)` and add the annotation `@EachConstraint(validateAs = Awesome.class)`. 42 | That’s all! 43 | 44 | [source] 45 | ---- 46 | // common boilerplate 47 | @Documented 48 | @Retention(RUNTIME) 49 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 50 | // this is important! 51 | @EachConstraint(validateAs = Awesome.class) 52 | @Constraint(validatedBy = CommonEachValidator.class) 53 | public @interface EachAwesome { 54 | 55 | // copy&paste all attributes from Awesome annotation here 56 | String message() default ""; 57 | Class[] groups() default {}; 58 | Class[] payload() default {}; 59 | String someAttribute(); 60 | } 61 | ---- 62 | 63 | 64 | === The old way 65 | 66 | The previous versions (before 2.1.0) used a different approach to write `@EachX` annotations (see https://github.com/{gh-name}/tree/v2.0.2[here]). 67 | It is still supported for custom constraints, but all the built-in annotations has been already updated to the new style. 68 | 69 | If you’re upgrading from an older version of Collection Validators, then you must update all built-in annotations to the new style. 70 | For example: 71 | 72 | [source] 73 | @EachSize(@Size(min = 5, max = 255)) -> @EachSize(min = 5, max = 255) 74 | 75 | You _should_ also update custom annotations. 76 | The old style is still supported, but may be deprecated in the future. 77 | 78 | 79 | == Maven 80 | 81 | Released versions are available in The Central Repository. 82 | Just add this artifact to your project: 83 | 84 | [source, xml, subs="verbatim, attributes"] 85 | ---- 86 | 87 | {group-id} 88 | {artifact-id} 89 | {version} 90 | 91 | ---- 92 | 93 | However if you want to use the last snapshot version, you have to add the JFrog OSS repository: 94 | 95 | [source, xml] 96 | ---- 97 | 98 | jfrog-oss-snapshot-local 99 | JFrog OSS repository for snapshots 100 | https://oss.jfrog.org/oss-snapshot-local 101 | 102 | true 103 | 104 | 105 | ---- 106 | 107 | 108 | == Requirements 109 | 110 | http://hibernate.org/validator/[Hibernate Validator] 4.3.1.Final and newer is supported, but 5.× is recommended. 111 | 112 | Please note that on older versions some Hibernate specific constraints doesn’t exist, so their `@EachX` annotations will not work (e.g. `@EachEAN`, `@EachMod10Check`, …). 113 | It’s described in JavaDoc. 114 | 115 | 116 | === Version detection 117 | 118 | In order to support multiple versions of Hibernate Validator at a time, we attempt to determine what version is being used at runtime using the package metadata for the `HibernateValidator` class. 119 | This can sometimes fail, particularly if your project creates an “uber JAR.” 120 | If the version cannot be detected, then it fallbacks to ≥ 5.1.0. 121 | 122 | 123 | == License 124 | 125 | This project is licensed under http://opensource.org/licenses/MIT[MIT license]. 126 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 4.0.0 6 | 7 | 8 | cz.jirutka.maven 9 | groovy-parent 10 | 1.3.2 11 | 12 | 13 | 14 | 15 | 16 | cz.jirutka.validator 17 | validator-collection 18 | 2.2.0 19 | jar 20 | 21 | validator-collection 22 | Universal bean validator for collection of simple types. 23 | https://github.com/jirutka/validator-collection 24 | 2013 25 | 26 | 27 | 28 | Jakub Jirutka 29 | jakub@jirutka.cz 30 | CTU in Prague 31 | http://www.cvut.cz 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | MIT 41 | http://opensource.org/licenses/MIT 42 | 43 | 44 | 45 | 46 | https://github.com/jirutka/validator-collection 47 | scm:git:git@github.com:jirutka/validator-collection.git 48 | 49 | 50 | 51 | travis 52 | https://travis-ci.org/jirutka/validator-collection 53 | 54 | 55 | 56 | github 57 | https://github.com/jirutka/validator-collection/issues 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | javax.inject 67 | javax.inject 68 | 1 69 | 70 | 71 | 72 | 73 | org.hibernate 74 | hibernate-validator 75 | 76 | 5.4.1.Final 77 | 78 | 79 | 80 | org.apache.commons 81 | commons-lang3 82 | 3.1 83 | 84 | 85 | 86 | 87 | javax.el 88 | javax.el-api 89 | 2.2.4 90 | provided 91 | 92 | 93 | 94 | 95 | org.glassfish.web 96 | javax.el 97 | 2.2.4 98 | provided 99 | 100 | 101 | 102 | 103 | 104 | org.codehaus.groovy 105 | groovy 106 | test 107 | 108 | 109 | 110 | org.spockframework 111 | spock-core 112 | test 113 | 114 | 115 | 116 | 117 | org.jsoup 118 | jsoup 119 | 1.8.2 120 | test 121 | 122 | 123 | 124 | org.slf4j 125 | slf4j-simple 126 | ${slf4j.version} 127 | test 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 139 | 140 | test-different-hv-version 141 | 142 | 143 | 144 | 145 | ${project.build.directory}/dependency 146 | 147 | 148 | 149 | 150 | 151 | maven-dependency-plugin 152 | 153 | 154 | 155 | copy 156 | 157 | 158 | ${dependency.directory} 159 | 160 | 161 | org.hibernate 162 | hibernate-validator 163 | ${hv.version.test} 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | maven-failsafe-plugin 173 | 174 | 175 | org.hibernate:hibernate-validator 176 | 177 | 178 | ${dependency.directory}/hibernate-validator-${hv.version.test}.jar 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /script/travis-deploy: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim: set ts=4: 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [ -z "$BINTRAY_API_KEY" ]; then 8 | echo '$BINTRAY_API_KEY is not set, skipping deploy.'; exit 0 9 | fi 10 | 11 | echo '==> Deploying artifact to JFrog OSS Maven repository' 12 | mvn deploy --settings .maven-bintray.xml -Dgpg.skip=true -DskipTests=true 13 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/CommonEachValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2016 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection; 25 | 26 | import cz.jirutka.validator.collection.constraints.EachConstraint; 27 | import cz.jirutka.validator.collection.internal.ConstraintDescriptorFactory; 28 | import cz.jirutka.validator.collection.internal.MessageInterpolatorContext; 29 | import org.apache.commons.lang3.Validate; 30 | import org.apache.commons.lang3.reflect.TypeUtils; 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | 34 | import javax.inject.Inject; 35 | import javax.validation.ConstraintValidator; 36 | import javax.validation.ConstraintValidatorContext; 37 | import javax.validation.MessageInterpolator.Context; 38 | import javax.validation.Validation; 39 | import javax.validation.ValidatorFactory; 40 | import javax.validation.metadata.ConstraintDescriptor; 41 | import java.lang.annotation.Annotation; 42 | import java.lang.reflect.TypeVariable; 43 | import java.util.*; 44 | import java.util.concurrent.ConcurrentHashMap; 45 | 46 | import static cz.jirutka.validator.collection.internal.AnnotationUtils.*; 47 | import static cz.jirutka.validator.collection.internal.ConstraintValidatorContextUtils.addConstraintViolationInIterable; 48 | import static java.util.Arrays.asList; 49 | import static java.util.Collections.unmodifiableList; 50 | import static java.util.Collections.unmodifiableMap; 51 | import static org.apache.commons.lang3.StringUtils.isEmpty; 52 | 53 | /** 54 | * Common validator for collection constraints that validates each element of 55 | * the given collection. 56 | */ 57 | @SuppressWarnings("unchecked") 58 | public class CommonEachValidator implements ConstraintValidator> { 59 | 60 | private static final Logger LOG = LoggerFactory.getLogger(CommonEachValidator.class); 61 | 62 | private static final ConstraintDescriptorFactory DESCRIPTOR_FACTORY = ConstraintDescriptorFactory.newInstance(); 63 | 64 | // injected by container, or set default during initialization 65 | private @Inject ValidatorFactory factory; 66 | 67 | // after initialization it's read-only 68 | private List descriptors; 69 | 70 | // after initialization it's read-only 71 | private Map>> validators; 72 | 73 | // modifiable after initialization; must be thread-safe! 74 | private Map validatorInstances; 75 | 76 | // after initialization it's read-only 77 | private boolean earlyInterpolation; 78 | 79 | 80 | public void initialize(Annotation eachAnnotation) { 81 | 82 | Class eachAType = eachAnnotation.annotationType(); 83 | LOG.trace("Initializing CommonEachValidator for {}", eachAType); 84 | 85 | if (factory == null) { 86 | LOG.debug("No ValidatorFactory injected, building default one"); 87 | factory = Validation.buildDefaultValidatorFactory(); 88 | } 89 | validatorInstances = new ConcurrentHashMap<>(2); 90 | 91 | if (eachAType.isAnnotationPresent(EachConstraint.class)) { 92 | Class constraintClass = eachAType.getAnnotation(EachConstraint.class).validateAs(); 93 | 94 | Annotation constraint = createConstraintAndCopyAttributes(constraintClass, eachAnnotation); 95 | ConstraintDescriptor descriptor = createConstraintDescriptor(constraint); 96 | 97 | descriptors = unmodifiableList(asList(descriptor)); 98 | 99 | // legacy and deprecated, will be removed in next major version! 100 | } else if (isWrapperAnnotation(eachAType)) { 101 | Annotation[] constraints = unwrapConstraints(eachAnnotation); 102 | Validate.notEmpty(constraints, "%s annotation does not contain any constraint", eachAType); 103 | 104 | List list = new ArrayList<>(constraints.length); 105 | for (Annotation constraint : constraints) { 106 | list.add( createConstraintDescriptor(constraint) ); 107 | } 108 | descriptors = unmodifiableList(list); 109 | earlyInterpolation = true; 110 | 111 | LOG.info("You're using legacy @EachX annotation style, this will be removed soon! " + 112 | "Please update your @EachX annotations."); 113 | 114 | } else { 115 | throw new IllegalArgumentException(String.format( 116 | "%s is not annotated with @EachConstraint and doesn't declare 'value' of type Annotation[] either.", 117 | eachAType.getName())); 118 | } 119 | // constraints are always of the same type, so just pick first 120 | ConstraintDescriptor descriptor = descriptors.get(0); 121 | 122 | validators = categorizeValidatorsByType(descriptor.getConstraintValidatorClasses()); 123 | Validate.notEmpty(validators, 124 | "No validator found for constraint: %s", descriptor.getAnnotation().annotationType()); 125 | } 126 | 127 | public boolean isValid(Collection collection, ConstraintValidatorContext context) { 128 | if (collection == null || collection.isEmpty()) { 129 | return true; //nothing to validate here 130 | } 131 | context.disableDefaultConstraintViolation(); //do not add wrapper's message 132 | 133 | int index = 0; 134 | for (Iterator it = collection.iterator(); it.hasNext(); index++) { 135 | Object element = it.next(); 136 | 137 | ConstraintValidator validator = element != null 138 | ? getValidatorInstance(element.getClass()) 139 | : getAnyValidatorInstance(); 140 | 141 | for (ConstraintDescriptor descriptor : descriptors) { 142 | validator.initialize(descriptor.getAnnotation()); 143 | 144 | if (! validator.isValid(element, context)) { 145 | LOG.debug("Element [{}] = '{}' is invalid according to: {}", 146 | index, element, validator.getClass().getName()); 147 | 148 | // early interpolation hack is needed only for legacy annotations 149 | // and will go away with them 150 | String message = earlyInterpolation 151 | ? createInterpolatedMessage(descriptor, element) 152 | : readAttribute(descriptor.getAnnotation(), "message", String.class); 153 | 154 | addConstraintViolationInIterable(context, message, index); 155 | return false; 156 | } 157 | } 158 | } 159 | return true; 160 | } 161 | 162 | public void setValidatorFactory(ValidatorFactory factory) { 163 | this.factory = factory; 164 | } 165 | 166 | 167 | /** 168 | * Whether the given annotation type contains the {@code value} attribute 169 | * of the type that extends {@code Annotation[]}. 170 | */ 171 | protected boolean isWrapperAnnotation(Class annotationType) { 172 | return hasAttribute(annotationType, "value") 173 | && Annotation[].class.isAssignableFrom(getAttributeType(annotationType, "value")); 174 | } 175 | 176 | protected Annotation[] unwrapConstraints(Annotation wrapper) { 177 | return readAttribute(wrapper, "value", Annotation[].class); 178 | } 179 | 180 | protected ConstraintDescriptor createConstraintDescriptor(Annotation constraint) { 181 | return DESCRIPTOR_FACTORY.buildConstraintDescriptor(constraint); 182 | } 183 | 184 | protected > 185 | Map> categorizeValidatorsByType(List> validatorClasses) { 186 | 187 | Map> validators = new LinkedHashMap<>(10); 188 | 189 | for (Class validator : validatorClasses) { 190 | Class type = determineTargetType(validator); 191 | if (type.isArray()) continue; 192 | 193 | LOG.trace("Found validator {} for type {}", validator.getName(), type.getName()); 194 | validators.put(type, validator); 195 | } 196 | return unmodifiableMap(validators); 197 | } 198 | 199 | protected Class determineTargetType(Class> validatorClass) { 200 | TypeVariable typeVar = ConstraintValidator.class.getTypeParameters()[1]; 201 | return TypeUtils.getRawType(typeVar, validatorClass); 202 | } 203 | 204 | /** 205 | * Returns initialized validator instance for the specified object type. 206 | * Instances are cached. 207 | * 208 | * @param type Type of the object to be validated. 209 | */ 210 | protected ConstraintValidator getValidatorInstance(Class type) { 211 | ConstraintValidator validator = validatorInstances.get(type); 212 | 213 | if (validator == null) { 214 | validator = findAndInitializeValidator(type); 215 | validatorInstances.put(type, validator); 216 | } 217 | return validator; 218 | } 219 | 220 | /** 221 | * Returns initialized validator instance for any object type. This is used 222 | * when the object to be validated is null so we can't determine 223 | * it's type. Instances are cached. 224 | */ 225 | protected ConstraintValidator getAnyValidatorInstance() { 226 | 227 | if (validatorInstances.isEmpty()) { 228 | Class type = validators.keySet().iterator().next(); 229 | return findAndInitializeValidator(type); 230 | 231 | } else { 232 | return validatorInstances.values().iterator().next(); 233 | } 234 | } 235 | 236 | protected ConstraintValidator findAndInitializeValidator(Class type) { 237 | LOG.trace("Looking for validator for type: {}", type.getName()); 238 | 239 | for (Class clazz : validators.keySet()) { 240 | if (clazz.isAssignableFrom(type)) { 241 | 242 | Class validatorClass = validators.get(clazz); 243 | 244 | LOG.trace("Initializing validator: {}", validatorClass.getName()); 245 | return factory.getConstraintValidatorFactory().getInstance(validatorClass); 246 | } 247 | } 248 | throw new IllegalArgumentException("No validator found for type: " + type.getName()); 249 | } 250 | 251 | /** 252 | * Reads and interpolates an error message for the given constraint and 253 | * value. 254 | * 255 | * @param descriptor Descriptor of the constraint that the value violated. 256 | * @param value The validated value. 257 | * @return An interpolated message. 258 | */ 259 | protected String createInterpolatedMessage(ConstraintDescriptor descriptor, Object value) { 260 | Context context = new MessageInterpolatorContext(descriptor, value); 261 | 262 | Annotation constraint = descriptor.getAnnotation(); 263 | String template = readAttribute(constraint, "message", String.class); 264 | 265 | return factory.getMessageInterpolator().interpolate(template, context); 266 | } 267 | 268 | /** 269 | * Instantiates constraint of the specified type and copies values of all 270 | * the common attributes from the given source constraint (of any type) 271 | * to it. 272 | * 273 | *

If the source constraint's {@code message} is empty, then it will 274 | * not copy it (so the default {@code message} of the target 275 | * constraint will be preserved).

276 | * 277 | * @param constraintType Type of the constraint to create. 278 | * @param source Any annotation to copy attribute values from. 279 | * @return An instance of the specified constraint. 280 | */ 281 | protected T createConstraintAndCopyAttributes(Class constraintType, Annotation source) { 282 | Map attributes = readAllAttributes(source); 283 | 284 | // if message is not set, keep message from original constraint instead 285 | if (isEmpty((String) attributes.get("message"))) { 286 | attributes.remove("message"); 287 | } 288 | return createAnnotation(constraintType, attributes); 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachAssertFalse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.AssertFalse; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see AssertFalse 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = AssertFalse.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachAssertFalse { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachAssertTrue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.AssertTrue; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see AssertTrue 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = AssertTrue.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachAssertTrue { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachConstraint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import java.lang.annotation.Annotation; 27 | import java.lang.annotation.Documented; 28 | import java.lang.annotation.Retention; 29 | import java.lang.annotation.Target; 30 | 31 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 32 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 33 | 34 | /** 35 | * A meta annotation for a collection pseudo constraint validated by 36 | * {@link cz.jirutka.validator.collection.CommonEachValidator CommonEachValidator}. 37 | * It's used to specify the actual constraint annotation which validator 38 | * should be used to validate the target. 39 | */ 40 | @Documented 41 | @Retention(RUNTIME) 42 | @Target(ANNOTATION_TYPE) 43 | public @interface EachConstraint { 44 | 45 | /** 46 | * Class of the actual constraint annotation. The target collection's items 47 | * will be validated with the validator of this constraint. 48 | */ 49 | Class validateAs(); 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachCreditCardNumber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2015 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import javax.validation.Constraint; 27 | import javax.validation.OverridesAttribute; 28 | import javax.validation.Payload; 29 | import javax.validation.ReportAsSingleViolation; 30 | import java.lang.annotation.Documented; 31 | import java.lang.annotation.Retention; 32 | import java.lang.annotation.Target; 33 | 34 | import static java.lang.annotation.ElementType.*; 35 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 36 | 37 | /** 38 | * Note: Constraint {@link org.hibernate.validator.constraints.CreditCardNumber CreditCardNumber} 39 | * was available even in Hibernate Validator 4.3.1, but it was composed from now deprecated 40 | * {@link org.hibernate.validator.constraints.ModCheck ModCheck} instead of 41 | * {@link org.hibernate.validator.constraints.LuhnCheck LuhnCheck}.Therefore this annotation 42 | * doesn't work in HV older than 5.1.0. 43 | * 44 | * @since Hibernate Validator 5.1.0 45 | * @see org.hibernate.validator.constraints.CreditCardNumber 46 | */ 47 | @Documented 48 | @Retention(RUNTIME) 49 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 50 | @EachLuhnCheck 51 | @ReportAsSingleViolation 52 | @Constraint(validatedBy = { }) 53 | public @interface EachCreditCardNumber { 54 | 55 | String message() default "{org.hibernate.validator.constraints.CreditCardNumber.message}"; 56 | 57 | Class[] groups() default { }; 58 | 59 | Class[] payload() default { }; 60 | 61 | /** 62 | * @return Whether non-digit characters in the validated input should be ignored ({@code true}) or result in a 63 | * validation error ({@code false}). Default is {@code false} 64 | * 65 | * @since Hibernate Validator 5.1.2 66 | */ 67 | @OverridesAttribute(constraint = EachLuhnCheck.class, name = "ignoreNonDigitCharacters") 68 | boolean ignoreNonDigitCharacters() default false; 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachDecimalMax.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.DecimalMax; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see DecimalMax 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = DecimalMax.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachDecimalMax { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | /** 56 | * The {@code String} representation of the max value according to the 57 | * {@code BigDecimal} string representation. 58 | * 59 | * @return value the element must be lower or equal to 60 | */ 61 | String value(); 62 | 63 | /** 64 | * Specifies whether the specified maximum is inclusive or exclusive. 65 | * By default, it is inclusive. 66 | * 67 | * @return {@code true} if the value must be lower or equal to the specified maximum, 68 | * {@code false} if the value must be lower 69 | * 70 | * @since Hibernate Validator 5.0.0 71 | */ 72 | boolean inclusive() default true; 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachDecimalMin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.DecimalMin; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see DecimalMin 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = DecimalMin.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachDecimalMin { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | /** 56 | * The {@code String} representation of the min value according to the 57 | * {@code BigDecimal} string representation. 58 | * 59 | * @return value the element must be higher or equal to 60 | */ 61 | String value(); 62 | 63 | /** 64 | * Specifies whether the specified minimum is inclusive or exclusive. 65 | * By default, it is inclusive. 66 | * 67 | * @return {@code true} if the value must be higher or equal to the specified minimum, 68 | * {@code false} if the value must be higher 69 | * 70 | * @since Hibernate Validator 5.0.0 71 | */ 72 | boolean inclusive() default true; 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachDigits.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.Digits; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see Digits 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = Digits.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachDigits { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | /** 56 | * @return maximum number of integral digits accepted for this number 57 | */ 58 | int integer(); 59 | 60 | /** 61 | * @return maximum number of fractional digits accepted for this number 62 | */ 63 | int fraction(); 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachEAN.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.EAN; 28 | import org.hibernate.validator.constraints.EAN.Type; 29 | 30 | import javax.validation.Constraint; 31 | import javax.validation.Payload; 32 | import java.lang.annotation.Documented; 33 | import java.lang.annotation.Retention; 34 | import java.lang.annotation.Target; 35 | 36 | import static java.lang.annotation.ElementType.*; 37 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 38 | 39 | /** 40 | * @since Hibernate Validator 5.1.0 41 | * @see EAN 42 | * @see CommonEachValidator 43 | */ 44 | @Documented 45 | @Retention(RUNTIME) 46 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 47 | @EachConstraint(validateAs = EAN.class) 48 | @Constraint(validatedBy = CommonEachValidator.class) 49 | public @interface EachEAN { 50 | 51 | String message() default ""; 52 | 53 | Class[] groups() default { }; 54 | 55 | Class[] payload() default { }; 56 | 57 | Type type() default Type.EAN13; 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachEmail.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.Email; 28 | 29 | import javax.validation.Constraint; 30 | import javax.validation.Payload; 31 | import javax.validation.constraints.Pattern; 32 | import java.lang.annotation.Documented; 33 | import java.lang.annotation.Retention; 34 | import java.lang.annotation.Target; 35 | 36 | import static java.lang.annotation.ElementType.*; 37 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 38 | 39 | /** 40 | * @see Email 41 | * @see CommonEachValidator 42 | */ 43 | @Documented 44 | @Retention(RUNTIME) 45 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 46 | @EachConstraint(validateAs = Email.class) 47 | @Constraint(validatedBy = CommonEachValidator.class) 48 | public @interface EachEmail { 49 | 50 | String message() default ""; 51 | 52 | Class[] groups() default { }; 53 | 54 | Class[] payload() default { }; 55 | 56 | /** 57 | * @return an additional regular expression the annotated string must match. The default is any string ('.*') 58 | */ 59 | String regexp() default ".*"; 60 | 61 | /** 62 | * @return used in combination with {@link #regexp()} in order to specify a regular expression option 63 | */ 64 | Pattern.Flag[] flags() default { }; 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachFuture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.Future; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see Future 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = Future.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachFuture { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachLength.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.Length; 28 | 29 | import javax.validation.Constraint; 30 | import javax.validation.Payload; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see Length 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = Length.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachLength { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | int min() default 0; 56 | 57 | int max() default Integer.MAX_VALUE; 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachLuhnCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.LuhnCheck; 28 | 29 | import javax.validation.Constraint; 30 | import javax.validation.Payload; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @since Hibernate Validator 5.1.0 40 | * @see LuhnCheck 41 | * @see CommonEachValidator 42 | */ 43 | @Documented 44 | @Retention(RUNTIME) 45 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 46 | @EachConstraint(validateAs = LuhnCheck.class) 47 | @Constraint(validatedBy = CommonEachValidator.class) 48 | public @interface EachLuhnCheck { 49 | 50 | String message() default ""; 51 | 52 | Class[] groups() default { }; 53 | 54 | Class[] payload() default { }; 55 | 56 | /** 57 | * @return the start index (inclusive) for calculating the checksum. If not specified 0 is assumed. 58 | */ 59 | int startIndex() default 0; 60 | 61 | /** 62 | * @return the end index (inclusive) for calculating the checksum. If not specified the whole value is considered. 63 | */ 64 | int endIndex() default Integer.MAX_VALUE; 65 | 66 | /** 67 | * @return The index of the check digit in the input. Per default it is assumed that the check digit is the last 68 | * digit of the specified range. If set, the digit at the specified index is used. If set 69 | * the following must hold true: 70 | * {@code checkDigitIndex > 0 && (checkDigitIndex < startIndex || checkDigitIndex >= endIndex}. 71 | */ 72 | int checkDigitIndex() default -1; 73 | 74 | /** 75 | * @return Whether non-digit characters in the validated input should be ignored ({@code true}) or result in a 76 | * validation error ({@code false}). 77 | */ 78 | boolean ignoreNonDigitCharacters() default true; 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachMax.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.Max; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see Max 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = Max.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachMax { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | /** 56 | * @return value the element must be lower or equal to 57 | */ 58 | long value(); 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachMin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.Min; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see Min 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = Min.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachMin { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | /** 56 | * @return value the element must be higher or equal to 57 | */ 58 | long value(); 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachMod10Check.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.Mod10Check; 28 | 29 | import javax.validation.Constraint; 30 | import javax.validation.Payload; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @since Hibernate Validator 5.1.0 40 | * @see Mod10Check 41 | * @see CommonEachValidator 42 | */ 43 | @Documented 44 | @Retention(RUNTIME) 45 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 46 | @EachConstraint(validateAs = Mod10Check.class) 47 | @Constraint(validatedBy = CommonEachValidator.class) 48 | public @interface EachMod10Check { 49 | 50 | String message() default ""; 51 | 52 | Class[] groups() default { }; 53 | 54 | Class[] payload() default { }; 55 | 56 | /** 57 | * @return The multiplier to be used for odd digits when calculating the Mod10 checksum. 58 | */ 59 | int multiplier() default 3; 60 | 61 | /** 62 | * @return The weight to be used for even digits when calculating the Mod10 checksum. 63 | */ 64 | int weight() default 1; 65 | 66 | /** 67 | * @return the start index (inclusive) for calculating the checksum. If not specified 0 is assumed. 68 | */ 69 | int startIndex() default 0; 70 | 71 | /** 72 | * @return the end index (inclusive) for calculating the checksum. If not specified the whole value is considered. 73 | */ 74 | int endIndex() default Integer.MAX_VALUE; 75 | 76 | /** 77 | * @return The index of the check digit in the input. Per default it is assumed that the check digit is the last 78 | * digit of the specified range. If set, the digit at the specified index is used. If set 79 | * the following must hold true:
80 | * {@code checkDigitIndex > 0 && (checkDigitIndex < startIndex || checkDigitIndex >= endIndex}. 81 | */ 82 | int checkDigitIndex() default -1; 83 | 84 | /** 85 | * @return Whether non-digit characters in the validated input should be ignored ({@code true}) or result in a 86 | * validation error ({@code false}). 87 | */ 88 | boolean ignoreNonDigitCharacters() default true; 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachMod11Check.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.Mod11Check; 28 | import org.hibernate.validator.constraints.Mod11Check.ProcessingDirection; 29 | 30 | import javax.validation.Constraint; 31 | import javax.validation.Payload; 32 | import java.lang.annotation.Documented; 33 | import java.lang.annotation.Retention; 34 | import java.lang.annotation.Target; 35 | 36 | import static java.lang.annotation.ElementType.*; 37 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 38 | 39 | /** 40 | * @since Hibernate Validator 5.1.0 41 | * @see Mod11Check 42 | * @see CommonEachValidator 43 | */ 44 | @Documented 45 | @Retention(RUNTIME) 46 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 47 | @EachConstraint(validateAs = Mod11Check.class) 48 | @Constraint(validatedBy = CommonEachValidator.class) 49 | public @interface EachMod11Check { 50 | 51 | String message() default ""; 52 | 53 | Class[] groups() default { }; 54 | 55 | Class[] payload() default { }; 56 | 57 | /** 58 | * @return The threshold for the Mod11 algorithm multiplier growth, if no value is specified the multiplier will grow indefinitely 59 | */ 60 | int threshold() default Integer.MAX_VALUE; 61 | 62 | /** 63 | * @return the start index (inclusive) for calculating the checksum. If not specified 0 is assumed. 64 | */ 65 | int startIndex() default 0; 66 | 67 | /** 68 | * @return the end index (inclusive) for calculating the checksum. If not specified the whole value is considered 69 | */ 70 | int endIndex() default Integer.MAX_VALUE; 71 | 72 | /** 73 | * @return The index of the check digit in the input. Per default it is assumed that the check digit is the last 74 | * digit of the specified range. If set, the digit at the specified index is used. If set 75 | * the following must hold true:
76 | * {@code checkDigitIndex > 0 && (checkDigitIndex < startIndex || checkDigitIndex >= endIndex}. 77 | */ 78 | int checkDigitIndex() default -1; 79 | 80 | /** 81 | * @return Whether non-digit characters in the validated input should be ignored ({@code true}) or result in a 82 | * validation error ({@code false}). 83 | */ 84 | boolean ignoreNonDigitCharacters() default false; 85 | 86 | /** 87 | * @return The {@code char} that represents the check digit when the Mod11 88 | * checksum equals 10. If not specified {@code 'X'} is assumed. 89 | */ 90 | char treatCheck10As() default 'X'; 91 | 92 | /** 93 | * @return The {@code char} that represents the check digit when the Mod11 94 | * checksum equals 11. If not specified {@code '0'} is assumed. 95 | */ 96 | char treatCheck11As() default '0'; 97 | 98 | /** 99 | * @return Returns {@code RIGHT_TO_LEFT} if the Mod11 checksum must be done from the rightmost to the leftmost digit. 100 | * e.g. Code 12345-?: 101 | *
    102 | *
  • {@code RIGHT_TO_LEFT} the sum (5*2 + 4*3 + 3*4 + 2*5 + 1*6) with check digit 5
  • 103 | *
  • {@code LEFT_TO_RIGHT} the sum (1*2 + 2*3 + 3*4 + 4*5 + 5*6) with check digit 7
  • 104 | *
105 | * If not specified {@code RIGHT_TO_LEFT} is assumed, it is the default Mod11 behavior. 106 | */ 107 | ProcessingDirection processingDirection() default ProcessingDirection.RIGHT_TO_LEFT; 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachNotBlank.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.NotBlank; 28 | 29 | import javax.validation.Constraint; 30 | import javax.validation.Payload; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see NotBlank 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = NotBlank.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachNotBlank { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachNotEmpty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2015 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import javax.validation.Constraint; 27 | import javax.validation.Payload; 28 | import javax.validation.ReportAsSingleViolation; 29 | import java.lang.annotation.Documented; 30 | import java.lang.annotation.Retention; 31 | import java.lang.annotation.Target; 32 | 33 | import static java.lang.annotation.ElementType.*; 34 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 35 | 36 | /** 37 | * @see org.hibernate.validator.constraints.NotEmpty 38 | */ 39 | @Documented 40 | @Retention(RUNTIME) 41 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 42 | @EachNotNull 43 | @EachSize(min = 1) 44 | @ReportAsSingleViolation 45 | @Constraint(validatedBy = { }) 46 | public @interface EachNotEmpty { 47 | 48 | String message() default "{org.hibernate.validator.constraints.NotEmpty.message}"; 49 | 50 | Class[] groups() default { }; 51 | 52 | Class[] payload() default { }; 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachNotNull.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.NotNull; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see NotNull 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = NotNull.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachNotNull { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachPast.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.Past; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see Past 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = Past.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachPast { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.Pattern; 31 | import javax.validation.constraints.Pattern.Flag; 32 | import java.lang.annotation.Documented; 33 | import java.lang.annotation.Retention; 34 | import java.lang.annotation.Target; 35 | 36 | import static java.lang.annotation.ElementType.*; 37 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 38 | 39 | /** 40 | * @see Pattern 41 | * @see CommonEachValidator 42 | */ 43 | @Documented 44 | @Retention(RUNTIME) 45 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 46 | @EachConstraint(validateAs = Pattern.class) 47 | @Constraint(validatedBy = CommonEachValidator.class) 48 | public @interface EachPattern { 49 | 50 | /** 51 | * @return the regular expression to match 52 | */ 53 | String regexp(); 54 | 55 | /** 56 | * @return array of {@code Flag}s considered when resolving the regular expression 57 | */ 58 | Flag[] flags() default { }; 59 | 60 | /** 61 | * @return the error message template 62 | */ 63 | String message() default ""; 64 | 65 | /** 66 | * @return the groups the constraint belongs to 67 | */ 68 | Class[] groups() default { }; 69 | 70 | /** 71 | * @return the payload associated to the constraint 72 | */ 73 | Class[] payload() default { }; 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachRange.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2015 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import javax.validation.Constraint; 27 | import javax.validation.OverridesAttribute; 28 | import javax.validation.Payload; 29 | import javax.validation.ReportAsSingleViolation; 30 | import java.lang.annotation.Documented; 31 | import java.lang.annotation.Retention; 32 | import java.lang.annotation.Target; 33 | 34 | import static java.lang.annotation.ElementType.*; 35 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 36 | 37 | /** 38 | * @see org.hibernate.validator.constraints.Range 39 | */ 40 | @Documented 41 | @Retention(RUNTIME) 42 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 43 | @EachMin(0) 44 | @EachMax(Long.MAX_VALUE) 45 | @ReportAsSingleViolation 46 | @Constraint(validatedBy = { }) 47 | public @interface EachRange { 48 | 49 | String message() default "{org.hibernate.validator.constraints.Range.message}"; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | @OverridesAttribute(constraint = EachMin.class, name = "value") long min() default 0; 56 | 57 | @OverridesAttribute(constraint = EachMax.class, name = "value") long max() default Long.MAX_VALUE; 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachSafeHtml.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.SafeHtml; 28 | import org.hibernate.validator.constraints.SafeHtml.Tag; 29 | import org.hibernate.validator.constraints.SafeHtml.WhiteListType; 30 | 31 | import javax.validation.Constraint; 32 | import javax.validation.Payload; 33 | import java.lang.annotation.Documented; 34 | import java.lang.annotation.Retention; 35 | import java.lang.annotation.Target; 36 | 37 | import static java.lang.annotation.ElementType.*; 38 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 39 | import static org.hibernate.validator.constraints.SafeHtml.WhiteListType.RELAXED; 40 | 41 | /** 42 | * @see SafeHtml 43 | * @see CommonEachValidator 44 | */ 45 | @Documented 46 | @Retention(RUNTIME) 47 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 48 | @EachConstraint(validateAs = SafeHtml.class) 49 | @Constraint(validatedBy = CommonEachValidator.class) 50 | public @interface EachSafeHtml { 51 | 52 | String message() default ""; 53 | 54 | Class[] groups() default { }; 55 | 56 | Class[] payload() default { }; 57 | 58 | /** 59 | * @return The built-in whitelist type which will be applied to the rich text value 60 | */ 61 | WhiteListType whitelistType() default RELAXED; 62 | 63 | /** 64 | * @return Additional whitelist tags which are allowed on top of the tags specified by the 65 | * {@link #whitelistType()}. 66 | */ 67 | String[] additionalTags() default { }; 68 | 69 | /** 70 | * @return Allows to specify additional whitelist tags with optional attributes. 71 | * @since Hibernate Validator 5.1.0 72 | */ 73 | Tag[] additionalTagsWithAttributes() default { }; 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachScriptAssert.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.ScriptAssert; 28 | 29 | import javax.validation.Constraint; 30 | import javax.validation.Payload; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see ScriptAssert 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = ScriptAssert.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachScriptAssert { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | /** 56 | * @return The name of the script language used by this constraint as 57 | * expected by the JSR 223 {@link javax.script.ScriptEngineManager}. A 58 | * {@link javax.validation.ConstraintDeclarationException} will be thrown upon script 59 | * evaluation, if no engine for the given language could be found. 60 | */ 61 | String lang(); 62 | 63 | /** 64 | * @return The script to be executed. The script must return 65 | * Boolean.TRUE, if the annotated element could 66 | * successfully be validated, otherwise Boolean.FALSE. 67 | * Returning null or any type other than Boolean will cause a 68 | * {@link javax.validation.ConstraintDeclarationException} upon validation. Any 69 | * exception occurring during script evaluation will be wrapped into 70 | * a ConstraintDeclarationException, too. Within the script, the 71 | * validated object can be accessed from the {@link javax.script.ScriptContext 72 | * script context} using the name specified in the 73 | * alias attribute. 74 | */ 75 | String script(); 76 | 77 | /** 78 | * @return The name, under which the annotated element shall be registered 79 | * within the script context. Defaults to "_this". 80 | */ 81 | String alias() default "_this"; 82 | 83 | /** 84 | * @return The name of the property for which you would like to report a validation error. 85 | * If given, the resulting constraint violation will be reported on the specified property. 86 | * If not given, the constraint violation will be reported on the annotated bean. 87 | * 88 | * @since Hibernate Validator 5.4.0 89 | */ 90 | String reportOn() default ""; 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachSize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.Size; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | /** 39 | * @see Size 40 | * @see CommonEachValidator 41 | */ 42 | @Documented 43 | @Retention(RUNTIME) 44 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 45 | @EachConstraint(validateAs = Size.class) 46 | @Constraint(validatedBy = CommonEachValidator.class) 47 | public @interface EachSize { 48 | 49 | String message() default ""; 50 | 51 | Class[] groups() default { }; 52 | 53 | Class[] payload() default { }; 54 | 55 | /** 56 | * @return size the element must be higher or equal to 57 | */ 58 | int min() default 0; 59 | 60 | /** 61 | * @return size the element must be lower or equal to 62 | */ 63 | int max() default Integer.MAX_VALUE; 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/constraints/EachURL.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | import org.hibernate.validator.constraints.URL; 28 | 29 | import javax.validation.Constraint; 30 | import javax.validation.Payload; 31 | import javax.validation.constraints.Pattern; 32 | import java.lang.annotation.Documented; 33 | import java.lang.annotation.Retention; 34 | import java.lang.annotation.Target; 35 | 36 | import static java.lang.annotation.ElementType.*; 37 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 38 | 39 | /** 40 | * @see URL 41 | * @see CommonEachValidator 42 | */ 43 | @Documented 44 | @Retention(RUNTIME) 45 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 46 | @EachConstraint(validateAs = URL.class) 47 | @Constraint(validatedBy = CommonEachValidator.class) 48 | public @interface EachURL { 49 | 50 | String message() default ""; 51 | 52 | Class[] groups() default { }; 53 | 54 | Class[] payload() default { }; 55 | 56 | /** 57 | * @return the protocol (scheme) the annotated string must match, eg ftp or http. 58 | * Per default any protocol is allowed 59 | */ 60 | String protocol() default ""; 61 | 62 | /** 63 | * @return the host the annotated string must match, eg localhost. Per default any host is allowed 64 | */ 65 | String host() default ""; 66 | 67 | /** 68 | * @return the port the annotated string must match, eg 80. Per default any port is allowed 69 | */ 70 | int port() default -1; 71 | 72 | /** 73 | * @return an additional regular expression the annotated URL must match. The default is any string ('.*') 74 | */ 75 | String regexp() default ".*"; 76 | 77 | /** 78 | * @return used in combination with {@link #regexp()} in order to specify a regular expression option 79 | */ 80 | Pattern.Flag[] flags() default { }; 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/internal/AnnotationUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2016 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.internal; 25 | 26 | import org.apache.commons.lang3.Validate; 27 | import org.hibernate.validator.internal.util.annotationfactory.AnnotationDescriptor; 28 | import org.hibernate.validator.internal.util.annotationfactory.AnnotationFactory; 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | import java.lang.annotation.Annotation; 33 | import java.lang.reflect.InvocationTargetException; 34 | import java.lang.reflect.Method; 35 | import java.util.HashMap; 36 | import java.util.Iterator; 37 | import java.util.Map; 38 | 39 | import static org.apache.commons.lang3.ClassUtils.isAssignable; 40 | 41 | public abstract class AnnotationUtils { 42 | 43 | private static final Logger LOG = LoggerFactory.getLogger(AnnotationUtils.class); 44 | 45 | @SuppressWarnings("unchecked") 46 | public static T readAttribute(Annotation annotation, String name, Class requiredType) 47 | throws IllegalArgumentException, IllegalStateException { 48 | 49 | Object result = AnnotationUtils.invokeNonArgMethod(annotation, name); 50 | 51 | Validate.isInstanceOf(requiredType, result, 52 | "Method %s should return instance of %s", name, requiredType.getSimpleName()); 53 | 54 | return (T) result; 55 | } 56 | 57 | /** 58 | * Whether the annotation type contains attribute of the specified name. 59 | */ 60 | public static boolean hasAttribute(Class annotationType, String attributeName) { 61 | 62 | for (Method m : annotationType.getDeclaredMethods()) { 63 | if (m.getName().equals(attributeName)) { 64 | return true; 65 | } 66 | } 67 | return false; 68 | } 69 | 70 | /** 71 | * Returns type of the specified attribute in the annotation type. 72 | */ 73 | public static Class getAttributeType(Class annotationType, String attributeName) { 74 | try { 75 | return annotationType.getDeclaredMethod(attributeName).getReturnType(); 76 | 77 | } catch (NoSuchMethodException ex) { 78 | throw new IllegalArgumentException(String.format( 79 | "No such attribute %s in %s", attributeName, annotationType.getName()), ex); 80 | } 81 | } 82 | 83 | /** 84 | * Returns annotation's attributes (name and value) as map. 85 | */ 86 | public static Map readAllAttributes(Annotation annotation) { 87 | Map attributes = new HashMap<>(); 88 | 89 | for (Method method : annotation.annotationType().getDeclaredMethods()) { 90 | try { 91 | Object value = method.invoke(annotation); 92 | attributes.put(method.getName(), value); 93 | 94 | } catch (IllegalAccessException | InvocationTargetException ex) { 95 | throw new IllegalStateException(ex); 96 | } 97 | } 98 | return attributes; 99 | } 100 | 101 | /** 102 | * Creates instance (proxy) of the specified annotation with the given 103 | * attributes. 104 | * 105 | * @param annotationType The annotation's class. 106 | * @param attributes A map with attribute values for the annotation to be created. 107 | * @param The type of the annotation. 108 | * 109 | * @return An instance of the annotation. 110 | * @throws IllegalArgumentException if some attribute has wrong type or 111 | * a required attribute is missing. 112 | */ 113 | public static T createAnnotation(Class annotationType, Map attributes) { 114 | 115 | // check if given attributes are defined in annotation 116 | for (Iterator it = attributes.keySet().iterator(); it.hasNext(); ) { 117 | String name = it.next(); 118 | Object value = attributes.get(name); 119 | 120 | if (value == null) { 121 | LOG.warn("Attribute's value must not be null; will be ignored"); 122 | it.remove(); 123 | continue; 124 | } 125 | if (!hasAttribute(annotationType, name)) { 126 | LOG.warn("Annotation {} does not define attribute: {}; will be ignored", 127 | annotationType.getName(), name); 128 | it.remove(); 129 | continue; 130 | } 131 | Class attrType = getAttributeType(annotationType, name); 132 | 133 | Validate.isTrue(isAssignable(value.getClass(), attrType), 134 | "Attribute '%s' expects %s, but given: %s (%s)", 135 | name, attrType.getName(), value, value.getClass().getName()); 136 | } 137 | // check if required attributes are given 138 | for (Method m : annotationType.getDeclaredMethods()) { 139 | Validate.isTrue(attributes.containsKey(m.getName()) || m.getDefaultValue() != null, 140 | "Missing required attribute: %s", m.getName()); 141 | } 142 | 143 | AnnotationDescriptor descriptor = AnnotationDescriptor.getInstance(annotationType, attributes); 144 | 145 | return AnnotationFactory.create(descriptor); 146 | } 147 | 148 | 149 | private static Object invokeNonArgMethod(Object object, String methodName) { 150 | Class clazz = object.getClass(); 151 | 152 | try { 153 | return clazz.getMethod(methodName).invoke(object); 154 | 155 | } catch (NoSuchMethodException ex) { 156 | throw new IllegalArgumentException( 157 | String.format("Class should declare method %s()", methodName), ex); 158 | 159 | } catch (InvocationTargetException | IllegalAccessException ex) { 160 | throw new IllegalStateException(ex); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/internal/ConstraintDescriptorFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.internal; 25 | 26 | import org.hibernate.validator.internal.metadata.core.ConstraintHelper; 27 | import org.hibernate.validator.internal.metadata.core.ConstraintOrigin; 28 | import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; 29 | 30 | import javax.validation.metadata.ConstraintDescriptor; 31 | import java.lang.annotation.Annotation; 32 | import java.lang.annotation.ElementType; 33 | import java.lang.reflect.Constructor; 34 | import java.lang.reflect.Member; 35 | 36 | /** 37 | * Factory that builds instances of {@link ConstraintDescriptorImpl}. 38 | * 39 | *

This is a workaround to support multiple versions of Hibernate Validator; 40 | * 4.3.0 and greater. The problem is that {@code ConstraintDescriptorImpl} is 41 | * internal class of the Hibernate Validator and its constructor's signature 42 | * has been several times changed between major versions. The class implements 43 | * public interface {@link ConstraintDescriptor}, but its implementation is 44 | * pretty complex (547 LOC), it seems that it can't be reimplemented simpler 45 | * and I hate code copy&pasting...

46 | */ 47 | public abstract class ConstraintDescriptorFactory { 48 | 49 | private static final ConstraintHelper CONSTRAINT_HELPER = new ConstraintHelper(); 50 | 51 | protected final Constructor constructor; 52 | 53 | 54 | private ConstraintDescriptorFactory() { 55 | try { 56 | this.constructor = ConstraintDescriptorImpl.class.getConstructor(getConstructorArguments()); 57 | } catch (NoSuchMethodException ex) { 58 | throw new IllegalStateException(ex); 59 | } 60 | } 61 | 62 | /** 63 | * Creates a new instance of factory for the version of Hibernate Validator 64 | * detected on classpath. 65 | */ 66 | public static ConstraintDescriptorFactory newInstance() { 67 | 68 | int version = HibernateValidatorInfo.getVersion(); 69 | 70 | if (version >= 5_1_0) { 71 | return new ConstraintDescriptorFactory() { 72 | Class[] getConstructorArguments() { 73 | return new Class[]{ ConstraintHelper.class, Member.class, Annotation.class, ElementType.class }; 74 | } 75 | ConstraintDescriptorImpl newInstance(Annotation annotation) throws ReflectiveOperationException { 76 | return constructor.newInstance(CONSTRAINT_HELPER, null, annotation, ElementType.LOCAL_VARIABLE); 77 | } 78 | }; 79 | } else if (version >= 5_0_0) { 80 | return new ConstraintDescriptorFactory() { 81 | Class[] getConstructorArguments() { 82 | return new Class[]{ Annotation.class, ConstraintHelper.class, Class.class, 83 | ElementType.class, ConstraintOrigin.class, Member.class }; 84 | } 85 | ConstraintDescriptorImpl newInstance(Annotation annotation) throws ReflectiveOperationException { 86 | return constructor.newInstance(annotation, CONSTRAINT_HELPER, null, ElementType.LOCAL_VARIABLE, 87 | ConstraintOrigin.DEFINED_LOCALLY, null); 88 | } 89 | }; 90 | } else if (version >= 4_3_0) { 91 | return new ConstraintDescriptorFactory() { 92 | Class[] getConstructorArguments() { 93 | return new Class[]{ Annotation.class, ConstraintHelper.class, Class.class, 94 | ElementType.class, ConstraintOrigin.class }; 95 | } 96 | ConstraintDescriptorImpl newInstance(Annotation annotation) throws ReflectiveOperationException { 97 | return constructor.newInstance(annotation, CONSTRAINT_HELPER, null, ElementType.LOCAL_VARIABLE, 98 | ConstraintOrigin.DEFINED_LOCALLY); 99 | } 100 | }; 101 | } else { 102 | throw new UnsupportedVersionException("Hibernate Validator older then 4.3.0 is not supported"); 103 | } 104 | } 105 | 106 | /** 107 | * @param annotation The constraint annotation. 108 | * @return An instance of {@link ConstraintDescriptorImpl} for the given 109 | * constraint. 110 | */ 111 | @SuppressWarnings("unchecked") 112 | public ConstraintDescriptor buildConstraintDescriptor(T annotation) { 113 | try { 114 | return newInstance(annotation); 115 | 116 | } catch (ReflectiveOperationException ex) { 117 | throw new IllegalStateException(ex); 118 | } 119 | } 120 | 121 | //////// Abstract methods //////// 122 | 123 | abstract ConstraintDescriptorImpl newInstance(Annotation annotation) throws ReflectiveOperationException; 124 | 125 | abstract Class[] getConstructorArguments(); 126 | 127 | 128 | 129 | //////// Inner classes //////// 130 | 131 | public static class UnsupportedVersionException extends IllegalStateException { 132 | 133 | public UnsupportedVersionException(String message) { 134 | super(message); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/internal/ConstraintValidatorContextUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2016 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.internal; 25 | 26 | import javax.validation.ConstraintValidatorContext; 27 | 28 | public abstract class ConstraintValidatorContextUtils { 29 | 30 | private static final int HV_VERSION = HibernateValidatorInfo.getVersion(); 31 | 32 | /** 33 | * Builds and adds a constraint violation inside an iterable value to the 34 | * given {@code ConstraintValidatorContext}. If running with Hibernate 35 | * Validator 5.x, then it also registers index of the violated value. 36 | * 37 | * @param context The Constraint validator context. 38 | * @param message The interpolated error message. 39 | * @param index Index of the invalid value inside a list (ignored on HV 4.x). 40 | */ 41 | public static void addConstraintViolationInIterable(ConstraintValidatorContext context, String message, int index) { 42 | if (HV_VERSION >= 5_0_0) { 43 | context.buildConstraintViolationWithTemplate(message) 44 | .addBeanNode() 45 | .inIterable() 46 | .atIndex(index) 47 | .addConstraintViolation(); 48 | } else { 49 | context.buildConstraintViolationWithTemplate(message) 50 | .addConstraintViolation(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/internal/HibernateValidatorInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.internal; 25 | 26 | import org.hibernate.validator.HibernateValidator; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | import static java.lang.Integer.parseInt; 31 | import static org.apache.commons.lang3.StringUtils.isNotEmpty; 32 | 33 | public abstract class HibernateValidatorInfo { 34 | 35 | private static final Logger LOG = LoggerFactory.getLogger(HibernateValidatorInfo.class); 36 | 37 | /** 38 | * Returns version of the Hibernate Validator determined from the package 39 | * info on classpath. 40 | * 41 | *

Version number is parsed as: 5.1.1.Final -> 511, 5.2.0-SNAPSHOT -> 520.

42 | * 43 | * @return A parsed version number, or {@link Integer#MAX_VALUE} if could not be determined. 44 | */ 45 | public static int getVersion() { 46 | 47 | Package pkg = HibernateValidator.class.getPackage(); 48 | 49 | if (pkg != null) { 50 | String version = pkg.getImplementationVersion(); 51 | String title = pkg.getImplementationTitle(); 52 | 53 | if (isNotEmpty(version) && "hibernate-validator".equals(title)) { 54 | LOG.info("Found Hibernate Validator {}", version); 55 | return parseVersion(version); 56 | } 57 | } 58 | LOG.warn("Could not determine Hibernate Validator version"); 59 | return Integer.MAX_VALUE; 60 | } 61 | 62 | static int parseVersion(String version) { 63 | String[] tokens = version.split("[.-]"); 64 | 65 | return parseInt(tokens[0]) * 100 66 | + parseInt(tokens[1]) * 10 67 | + parseInt(tokens[2]); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/cz/jirutka/validator/collection/internal/MessageInterpolatorContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.internal; 25 | 26 | import org.apache.commons.lang3.builder.EqualsBuilder; 27 | import org.apache.commons.lang3.builder.HashCodeBuilder; 28 | 29 | import javax.validation.MessageInterpolator; 30 | import javax.validation.metadata.ConstraintDescriptor; 31 | 32 | public class MessageInterpolatorContext implements MessageInterpolator.Context { 33 | 34 | private final ConstraintDescriptor constraintDescriptor; 35 | 36 | private final Object validatedValue; 37 | 38 | 39 | public MessageInterpolatorContext(ConstraintDescriptor constraintDescriptor, Object validatedValue) { 40 | this.constraintDescriptor = constraintDescriptor; 41 | this.validatedValue = validatedValue; 42 | } 43 | 44 | 45 | public ConstraintDescriptor getConstraintDescriptor() { 46 | return constraintDescriptor; 47 | } 48 | 49 | public Object getValidatedValue() { 50 | return validatedValue; 51 | } 52 | 53 | public T unwrap(Class type) { 54 | throw new UnsupportedOperationException("Not implemented"); 55 | } 56 | 57 | @Override 58 | public boolean equals(Object obj) { 59 | // this is normally not called, so use just brief reflection method 60 | return EqualsBuilder.reflectionEquals(this, obj); 61 | } 62 | 63 | @Override 64 | public int hashCode() { 65 | // this is normally not called, so use just brief reflection method 66 | return HashCodeBuilder.reflectionHashCode(this); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/groovy/cz/jirutka/validator/collection/CommonEachValidatorIT.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2015 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection 25 | 26 | import cz.jirutka.validator.collection.internal.HibernateValidatorInfo 27 | import spock.lang.Ignore 28 | import spock.lang.Issue 29 | import spock.lang.Specification 30 | import spock.lang.Unroll 31 | 32 | import static cz.jirutka.validator.collection.TestUtils.evalClassWithConstraint 33 | import static cz.jirutka.validator.collection.TestUtils.validate 34 | 35 | @Unroll 36 | class CommonEachValidatorIT extends Specification { 37 | 38 | static HV_VERSION = HibernateValidatorInfo.getVersion() 39 | 40 | def constraint = null 41 | 42 | 43 | def 'validate @EachX for common constraint [ #desc ]'() { 44 | given: 45 | constraint = '@EachSize(min=2, max=6)' 46 | expect: 47 | assertViolations values, isValid, invalidIndex, 'size must be between 2 and 6' 48 | where: 49 | values | desc || isValid | invalidIndex 50 | ['f', 'ab'] | 'first value invalid' || false | 0 51 | ['ab', ''] | 'last value invalid' || false | 1 52 | ['foo'] | 'valid value' || true | null 53 | ['ab', 'cd'] | 'valid values' || true | null 54 | [null, 'ab'] | 'valid values with null' || true | null 55 | [] | 'empty list' || true | null 56 | null | 'null' || true | null 57 | } 58 | 59 | def 'validate composite constraint with two @EachX [ #desc ]'() { 60 | given: 61 | constraint = '@EachComposite' 62 | expect: 63 | assertViolations values, isValid, invalidIndex, message 64 | where: 65 | values | desc || isValid | invalidIndex | message 66 | ['f'] | 'value invalid by first cons.' || false | 0 | 'size must be between 2 and 8' 67 | ['foo', '132'] | 'value invalid by second cons.' || false | 1 | 'must contain a-z only' 68 | ['ab', 'cd'] | 'valid values' || true | null | null 69 | } 70 | 71 | def 'validate @EachX for constraint that validates nulls [ #desc ]'() { 72 | given: 73 | constraint = '@EachNotNull' 74 | expect: 75 | assertViolations values, isValid, 1, 'may not be null' 76 | where: 77 | values | desc || isValid 78 | ['a', null] | 'a null value' || false 79 | ['a', 'b'] | 'not null values' || true 80 | } 81 | 82 | @Ignore('should be fixed!') @Issue('#8') 83 | def 'validate @EachX for pure composite constraint [ #desc ]'() { 84 | given: 85 | constraint = '@EachRange(min=16L, max=64L)' 86 | expect: 87 | assertViolations values, isValid, 0, 'must be between 16 and 64' 88 | where: 89 | values | desc || isValid 90 | [6] | 'invalid value' || false 91 | [42] | 'valid value' || true 92 | } 93 | 94 | @Ignore('should be fixed!') @Issue('#8') 95 | def 'validate @EachX for half-composite constraint [ #desc ]'() { 96 | given: 97 | constraint = '@EachNotBlank' 98 | expect: 99 | assertViolations values, isValid, invalidIndex, 'may not be empty' 100 | where: 101 | values | desc || isValid | invalidIndex 102 | [''] | 'value invalid by top validator' || false | 0 103 | ['foo', null] | 'value invalid by composite cons.' || false | 1 104 | ['allons-y!'] | 'valid value' || true | null 105 | } 106 | 107 | @Ignore('should be fixed!') @Issue('#8') 108 | def 'validate @EachX for constraint that uses @OverridesAttribute [ #desc value ]'() { 109 | given: 110 | constraint = '@EachURL(protocol="https", regexp=".*[^x]$")' 111 | expect: 112 | assertViolations values, isValid, 0, 'must be a valid URL' 113 | where: 114 | values | desc || isValid 115 | ['http://fit.cvut.cz'] | "invalid normal attribute's" || false 116 | ['https://fit.cvut.cx'] | "invalid overrided attribute's" || false 117 | ['https://fit.cvut.cz'] | 'valid' || true 118 | } 119 | 120 | def 'validate @EachX with custom message template'() { 121 | given: 122 | constraint = '@EachURL(protocol="https", message="must be a valid URL with {protocol}")' 123 | expect: 124 | assertViolations(['http://fit.cvut.cz'], false, 0, 'must be a valid URL with https') 125 | } 126 | 127 | def 'validate legacy @EachX constraint [ #desc ]'() { 128 | given: 129 | constraint = '@LegacyEachSize(@Size(min=2, max=6))' 130 | expect: 131 | assertViolations values, isValid, 0, 'size must be between 2 and 6' 132 | where: 133 | values | desc || isValid 134 | ['f', 'ab'] | 'invalid value' || false 135 | ['ab', 'cd'] | 'valid values' || true 136 | } 137 | 138 | 139 | //////// Helpers //////// 140 | 141 | void assertViolations(Object value, boolean shouldBeValid, Integer invalidIndex, String expectedMessage) { 142 | def entity = evalClassWithConstraint(constraint, value) 143 | def propertyPath = HV_VERSION >= 5_0_0 ? "valuesList[${invalidIndex}]" : 'valuesList' 144 | def violations = validate(entity) 145 | 146 | assert violations.isEmpty() == shouldBeValid 147 | 148 | if (!shouldBeValid) { 149 | assert violations.size() == 1 150 | assert violations[0].invalidValue == value 151 | assert violations[0].propertyPath.toString() == propertyPath 152 | assert violations[0].rootBean.is(entity) 153 | assert violations[0].rootBeanClass == entity.class 154 | assert violations[0].message == expectedMessage 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/test/groovy/cz/jirutka/validator/collection/CommonEachValidatorTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection 25 | 26 | import cz.jirutka.validator.collection.fixtures.LegacyEachSize 27 | import spock.lang.Specification 28 | 29 | import javax.validation.MessageInterpolator 30 | import javax.validation.MessageInterpolator.Context 31 | import javax.validation.ValidatorFactory 32 | import javax.validation.constraints.Pattern 33 | import javax.validation.constraints.Size 34 | import javax.validation.metadata.ConstraintDescriptor 35 | 36 | import static cz.jirutka.validator.collection.TestUtils.createAnnotation 37 | 38 | // TODO more tests 39 | class CommonEachValidatorTest extends Specification { 40 | 41 | def interpolator = Mock(MessageInterpolator) 42 | def factory = Stub(ValidatorFactory) { 43 | getMessageInterpolator() >> interpolator 44 | } 45 | def validator = new CommonEachValidator(validatorFactory: factory) 46 | 47 | 48 | def 'createMessage: should extract message template and interpolate it'() { 49 | given: 50 | def msgTemplate = 'must match "{regexp}"' 51 | def descriptor = Stub(ConstraintDescriptor) { 52 | getAnnotation() >> createAnnotation(Pattern, regexp: '[a-z]', message: msgTemplate) 53 | } 54 | def value = new Object() 55 | def expected = 'must match "[a-z]"' 56 | when: 57 | def actual = validator.createInterpolatedMessage(descriptor, value) 58 | then: 59 | 1 * interpolator.interpolate(msgTemplate, { Context cxt -> 60 | cxt.constraintDescriptor == descriptor && cxt.validatedValue == value 61 | }) >> expected 62 | and: 63 | actual == expected 64 | } 65 | 66 | def 'unwrapConstraints'() { 67 | given: 68 | def expected = [ createAnnotation(Size, min: 10), createAnnotation(Size) ] as Size[] 69 | def eachAnno = createAnnotation(LegacyEachSize, value: expected) 70 | expect: 71 | validator.unwrapConstraints(eachAnno) == expected 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/groovy/cz/jirutka/validator/collection/TestUtils.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2015 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection 25 | 26 | import org.hibernate.validator.internal.util.annotationfactory.AnnotationDescriptor 27 | import org.hibernate.validator.internal.util.annotationfactory.AnnotationFactory 28 | 29 | import javax.validation.Validation 30 | 31 | class TestUtils { 32 | 33 | static evalClassWithConstraint(annotationLine, List values) { 34 | def value = values ? "[ ${values.collect{ toLiteral(it) }.join(',')} ]" : null 35 | 36 | def template = """ 37 | import cz.jirutka.validator.collection.constraints.* 38 | import cz.jirutka.validator.collection.fixtures.* 39 | import javax.validation.constraints.* 40 | 41 | class TestMock { 42 | ${annotationLine.replace('"', "'")} 43 | public List valuesList = $value 44 | } 45 | """ 46 | new GroovyClassLoader().parseClass(template).newInstance() 47 | } 48 | 49 | static evalClassWithConstraint(Class annotationType, Map attributes, List values) { 50 | evalClassWithConstraint(createAnnotationString(annotationType, attributes), values) 51 | } 52 | 53 | static toLiteral(value) { 54 | switch (value) { 55 | case null : return null 56 | case String : return "'${value.toString()}'" 57 | case Long : return "${value}L" 58 | case List : return '[' + value.collect { toLiteral(it) }.join(', ') + ']' 59 | case Map : return '[' + value.collect { k, v -> "${k}: ${ toLiteral(v) }" }.join(',') + ']' 60 | case Enum : return "${value.declaringClass.name}.${value.name()}" 61 | case Date : return "new Date(${toLiteral(value.time)})" 62 | default : return String.valueOf(value) 63 | } 64 | } 65 | 66 | static createAnnotation(Class annotationType, Map attributes) { 67 | createAnnotation(attributes, annotationType) 68 | } 69 | 70 | static createAnnotation(Map attributes=[:], Class annotationType) { 71 | def desc = AnnotationDescriptor.getInstance(annotationType, attributes) 72 | AnnotationFactory.create(desc) 73 | } 74 | 75 | static createAnnotationString(Class annotationType, Map attributes) { 76 | def attrsLine = attributes.collect { k, v -> "${k}=${toLiteral(v)}" }.join(', ') 77 | "@${annotationType.name}(${attrsLine})" 78 | } 79 | 80 | static validate(entity) { 81 | Validation.buildDefaultValidatorFactory().validator.validate(entity) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/groovy/cz/jirutka/validator/collection/constraints/EachAnnotationIT.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2015 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.constraints 25 | 26 | import cz.jirutka.validator.collection.internal.HibernateValidatorInfo 27 | import org.apache.commons.lang3.ClassUtils 28 | import org.hibernate.validator.constraints.CreditCardNumber 29 | import org.hibernate.validator.constraints.NotEmpty 30 | import org.hibernate.validator.constraints.Range 31 | import spock.lang.Specification 32 | import spock.lang.Unroll 33 | 34 | import static cz.jirutka.validator.collection.TestUtils.evalClassWithConstraint 35 | import static cz.jirutka.validator.collection.TestUtils.validate 36 | 37 | @Unroll 38 | class EachAnnotationIT extends Specification { 39 | 40 | static final HV_VERSION = HibernateValidatorInfo.getVersion() 41 | 42 | // List of @Each* annotations for constraints defined in JSR 303/349. 43 | static final CONSTRAINTS_JSR = [ 44 | EachAssertFalse, EachAssertTrue, EachDecimalMax, EachDecimalMin, 45 | EachDigits, EachFuture, EachMax, EachMin, EachNotNull, EachPast, 46 | EachPattern, EachSize 47 | ] 48 | 49 | // List of @Each* annotations for Hibernate constraints in HV 4.3.0. 50 | static final CONSTRAINTS_HV = [ 51 | EachEmail, EachLength, EachNotBlank, EachNotEmpty, EachRange, 52 | EachScriptAssert, EachURL 53 | ] 54 | 55 | // List of @Each* annotations for Hibernate constraints in HV 5.1.0 and newer. 56 | static final CONSTRAINTS_5_1_0 = [ 57 | EachCreditCardNumber, EachEAN, EachLuhnCheck, EachMod10Check, 58 | EachMod11Check, EachSafeHtml 59 | ] 60 | 61 | // List of @Each* annotations which are only a composition of other @Each* annotations. 62 | static final COMPOSITE_CONSTRAINTS = [ 63 | EachCreditCardNumber, EachNotEmpty, EachRange 64 | ] 65 | 66 | 67 | def 'verify that @#name is annotated with @EachConstraint(validateAs = #expValidateAsName)'() { 68 | expect: 69 | constraint.isAnnotationPresent(EachConstraint) 70 | and: 71 | def validateAs = constraint.getAnnotation(EachConstraint).validateAs() 72 | constraint.simpleName == /Each${validateAs.simpleName}/ 73 | where: 74 | constraint << (eachConstraints - COMPOSITE_CONSTRAINTS) 75 | name = constraint.simpleName 76 | expValidateAsName = name.replaceFirst('^Each', '') + '.class' 77 | } 78 | 79 | def 'verify that #constraint.simpleName defines same attributes as its validateAs constraint'() { 80 | setup: 81 | def validateAs = constraint.getAnnotation(EachConstraint).validateAs() 82 | expect: 83 | attributesTypesSet(constraint).containsAll attributesTypesSet(validateAs) 84 | where: 85 | constraint << (eachConstraints - COMPOSITE_CONSTRAINTS) 86 | } 87 | 88 | def 'verify that @#constraint.simpleName defines same attributes as #validateAs.simpleName'() { 89 | setup: 90 | // skip test for constraints that doesn't work in the current HV version 91 | if (!eachConstraints.contains(constraint)) return 92 | expect: 93 | attributesTypesSet(constraint).containsAll attributesTypesSet(validateAs) 94 | where: 95 | constraint | validateAs 96 | EachNotEmpty | NotEmpty 97 | EachRange | Range 98 | EachCreditCardNumber | CreditCardNumber 99 | } 100 | 101 | def 'validate @#constraintName on collection of #valuesType'() { 102 | setup: 103 | // skip test for constraints that doesn't work in the current HV version 104 | if (!eachConstraints.contains(constraint)) return 105 | and: 106 | def validEntity = evalClassWithConstraint(constraint, attributes, validValue) 107 | def invalidEntity = evalClassWithConstraint(constraint, attributes, invalidValue) 108 | expect: 109 | validate(validEntity).empty 110 | ! validate(invalidEntity).empty 111 | where: 112 | constraint | attributes | validValue | invalidValue 113 | EachAssertFalse | [:] | [false, false] | [false, true] 114 | EachAssertTrue | [:] | [true, true] | [true, false] 115 | EachCreditCardNumber | [:] | ['79927398713'] | ['79927398714'] 116 | EachDecimalMax | [value: '3'] | [1, 2, 3] | [2, 3, 4] 117 | EachDecimalMax | [value: '3'] | ['1', '2', '3'] | ['2', '3', '4'] 118 | EachDecimalMin | [value: '3'] | [3, 4, 5] | [2, 3, 4] 119 | EachDecimalMin | [value: '3'] | ['3', '4', '5'] | ['2', '3', '4'] 120 | EachDigits | [integer: 2, fraction: 1] | [42.1, 13.2] | [42.1, 3.14] 121 | EachDigits | [integer: 2, fraction: 1] | ['42.1', '13.2'] | ['42.1', '3.14'] 122 | EachEAN | [:] | ['1234567890128'] | ['1234567890128', '66'] 123 | EachEmail | [:] | ['x@y.z', 'a@b.c'] | ['x@y.z', 'ab.c'] 124 | EachFuture | [:] | [futureDate()] | [pastDate()] 125 | EachLength | [min: 1, max: 3] | ['a', 'foo'] | ['a', 'allons-y!'] 126 | EachLuhnCheck | [:] | ['79927398713'] | ['79927398714'] 127 | EachMax | [value: 3L] | [1, 2, 3] | [2, 3, 4] 128 | EachMax | [value: 3L] | ['1', '2', '3'] | ['2', '3', '4'] 129 | EachMin | [value: 3L] | [3, 4, 5] | [1, 2, 3] 130 | EachMin | [value: 3L] | ['3', '4', '5'] | ['1', '2', '3'] 131 | EachMod10Check | [:] | ['123'] | ['123', '124'] 132 | EachMod11Check | [:] | ['124'] | ['124', '125'] 133 | EachNotBlank | [:] | ['foo', 'bar'] | ['foo', ''] 134 | EachNotEmpty | [:] | ['x', 'yz'] | ['x', ''] 135 | EachNotEmpty | [:] | [[1], [2, 3]] | [[1], []] 136 | EachNotEmpty | [:] | [[a: 1], [b: 2]] | [[a: 1], [:]] 137 | EachNotNull | [:] | ['foo', 'bar'] | ['foo', null] 138 | EachPast | [:] | [pastDate()] | [futureDate()] 139 | EachPattern | [regexp: '[A-Z]+'] | ['FOO', 'BAR'] | ['FOO', '123'] 140 | EachRange | [min: 3L, max: 6L] | [3, 4, 5] | [6, 7, 8] 141 | EachRange | [min: 3L, max: 6L] | ['3', '4', '5'] | ['6', '7', '8'] 142 | EachSafeHtml | [:] | ['foo'] | ['WAT?'] 143 | EachSize | [min: 1, max: 2] | ['a', 'xy'] | ['a', 'foo'] 144 | EachSize | [min: 1, max: 2] | [[1], [2, 3]] | [[1], [2, 3, 4]] 145 | EachSize | [min: 1, max: 2] | [[a: 1], [b: 2]] | [[a: 1], [:]] 146 | EachURL | [protocol: 'https'] | ['https://nic.cz'] | ['http://nic.cz'] 147 | 148 | constraintName = ClassUtils.getSimpleName(constraint) // using ClassUtils to avoid NoClassDefFoundError 149 | valuesType = validValue[0].getClass().simpleName + 's' 150 | } 151 | 152 | 153 | //////// Helpers //////// 154 | 155 | static getEachConstraints() { 156 | (CONSTRAINTS_JSR + CONSTRAINTS_HV + (HV_VERSION >= 5_1_0 ? CONSTRAINTS_5_1_0 : [])).toSet() 157 | } 158 | 159 | def attributesTypesSet(Class annotation) { 160 | annotation.declaredMethods.collect(new HashSet()) { m -> 161 | [m.name, m.returnType] 162 | } 163 | } 164 | 165 | def futureDate() { 166 | new Date().plus(1) 167 | } 168 | 169 | def pastDate() { 170 | new Date().minus(1) 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/test/groovy/cz/jirutka/validator/collection/internal/AnnotationUtilsTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.internal 25 | 26 | import cz.jirutka.validator.collection.TestUtils 27 | import spock.lang.Specification 28 | import spock.lang.Unroll 29 | 30 | import javax.validation.constraints.NotNull 31 | import javax.validation.constraints.Pattern 32 | import javax.validation.constraints.Size 33 | 34 | import static cz.jirutka.validator.collection.internal.AnnotationUtils.* 35 | 36 | class AnnotationUtilsTest extends Specification { 37 | 38 | 39 | //////// readAttribute() //////// 40 | 41 | def "readAttribute: return attribute's value"() { 42 | given: 43 | def attrs = value != null ? [(name): value] : [:] 44 | def annotation = TestUtils.createAnnotation(Size, attrs) 45 | expect: 46 | readAttribute(annotation, name, reqType) == expected 47 | where: 48 | name | reqType | value || expected 49 | 'min' | Integer | 1 || 1 50 | 'message' | String | null || '{javax.validation.constraints.Size.message}' 51 | 'groups' | Class[] | [String] as Class[] || [String] 52 | } 53 | 54 | @Unroll 55 | def "readAttribute: throw IllegalArgumentException when attribute #reason"() { 56 | given: 57 | def annotation = TestUtils.createAnnotation(NotNull) 58 | when: 59 | readAttribute(annotation, attrName, attrType) 60 | then: 61 | thrown IllegalArgumentException 62 | where: 63 | attrName | attrType | reason 64 | 'foo' | String | "doesn't exist" 65 | 'message' | Integer | "isn't instance of required type" 66 | } 67 | 68 | 69 | //////// hasAttribute() //////// 70 | 71 | @Unroll 72 | def 'hasAttribute: return #expected for #desc attribute'() { 73 | expect: 74 | hasAttribute(Size, name) == expected 75 | where: 76 | name | expected 77 | 'min' | true 78 | 'foo' | false 79 | 80 | desc = expected ? 'existing' : 'undefined' 81 | } 82 | 83 | 84 | //////// readAllAttributes() //////// 85 | 86 | def 'readAllAttributes: return attributes as map'() { 87 | given: 88 | def attrs = [message: 'allons-y!', max: 10] 89 | def annotation = TestUtils.createAnnotation(Size, attrs) 90 | def expected = [groups: [], payload: [], min: 0] + attrs 91 | expect: 92 | readAllAttributes(annotation) == expected 93 | } 94 | 95 | 96 | //////// createAnnotation() //////// 97 | 98 | def 'createAnnotation: create annotation when given valid attributes'() { 99 | given: 100 | def attributes = [min: 42, message: 'allons-y!'] 101 | when: 102 | def actual = createAnnotation(Size, attributes) 103 | then: 104 | actual instanceof Size 105 | actual.min() == attributes['min'] 106 | actual.message() == attributes['message'] 107 | } 108 | 109 | @Unroll 110 | def 'createAnnotation: create annotation and ignore #desc'() { 111 | when: 112 | def actual = createAnnotation(Size, attributes) 113 | then: 114 | actual instanceof Size 115 | actual.message() == '{javax.validation.constraints.Size.message}' 116 | where: 117 | attributes | desc 118 | [undefined: 666] | 'undefined attribute' 119 | [message: null] | 'attribute with null' 120 | } 121 | 122 | def 'createAnnotation: throw IllegalArgumentException when wrong attribute type'() { 123 | when: 124 | createAnnotation(Size, [min: 'fail']) 125 | then: 126 | def ex = thrown(IllegalArgumentException) 127 | ex.message == "Attribute 'min' expects int, but given: fail (java.lang.String)" 128 | } 129 | 130 | def 'createAnnotation: throw IllegalArgumentException when omit required attribute'() { 131 | when: 132 | createAnnotation(Pattern, [message: 'fail']) 133 | then: 134 | def ex = thrown(IllegalArgumentException) 135 | ex.message == 'Missing required attribute: regexp' 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/test/groovy/cz/jirutka/validator/collection/internal/HibernateValidatorInfoTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.internal 25 | 26 | import spock.lang.Specification 27 | import spock.lang.Unroll 28 | 29 | @Unroll 30 | class HibernateValidatorInfoTest extends Specification { 31 | 32 | def 'parse version: #input'() { 33 | expect: 34 | HibernateValidatorInfo.parseVersion(input) == expected 35 | where: 36 | input | expected 37 | '5.1.1.Final' | 511 38 | '5.2.0-SNAPSHOT' | 520 39 | '4.0.0.GA' | 400 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/cz/jirutka/validator/collection/fixtures/EachComposite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.fixtures; 25 | 26 | import cz.jirutka.validator.collection.constraints.EachPattern; 27 | import cz.jirutka.validator.collection.constraints.EachSize; 28 | 29 | import javax.validation.Constraint; 30 | import javax.validation.Payload; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.FIELD; 36 | import static java.lang.annotation.ElementType.METHOD; 37 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 38 | 39 | @EachSize(min=2, max=8) 40 | @EachPattern(regexp="[a-z]+", message="must contain a-z only") 41 | @Documented 42 | @Retention(RUNTIME) 43 | @Target({ METHOD, FIELD }) 44 | @Constraint(validatedBy = {}) 45 | public @interface EachComposite { 46 | 47 | String message() default ""; 48 | Class[] groups() default {}; 49 | Class[] payload() default {}; 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/cz/jirutka/validator/collection/fixtures/LegacyEachSize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2013-2014 Jakub Jirutka . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package cz.jirutka.validator.collection.fixtures; 25 | 26 | import cz.jirutka.validator.collection.CommonEachValidator; 27 | 28 | import javax.validation.Constraint; 29 | import javax.validation.Payload; 30 | import javax.validation.constraints.Size; 31 | import java.lang.annotation.Documented; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.Target; 34 | 35 | import static java.lang.annotation.ElementType.*; 36 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 37 | 38 | @Documented 39 | @Retention(RUNTIME) 40 | @Target({METHOD, FIELD, ANNOTATION_TYPE}) 41 | @Constraint(validatedBy = CommonEachValidator.class) 42 | public @interface LegacyEachSize { 43 | 44 | String message() default ""; 45 | Class[] groups() default {}; 46 | Class[] payload() default {}; 47 | 48 | Size[] value(); 49 | } 50 | -------------------------------------------------------------------------------- /src/test/resources/simplelogger.properties: -------------------------------------------------------------------------------- 1 | org.slf4j.simpleLogger.defaultLogLevel=trace 2 | --------------------------------------------------------------------------------