annotated tag v3.0-alpha-1 created (now e896c7a)
This is an automated email from the git hooks/post-receive script. New change to annotated tag v3.0-alpha-1 in repository nuiton-validator. See https://gitlab.nuiton.org/nuiton/nuiton-validator.git at e896c7a (tag) tagging 904321926398881581a338e5a9c67828969cab69 (commit) tagged by Maven Release Manager on Tue Jul 23 15:54:51 2013 +0000 - Log ----------------------------------------------------------------- [maven-release-plugin] copy for tag nuiton-validator-3.0-alpha-1 ----------------------------------------------------------------------- This annotated tag includes the following new commits: new 9043219 [maven-release-plugin] copy for tag nuiton-validator-3.0-alpha-1 The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 904321926398881581a338e5a9c67828969cab69 Author: Maven Release Manager <???> Date: Tue Jul 23 15:54:51 2013 +0000 [maven-release-plugin] copy for tag nuiton-validator-3.0-alpha-1 -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to annotated tag v3.0-alpha-1 in repository nuiton-validator. See https://gitlab.nuiton.org/nuiton/nuiton-validator.git commit 904321926398881581a338e5a9c67828969cab69 Author: Maven Release Manager <???> Date: Tue Jul 23 15:54:51 2013 +0000 [maven-release-plugin] copy for tag nuiton-validator-3.0-alpha-1 --- LICENSE.txt | 166 ++++++ README.txt | 0 pom.xml | 308 ++++++++++++ src/license/THIRD-PARTY.properties | 20 + .../validator/AbstractNuitonValidatorProvider.java | 119 +++++ .../java/org/nuiton/validator/NuitonValidator.java | 86 ++++ .../nuiton/validator/NuitonValidatorFactory.java | 176 +++++++ .../org/nuiton/validator/NuitonValidatorModel.java | 86 ++++ .../nuiton/validator/NuitonValidatorProvider.java | 104 ++++ .../nuiton/validator/NuitonValidatorResult.java | 308 ++++++++++++ .../org/nuiton/validator/NuitonValidatorScope.java | 78 +++ .../bean/AbstractNuitonValidatorContext.java | 389 ++++++++++++++ .../nuiton/validator/bean/AbstractValidator.java | 390 ++++++++++++++ .../validator/bean/AbstractValidatorEvent.java | 85 ++++ .../nuiton/validator/bean/ValidatorCreator.java | 53 ++ .../nuiton/validator/bean/ValidatorListener.java | 47 ++ .../validator/bean/list/BeanListValidator.java | 560 +++++++++++++++++++++ .../bean/list/BeanListValidatorEvent.java | 56 +++ .../bean/list/BeanListValidatorListener.java | 37 ++ .../bean/list/BeanListValidatorMessage.java | 152 ++++++ .../nuiton/validator/bean/list/package-info.java | 58 +++ .../org/nuiton/validator/bean/package-info.java | 71 +++ .../validator/bean/simple/SimpleBeanValidator.java | 478 ++++++++++++++++++ .../bean/simple/SimpleBeanValidatorEvent.java | 51 ++ .../bean/simple/SimpleBeanValidatorListener.java | 38 ++ .../bean/simple/SimpleBeanValidatorMessage.java | 144 ++++++ .../bean/simple/SimpleBeanValidators.java | 75 +++ .../nuiton/validator/bean/simple/package-info.java | 57 +++ .../java/org/nuiton/validator/package-info.java | 55 ++ .../validator/xwork2/XWork2NuitonValidator.java | 135 +++++ .../xwork2/XWork2NuitonValidatorProvider.java | 309 ++++++++++++ .../validator/xwork2/XWork2ScopeValidator.java | 224 +++++++++ .../validator/xwork2/XWork2ValidatorUtil.java | 232 +++++++++ .../field/CollectionFieldExpressionValidator.java | 489 ++++++++++++++++++ .../xwork2/field/CollectionUniqueKeyValidator.java | 323 ++++++++++++ .../xwork2/field/EmailFieldValidator.java | 66 +++ .../field/ExistingDirectoryFieldValidator.java | 95 ++++ .../xwork2/field/ExistingFileFieldValidator.java | 95 ++++ .../field/FieldExpressionWithParamsValidator.java | 223 ++++++++ .../xwork2/field/FrenchCityNameFieldValidator.java | 75 +++ .../xwork2/field/FrenchFinessFieldValidator.java | 92 ++++ .../xwork2/field/FrenchLastNameFieldValidator.java | 73 +++ .../field/FrenchPhoneNumberFieldValidator.java | 76 +++ .../xwork2/field/FrenchPostCodeFieldValidator.java | 76 +++ .../xwork2/field/FrenchSiretFieldValidator.java | 176 +++++++ .../field/NotExistingDirectoryFieldValidator.java | 94 ++++ .../field/NotExistingFileFieldValidator.java | 95 ++++ .../field/NuitonFieldExpressionValidator.java | 136 +++++ .../xwork2/field/NuitonFieldValidatorSupport.java | 139 +++++ .../xwork2/field/RequiredFileFieldValidator.java | 95 ++++ .../field/SkipableRequiredFieldValidator.java | 43 ++ .../SkipableRequiredStringFieldValidator.java | 43 ++ .../VATIdentificationNumberFieldValidator.java | 78 +++ .../validator/xwork2/field/package-info.java | 31 ++ .../org/nuiton/validator/xwork2/package-info.java | 31 ++ .../org.nuiton.validator.NuitonValidatorProvider | 1 + .../i18n/nuiton-validator_en_GB.properties | 4 + .../i18n/nuiton-validator_es_ES.properties | 4 + .../i18n/nuiton-validator_fr_FR.properties | 4 + src/site/apt/index.apt | 98 ++++ src/site/apt/versions.apt | 33 ++ src/site/site_fr.xml | 109 ++++ .../validator/AbstractValidatorDetectorTest.java | 159 ++++++ .../validator/NuitonValidatorFactoryTest.java | 59 +++ .../org/nuiton/validator/ValidatorTestHelper.java | 173 +++++++ .../java/org/nuiton/validator/bean/SimpleBean.java | 78 +++ .../validator/bean/list/BeanListValidatorTest.java | 528 +++++++++++++++++++ .../bean/simple/SimpleBeanValidatorTest.java | 313 ++++++++++++ .../java/org/nuiton/validator/model/Company.java | 55 ++ .../java/org/nuiton/validator/model/Contact.java | 91 ++++ .../validator/model/HealthEstablishment.java | 44 ++ .../model/ModelValidatorDetectorTestImpl.java | 186 +++++++ .../java/org/nuiton/validator/model/Person.java | 93 ++++ src/test/java/org/nuiton/validator/model/Pet.java | 98 ++++ src/test/java/org/nuiton/validator/model/Race.java | 55 ++ .../xwork2/XWork2NuitonValidatorProviderTest.java | 167 ++++++ .../xwork2/XWork2NuitonValidatorTest.java | 59 +++ .../xwork2/field/AbstractFieldValidatorTest.java | 132 +++++ .../AbstractValidatorBeanFieldValidatorTest.java | 37 ++ .../CollectionFieldExpressionValidatorTest.java | 265 ++++++++++ .../field/CollectionUniqueKeyValidatorTest.java | 114 +++++ .../xwork2/field/EmailFieldValidatorTest.java | 68 +++ .../field/ExistingDirectoryFieldValidatorTest.java | 57 +++ .../field/ExistingFileFieldValidatorTest.java | 57 +++ .../xwork2/field/FieldExpressionBean.java | 131 +++++ .../FieldExpressionWithParamsValidatorTest.java | 144 ++++++ .../field/FrenchCityNameFieldValidatorTest.java | 106 ++++ .../field/FrenchFinessFieldValidatorTest.java | 85 ++++ .../field/FrenchLastNameFieldValidatorTest.java | 87 ++++ .../field/FrenchPhoneNumberFieldValidatorTest.java | 134 +++++ .../field/FrenchPostCodeFieldValidatorTest.java | 92 ++++ .../field/FrenchSiretFieldValidatorTest.java | 103 ++++ .../NotExistingDirectoryFieldValidatorTest.java | 60 +++ .../field/NotExistingFileFieldValidatorTest.java | 63 +++ .../field/RequiredFileFieldValidatorTest.java | 56 +++ .../VATIdentificationNumberFieldValidatorTest.java | 80 +++ .../validator/xwork2/field/ValidatorBean.java | 182 +++++++ src/test/resources/log4j.properties | 32 ++ .../validator/bean/SimpleBean-error-validation.xml | 42 ++ .../validator/bean/SimpleBean-fatal-validation.xml | 46 ++ .../validator/bean/SimpleBean-info-validation.xml | 36 ++ .../bean/SimpleBean-marchepo-error-validation.xml | 37 ++ .../bean/SimpleBean-simple-validation.xml | 42 ++ .../bean/SimpleBean-warning-validation.xml | 36 ++ .../legacy/SimpleBean-error-validation.xml | 42 ++ .../legacy/SimpleBean-fatal-validation.xml | 46 ++ .../legacy/SimpleBean-info-validation.xml | 36 ++ .../legacy/SimpleBean-simple-validation.xml | 42 ++ .../legacy/SimpleBean-warning-validation.xml | 36 ++ .../validator/model/Company-error-validation.xml | 41 ++ .../validator/model/Contact-error-validation.xml | 57 +++ .../model/HealthEstablishment-error-validation.xml | 33 ++ .../validator/model/Person-error-validation.xml | 41 ++ .../validator/model/Person-warning-validation.xml | 37 ++ .../model/Pet-context-info-validation.xml | 33 ++ .../validator/model/Pet-error-validation.xml | 33 ++ .../field/FieldExpressionBean-error-validation.xml | 122 +++++ .../field/ValidatorBean-error-validation.xml | 177 +++++++ src/test/resources/validators.xml | 75 +++ 119 files changed, 13377 insertions(+) diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..e69de29 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..acaeea5 --- /dev/null +++ b/pom.xml @@ -0,0 +1,308 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>mavenpom4redmineAndCentral</artifactId> + <version>3.4.13</version> + </parent> + + <artifactId>nuiton-validator</artifactId> + <version>3.0-alpha-1</version> + + <name>Nuiton Validator</name> + <description>Simple Validator API</description> + <url>http://maven-site.nuiton.org/nuiton-validator</url> + <inceptionYear>2013</inceptionYear> + + <developers> + + <developer> + <name>Tony Chemit</name> + <id>tchemit</id> + <email>chemit at codelutin dot com</email> + <organization>CodeLutin</organization> + <organizationUrl>http://www.codelutin.com/</organizationUrl> + <timezone>Europe/Paris</timezone> + <roles> + <role>developer</role> + </roles> + </developer> + + </developers> + + <scm> + <connection> + scm:svn:http://svn.nuiton.org/svn/nuiton-validator/tags/nuiton-validator-3.0-alpha-1 + </connection> + <developerConnection> + scm:svn:http://svn.nuiton.org/svn/nuiton-validator/tags/nuiton-validator-3.0-alpha-1 + </developerConnection> + <url>http://nuiton.org/projects/nuiton-validator/repository/show/tags/nuiton-validator-3.0-alpha-1</url> + </scm> + <distributionManagement> + <site> + <id>${platform}</id> + <url>${our.site.repository}/${projectId}</url> + </site> + </distributionManagement> + + <properties> + + <projectId>nuiton-validator</projectId> + + <nuitonI18nVersion>2.5.2</nuitonI18nVersion> + + <!-- i18n configuration --> + <i18n.bundles>fr_FR,en_GB,es_ES</i18n.bundles> + + <!-- Documentation is in apt format --> + <siteSourcesType>apt</siteSourcesType> + + <!-- extra files to include in release --> + <redmine.releaseFiles>${redmine.libReleaseFiles}</redmine.releaseFiles> + + </properties> + + <dependencies> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + <version>2.6.12</version> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + <version>${nuitonI18nVersion}</version> + </dependency> + + <dependency> + <groupId>org.apache.struts.xwork</groupId> + <artifactId>xwork-core</artifactId> + <version>2.3.15.1</version> + <exclusions> + <exclusion> + <groupId>asm</groupId> + <artifactId>asm</artifactId> + </exclusion> + <exclusion> + <groupId>asm</groupId> + <artifactId>asm-commons</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + </dependency> + + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>provided</scope> + </dependency> + + </dependencies> + + <build> + <pluginManagement> + <plugins> + + <!-- plugin i18n --> + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>i18n-maven-plugin</artifactId> + <version>${nuitonI18nVersion}</version> + </plugin> + + </plugins> + </pluginManagement> + <plugins> + + <!-- plugin i18n --> + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>i18n-maven-plugin</artifactId> + <configuration> + <silent>true</silent> + <bundles>fr_FR,en_GB,es_ES</bundles> + </configuration> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>gen</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <id>attach-test</id> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + + <profiles> + + <profile> + <id>reporting</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <reporting> + <plugins> + + <plugin> + <artifactId>maven-project-info-reports-plugin</artifactId> + <version>${projectInfoReportsPluginVersion}</version> + <reportSets> + <reportSet> + <reports> + <report>project-team</report> + <report>mailing-list</report> + <report>cim</report> + <report>issue-tracking</report> + <report>license</report> + <report>scm</report> + <report>dependency-info</report> + <report>dependencies</report> + <report>dependency-convergence</report> + <report>plugin-management</report> + <report>plugins</report> + <report>dependency-management</report> + <report>summary</report> + </reports> + </reportSet> + </reportSets> + </plugin> + + </plugins> + </reporting> + + </profile> + + <!-- create assemblies at release time --> + <profile> + <id>assembly-profile</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + <build> + <defaultGoal>package</defaultGoal> + <plugins> + + <!-- launch in a release the assembly automaticly --> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>create-assemblies</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + <configuration> + <attach>false</attach> + <descriptorRefs> + <descriptorRef>deps</descriptorRef> + <descriptorRef>full</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + + </plugins> + + </build> + </profile> + + <!-- perform only on a release stage when using the maven-release-plugin --> + <profile> + <id>release-profile</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <build> + <plugins> + + <!-- always compute tests source jar --> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <executions> + <execution> + <id>attach-test-sources</id> + </execution> + </executions> + </plugin> + + <!-- always compute tests javadoc jar --> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + <executions> + <execution> + <id>attach-test-javadoc</id> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + </profile> + + </profiles> +</project> diff --git a/src/license/THIRD-PARTY.properties b/src/license/THIRD-PARTY.properties new file mode 100644 index 0000000..df76be0 --- /dev/null +++ b/src/license/THIRD-PARTY.properties @@ -0,0 +1,20 @@ +# Generated by org.codehaus.mojo.license.AddThirdPartyMojo +#------------------------------------------------------------------------------- +# Already used licenses in project : +# - BSD License +# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 +# - Common Public License Version 1.0 +# - Indiana University Extreme! Lab Software License, vesion 1.1.1 +# - Lesser General Public License (LGPL) v 3.0 +# - Lesser General Public License (LPGL) +# - Lesser General Public License (LPGL) v 2.1 +# - MIT License +# - New BSD License +# - The Apache Software License, Version 2.0 +#------------------------------------------------------------------------------- +# Please fill the missing licenses for dependencies : +# +# +#Sat Jul 20 16:25:49 CEST 2013 +commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 +javassist--javassist--3.11.0.GA=The Apache Software License, Version 2.0 diff --git a/src/main/java/org/nuiton/validator/AbstractNuitonValidatorProvider.java b/src/main/java/org/nuiton/validator/AbstractNuitonValidatorProvider.java new file mode 100644 index 0000000..5ff165a --- /dev/null +++ b/src/main/java/org/nuiton/validator/AbstractNuitonValidatorProvider.java @@ -0,0 +1,119 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * Abstract provider of validator. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public abstract class AbstractNuitonValidatorProvider implements NuitonValidatorProvider { + + protected Map<ModelEntry<?>, NuitonValidatorModel<?>> models; + + protected final String name; + + public AbstractNuitonValidatorProvider(String name) { + this.name = name; + } + + @Override + public <O> NuitonValidatorModel<O> getModel(Class<O> type, String context, NuitonValidatorScope... scopes) { + ModelEntry<O> key = ModelEntry.createModelEntry(type, context, scopes); + + @SuppressWarnings({"unchecked"}) + NuitonValidatorModel<O> model = (NuitonValidatorModel<O>) getModels().get(key); + + if (model == null) { + model = newModel(type, context, scopes); + } + return model; + } + + protected Map<ModelEntry<?>, NuitonValidatorModel<?>> getModels() { + if (models == null) { + models = new HashMap<ModelEntry<?>, NuitonValidatorModel<?>>(); + } + return models; + } + + protected static class ModelEntry<O> implements Serializable { + + private static final long serialVersionUID = 1L; + + protected final Class<O> type; + + protected final String context; + + protected final NuitonValidatorScope[] scopes; + + public static <O> ModelEntry<O> createModelEntry(Class<O> type, + String context, + NuitonValidatorScope... scopes) { + return new ModelEntry<O>(type, context, scopes); + } + + protected ModelEntry(Class<O> type, + String context, + NuitonValidatorScope... scopes) { + this.type = type; + this.context = context; + this.scopes = scopes == null ? NuitonValidatorScope.values() : scopes; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ModelEntry)) return false; + + ModelEntry<?> that = (ModelEntry<?>) o; + + if (context != null ? !context.equals(that.context) : that.context != null) + return false; + if (!Arrays.equals(scopes, that.scopes)) return false; + return type.equals(that.type); + + } + + @Override + public int hashCode() { + int result = type.hashCode(); + result = 31 * result + (context != null ? context.hashCode() : 0); + result = 31 * result + Arrays.hashCode(scopes); + return result; + } + } + + @Override + public String getName() { + return name; + } + +} diff --git a/src/main/java/org/nuiton/validator/NuitonValidator.java b/src/main/java/org/nuiton/validator/NuitonValidator.java new file mode 100644 index 0000000..abfc1f1 --- /dev/null +++ b/src/main/java/org/nuiton/validator/NuitonValidator.java @@ -0,0 +1,86 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import java.util.Set; + +/** + * Contract of a validator. + * <p/> + * To obtain validator, see the {@link NuitonValidatorFactory} api. + * + * @author tchemit <chemit@codelutin.com> + * @see NuitonValidatorFactory + * @since 2.0 + */ +public interface NuitonValidator<O> { + + /** + * Validates the given object and returns the result of validation. + * + * @param object the object to validate + * @return the result of validation for the given object + * @throws NullPointerException if object is {@code null}. + */ + NuitonValidatorResult validate(O object) throws NullPointerException; + + /** + * Obtains the model of the validator. + * + * @return the model of the validator + */ + NuitonValidatorModel<O> getModel(); + + /** + * Obtains the set of effective scopes for the validator : means the very + * scopes that the validator is dealing with. + * <p/> + * This is a subset of the model authorized scopes. + * + * @return the set of effective scopes of the validator + */ + Set<NuitonValidatorScope> getEffectiveScopes(); + + /** + * Obtains the set of effective fields for the validator : means the very + * fields validated by the validator. + * <p/> + * This is a sub set of fields of the object to validate. + * + * @return the set of effective fields of the validator + */ + Set<String> getEffectiveFields(); + + /** + * Obtains the set of effective fields for the validator for the given scope + * : means the very fields validated by the validator. + * <p/> + * This is a subset of effective fields of the validator. + * + * @param scope given scope to use + * @return the set of effective fields of the validator for the given scope + */ + Set<String> getEffectiveFields(NuitonValidatorScope scope); + +} diff --git a/src/main/java/org/nuiton/validator/NuitonValidatorFactory.java b/src/main/java/org/nuiton/validator/NuitonValidatorFactory.java new file mode 100644 index 0000000..7a6ac47 --- /dev/null +++ b/src/main/java/org/nuiton/validator/NuitonValidatorFactory.java @@ -0,0 +1,176 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Map; +import java.util.ServiceLoader; +import java.util.TreeMap; + +/** + * Factory to obtain new validators. + * <p/> + * The factory contains a cache of {@link NuitonValidatorModel}. + * <p/> + * To obtain a new validator with no context, use this code : + * <pre> + * NuitonValidator<O> validator = NuitonValidatorFactory.newValidator(O.class); + * </pre> + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class NuitonValidatorFactory { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(NuitonValidatorFactory.class); + + protected static String defaultProviderName; + + protected static Map<String, NuitonValidatorProvider> providers; + + public static <O> NuitonValidator<O> newValidator(Class<O> type, + NuitonValidatorScope... scopes) { + NuitonValidator<O> result = newValidator(type, null, scopes); + return result; + } + + public static <O> NuitonValidator<O> newValidator(Class<O> type, + String context, + NuitonValidatorScope... scopes) { + + String providerName = getDefaultProviderName(); + + NuitonValidator<O> result = newValidator(providerName, + type, + context, + scopes); + return result; + } + + public static <O> NuitonValidator<O> newValidator(String providerName, + Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + if (type == null) { + throw new NullPointerException( + "type parameter can not be null."); + } + + // get the provider + NuitonValidatorProvider provider = getProvider(providerName); + + + // obtain validator model form the provider + NuitonValidatorModel<O> model = + provider.getModel(type, context, scopes); + + // obtain validator from the the provider + NuitonValidator<O> result = provider.newValidator(model); + return result; + } + + public static Map<String, NuitonValidatorProvider> getProviders() { + if (providers == null) { + providers = new TreeMap<String, NuitonValidatorProvider>(); + ServiceLoader<NuitonValidatorProvider> serviceLoader = + ServiceLoader.load(NuitonValidatorProvider.class); + + for (NuitonValidatorProvider provider : serviceLoader) { + if (log.isInfoEnabled()) { + log.info("obtain validator provider " + provider.getName()); + } + providers.put(provider.getName(), provider); + } + } + return providers; + } + + public static NuitonValidatorProvider getProvider(String providerName) throws IllegalArgumentException, NullPointerException { + + if (providerName == null) { + + // take the default validator provider name + throw new NullPointerException( + "providerName parameter can not be null."); + } + + NuitonValidatorProvider provider = getProviders().get(providerName); + if (provider == null) { + throw new IllegalArgumentException( + "Could not find provider named '" + + defaultProviderName + "', existing providers are : " + + getProviders().keySet()); + } + return provider; + } + + public static NuitonValidatorProvider getDefaultProvider() { + String providerName = getDefaultProviderName(); + NuitonValidatorProvider provider = getProvider(providerName); + return provider; + } + + public static String getDefaultProviderName() throws IllegalStateException { + + if (defaultProviderName == null) { + + // takes the first provider from existing provider + + Map<String, NuitonValidatorProvider> providers = getProviders(); + if (providers.isEmpty()) { + throw new IllegalStateException( + "Could not find any provider of validator."); + } + defaultProviderName = providers.keySet().iterator().next(); + + if (log.isInfoEnabled()) { + log.info("Set the default provider name to " + defaultProviderName); + } + } + + return defaultProviderName; + } + + public static void setDefaultProviderName(String defaultProviderName) throws IllegalArgumentException, NullPointerException { + + if (defaultProviderName == null) { + throw new NullPointerException("defaultProviderName can not be null."); + } + // check provider exists + getProvider(defaultProviderName); + + NuitonValidatorFactory.defaultProviderName = defaultProviderName; + } + + protected NuitonValidatorFactory() { + // avoid instanciation of this factory + } + + +} diff --git a/src/main/java/org/nuiton/validator/NuitonValidatorModel.java b/src/main/java/org/nuiton/validator/NuitonValidatorModel.java new file mode 100644 index 0000000..fdd7422 --- /dev/null +++ b/src/main/java/org/nuiton/validator/NuitonValidatorModel.java @@ -0,0 +1,86 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + * Represents the model of a {@link NuitonValidator}. + * <p/> + * This model describing properties of a validator : + * <ul> + * <li>{@link #type} : the type of object which can be validated by the validator</li> + * <li>{@link #context} : the context of validation, if no context is required then the context is {@code null}. + * <li>{@link #scopes} : the scopes of validation (see {@link NuitonValidatorScope})</li> + * <li>{@link #fields} : the fields that can be validated by the validator</li> + * </ul> + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class NuitonValidatorModel<O> implements Serializable { + + private static final long serialVersionUID = 1L; + + /** Type of object to validate */ + protected Class<O> type; + + /** Context of validation (can be {@code null}, for no context). */ + protected String context; + + /** Set of scopes that can be validated for the type and context */ + protected Set<NuitonValidatorScope> scopes; + + /** Set of fields that can be validated for the type and context */ + protected Map<NuitonValidatorScope, String[]> fields; + + public NuitonValidatorModel(Class<O> type, + String context, + Set<NuitonValidatorScope> scopes, + Map<NuitonValidatorScope, String[]> fields) { + this.type = type; + this.context = context; + this.scopes = Collections.unmodifiableSet(scopes); + this.fields = Collections.unmodifiableMap(fields); + } + + public Class<O> getType() { + return type; + } + + public String getContext() { + return context; + } + + public Set<NuitonValidatorScope> getScopes() { + return scopes; + } + + public Map<NuitonValidatorScope, String[]> getFields() { + return fields; + } +} diff --git a/src/main/java/org/nuiton/validator/NuitonValidatorProvider.java b/src/main/java/org/nuiton/validator/NuitonValidatorProvider.java new file mode 100644 index 0000000..67399d5 --- /dev/null +++ b/src/main/java/org/nuiton/validator/NuitonValidatorProvider.java @@ -0,0 +1,104 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import java.io.File; +import java.util.ServiceLoader; +import java.util.SortedSet; +import java.util.regex.Pattern; + +/** + * Provider of {@link NuitonValidator}. + * <p/> + * An implementation of a such class provides a implementation of a validator models + * and also of validator. + * <p/> + * <b>Note:</b> Providers are used in the {@link NuitonValidatorFactory} and + * should be registered via the {@link ServiceLoader} api. + * + * @author tchemit <chemit@codelutin.com> + * @see NuitonValidatorModel + * @see NuitonValidator + * @see ServiceLoader + * @since 2.0 + */ +public interface NuitonValidatorProvider { + + /** + * Obtains the name of the provider. + * + * @return the name of the provider. + */ + String getName(); + + /** + * Obtain a validator model, the model should be cached and not be + * reinstanciated at each time a validator model is asked. + * + * @param type type of the class to validate + * @param context context of validation ({@code null} if no context) + * @param scopes filtered scope (if nothing given, then use all scopes) + * @param <O> type of the class to validate + * @return the cached model of validation + */ + <O> NuitonValidatorModel<O> getModel(Class<O> type, + String context, + NuitonValidatorScope... scopes); + + /** + * Instanciate a new validator model for the given parameters. + * + * @param type type of the class to validate + * @param context context of validation ({@code null} if no context) + * @param scopes filtered scope (if nothing given, then use all scopes) + * @param <O> type of the class to validate + * @return the new instanciated model of validation + */ + <O> NuitonValidatorModel<O> newModel(Class<O> type, + String context, + NuitonValidatorScope... scopes); + + /** + * Obtains a new validator for the given {@code model}. + * + * @param model the model of validator to use + * @param <O> type of class to validate + * @return the new validator + */ + <O> NuitonValidator<O> newValidator(NuitonValidatorModel<O> model); + + /** + * Detects in the given directory validators. + * + * @param sourceRoot root directory where to seek for validators + * @param contextFilter the pattern of context to seek + * @param scopes scopes to seek (if none given, will seek for all scopes) + * @param types types of class to seek + * @return the set of validators found + */ + SortedSet<NuitonValidator<?>> detectValidators(File sourceRoot, + Pattern contextFilter, + NuitonValidatorScope[] scopes, + Class<?>... types); +} diff --git a/src/main/java/org/nuiton/validator/NuitonValidatorResult.java b/src/main/java/org/nuiton/validator/NuitonValidatorResult.java new file mode 100644 index 0000000..d3dfa8c --- /dev/null +++ b/src/main/java/org/nuiton/validator/NuitonValidatorResult.java @@ -0,0 +1,308 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import org.apache.commons.collections.MapUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +/** + * Contains validation messages coming from the method + * {@link NuitonValidator#validate(Object)}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class NuitonValidatorResult { + + public static class FieldMap<V> extends TreeMap<String, V> { + + private static final long serialVersionUID = 1L; + } + + protected EnumMap<NuitonValidatorScope, FieldMap<List<String>>> messages; + + protected Map<String, FieldMap<Object>> tagValues; + + public boolean isValid() { + return !hasFatalMessages() && !hasErrorMessagess(); + } + + public void clear() { + messages.clear(); + } + + public boolean isEmpty() { + return messages.isEmpty(); + } + + public boolean hasMessagesForScope(NuitonValidatorScope scope) { + boolean result = false; + if (messages != null) { + FieldMap<List<String>> map = messages.get(scope); + result = !MapUtils.isEmpty(map); + } + return result; + } + + public boolean hasMessagesForScope(String field, + NuitonValidatorScope scope) { + boolean result = false; + if (messages != null) { + result = messages.containsKey(scope); + + if (result) { + FieldMap<List<String>> fieldMap = messages.get(scope); + result = fieldMap != null && fieldMap.containsKey(field); + } + } + return result; + } + + public boolean hasFatalMessages() { + boolean result = hasMessagesForScope(NuitonValidatorScope.FATAL); + return result; + } + + public boolean hasErrorMessagess() { + boolean result = hasMessagesForScope(NuitonValidatorScope.ERROR); + return result; + } + + public boolean hasInfoMessages() { + boolean result = hasMessagesForScope(NuitonValidatorScope.INFO); + return result; + } + + public boolean hasWarningMessages() { + boolean result = hasMessagesForScope(NuitonValidatorScope.WARNING); + return result; + } + + public void addMessagesForScope(NuitonValidatorScope scope, + Map<String, List<String>> newMessages) { + if (messages == null) { + messages = new EnumMap<NuitonValidatorScope, FieldMap<List<String>>>(NuitonValidatorScope.class); + } + + FieldMap<List<String>> fieldMap = messages.get(scope); + + if (fieldMap == null) { + fieldMap = new FieldMap<List<String>>(); + messages.put(scope, fieldMap); + } + + for (Map.Entry<String, List<String>> entry : newMessages.entrySet()) { + String fieldName = entry.getKey(); + List<String> messages = entry.getValue(); + List<String> oldMessages = fieldMap.get(fieldName); + if (oldMessages == null) { + oldMessages = messages; + fieldMap.put(fieldName, oldMessages); + } else { + oldMessages.addAll(messages); + } + } + } + + public void setMessagesForScope(NuitonValidatorScope scope, + String field, + List<String> messages) { + + if (this.messages == null) { + this.messages = new EnumMap<NuitonValidatorScope, FieldMap<List<String>>>(NuitonValidatorScope.class); + } + + FieldMap<List<String>> fieldMap = this.messages.get(scope); + if (fieldMap == null) { + fieldMap = new FieldMap<List<String>>(); + this.messages.put(scope, fieldMap); + } + fieldMap.put(field, messages); + } + + public List<String> getMessagesForScope(NuitonValidatorScope scope) { + + List<String> result = new ArrayList<String>(); + if (messages != null) { + FieldMap<List<String>> fieldMap = messages.get(scope); + for (List<String> messages : fieldMap.values()) { + result.addAll(messages); + } + } + return result; + } + + public List<String> getMessagesForScope(String field, + NuitonValidatorScope scope) { + + List<String> result = null; + if (messages != null) { + FieldMap<List<String>> fieldMap = messages.get(scope); + result = fieldMap.get(field); + } + if (result == null) { + result = Collections.emptyList(); + } + return result; + } + + public List<String> getFatalMessages(String field) { + List<String> result = + getMessagesForScope(field, NuitonValidatorScope.FATAL); + return result; + } + + public List<String> getErrorMessages(String field) { + List<String> result = + getMessagesForScope(field, NuitonValidatorScope.ERROR); + return result; + } + + public List<String> getInfoMessages(String field) { + List<String> result = + getMessagesForScope(field, NuitonValidatorScope.INFO); + return result; + } + + public List<String> getWarningMessages(String field) { + List<String> result = + getMessagesForScope(field, NuitonValidatorScope.WARNING); + return result; + } + + public Map<String, Object> getTagValues(String field) { + Map<String, Object> result = null; + if (tagValues != null) { + result = tagValues.get(field); + } + if (result == null) { + result = Collections.emptyMap(); + } + return result; + } + + public List<String> getFieldsForScope(NuitonValidatorScope scope) { + + List<String> result = null; + if (messages != null) { + FieldMap<List<String>> fieldMap = messages.get(scope); + if (fieldMap != null) { + result = new ArrayList<String>(fieldMap.keySet()); + } + } + if (result == null) { + result = Collections.emptyList(); + } + return result; + } + + public List<String> getFieldsForFatal() { + List<String> result = getFieldsForScope(NuitonValidatorScope.FATAL); + return result; + } + + public List<String> getFieldsForError() { + List<String> result = getFieldsForScope(NuitonValidatorScope.ERROR); + return result; + } + + public List<String> getFieldsForInfo() { + List<String> result = getFieldsForScope(NuitonValidatorScope.INFO); + return result; + } + + public List<String> getFieldsForWarning() { + List<String> result = getFieldsForScope(NuitonValidatorScope.WARNING); + return result; + } + + public void clearMessagesForScope(NuitonValidatorScope scope) { + if (messages != null) { + messages.remove(scope); + } + } + + public NuitonValidatorScope getFieldHighestScope(String field) { + if (messages == null) { + return null; + } + if (containsField(field, NuitonValidatorScope.FATAL)) { + return NuitonValidatorScope.FATAL; + } + if (containsField(field, NuitonValidatorScope.ERROR)) { + return NuitonValidatorScope.ERROR; + } + if (containsField(field, NuitonValidatorScope.WARNING)) { + return NuitonValidatorScope.WARNING; + } + if (containsField(field, NuitonValidatorScope.INFO)) { + return NuitonValidatorScope.INFO; + } + + // no scope for the field + return null; + } + + public NuitonValidatorScope[] getFieldScopes(String field) { + Set<NuitonValidatorScope> result = new HashSet<NuitonValidatorScope>(); + if (messages != null) { + + if (containsField(field, NuitonValidatorScope.FATAL)) { + result.add(NuitonValidatorScope.FATAL); + } + if (containsField(field, NuitonValidatorScope.ERROR)) { + result.add(NuitonValidatorScope.ERROR); + } + if (containsField(field, NuitonValidatorScope.WARNING)) { + result.add(NuitonValidatorScope.WARNING); + } + if (containsField(field, NuitonValidatorScope.INFO)) { + result.add(NuitonValidatorScope.INFO); + } + } + + return result.toArray(new NuitonValidatorScope[result.size()]); + } + + protected boolean containsField(String field, NuitonValidatorScope scope) { + FieldMap<List<String>> fieldMap = messages.get(scope); + return fieldMap != null && fieldMap.containsKey(field); + } + + protected EnumMap<NuitonValidatorScope, FieldMap<List<String>>> getMessages() { + return messages; + } + + protected Map<String, FieldMap<Object>> getTagValues() { + return tagValues; + } +} diff --git a/src/main/java/org/nuiton/validator/NuitonValidatorScope.java b/src/main/java/org/nuiton/validator/NuitonValidatorScope.java new file mode 100644 index 0000000..5a2b64b --- /dev/null +++ b/src/main/java/org/nuiton/validator/NuitonValidatorScope.java @@ -0,0 +1,78 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import static org.nuiton.i18n.I18n.n_; + +/** + * The differents levels of messages in validation process. + * <p/> + * The order of the enum defines the severity of validation. + * <p/> + * Always begin with fatal, then error, then if no error found, try warning, then info... + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public enum NuitonValidatorScope { + + /** + * the fatal error scope level. + * <p/> + * When a message of a such scope is found on a validator, then the + * validator is invalid and modified. + */ + FATAL(n_("validator.scope.fatal.label")), + /** + * the error scope level. + * <p/> + * When a message of a such scope is found on a validator, then the + * validator is invalid and modified. + */ + ERROR(n_("validator.scope.error.label")), + /** + * the warning scope level. + * <p/> + * When a message of a such scope is found on a validator, then the + * validator is still valid but modified. + */ + WARNING(n_("validator.scope.warning.label")), + /** + * the information scope level. + * <p/> + * When a message of a sucg scope is found on a validator, then the + * validator is still valid and not modified. + */ + INFO(n_("validator.scope.info.label")); + + private final String label; + + NuitonValidatorScope(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } +} diff --git a/src/main/java/org/nuiton/validator/bean/AbstractNuitonValidatorContext.java b/src/main/java/org/nuiton/validator/bean/AbstractNuitonValidatorContext.java new file mode 100644 index 0000000..2e1f646 --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/AbstractNuitonValidatorContext.java @@ -0,0 +1,389 @@ +package org.nuiton.validator.bean; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.commons.beanutils.ConversionException; +import org.apache.commons.beanutils.Converter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.converter.ConverterUtil; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorResult; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; + +import java.beans.Introspector; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Defines a context of validation used for a single bean. + * <p/> + * {@link BeanValidator} will then used one of this object and + * {@link BeanListValidator} as many as it contains beans. + * <p/> + * This object box a {@link NuitonValidator} to get validation state each time + * a higher validator requires it. + * <p/> + * It also offers the way to create events (merge logic + * + * @param <O> type of bean to validate + * @param <V> type of bean validator used + * @param <E> type of event to create + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public abstract class AbstractNuitonValidatorContext<O, V, E> { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(AbstractNuitonValidatorContext.class); + + /** Bean to validate. */ + protected O bean; + + /** + * State of validation (keep all messages of validation for the filled + * bean). + */ + protected NuitonValidatorResult messages; + + /** Validator. */ + protected NuitonValidator<O> validator; + + /** map of conversion errors detected by this validator */ + protected final Map<String, String> conversionErrors; + + /** + * State to know if the validator can be used (we keep this state for + * performance reasons : do not want to compute this value each time a + * validation is asked...). + */ + protected boolean canValidate; + + protected abstract E createEvent(V source, + O bean, + String field, + NuitonValidatorScope scope, + String[] toAdd, + String[] toDelete); + + public AbstractNuitonValidatorContext() { + conversionErrors = Maps.newTreeMap(); + } + + public O getBean() { + return bean; + } + + public void setBean(O bean) { + if (log.isDebugEnabled()) { + log.debug(this + " : " + bean); + } + + // clean conversions of previous bean + conversionErrors.clear(); + this.bean = bean; + + setCanValidate(!validator.getEffectiveFields().isEmpty() && bean != null); + } + + public NuitonValidator<O> getValidator() { + return validator; + } + + public NuitonValidatorResult getMessages() { + return messages; + } + + public boolean isCanValidate() { + return canValidate; + } + + public void setCanValidate(boolean canValidate) { + this.canValidate = canValidate; + } + + public boolean isValid() { + return messages == null || messages.isValid(); + } + + public boolean hasFatalErrors() { + boolean result = messages != null && messages.hasFatalMessages(); + return result; + } + + public boolean hasErrors() { + boolean result = messages != null && messages.hasErrorMessagess(); + return result; + } + + public boolean hasWarnings() { + boolean result = messages != null && messages.hasWarningMessages(); + return result; + } + + public boolean hasInfos() { + boolean result = messages != null && messages.hasInfoMessages(); + return result; + } + + public boolean isValid(String fieldName) { + + // field is valid if no fatal messages nor error messages + boolean result = !( + messages.hasMessagesForScope(fieldName, NuitonValidatorScope.FATAL) || + messages.hasMessagesForScope(fieldName, NuitonValidatorScope.ERROR)); + + return result; + } + + public NuitonValidatorScope getHighestScope(String field) { + + NuitonValidatorScope scope = messages.getFieldHighestScope(field); + return scope; + } + + public void setValidator(NuitonValidator<O> validator) { + this.validator = validator; + } + + public NuitonValidatorResult validate() { + NuitonValidatorResult result = validator.validate(bean); + + // treate conversion errors + // reinject them + for (Map.Entry<String, String> entry : conversionErrors.entrySet()) { + + + // remove from validation, errors occurs on this field + String field = entry.getKey(); + + + List<String> errors = result.getErrorMessages(field); + + String conversionError = entry.getValue(); + if (errors != null) { + errors.clear(); + errors.add(conversionError); + } else { + errors = Collections.singletonList(conversionError); + } + + result.setMessagesForScope(NuitonValidatorScope.ERROR, field, errors); + } + return result; + } + + /** + * Convert a value. + * <p/> + * If an error occurs, then add an error in validator. + * + * @param <T> the type of conversion + * @param fieldName the name of the bean property + * @param value the value to convert + * @param valueClass the type of converted value + * @return the converted value, or null if conversion was not ok + */ + @SuppressWarnings({"unchecked"}) + public <T> T convert(String fieldName, String value, Class<T> valueClass) { + if (fieldName == null) { + throw new IllegalArgumentException("fieldName can not be null"); + } + if (valueClass == null) { + throw new IllegalArgumentException("valueClass can not be null"); + } + + // on ne convertit pas si il y a un bean et que le resultat de la + // validation pourra etre affiche quelque part + if (!isCanValidate() || value == null) { + return null; + } + + // remove the previous conversion error for the field + conversionErrors.remove(fieldName); + + T result; + try { + Converter converter = ConverterUtil.getConverter(valueClass); + if (converter == null) { + throw new RuntimeException( + "could not find converter for the type " + valueClass); + } + result = (T) converter.convert(valueClass, value); + /* Why this test ? if (result != null && !value.equals(result.toString())) { + conversionErrors.put(fieldName, "error.convertor." + Introspector.decapitalize(valueClass.getSimpleName())); + result = null; + validate(); + }*/ + } catch (ConversionException e) { + // get + String s = Introspector.decapitalize(valueClass.getSimpleName()); + conversionErrors.put(fieldName, "error.convertor." + s); + throw e; + } + return result; + } + + public List<E> mergeMessages(V beanValidator, + NuitonValidatorResult newMessages) { + + if (newMessages == null && messages == null) { + + // no messages ever registred and ask to delete them, so nothing + // to do + return null; + } + + Set<NuitonValidatorScope> scopes = getValidator().getEffectiveScopes(); + + // list of events to send after the merge of messages + List<E> events = Lists.newArrayList(); + + for (NuitonValidatorScope scope : scopes) { + + // do the merge at scope level + mergeMessages(beanValidator, scope, newMessages, events); + + } + + if (newMessages != null) { + + //TODO tchemit 2011-01-23 Perharps it will necessary to clear the messages for memory performance ? + + // finally keep the new messages as the current messages + this.messages = newMessages; + } + + return events; + } + + protected void mergeMessages(V beanValidator, + NuitonValidatorScope scope, + NuitonValidatorResult newMessages, + List<E> events) { + + + if (newMessages == null) { + + // special case to empty all messages + + List<String> fieldsForScope = messages.getFieldsForScope(scope); + + for (String field : fieldsForScope) { + List<String> messagesForScope = messages.getMessagesForScope(field, scope); + events.add(createEvent(beanValidator, bean, field, scope, null, messagesForScope.toArray(new String[messagesForScope.size()]))); + } + + // suppress all messages for this scope + messages.clearMessagesForScope(scope); + + + } else { + + List<String> newFields = newMessages.getFieldsForScope(scope); + + if (messages == null) { + + // first time of a merge, just add new messages + + for (String field : newFields) { + List<String> messagesForScope = newMessages.getMessagesForScope(field, scope); + events.add(createEvent(beanValidator, bean, field, scope, messagesForScope.toArray(new String[messagesForScope.size()]), null)); + } + + // nothing else to do + return; + } + + List<String> oldFields = messages.getFieldsForScope(scope); + + Iterator<String> itr; + + // detects field with only new messages + itr = newFields.iterator(); + while (itr.hasNext()) { + String newField = itr.next(); + + if (!oldFields.contains(newField)) { + + // this fields has now messages but not before : new messages + List<String> messagesForScope = newMessages.getMessagesForScope(newField, scope); + events.add(createEvent(beanValidator, bean, newField, scope, messagesForScope.toArray(new String[messagesForScope.size()]), null)); + + // treated field + itr.remove(); + } + } + + // detects fields with only obsolete messages + itr = oldFields.iterator(); + while (itr.hasNext()) { + String oldField = itr.next(); + + if (!newFields.contains(oldField)) { + + // this fields has no more messages + List<String> messagesForScope = messages.getMessagesForScope(oldField, scope); + events.add(createEvent(beanValidator, bean, oldField, scope, null, messagesForScope.toArray(new String[messagesForScope.size()]))); + + // treated field + itr.remove(); + } + } + + // now deal with mixte field (toAdd and toDelete) + for (String field : newFields) { + + List<String> newMessagesForScope = newMessages.getMessagesForScope(field, scope); + List<String> oldMessagesForScope = messages.getMessagesForScope(field, scope); + + // get old obsoletes messages to delete + Set<String> toDelete = new HashSet<String>(oldMessagesForScope); + toDelete.removeAll(newMessagesForScope); + + // get new messages to add + Set<String> toAdd = new HashSet<String>(newMessagesForScope); + toAdd.removeAll(oldMessagesForScope); + + events.add(createEvent( + beanValidator, + bean, + field, + scope, + toAdd.isEmpty() ? null : toAdd.toArray(new String[toAdd.size()]), + toDelete.isEmpty() ? null : toDelete.toArray(new String[toDelete.size()]) + )); + + } + } + } +} diff --git a/src/main/java/org/nuiton/validator/bean/AbstractValidator.java b/src/main/java/org/nuiton/validator/bean/AbstractValidator.java new file mode 100644 index 0000000..c885661 --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/AbstractValidator.java @@ -0,0 +1,390 @@ +package org.nuiton.validator.bean; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.apache.commons.lang3.ObjectUtils; +import org.nuiton.util.beans.BeanUtil; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorModel; +import org.nuiton.validator.NuitonValidatorProvider; +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.event.EventListenerList; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Set; + +/** + * TODO + * + * @param <O> type of bean to validate + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public abstract class AbstractValidator<O> { + + /** + * Name of the bounded property {@code context}. + * + * @see #getContext() + * @see #setContext(String) + */ + public static final String CONTEXT_PROPERTY = "context"; + + /** + * Name of the bounded property {@code scopes}. + * + * @see #getScopes() + * @see #setScopes(NuitonValidatorScope...) + */ + public static final String SCOPES_PROPERTY = "scopes"; + + /** + * Name of the bounded property {@link #valid}. + * + * @see #valid + * @see #isValid() + * @see #setValid(boolean) + */ + public static final String VALID_PROPERTY = "valid"; + + /** + * Name of the bounded property {@link #changed}. + * + * @see #changed + * @see #isChanged() + * @see #setChanged(boolean) + */ + public static final String CHANGED_PROPERTY = "changed"; + +// /** Logger. */ +// private static final Log log = LogFactory.getLog(BeanValidator.class); + +// /** +// * The delegate validator used to validate the bean. +// * +// * @since 2.5.2 +// */ +// protected NuitonValidator<O> delegate; + + /** + * State to indicate that validator has changed since the last time bean was + * setted. + */ + protected boolean changed; + + /** State of the validator (is true if no errors of error scope is found). */ + protected boolean valid = true; + + /** + * State to know if the validator can be used (we keep this state for + * performance reasons : do not want to compute this value each time a + * validation is asked...). + */ + protected boolean canValidate = true; + + /** Listener that listens on bean modification. */ + protected final PropertyChangeListener l; + + /** delegate property change support */ + protected final PropertyChangeSupport pcs; + + /** A list of event listeners for this validators */ + protected final EventListenerList listenerList = new EventListenerList(); + + /** + * The provider of delegate validators. + * <p/> + * It will also produce validator model. + * + * @see NuitonValidatorProvider + */ + protected final NuitonValidatorProvider validatorProvider; + + + protected AbstractValidator(NuitonValidatorProvider validatorProvider, + Class<O> beanClass) { + + // check if given bean class is Javabean compiliant + boolean javaBeanCompiliant = BeanUtil.isJavaBeanCompiliant(beanClass); + Preconditions.checkState( + javaBeanCompiliant, + beanClass.getName() + " is not JavaBean compiliant (" + + BeanUtil.ADD_PROPERTY_CHANGE_LISTENER + ", or " + + BeanUtil.REMOVE_PROPERTY_CHANGE_LISTENER + + " method not found)."); + + this.validatorProvider = validatorProvider; + + pcs = new PropertyChangeSupport(this); + +// // build delegate validator +// rebuildDelegateValidator( +// beanClass, +// context, +// scopes +// ); + +// // context has changed +// firePropertyChange(CONTEXT_PROPERTY, +// null, +// context +// ); +// +// // scopes has changed +// firePropertyChange(SCOPES_PROPERTY, +// null, +// scopes +// ); + + l = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + + O bean = (O) evt.getSource(); + + // the bean has changed, replay validation + doValidate(bean); + } + }; + } + + /** + * Obtain the {@link #changed} property value. + * <p/> + * Returns {@code true} if bean was modified since last + * time a bean was attached. + * + * @return {@code true} if bean was modified since last attachement of + * a bean. + */ + public boolean isChanged() { + return changed; + } + + /** + * To force the value of the property {@link #changed}. + * + * @param changed flag to force reset of property {@link #changed} + */ + public void setChanged(boolean changed) { + this.changed = changed; + + // force the property to be fired (never pass the older value) + firePropertyChange(CHANGED_PROPERTY, null, changed); + } + + public boolean isCanValidate() { + return canValidate; + } + + public void setCanValidate(boolean canValidate) { + this.canValidate = canValidate; + } + + /** + * Obtain the {@link #valid} property value. + * + * @return {@code true} if attached bean is valid (no error or fatal messages) + */ + public boolean isValid() { + return valid; + } + + /** + * Change the value of the {@link #valid} property. + * + * @param valid the new value of the property + */ + public void setValid(boolean valid) { + this.valid = valid; + + // force the property to be fired (never pass the older value) + firePropertyChange(VALID_PROPERTY, null, valid); + } + + + public String getContext() { + return getModel().getContext(); + } + + public void setContext(String context) { + + String oldContext = getContext(); + + if (ObjectUtils.equals(context, oldContext)) { + + // same context do nothing + return; + } + + NuitonValidatorModel<O> model = getModel(); + + // compute the new validator model + NuitonValidatorScope[] scopes = model.getScopes().toArray( + new NuitonValidatorScope[model.getScopes().size()]); + + rebuildDelegateValidator( + model.getType(), + context, + scopes + ); + + firePropertyChange(CONTEXT_PROPERTY, + oldContext, + context + ); + } + + public Set<NuitonValidatorScope> getScopes() { + return getModel().getScopes(); + } + + public Set<NuitonValidatorScope> getEffectiveScopes() { + return getDelegate().getEffectiveScopes(); + } + + public Set<String> getEffectiveFields() { + return getDelegate().getEffectiveFields(); + } + + public Set<String> getEffectiveFields(NuitonValidatorScope scope) { + return getDelegate().getEffectiveFields(scope); + } + + public void setScopes(NuitonValidatorScope... scopes) { + + Set<NuitonValidatorScope> oldScopes = getScopes(); + + rebuildDelegateValidator( + getModel().getType(), + getModel().getContext(), + scopes + ); + + firePropertyChange(SCOPES_PROPERTY, + oldScopes, + scopes + ); + } + + public abstract void doValidate(); + + public abstract boolean hasFatalErrors(); + + public abstract boolean hasErrors(); + + public abstract boolean hasWarnings(); + + public abstract boolean hasInfos(); + + public abstract boolean isValid(String fieldName); + + public abstract NuitonValidatorScope getHighestScope(String field); + + public abstract <T> T convert(O bean, String fieldName, String value, Class<T> valueClass); + + protected abstract void doValidate(O bean); + + protected abstract NuitonValidator<O> getDelegate(); + + protected abstract void rebuildDelegateValidator(Class<O> beanType, + String context, + NuitonValidatorScope... scopes); + + public Class<O> getType() { + return getModel().getType(); + } + + /** + * Test a the validator contains the field given his name + * + * @param fieldName the name of the searched field + * @return <code>true</code> if validator contaisn this field, + * <code>false</code> otherwise + */ + public boolean containsField(String fieldName) { + Set<String> effectiveFields = getDelegate().getEffectiveFields(); + boolean result = effectiveFields.contains(fieldName); + return result; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public void firePropertyChange(String propertyName, + Object oldValue, + Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected NuitonValidatorModel<O> getModel() { + return getDelegate().getModel(); + } + +// protected NuitonValidator<O> rebuildDelegateValidator(Class<O> beanType, +// String context, +// NuitonValidatorScope... scopes) { +// +// // changing context could change fields definition +// // so dettach bean, must rebuild the fields +// +// // Dettach the bean before any thing, because with the new delegate +// // validator some old fields could not be used any longer, and then +// // listeners will never have the full reset of their model... +// +// // remove all validators. +// +// if (scopes == null || scopes.length == 0) { +// scopes = NuitonValidatorScope.values(); +// } +// +// // compute the new validator model +// NuitonValidatorModel<O> model = validatorProvider.getModel(beanType, +// context, +// scopes +// ); +// +// // remove old delegate validator +// NuitonValidator<O> delegate = validatorProvider.newValidator(model); +// } +} diff --git a/src/main/java/org/nuiton/validator/bean/AbstractValidatorEvent.java b/src/main/java/org/nuiton/validator/bean/AbstractValidatorEvent.java new file mode 100644 index 0000000..42aca5e --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/AbstractValidatorEvent.java @@ -0,0 +1,85 @@ +package org.nuiton.validator.bean; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.NuitonValidatorScope; + +import java.util.EventObject; + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public abstract class AbstractValidatorEvent<V> extends EventObject { + + private static final long serialVersionUID = 1L; + + /** the field impacted by the validator */ + protected String field; + + /** the scope impacted by the event */ + protected NuitonValidatorScope scope; + + protected String[] messagestoAdd; + + protected String[] messagestoDelete; + + public abstract Object getBean(); + + public AbstractValidatorEvent(V source, + String field, + NuitonValidatorScope scope, + String[] messagestoAdd, + String[] messagestoDelete) { + super(source); + this.field = field; + this.scope = scope; + this.messagestoAdd = messagestoAdd; + this.messagestoDelete = messagestoDelete; + } + + @Override + public V getSource() { + return (V) super.getSource(); + } + + public String[] getMessagesToAdd() { + return messagestoAdd; + } + + public String[] getMessagesToDelete() { + return messagestoDelete; + } + + public NuitonValidatorScope getScope() { + return scope; + } + + public String getField() { + return field; + } + +} diff --git a/src/main/java/org/nuiton/validator/bean/ValidatorCreator.java b/src/main/java/org/nuiton/validator/bean/ValidatorCreator.java new file mode 100644 index 0000000..eeb8ce8 --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/ValidatorCreator.java @@ -0,0 +1,53 @@ +package org.nuiton.validator.bean; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.NuitonValidatorProvider; +import org.nuiton.validator.NuitonValidatorScope; + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public interface ValidatorCreator<V> { + + /** + * Given the parameters, instanciate a new {@link V}. + * + * @param provider the delegate validator provider + * @param type the type of object to validate + * @param context the context of validation (can be {@code null}) + * @param scopes scopes to use (if none given, will use all available scopes) + * @param <O> type of object to validate + * @return the new instance of bean validator + */ + <O> V newValidator(NuitonValidatorProvider provider, + Class<O> type, + String context, + NuitonValidatorScope... scopes + + ); +} diff --git a/src/main/java/org/nuiton/validator/bean/ValidatorListener.java b/src/main/java/org/nuiton/validator/bean/ValidatorListener.java new file mode 100644 index 0000000..36e2fa1 --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/ValidatorListener.java @@ -0,0 +1,47 @@ +package org.nuiton.validator.bean; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.bean.list.BeanListValidator; +import org.nuiton.validator.bean.list.BeanListValidatorEvent; + +import java.util.EventListener; + +/** + * The definition of an event on {@link BeanListValidatorEvent} + * to be fired by a {@link BeanListValidator}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public interface ValidatorListener<E extends AbstractValidatorEvent<?>> extends EventListener { + + /** + * Invoked when the {@link E} detects some changes for a + * given bean / field / scope. + * + * @param event the event + */ + void onFieldChanged(E event); +} diff --git a/src/main/java/org/nuiton/validator/bean/list/BeanListValidator.java b/src/main/java/org/nuiton/validator/bean/list/BeanListValidator.java new file mode 100644 index 0000000..1e535c6 --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/list/BeanListValidator.java @@ -0,0 +1,560 @@ +package org.nuiton.validator.bean.list; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.apache.commons.beanutils.ConversionException; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.beans.BeanUtil; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorFactory; +import org.nuiton.validator.NuitonValidatorModel; +import org.nuiton.validator.NuitonValidatorProvider; +import org.nuiton.validator.NuitonValidatorResult; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.AbstractNuitonValidatorContext; +import org.nuiton.validator.bean.AbstractValidator; + +import java.beans.PropertyChangeListener; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * To validate a list of beans. + * <p/> + * Each bean of the list will be associated with a {@link NuitonValidatorContext}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public class BeanListValidator<O> extends AbstractValidator<O> { + + /** Logger. */ + private static final Log log = LogFactory.getLog(BeanListValidator.class); + + /** + * Obtain a new {@link BeanListValidator} for the given parameters. + * <p/> + * <b>Note:</b> It will use the default provider of {@link NuitonValidator} + * + * @param type type of bean to validate + * @param context context of validation + * @param scopes authorized scopes (if {@code null}, will use all scopes) + * @param <O> type of bean to validate + * @return the new instanciated {@link BeanListValidator}. + * @throws NullPointerException if type is {@code null} + * @see NuitonValidatorFactory#getDefaultProviderName() + */ + public static <O> BeanListValidator<O> newValidator(Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + + // get the provider default name + String providerName = NuitonValidatorFactory.getDefaultProviderName(); + + // get the bean validator with this provider + BeanListValidator<O> beanValidator = newValidator(providerName, + type, + context, + scopes + ); + return beanValidator; + } + + /** + * Obtain a new {@link BeanListValidator} for the given parameters. + * <p/> + * <b>Note:</b> It will use the provider of {@link NuitonValidator} + * defined by the {@code providerName}. + * + * @param providerName name of {@link NuitonValidator} to use + * @param type type of bean to validate + * @param context context of validation + * @param scopes authorized scopes (if {@code null}, will use all scopes) + * @param <O> type of bean to validate + * @return the new instanciated {@link BeanListValidator}. + * @throws NullPointerException if type is {@code null} + * @see NuitonValidatorFactory#getProvider(String) + */ + public static <O> BeanListValidator<O> newValidator(String providerName, + Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + Preconditions.checkNotNull(type, "type parameter can not be null."); + + // get delegate validator provider + NuitonValidatorProvider provider = + NuitonValidatorFactory.getProvider(providerName); + + Preconditions.checkState( + provider != null, + "Could not find provider with name " + providerName); + + // create the new instance of bean validator + BeanListValidator<O> validator = new BeanListValidator<O>( + provider, type, context, scopes + ); + + return validator; + } + + /** + * Context for each bean registred. + * + * @since 2.5.2 + */ + protected final Map<O, NuitonValidatorContext<O>> contexts; + + /** + * The delegate validator used to validate the bean. + * + * @since 2.5.2 + */ + protected NuitonValidator<O> delegate; + + public BeanListValidator(NuitonValidatorProvider validatorProvider, + Class<O> beanClass, + String context) { + + this(validatorProvider, beanClass, + context, + NuitonValidatorScope.values() + ); + } + + public BeanListValidator(NuitonValidatorProvider validatorProvider, + Class<O> beanClass, + String context, + NuitonValidatorScope... scopes) { + + super(validatorProvider, beanClass); + + contexts = Maps.newHashMap(); + + // build delegate validator + rebuildDelegateValidator(beanClass, context, scopes); + + // context has changed + firePropertyChange(CONTEXT_PROPERTY, + null, + context + ); + + // scopes has changed + firePropertyChange(SCOPES_PROPERTY, + null, + scopes + ); + } + + /** + * Add a bean to validate. + * <p/> + * The bean can not be null, nor registered twice in the validator. + * + * @param bean the bean to attach (can not be {@code null}). + */ + public void addBean(O bean) { + + // bean can not be null + Preconditions.checkNotNull(bean); + + // can not register twice the same bean + Preconditions.checkState(!contexts.containsKey(bean), + "The bean " + bean + + " is already registred in this validator."); + + if (log.isDebugEnabled()) { + log.debug(this + " : " + bean); + } + + // create validator for this bean + NuitonValidator<O> validator = validatorProvider.newValidator(getModel()); + + // register it + NuitonValidatorContext<O> newcontext = + new NuitonValidatorContext<O>(bean, validator); + newcontext.setValidator(validator); + newcontext.setBean(bean); + + contexts.put(bean, newcontext); + + setCanValidate(isCanValidate() && newcontext.isCanValidate()); + + try { + + BeanUtil.addPropertyChangeListener(l, bean); + } catch (Exception eee) { + if (log.isInfoEnabled()) { + log.info("Can't register as listener for bean " + bean.getClass() + + " for reason " + eee.getMessage(), eee); + } + } + validate(bean); + + setChanged(false); + setValid(isValid0()); +// firePropertyChange(BEAN_PROPERTY, oldBean, bean); + } + + public void addAllBeans(Collection<O> beansToAdd) { + for (O bean : beansToAdd) { + addBean(bean); + } + } + + /** + * Remove the given bean from the validaotr. + * <p/> + * The bean can not be {@code null}, nor not has been previously + * registred in this validator. + * + * @param bean the bean to unregister + */ + public void removeBean(O bean) { + + // bean can not be null + Preconditions.checkNotNull(bean); + + if (log.isDebugEnabled()) { + log.debug(this + " : " + bean); + } + + // remove all messages for all fields of the validator + NuitonValidatorContext<O> context = getContext(bean); + + mergeMessages(context, null); + + contexts.remove(bean); + + try { + BeanUtil.removePropertyChangeListener(l, bean); + } catch (Exception eee) { + if (log.isInfoEnabled()) { + log.info("Can't unregister as listener for bean " + bean.getClass() + + " for reason " + eee.getMessage(), eee); + } + } + } + + /** + * Remove all the given beans fro this validator. + * <p/> + * Like in method {@link #removeBean(Object)}, each bean must be not + * {@code null} and has been previously registred in this validator. + * + * @param beansToRemove beans to remove from this validator + */ + public void removeAllBeans(Collection<O> beansToRemove) { + for (O bean : beansToRemove) { + removeBean(bean); + } + } + + /** + * Shortcut method to unregister all previously registred beans from + * this validator. + */ + public void removeAllBeans() { + Set<O> beansToRemove = getBeans(); + removeAllBeans(beansToRemove); + } + + @Override + public boolean hasFatalErrors() { + boolean result = false; + for (NuitonValidatorContext<O> context : contexts.values()) { + result = context.hasFatalErrors(); + if (result) { + break; + } + } + return result; + } + + @Override + public boolean hasErrors() { + boolean result = false; + for (NuitonValidatorContext<O> context : contexts.values()) { + result = context.hasErrors(); + if (result) { + break; + } + } + return result; + } + + @Override + public boolean hasWarnings() { + boolean result = false; + for (NuitonValidatorContext<O> context : contexts.values()) { + result = context.hasWarnings(); + if (result) { + break; + } + } + return result; + } + + @Override + public boolean hasInfos() { + boolean result = false; + for (NuitonValidatorContext<O> context : contexts.values()) { + result = context.hasInfos(); + if (result) { + break; + } + } + return result; + } + + @Override + public boolean isValid(String fieldName) { + boolean result = true; + + for (NuitonValidatorContext<O> context : contexts.values()) { + result = context.isValid(fieldName); + if (!result) { + break; + } + } + return result; + } + + @Override + public NuitonValidatorScope getHighestScope(String field) { + Set<NuitonValidatorScope> scopes = Sets.newHashSet(); + for (NuitonValidatorContext<O> context : contexts.values()) { + scopes.add(context.getHighestScope(field)); + } + NuitonValidatorScope scope = null; + if (scopes.isEmpty()) { + List<NuitonValidatorScope> scopeList = Lists.newArrayList(scopes); + Collections.sort(scopeList); + scope = scopeList.get(0); + } + return scope; + } + + @Override + public void doValidate() { + validate(); + setValid(isValid0()); + setChanged(true); + } + + /** + * Convert a value. + * <p/> + * If an error occurs, then add an error in validator. + * + * @param <T> the type of conversion + * @param fieldName the name of the bean property + * @param value the value to convert + * @param valueClass the type of converted value + * @return the converted value, or null if conversion was not ok + */ + @Override + public <T> T convert(O bean, + String fieldName, + String value, + Class<T> valueClass) { + NuitonValidatorContext<O> context = getContext(bean); + T convert = null; + try { + convert = context.convert(fieldName, value, valueClass); + } catch (ConversionException e) { + // must revalidate + validate(); + } + return convert; + } + + public void addBeanListValidatorListener(BeanListValidatorListener listener) { + listenerList.add(BeanListValidatorListener.class, listener); + } + + public void removeBeanListValidatorListener(BeanListValidatorListener listener) { + listenerList.remove(BeanListValidatorListener.class, listener); + } + + public BeanListValidatorListener[] getBeanListValidatorListeners() { + return listenerList.getListeners(BeanListValidatorListener.class); + } + + public Set<O> getBeans() { + return ImmutableSet.copyOf(contexts.keySet()); + } + + @Override + protected void doValidate(O bean) { + validate(bean); + setValid(isValid0()); + setChanged(true); + } + + @Override + protected NuitonValidator<O> getDelegate() { + return delegate; + } + + @Override + protected void rebuildDelegateValidator(Class<O> beanType, + String context, + NuitonValidatorScope... scopes) { + + // changing context could change fields definition + // so dettach bean, must rebuild the fields + + // Dettach the bean before any thing, because with the new delegate + // validator some old fields could not be used any longer, and then + // listeners will never have the full reset of their model... + + // remove all validators. + + if (scopes == null || scopes.length == 0) { + scopes = NuitonValidatorScope.values(); + } + + // compute the new validator model + NuitonValidatorModel<O> model = validatorProvider.getModel(beanType, + context, + scopes + ); + + // remove old delegate validator + delegate = validatorProvider.newValidator(model); + } + + /** + * il faut eviter le code re-intrant (durant une validation, une autre est + * demandee). Pour cela on fait la validation dans un thread, et tant que la + * premiere validation n'est pas fini, on ne repond pas aux solicitations. + * Cette method est public pour permettre de force une validation par + * programmation, ce qui est utile par exemple si le bean ne supporte pas + * les {@link PropertyChangeListener} + * <p/> + * <b>Note:</b> la methode est protected et on utilise la methode + * {@link #doValidate()} car la méthode ne modifie pas les etats + * internes et cela en rend son utilisation delicate (le validateur entre + * dans un etat incoherent par rapport aux messages envoyés). + */ + protected void validate() { + + // on ne valide que si il y a un bean et que le resultat de la validation + // pourra etre affiche quelque part + if (isCanValidate()) { + + for (O bean : contexts.keySet()) { + + validate(bean); + } + } + } + + protected void validate(O bean) { + NuitonValidatorContext<O> validator = getContext(bean); + NuitonValidatorResult result = validator.validate(); + mergeMessages(validator, result); + } + + protected boolean isValid0() { + boolean result = true; + for (NuitonValidatorContext<O> context : contexts.values()) { + result = context.isValid(); + if (!result) { + break; + } + } + return result; + } + + protected void mergeMessages(NuitonValidatorContext<O> context, + NuitonValidatorResult newMessages) { + + List<BeanListValidatorEvent> events = context.mergeMessages( + this, newMessages); + + if (CollectionUtils.isNotEmpty(events)) { + + // send all messages + for (BeanListValidatorEvent event : events) { + fireFieldChanged(event); + } + } + } + + protected void fireFieldChanged(BeanListValidatorEvent evt) { + + for (BeanListValidatorListener listener : + listenerList.getListeners(BeanListValidatorListener.class)) { + listener.onFieldChanged(evt); + } + } + + public NuitonValidatorContext<O> getContext(O bean) { + NuitonValidatorContext<O> context = contexts.get(bean); + Preconditions.checkState( + context != null, + "Bean " + bean + " was not register in this list validator"); + return context; + } + + + public static class NuitonValidatorContext<O> extends AbstractNuitonValidatorContext<O, BeanListValidator<O>, BeanListValidatorEvent> { + + public NuitonValidatorContext(O bean, NuitonValidator<O> validator) { + setValidator(validator); + setBean(bean); + } + + @Override + protected BeanListValidatorEvent createEvent(BeanListValidator<O> source, + O bean, + String field, + NuitonValidatorScope scope, + String[] toAdd, + String[] toDelete) { + return new BeanListValidatorEvent( + source, + bean, + field, + scope, + toAdd, + toDelete + ); + } + } +} diff --git a/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorEvent.java b/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorEvent.java new file mode 100644 index 0000000..777253e --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorEvent.java @@ -0,0 +1,56 @@ +package org.nuiton.validator.bean.list; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.AbstractValidatorEvent; + +/** + * Event to be fired when some messages changed on a given field / scope of a bean. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public class BeanListValidatorEvent extends AbstractValidatorEvent<BeanListValidator<?>> { + + private static final long serialVersionUID = 1L; + + /** the bean on which event occurs. */ + protected Object bean; + + public BeanListValidatorEvent(BeanListValidator<?> source, + Object bean, + String field, + NuitonValidatorScope scope, + String[] messagestoAdd, + String[] messagestoDelete) { + super(source, field, scope, messagestoAdd, messagestoDelete); + this.bean = bean; + } + + public Object getBean() { + return bean; + } + +} diff --git a/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorListener.java b/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorListener.java new file mode 100644 index 0000000..e03ff69 --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorListener.java @@ -0,0 +1,37 @@ +package org.nuiton.validator.bean.list; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.bean.ValidatorListener; + +/** + * The definition of an event on {@link BeanListValidatorEvent} + * to be fired by a {@link BeanListValidator}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public interface BeanListValidatorListener extends ValidatorListener<BeanListValidatorEvent> { + +} diff --git a/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorMessage.java b/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorMessage.java new file mode 100644 index 0000000..a9273dd --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/list/BeanListValidatorMessage.java @@ -0,0 +1,152 @@ +package org.nuiton.validator.bean.list; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.NuitonValidatorScope; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import static org.nuiton.i18n.I18n._; + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public class BeanListValidatorMessage<E extends BeanListValidatorMessage<?>> implements Comparable<E>, Serializable { + + private static final long serialVersionUID = 1L; + + /** the validator that produce the message */ + protected BeanListValidator<?> validator; + + /** the bean on which event occurs. */ + protected Object bean; + + /** the field that produce the message */ + protected String field; + + /** the label of the message (to be displayed somewhere) */ + protected String message; + + /** the scope of the message */ + protected NuitonValidatorScope scope; + + public BeanListValidatorMessage(BeanListValidator<?> validator, + Object bean, + String field, + String message, + NuitonValidatorScope scope) { + this.field = field; + this.bean = bean; + this.validator = validator; + this.message = message == null ? null : message.trim(); + this.scope = scope; + } + + public BeanListValidator<?> getValidator() { + return validator; + } + + public String getField() { + return field; + } + + public NuitonValidatorScope getScope() { + return scope; + } + + public String getMessage() { + return message; + } + + public Object getBean() { + return bean; + } + + @Override + public int compareTo(E o) { + // sort on scope + int result = getScope().compareTo(o.getScope()); + if (result == 0) { + // sort on field name + result = field.compareTo(o.field); + if (result == 0) { + // sort on message + result = message.compareTo(o.message); + } + } + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof BeanListValidatorMessage<?>)) { + return false; + } + + BeanListValidatorMessage<?> that = (BeanListValidatorMessage<?>) o; + + return field.equals(that.field) && + (message != null ? !message.equals(that.message) : that.message == null) && + scope == that.scope; + } + + @Override + public int hashCode() { + int result = field.hashCode(); + result = 31 * result + (bean != null ? bean.hashCode() : 0); + result = 31 * result + (message != null ? message.hashCode() : 0); + result = 31 * result + (scope != null ? scope.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return bean + "[" + scope + "] - " + getI18nError(message); + } + + public String getI18nError(String error) { + String text; + if (!error.contains("##")) { + text = _(error); + } else { + StringTokenizer stk = new StringTokenizer(error, "##"); + String errorName = stk.nextToken(); + List<String> args = new ArrayList<String>(); + while (stk.hasMoreTokens()) { + args.add(stk.nextToken()); + } + text = _(errorName, args.toArray()); + } + return text; + } +} diff --git a/src/main/java/org/nuiton/validator/bean/list/package-info.java b/src/main/java/org/nuiton/validator/bean/list/package-info.java new file mode 100644 index 0000000..0a4b06a --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/list/package-info.java @@ -0,0 +1,58 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/** + * Package of Nuiton - BeanListValidator api. + * + * <h1>The <b>BeanValidator</b> api</h1> + * <p> + * The {@link org.nuiton.validator.bean.list.BeanListValidator} purpose is to validate + * a list of bean, with a listener api to interact with outside world. + * </p> + * It is mainly used in GUI parts of an application (Jaxx-validator use it). + * <br/> + * The idea is to attach the bean to validate insed the validator, then the + * validator listen any modification of the bean to revalidate it and fires + * events when messages has changed on a field. + * + * <pre> + * BeanListValidatorListener listener = new BeanListValidatorListener() {XXX}; + * BeanValidator<O> validator = XXX; + * validator.addBeanListValidatorListener(listener); + * validator.addBean(bean1); + * validator.addBean(bean2); + * </pre> + * + * <h2>Obtain a validator</h2> + * To obtain a bean validator use one of the factory method on the + * {@link org.nuiton.validator.bean.list.BeanListValidator}. + * <br/> + * <pre> + * BeanListValidator<O> validator = BeanListValidator.newValidator(O.class); + * </pre> + * + * <strong>To be continued...</strong> + * + * @since 2.0 + */ +package org.nuiton.validator.bean.list; diff --git a/src/main/java/org/nuiton/validator/bean/package-info.java b/src/main/java/org/nuiton/validator/bean/package-info.java new file mode 100644 index 0000000..b0f2bae --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/package-info.java @@ -0,0 +1,71 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/** + * Package of Nuiton- beanValidator api. + * + * <strong>This api is deprecated since version 2.5.2 and will be removed in version 3.0</strong> + * + * <h1>The <b>BeanValidator</b> api</h1> + * <p> + * The {@link org.nuiton.validator.bean.BeanValidator} purpose is to validate + * a bean, with a listener api to interact with outside world. + * </p> + * It is mainly used in GUI parts of an application (Jaxx-validator use it). + * <br/> + * The idea is to attach the bean to validate insed the validator, then the + * validator listen any modification of the bean to revalidate it and fires + * events when messages has changed on a field. + * + * <pre> + * BeanValidatorListener listener = new BeanValidatorListener() {XXX}; + * BeanValidator<O> validator = XXX; + * validator.addBeanValidatorListener(listener); + * validator.setBean(o); + * </pre> + * + * <h2>Obtain a validator</h2> + * To obtain a bean validator use the factory of validators + * {@link org.nuiton.validator.bean.BeanValidatorFactory}. + * <br/> + * <pre> + * BeanValidator<O> validator = BeanValidatorFactory.newBeanValidator(O.class); + * </pre> + * + * <h2>Using the {@link org.nuiton.validator.bean.BeanValidatorFactory.BeanValidatorCreator}</h2> + * + * It is possible to use a {@link org.nuiton.validator.bean.BeanValidatorFactory.BeanValidatorCreator} to change the + * implementation of {@link org.nuiton.validator.bean.BeanValidator} + * instanticated by the factory. + * + * For this just use the method + * {@link org.nuiton.validator.bean.BeanValidatorFactory#setCreator(BeanValidatorCreator)}. + * + * By default it will us a default creator + * ({@link org.nuiton.validator.bean.BeanValidatorFactory.DefaultBeanValidatorCreator}). + * + * <strong>To be continued...</strong> + * + * @since 2.0 + */ +package org.nuiton.validator.bean; diff --git a/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidator.java b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidator.java new file mode 100644 index 0000000..439ed3b --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidator.java @@ -0,0 +1,478 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.bean.simple; + +import com.google.common.base.Preconditions; +import org.apache.commons.beanutils.ConversionException; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.beans.BeanUtil; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorFactory; +import org.nuiton.validator.NuitonValidatorModel; +import org.nuiton.validator.NuitonValidatorProvider; +import org.nuiton.validator.NuitonValidatorResult; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.AbstractNuitonValidatorContext; +import org.nuiton.validator.bean.AbstractValidator; + +import java.beans.PropertyChangeListener; +import java.util.List; + +/** + * Validator for a javaBean object. + * <p/> + * A such validator is designed to validate to keep the validation of a bean, + * means the bean is attached to the validator (via the context field {@link #context}. + * <p/> + * A such validator is also a JavaBean and you can listen his states + * modifications via the classic java bean api. + * <p/> + * <strong>Note:</strong> The {@link SimpleBeanValidator} should never be used for + * validation in a service approch since it needs to keep a reference to the + * bean to validate. + * + * @author tchemit <chemit@codelutin.com> + * @see SimpleBeanValidatorListener + * @since 2.5.2 + */ +public class SimpleBeanValidator<O> extends AbstractValidator<O> { + + /** + * Name of the bounded property {@code bean}. + * + * @see #getBean() + * @see #setBean(Object) + */ + public static final String BEAN_PROPERTY = "bean"; + + /** Logger. */ + private static final Log log = LogFactory.getLog(SimpleBeanValidator.class); + + /** + * Obtain a new {@link SimpleBeanValidator} for the given parameters. + * <p/> + * <b>Note:</b> It will use the default provider of {@link NuitonValidator} + * + * @param type type of bean to validate + * @param context context of validation + * @param scopes authorized scopes (if {@code null}, will use all scopes) + * @param <O> type of bean to validate + * @return the new instanciated {@link SimpleBeanValidator}. + * @throws NullPointerException if type is {@code null} + * @see NuitonValidatorFactory#getDefaultProviderName() + */ + public static <O> SimpleBeanValidator<O> newValidator( + Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + + // get the provider default name + String providerName = NuitonValidatorFactory.getDefaultProviderName(); + + // get the bean validator with this provider + SimpleBeanValidator<O> beanValidator = newValidator(providerName, + type, + context, + scopes + ); + return beanValidator; + } + + /** + * Obtain a new {@link SimpleBeanValidator} for the given parameters. + * <p/> + * <b>Note:</b> It will use the provider of {@link NuitonValidator} + * defined by the {@code providerName}. + * + * @param providerName name of {@link NuitonValidator} to use + * @param type type of bean to validate + * @param context context of validation + * @param scopes authorized scopes (if {@code null}, will use all scopes) + * @param <O> type of bean to validate + * @return the new instanciated {@link SimpleBeanValidator}. + * @throws NullPointerException if type is {@code null} + * @see NuitonValidatorFactory#getProvider(String) + */ + public static <O> SimpleBeanValidator<O> newValidator( + String providerName, + Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + Preconditions.checkNotNull(type, + "type parameter can not be null."); + + // get delegate validator provider + NuitonValidatorProvider provider = + NuitonValidatorFactory.getProvider(providerName); + + Preconditions.checkState( + provider != null, + "Could not find provider with name " + providerName); + + // create the new instance of bean validator + SimpleBeanValidator<O> validator = new SimpleBeanValidator<O>( + provider, type, context, scopes); + + return validator; + } + + /** + * Context of the registred bean to validate. + * + * @since 2.5.2 + */ + protected final NuitonValidatorContext<O> context; + + /** + * To chain to another validator (acting as parent of this one). + * + * @since 2.5.2 + */ + protected SimpleBeanValidator<?> parentValidator; + + public SimpleBeanValidator(NuitonValidatorProvider validatorProvider, + Class<O> beanClass, + String context) { + + this(validatorProvider, beanClass, + context, + NuitonValidatorScope.values() + ); + } + + public SimpleBeanValidator(NuitonValidatorProvider validatorProvider, + Class<O> beanClass, + String context, + NuitonValidatorScope... scopes) { + + super(validatorProvider, beanClass); + + this.context = new NuitonValidatorContext<O>(); + + // build delegate validator + rebuildDelegateValidator(beanClass, context, scopes); + + // context has changed + firePropertyChange(CONTEXT_PROPERTY, + null, + context + ); + + // scopes has changed + firePropertyChange(SCOPES_PROPERTY, + null, + scopes + ); + } + + /** + * Obtain the actual bean attached to the validator. + * + * @return the bean attached to the validor or {@code null} if no bean + * is attached + */ + public O getBean() { + return context.getBean(); + } + + /** + * Change the attached bean. + * <p/> + * As a side effect, the internal + * {@link AbstractNuitonValidatorContext#messages} will be reset. + * + * @param bean the bean to attach (can be {@code null} to reset the + * validator). + */ + public void setBean(O bean) { + O oldBean = getBean(); + if (log.isDebugEnabled()) { + log.debug(this + " : " + bean); + } + + if (oldBean != null) { + try { + BeanUtil.removePropertyChangeListener(l, oldBean); + } catch (Exception eee) { + if (log.isInfoEnabled()) { + log.info("Can't unregister as listener for bean " + oldBean.getClass() + + " for reason " + eee.getMessage(), eee); + } + } + } + context.setBean(bean); + + if (bean == null) { + + // remove all messages for all fields of the validator + + mergeMessages(null); + + } else { + try { + + BeanUtil.addPropertyChangeListener(l, bean); + } catch (Exception eee) { + if (log.isInfoEnabled()) { + log.info("Can't register as listener for bean " + bean.getClass() + + " for reason " + eee.getMessage(), eee); + } + } + validate(); + } + setChanged(false); + setValid(context.isValid()); + firePropertyChange(BEAN_PROPERTY, oldBean, bean); + } + + public SimpleBeanValidator<?> getParentValidator() { + return parentValidator; + } + + public void setParentValidator(SimpleBeanValidator<?> parentValidator) { + this.parentValidator = parentValidator; + } + + @Override + public boolean hasFatalErrors() { + boolean result = context.hasFatalErrors(); + return result; + } + + @Override + public boolean hasErrors() { + boolean result = context.hasErrors(); + return result; + } + + @Override + public boolean hasWarnings() { + boolean result = context.hasWarnings(); + return result; + } + + @Override + public boolean hasInfos() { + boolean result = context.hasInfos(); + return result; + } + + @Override + public boolean isValid(String fieldName) { + + // field is valid if no fatal messages nor error messages + boolean result = context.isValid(fieldName); + return result; + } + + @Override + public NuitonValidatorScope getHighestScope(String field) { + NuitonValidatorScope scope = context.getHighestScope(field); + return scope; + } + + @Override + public <T> T convert(O bean, String fieldName, String value, Class<T> valueClass) { + Preconditions.checkState( + ObjectUtils.equals(bean, getBean()), + "Can not validate the bean [" + bean + + "] which is not the one registred [" + bean + + "] in this validator."); + + T convert = convert(fieldName, value, valueClass); + return convert; + } + + @Override + public void doValidate() { + validate(); + setValid(context.isValid()); + setChanged(true); + } + + /** + * Convert a value. + * <p/> + * If an error occurs, then add an error in validator. + * + * @param <T> the type of conversion + * @param fieldName the name of the bean property + * @param value the value to convert + * @param valueClass the type of converted value + * @return the converted value, or null if conversion was not ok + */ + public <T> T convert(String fieldName, String value, Class<T> valueClass) { + T convert = null; + + try { + convert = context.convert(fieldName, value, valueClass); + } catch (ConversionException e) { + // must revalidate + validate(); + } + return convert; + } + + public void addSimpleBeanValidatorListener(SimpleBeanValidatorListener listener) { + listenerList.add(SimpleBeanValidatorListener.class, listener); + } + + public void removeSimpleBeanValidatorListener(SimpleBeanValidatorListener listener) { + listenerList.remove(SimpleBeanValidatorListener.class, listener); + } + + public SimpleBeanValidatorListener[] getSimpleBeanValidatorListeners() { + return listenerList.getListeners(SimpleBeanValidatorListener.class); + } + + @Override + protected void doValidate(O bean) { + + Preconditions.checkState( + ObjectUtils.equals(bean, getBean()), + "Can not validate the bean [" + bean + + "] which is not the one registred [" + bean + + "] in this validator."); + + doValidate(); + } + + @Override + protected NuitonValidator<O> getDelegate() { + return context.getValidator(); + } + + @Override + protected void rebuildDelegateValidator(Class<O> beanType, + String context, + NuitonValidatorScope... scopes) { + + // changing context could change fields definition + // so dettach bean, must rebuild the fields + + // Dettach the bean before any thing, because with the new delegate + // validator some old fields could not be used any longer, and then + // listeners will never have the full reset of their model... + if (getBean() != null) { + setBean(null); + } + + if (scopes == null || scopes.length == 0) { + scopes = NuitonValidatorScope.values(); + } + + // compute the new validator model + NuitonValidatorModel<O> validatorModel = validatorProvider.getModel(beanType, + context, + scopes + ); + + // remove old delegate validator + NuitonValidator<O> delegate = validatorProvider.newValidator(validatorModel); + this.context.setValidator(delegate); + } + + /** + * il faut eviter le code re-intrant (durant une validation, une autre est + * demandee). Pour cela on fait la validation dans un thread, et tant que la + * premiere validation n'est pas fini, on ne repond pas aux solicitations. + * Cette method est public pour permettre de force une validation par + * programmation, ce qui est utile par exemple si le bean ne supporte pas + * les {@link PropertyChangeListener} + * <p/> + * <b>Note:</b> la methode est protected et on utilise la methode + * {@link #doValidate()} car la méthode ne modifie pas les etats + * internes et cela en rend son utilisation delicate (le validateur entre + * dans un etat incoherent par rapport aux messages envoyés). + */ + protected void validate() { + + // on ne valide que si il y a un bean et que le resultat de la validation + // pourra etre affiche quelque part + if (isCanValidate()) { + + NuitonValidatorResult result = context.validate(); + + mergeMessages(result); + + if (parentValidator != null) { + // chained validation + // the parent validator should not be changed from this validation + boolean wasModified = parentValidator.isChanged(); + parentValidator.doValidate(); + if (!wasModified) { + // push back old state + parentValidator.setChanged(false); + } + } + } + } + + protected void fireFieldChanged(SimpleBeanValidatorEvent evt) { + + for (SimpleBeanValidatorListener listener : + listenerList.getListeners(SimpleBeanValidatorListener.class)) { + listener.onFieldChanged(evt); + } + } + + protected void mergeMessages(NuitonValidatorResult newMessages) { + + List<SimpleBeanValidatorEvent> events = context.mergeMessages(this, + newMessages); + + if (CollectionUtils.isNotEmpty(events)) { + + // send all messages + for (SimpleBeanValidatorEvent event : events) { + fireFieldChanged(event); + } + } + } + + protected static class NuitonValidatorContext<O> extends AbstractNuitonValidatorContext<O, SimpleBeanValidator<O>, SimpleBeanValidatorEvent> { + + @Override + protected SimpleBeanValidatorEvent createEvent(SimpleBeanValidator<O> source, + O bean, + String field, + NuitonValidatorScope scope, + String[] toAdd, + String[] toDelete) { + SimpleBeanValidatorEvent evt = new SimpleBeanValidatorEvent( + source, + field, + scope, + toAdd, + toDelete + ); + return evt; + } + } +} diff --git a/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorEvent.java b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorEvent.java new file mode 100644 index 0000000..da472bc --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorEvent.java @@ -0,0 +1,51 @@ +package org.nuiton.validator.bean.simple; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.AbstractValidatorEvent; + +/** + * Event to be fired when some messages changed on a given field / scope of a bean. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public class SimpleBeanValidatorEvent extends AbstractValidatorEvent<SimpleBeanValidator<?>> { + + private static final long serialVersionUID = 1L; + + public SimpleBeanValidatorEvent(SimpleBeanValidator<?> source, + String field, + NuitonValidatorScope scope, + String[] messagestoAdd, + String[] messagestoDelete) { + super(source, field, scope, messagestoAdd, messagestoDelete); + } + + @Override + public Object getBean() { + return getSource().getBean(); + } +} diff --git a/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorListener.java b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorListener.java new file mode 100644 index 0000000..5e28b8f --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorListener.java @@ -0,0 +1,38 @@ +package org.nuiton.validator.bean.simple; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.bean.ValidatorListener; +import org.nuiton.validator.bean.list.BeanListValidator; + +/** + * The definition of an event on {@link SimpleBeanValidatorEvent} + * to be fired by a {@link BeanListValidator}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public interface SimpleBeanValidatorListener extends ValidatorListener<SimpleBeanValidatorEvent> { + +} diff --git a/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorMessage.java b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorMessage.java new file mode 100644 index 0000000..3ca40e4 --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorMessage.java @@ -0,0 +1,144 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.bean.simple; + +import org.nuiton.validator.NuitonValidatorScope; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import static org.nuiton.i18n.I18n._; + +/** + * The object to box a validation message. + * + * @param <E> type of message (use for override {@link #compareTo(Object)} + * method. + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public class SimpleBeanValidatorMessage<E extends SimpleBeanValidatorMessage<?>> implements Comparable<E>, Serializable { + + private static final long serialVersionUID = 1L; + + /** the validator that produce the message */ + protected SimpleBeanValidator<?> validator; + + /** the field that produce the message */ + protected String field; + + /** the label of the message (to be displayed somewhere) */ + protected String message; + + /** the scope of the message */ + protected NuitonValidatorScope scope; + + public SimpleBeanValidatorMessage(SimpleBeanValidator<?> validator, + String field, + String message, + NuitonValidatorScope scope) { + this.field = field; + this.validator = validator; + this.message = message == null ? null : message.trim(); + this.scope = scope; + } + + public SimpleBeanValidator<?> getValidator() { + return validator; + } + + public String getField() { + return field; + } + + public NuitonValidatorScope getScope() { + return scope; + } + + public String getMessage() { + return message; + } + + @Override + public int compareTo(E o) { + // sort on scope + int result = getScope().compareTo(o.getScope()); + if (result == 0) { + // sort on field name + result = field.compareTo(o.field); + if (result == 0) { + // sort on message + result = message.compareTo(o.message); + } + } + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SimpleBeanValidatorMessage<?>)) { + return false; + } + + SimpleBeanValidatorMessage<?> that = (SimpleBeanValidatorMessage<?>) o; + + return field.equals(that.field) && + (message != null ? !message.equals(that.message) : that.message == null) && + scope == that.scope; + } + + @Override + public int hashCode() { + int result = field.hashCode(); + result = 31 * result + (message != null ? message.hashCode() : 0); + result = 31 * result + (scope != null ? scope.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return scope + " - " + getI18nError(message); + } + + public String getI18nError(String error) { + String text; + if (!error.contains("##")) { + text = _(error); + } else { + StringTokenizer stk = new StringTokenizer(error, "##"); + String errorName = stk.nextToken(); + List<String> args = new ArrayList<String>(); + while (stk.hasMoreTokens()) { + args.add(stk.nextToken()); + } + text = _(errorName, args.toArray()); + } + return text; + } +} diff --git a/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidators.java b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidators.java new file mode 100644 index 0000000..33dc1c0 --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/simple/SimpleBeanValidators.java @@ -0,0 +1,75 @@ +package org.nuiton.validator.bean.simple; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.NuitonValidatorScope; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; + +/** + * Useful methods arond {@link SimpleBeanValidator}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.4 + */ +public class SimpleBeanValidators { + + protected SimpleBeanValidators() { + // no constructor on helper class + } + + public static EnumSet<NuitonValidatorScope> getScopes( + List<SimpleBeanValidatorMessage<?>> messages) { + EnumSet<NuitonValidatorScope> result = + EnumSet.noneOf(NuitonValidatorScope.class); + for (SimpleBeanValidatorMessage<?> m : messages) { + result.add(m.getScope()); + } + return result; + } + + public static EnumMap<NuitonValidatorScope, Integer> getScopesCount( + List<SimpleBeanValidatorMessage<?>> messages) { + EnumMap<NuitonValidatorScope, Integer> result = + new EnumMap<NuitonValidatorScope, Integer>(NuitonValidatorScope.class); + for (NuitonValidatorScope s : NuitonValidatorScope.values()) { + result.put(s, 0); + } + for (SimpleBeanValidatorMessage<?> m : messages) { + + NuitonValidatorScope scope = m.getScope(); + + result.put(scope, result.get(scope) + 1); + } + + for (NuitonValidatorScope s : NuitonValidatorScope.values()) { + if (result.get(s) == 0) { + result.remove(s); + } + } + return result; + } +} diff --git a/src/main/java/org/nuiton/validator/bean/simple/package-info.java b/src/main/java/org/nuiton/validator/bean/simple/package-info.java new file mode 100644 index 0000000..703954b --- /dev/null +++ b/src/main/java/org/nuiton/validator/bean/simple/package-info.java @@ -0,0 +1,57 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/** + * Package of Nuiton - Simple Bean Validator api. + * + * <h1>The <b>SimpleBeanValidator</b> api</h1> + * <p> + * The {@link org.nuiton.validator.bean.simple.SimpleBeanValidator} purpose is to validate + * a bean, with a listener api to interact with outside world. + * </p> + * It is mainly used in GUI parts of an application (Jaxx-validator use it). + * <br/> + * The idea is to attach the bean to validate insed the validator, then the + * validator listen any modification of the bean to revalidate it and fires + * events when messages has changed on a field. + * + * <pre> + * SimpleBeanValidatorListener listener = new SimpleBeanValidatorListener() {XXX}; + * SimpleBeanValidator<O> validator = XXX; + * validator.addSimpleBeanValidatorListener(listener); + * validator.setBean(o); + * </pre> + * + * <h2>Obtain a validator</h2> + * To obtain a bean validator use the factory method of the + * {@link org.nuiton.validator.bean.simple.SimpleBeanValidator}. + * <br/> + * <pre> + * SimpleBeanValidator<O> validator = SimpleBeanValidator.newValidator(...); + * </pre> + * + * <strong>To be continued...</strong> + * + * @since 2.0 + */ +package org.nuiton.validator.bean.simple; diff --git a/src/main/java/org/nuiton/validator/package-info.java b/src/main/java/org/nuiton/validator/package-info.java new file mode 100644 index 0000000..1219e4b --- /dev/null +++ b/src/main/java/org/nuiton/validator/package-info.java @@ -0,0 +1,55 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/** + * Package of Nuiton-validator api. + * + * <h1>The <b>Validator</b> api</h1> + * <p> + * The {@link org.nuiton.validator.NuitonValidator} is the object responsible + * to launch validation for a given object and then return the result of + * validation in a {@link org.nuiton.validator.NuitonValidatorResult} via the + * method {@link org.nuiton.validator.NuitonValidator#validate(Object)}. + * </p> + * + * <pre> + * NuitonValidator<O> validator = XXX; + * NuitonValidatorResult result = validator.validate(o); + * </pre> + * + * <h2>Obtain a validator</h2> + * To obtain a validator use the factory of validators : {@link org.nuiton.validator.NuitonValidatorFactory}. + * <br/> + * <pre> + * NuitonValidator<O> validator = NuitonValidatorFactory.newValidator(O.class); + * </pre> + * + * <h2>Implements the validator api</h2> + * + * At the moment, there is an offered implementation based on xwork2 framework. + * + * <strong>To be continued...</strong> + * + * @since 2.0 + */ +package org.nuiton.validator; diff --git a/src/main/java/org/nuiton/validator/xwork2/XWork2NuitonValidator.java b/src/main/java/org/nuiton/validator/xwork2/XWork2NuitonValidator.java new file mode 100644 index 0000000..7518c5f --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/XWork2NuitonValidator.java @@ -0,0 +1,135 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2; + +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorModel; +import org.nuiton.validator.NuitonValidatorResult; +import org.nuiton.validator.NuitonValidatorScope; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Implementation of {@link NuitonValidator} using {@code XWork2} validators. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class XWork2NuitonValidator<O> implements NuitonValidator<O> { + + protected NuitonValidatorModel<O> model; + + /** xworks scope validators * */ + protected Map<NuitonValidatorScope, XWork2ScopeValidator<O>> validators; + + public XWork2NuitonValidator(NuitonValidatorModel<O> model) { + + this.model = model; + + // init validators + validators = new EnumMap<NuitonValidatorScope, XWork2ScopeValidator<O>>(NuitonValidatorScope.class); + + Class<O> type = model.getType(); + String context = model.getContext(); + + Map<NuitonValidatorScope, String[]> fieldsMap = model.getFields(); + + for (Map.Entry<NuitonValidatorScope, String[]> entry : fieldsMap.entrySet()) { + + NuitonValidatorScope scope = entry.getKey(); + + String scopeContext = + XWork2ValidatorUtil.getContextForScope( + context, + scope + ); + + Set<String> fields = new HashSet<String>( + Arrays.asList(entry.getValue())); + + XWork2ScopeValidator<O> newValidator = + XWork2ValidatorUtil.newXWorkScopeValidator( + type, + scopeContext, + fields + ); + + validators.put(scope, newValidator); + } + } + + @Override + public NuitonValidatorResult validate(O object) throws NullPointerException { + + if (object == null) { + throw new NullPointerException("object parameter can not be null."); + } + + NuitonValidatorResult result = new NuitonValidatorResult(); + + for (NuitonValidatorScope scope : validators.keySet()) { + + XWork2ScopeValidator<O> validator = validators.get(scope); + + Map<String, List<String>> newMessages = validator.validate(object); + + result.addMessagesForScope(scope, newMessages); + } + return result; + } + + @Override + public Set<NuitonValidatorScope> getEffectiveScopes() { + return validators.keySet(); + } + + @Override + public Set<String> getEffectiveFields() { + Set<String> result = new HashSet<String>(); + for (XWork2ScopeValidator<O> scopeValidator : validators.values()) { + result.addAll(scopeValidator.getFieldNames()); + } + return result; + } + + @Override + public Set<String> getEffectiveFields(NuitonValidatorScope scope) { + Set<String> result = new HashSet<String>(); + XWork2ScopeValidator<O> scopeValidator = validators.get(scope); + if (scopeValidator != null) { + result.addAll(scopeValidator.getFieldNames()); + } + return result; + } + + @Override + public NuitonValidatorModel<O> getModel() { + return model; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorProvider.java b/src/main/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorProvider.java new file mode 100644 index 0000000..c70265a --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorProvider.java @@ -0,0 +1,309 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.StringUtil; +import org.nuiton.validator.AbstractNuitonValidatorProvider; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorModel; +import org.nuiton.validator.NuitonValidatorScope; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Provider of validator for the xworks nuiton validator. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class XWork2NuitonValidatorProvider extends AbstractNuitonValidatorProvider { + + public static final String PROVIDER_NAME = "xwork2"; + + /** Logger. */ + private static final Log log = + LogFactory.getLog(XWork2NuitonValidatorProvider.class); + + public XWork2NuitonValidatorProvider() { + super(PROVIDER_NAME); + } + + @Override + public <O> NuitonValidatorModel<O> newModel(Class<O> type, + String context, + NuitonValidatorScope... scopes) { + + if (scopes.length == 0) { + // use all scopes + scopes = NuitonValidatorScope.values(); + } + + Map<NuitonValidatorScope, String[]> fields = + XWork2ValidatorUtil.detectFields(type, context, scopes); + + Set<NuitonValidatorScope> scopeSet = + EnumSet.noneOf(NuitonValidatorScope.class); + scopeSet.addAll(Arrays.asList(scopes)); + + return new NuitonValidatorModel<O>(type, context, scopeSet, fields); + } + + @Override + public <O> XWork2NuitonValidator<O> newValidator(NuitonValidatorModel<O> model) { + return new XWork2NuitonValidator<O>(model); + } + + @Override + public SortedSet<NuitonValidator<?>> detectValidators(File sourceRoot, + Pattern contextFilter, + NuitonValidatorScope[] scopes, + Class<?>... types) { + + if (scopes == null) { + + // use all scopes + scopes = NuitonValidatorScope.values(); + } + + SortedSet<NuitonValidator<?>> result = + new TreeSet<NuitonValidator<?>>(new ValidatorComparator()); + + for (Class<?> c : types) { + File dir = getClassDir(sourceRoot, c); + if (!dir.exists()) { + + // pas de repertoire adequate + if (log.isDebugEnabled()) { + log.debug("skip none existing directory " + dir); + } + continue; + } + String[] contexts = getContexts(c, dir); + if (log.isDebugEnabled()) { + log.debug("contexts : " + Arrays.toString(contexts)); + } + + if (contexts.length > 0) { + String[] realContexts = getContextsWithoutScopes(contexts); + + if (log.isDebugEnabled()) { + log.debug("realContexts : " + + Arrays.toString(realContexts)); + } + + if (contextFilter != null) { + + // filter contexts + realContexts = getFilterContexts(contextFilter, + realContexts + ); + if (log.isDebugEnabled()) { + log.debug("filterContexts : " + + Arrays.toString(realContexts)); + } + } + + for (String context : realContexts) { + + // on cherche le validateur + NuitonValidator<?> validator = getValidator( + c, + context.isEmpty() ? null : context, + scopes + ); + if (validator != null) { + // on enregistre le validateur + result.add(validator); + } + } + } + } + return result; + } + + /** + * Pour un context et un type d'entité donné, instancie un validateur et + * test si ce validateur est utilisable (i.e qu'il admet des champs à + * valider). + * <p/> + * Si aucun champ n'est trouvé dans le validateur, alors on retourne null. + * + * @param <O> le type du bean + * @param klass le type du bean + * @param context le context du validateur + * @param scopes les scopes a utiliser (si {@code null} alors pas de + * filtre sur les scopes) + * @return le validateur initialisé, ou <code>null</code> si aucun scope + * détecté dans le validateur. + */ + protected <O> NuitonValidator<O> getValidator(Class<O> klass, + String context, + NuitonValidatorScope... scopes) { + + NuitonValidatorModel<O> model = newModel(klass, context, scopes); + + XWork2NuitonValidator<O> valitator = newValidator(model); + + Set<NuitonValidatorScope> realScopes = valitator.getEffectiveScopes(); + if (realScopes.isEmpty()) { + valitator = null; + if (log.isDebugEnabled()) { + log.debug(klass + " : validator skip (no scopes detected)"); + } + } else { + if (log.isDebugEnabled()) { + log.debug(klass + " : keep validator " + valitator); + } + } + return valitator; + } + + protected File getClassDir(File sourceRoot, Class<?> clazz) { + String path = clazz.getPackage().getName(); + path = path.replaceAll("\\.", StringUtil.getFileSeparatorRegex()); + File dir = new File(sourceRoot, path); + return dir; + } + + protected String[] getContexts(Class<?> clazz, File dir) { + Set<String> result = new TreeSet<String>(); + ValidatorFilenameFilter filter = new ValidatorFilenameFilter(clazz); + if (log.isDebugEnabled()) { + log.debug("dir : " + dir); + } + String[] files = dir.list(filter); + for (String file : files) { + if (log.isDebugEnabled()) { + log.debug("file " + file); + } + String context = file.substring( + filter.prefix.length(), + file.length() - ValidatorFilenameFilter.SUFFIX.length() + ); + if (log.isDebugEnabled()) { + log.debug("detect " + clazz.getSimpleName() + + " context [" + context + "]"); + } + result.add(context); + } + return result.toArray(new String[result.size()]); + } + + protected String[] getContextsWithoutScopes(String[] contexts) { + Set<String> result = new TreeSet<String>(); + NuitonValidatorScope[] scopes = NuitonValidatorScope.values(); + for (String context : contexts) { + for (NuitonValidatorScope scope : scopes) { + String scopeName = scope.name().toLowerCase(); + if (!context.endsWith(scopeName)) { + // pas concerne par ce scope + continue; + } + if (log.isDebugEnabled()) { + log.debug("detect context : " + context); + } + String realContext = context.substring( + 0, + context.length() - scopeName.length() + ); + if (realContext.endsWith("-")) { + realContext = realContext.substring( + 0, + realContext.length() - 1 + ); + } + result.add(realContext); + } + } + return result.toArray(new String[result.size()]); + } + + protected String[] getFilterContexts(Pattern contextFilter, + String[] realContexts) { + List<String> result = new ArrayList<String>(); + for (String c : realContexts) { + Matcher m = contextFilter.matcher(c); + if (m.matches()) { + result.add(c); + } + } + return result.toArray(new String[result.size()]); + } + + protected static class ValidatorFilenameFilter implements FilenameFilter { + + protected static final String SUFFIX = "-validation.xml"; + + protected Class<?> clazz; + + protected String prefix; + + public ValidatorFilenameFilter(Class<?> clazz) { + this.clazz = clazz; + prefix = clazz.getSimpleName() + "-"; + } + + @Override + public boolean accept(File dir, String name) { + boolean result = name.endsWith(SUFFIX); + if (result) { + result = name.startsWith(prefix); + } + return result; + } + } + + protected static class ValidatorComparator implements Comparator<NuitonValidator<?>> { + + @Override + public int compare(NuitonValidator<?> o1, NuitonValidator<?> o2) { + + NuitonValidatorModel<?> model1 = ((XWork2NuitonValidator<?>) o1).getModel(); + NuitonValidatorModel<?> model2 = ((XWork2NuitonValidator<?>) o2).getModel(); + + String contextName1 = + model1.getType().getSimpleName() + "-" + + (model1.getContext() == null ? "" : model1.getContext()); + String contextName2 = + model2.getType().getSimpleName() + "-" + + (model2.getContext() == null ? "" : model2.getContext()); + return contextName1.compareTo(contextName2); + } + } + +} diff --git a/src/main/java/org/nuiton/validator/xwork2/XWork2ScopeValidator.java b/src/main/java/org/nuiton/validator/xwork2/XWork2ScopeValidator.java new file mode 100644 index 0000000..bb166bf --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/XWork2ScopeValidator.java @@ -0,0 +1,224 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ValidationAwareSupport; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.validator.ActionValidatorManager; +import com.opensymphony.xwork2.validator.DelegatingValidatorContext; +import com.opensymphony.xwork2.validator.ValidationException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A customized validator for a given bean. + * <p/> + * Use the method {@link #validate(Object)} to obtain the messages detected by + * the validator for the given bean. + * + * @param <O> type of the bean to validate. + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class XWork2ScopeValidator<O> { + + /** Logger */ + private static final Log log = LogFactory.getLog(XWork2ScopeValidator.class); + + protected final static Map<String, List<String>> EMPTY_RESULT = + Collections.unmodifiableMap(new HashMap<String, List<String>>()); + + /** the type of bean to validate */ + protected final Class<O> type; + + /** the validation named context (can be null) */ + protected String context; + + /** the list of field names detected for this validator */ + protected Set<String> fieldNames; + + // -- + // XWorks fields + // -- + + protected ValidationAwareSupport validationSupport; + + protected DelegatingValidatorContext validationContext; + + protected ActionValidatorManager validator; + + protected ValueStack vs; + + protected XWork2ScopeValidator(Class<O> type, + String context, + Set<String> fieldNames, + ValueStack vs) { + + this.type = type; + this.context = context; + this.fieldNames = fieldNames; + + validationSupport = new ValidationAwareSupport(); + validationContext = new DelegatingValidatorContext(validationSupport); + + if (vs == null) { + + // create a standalone value stack + vs = XWork2ValidatorUtil.createValuestack(); + if (log.isDebugEnabled()) { + log.debug("create a standalone value stack " + vs); + } + } else { + if (log.isDebugEnabled()) { + log.debug("use given value stack " + vs); + } + } + + this.vs = vs; + + validator = XWork2ValidatorUtil.newValidationManager(vs); + } + + public Class<O> getType() { + return type; + } + + public String getContext() { + return context; + } + + public Set<String> getFieldNames() { + return fieldNames; + } + + public ActionValidatorManager getValidator() { + return validator; + } + + /** + * Test if the validator contains the field given his name + * + * @param fieldName the name of the searched field + * @return <code>true</code> if validator contaisn this field, + * <code>false</code> otherwise + */ + public boolean containsField(String fieldName) { + return fieldNames.contains(fieldName); + } + + /** + * Valide le bean donné et retourne les messages produits. + * + * @param bean le bean a valider (il doit etre non null) + * @return le dictionnaire des messages produits par la validation indexées + * par le nom du champs du bean impacté. + */ + public Map<String, List<String>> validate(O bean) { + + if (bean == null) { + throw new NullPointerException( + "bean parameter can not be null in method validate"); + } + + Map<String, List<String>> result = EMPTY_RESULT; + + + if (fieldNames.isEmpty()) { + return result; + } + + // on lance la validation uniquement si des champs sont a valider + try { + + //TC - 20081024 : since context is in a ThreadLocal variable, + // we must do the check + if (ActionContext.getContext() == null) { + ActionContext.setContext(new ActionContext(vs.getContext())); + } + + validator.validate(bean, context, validationContext); + + if (log.isTraceEnabled()) { + log.trace("Action errors: " + + validationContext.getActionErrors()); + log.trace("Action messages: " + + validationContext.getActionMessages()); + log.trace("Field errors: " + + validationContext.getFieldErrors()); + } + + if (log.isDebugEnabled()) { + log.debug(this + " : " + + validationContext.getFieldErrors()); + } + + // retreave errors by field + if (validationContext.hasFieldErrors()) { + Map<?, ?> messages = validationContext.getFieldErrors(); + result = new HashMap<String, List<String>>(messages.size()); + for (Object fieldName : messages.keySet()) { + Collection<?> c = + (Collection<?>) messages.get(fieldName); + List<String> mm = new ArrayList<String>(c.size()); + for (Object message : c) { + // tchemit 2010-08-28 : trim the incoming message + // (I18n will not translate it otherwise) + String messageStr = message == null ? "" : message + ""; + mm.add(messageStr.trim()); + } + result.put(fieldName + "", mm); + } + } + + } catch (ValidationException eee) { + if (log.isWarnEnabled()) { + log.warn("Error during validation on " + type + + " for reason : " + eee.getMessage(), eee); + } + + } finally { + + // on nettoye toujours le validateur apres operation + validationSupport.clearErrorsAndMessages(); + } + + return result; + } + + @Override + public String toString() { + return super.toString() + "<beanClass:" + type + + ", contextName:" + context + ">"; + } + +} diff --git a/src/main/java/org/nuiton/validator/xwork2/XWork2ValidatorUtil.java b/src/main/java/org/nuiton/validator/xwork2/XWork2ValidatorUtil.java new file mode 100644 index 0000000..e393b47 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/XWork2ValidatorUtil.java @@ -0,0 +1,232 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.ConfigurationManager; +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.ValueStackFactory; +import com.opensymphony.xwork2.validator.ActionValidatorManager; +import com.opensymphony.xwork2.validator.FieldValidator; +import com.opensymphony.xwork2.validator.Validator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.beans.BeanUtil; +import org.nuiton.validator.NuitonValidatorScope; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +/** + * Usefull methods to works with work2 validator api. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class XWork2ValidatorUtil { + + /** Logger. */ + private static final Log log = LogFactory.getLog(XWork2ValidatorUtil.class); + + /** + * a shared value stack to allow external operations on it (for example add + * some datas in stack to be usedby validators + */ + static private ValueStack sharedValueStack; + + public static ValueStack getSharedValueStack() { + if (sharedValueStack == null) { + + // init context + sharedValueStack = createValuestack(); + if (log.isDebugEnabled()) { + log.debug("init shared value stack " + sharedValueStack); + } + } + return sharedValueStack; + } + + public static ValueStack createValuestack() { + + ConfigurationManager confManager = new ConfigurationManager(); + Configuration conf = confManager.getConfiguration(); + Container container = conf.getContainer(); + ValueStackFactory stackFactory = container.getInstance(ValueStackFactory.class); + ValueStack vs = stackFactory.createValueStack(); + return vs; + } + + public static <O> XWork2ScopeValidator<O> newXWorkScopeValidator(Class<O> beanClass, String contextName, + Set<String> fields) { + return newXWorkScopeValidator(beanClass, contextName, fields, getSharedValueStack()); + } + + public static <O> XWork2ScopeValidator<O> newXWorkScopeValidator(Class<O> beanClass, String contextName, + Set<String> fields, ValueStack vs) { + + return new XWork2ScopeValidator<O>(beanClass, contextName, fields, vs); + } + + + public static String getContextForScope(String context, NuitonValidatorScope scope) { + return (context == null ? "" : context + "-") + scope.name().toLowerCase(); + } + + protected static ActionValidatorManager newValidationManager(ValueStack vs) { + + if (vs == null) { + vs = createValuestack(); + + if (log.isDebugEnabled()) { + log.debug("create a standalone value stack " + vs); + } + } else { + if (log.isDebugEnabled()) { + log.debug("use given value stack " + vs); + } + } + + ActionContext context = new ActionContext(vs.getContext()); + + // must set the action context otherwise can't obtain after validators + // with the method validator.getValidators(XXX) + // Later in the code, we could not having reference to the ValueStack + // before using a validator... Must be cleaned... + ActionContext.setContext(context); + + // init validator + Container container = context.getContainer(); + ActionValidatorManager validatorManager = + container.getInstance(ActionValidatorManager.class, "no-annotations"); + + //FIXME-tchemit 2012-07-17 work-around to fix http://nuiton.org/issues/2191 + //FIXME-tchemit 2012-07-17 will remove this when using xworks-core which fixes https://issues.apache.org/jira/browse/WW-3850 +// if (validatorManager instanceof DefaultActionValidatorManager) { +// +// FileManagerFactory fileManagerFactory = container.getInstance(FileManagerFactory.class); +// fileManagerFactory.setReloadingConfigs(String.valueOf(Boolean.FALSE)); +// ((DefaultActionValidatorManager) validatorManager).setFileManagerFactory(fileManagerFactory); +// } + + return validatorManager; + } + + public static <O> Map<NuitonValidatorScope, String[]> detectFields(Class<O> type, String context, + NuitonValidatorScope[] scopeUniverse) { + + Set<String> availableFields = BeanUtil.getReadableProperties(type); + + ActionValidatorManager validatorManager = newValidationManager(null); + + Map<NuitonValidatorScope, String[]> fields = new TreeMap<NuitonValidatorScope, String[]>(); + + for (NuitonValidatorScope scope : scopeUniverse) { + + Set<String> fieldNames = + detectFieldsForScope(validatorManager, type, scope, context, availableFields, false); + + if (log.isDebugEnabled()) { + log.debug("detected validator fields for scope " + scope + + ":" + context + " : " + fieldNames); + } + + if (!fieldNames.isEmpty()) { + + // fields detected in this validator, keep it + + fields.put(scope, fieldNames.toArray(new String[fieldNames.size()])); + } + } + + return fields; + + } + + protected static Set<String> detectFieldsForScope(ActionValidatorManager validator, + Class<?> type, + NuitonValidatorScope scope, + String context, + Set<String> availableFields, + boolean includeDefaultContext) { + + String scopeContext = getContextForScope(context, scope); + + Set<String> fields = new HashSet<String>(); + + int skip = 0; + if (scopeContext != null && !includeDefaultContext) { + // count the number of validator to skip + for (Validator<?> v : validator.getValidators(type, null)) { + // we only work on FieldValidator at the moment + if (v instanceof FieldValidator) { + skip++; + } + } + } + + for (Validator<?> v : validator.getValidators(type, scopeContext)) { + + // we only work on FieldValidator at the moment + if (v instanceof FieldValidator) { + if (skip > 0) { + skip--; + continue; + } + FieldValidator fieldValidator = (FieldValidator) v; + if (log.isDebugEnabled()) { + log.debug("context " + context + " - field " + + fieldValidator.getFieldName()); + } + String fName = fieldValidator.getFieldName(); + if (availableFields.contains(fName)) { + + // safe field + fields.add(fName); + } else { + + if (BeanUtil.isNestedReadableProperty(type, fName)) { + + fields.add(fName); + + } else { + // not a readable property, can not add it + String message = + "Field " + fName + " in scope [" + scopeContext + "] is not a readable property of " + + type.getName(); + if (log.isErrorEnabled()) { + log.error(message); + } + throw new IllegalStateException(message); + } + } + } + } + + return fields; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/CollectionFieldExpressionValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/CollectionFieldExpressionValidator.java new file mode 100644 index 0000000..81767af --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/CollectionFieldExpressionValidator.java @@ -0,0 +1,489 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldExpressionValidator; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * Un validateur basé sur {@link FieldExpressionValidator} qui valide sur une + * collection de propriéte. + * + * @author tchemit <chemit@codelutin.com> + */ +public class CollectionFieldExpressionValidator extends NuitonFieldExpressionValidator { + + public enum Mode { + + /** au moins une entrée de la collection doit etre valide */ + AT_LEAST_ONE, + /** exactement une entrée dela collection doit être valide */ + EXACTLY_ONE, + /** toutes les valeurs de la collection doivent etre valides */ + ALL, + /** aucune valeur de la collection doivent etre valides */ + NONE, + /** detection de clef unique */ + UNIQUE_KEY + } + + /** le mode de validation sur la liste */ + protected Mode mode; + + /** + * pour indiquer la propriété qui contient la liste à valider. + * <p/> + * Si cette prorpiété n'est pas renseignée alors on utilise la + * {@link #getFieldName()} pour obtenir la collection. + * <p/> + * Cela permet d'effectuer une validation si une collection mais portant + * en fait sur un autre champs + * + * @since 1.5 + */ + protected String collectionFieldName; + + /** + * drapeau pour utiliser le contexte de parcours pour valider + * l'expression, on dispose donc alors des variables previous, current, + * index, size et empty dans l'expression. + * <p/> + * Sinon l'expression s'applique directement sur l'entrée courant dans le + * parcours sans préfixe. + */ + protected boolean useSensitiveContext; + + /** + * expression a valider sur la premiètre entrée de la collection. + * <p/> + * Note : Pour le moment, on autorise uniquement cela en mode ALL. + */ + protected String expressionForFirst; + + /** + * expression a valider sur la dernière entrée de la collection. + * <p/> + * Note : Pour le moment, on autorise uniquement cela en mode ALL. + */ + protected String expressionForLast; + + /** + * la liste des propriétés d'une entrée de la collection qui définit la + * clef unique (en mode UNIQUE_KEY). + */ + protected String[] keys; + + /** le context de parcours */ + protected WalkerContext c; + + private boolean useFirst, useLast; + + public Mode getMode() { + return mode; + } + + public void setMode(Mode mode) { + this.mode = mode; + } + + public String getCollectionFieldName() { + return collectionFieldName; + } + + public void setCollectionFieldName(String collectionFieldName) { + this.collectionFieldName = collectionFieldName; + } + + public boolean isUseSensitiveContext() { + return useSensitiveContext; + } + + public void setUseSensitiveContext(boolean useSensitiveContext) { + this.useSensitiveContext = useSensitiveContext; + } + + public String getExpressionForFirst() { + return expressionForFirst; + } + + public void setExpressionForFirst(String expressionForFirst) { + this.expressionForFirst = expressionForFirst; + } + + public String getExpressionForLast() { + return expressionForLast; + } + + public void setExpressionForLast(String expressionForLast) { + this.expressionForLast = expressionForLast; + } + + public String[] getKeys() { + return keys; + } + + public void setKeys(String[] keys) { + if (keys != null && keys.length == 1 && keys[0].contains(",")) { + this.keys = keys[0].split(","); + } else { + this.keys = keys; + } + } + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + if (mode == null) { + throw new ValidationException("no mode defined!"); + } + useFirst = expressionForFirst != null && !expressionForFirst.trim().isEmpty(); + useLast = expressionForLast != null && !expressionForLast.trim().isEmpty(); + + if (useFirst && mode != Mode.ALL) { + throw new ValidationException("can only use expressionForFirst in " + + "mode ALL but was " + mode); + } + if (useLast && mode != Mode.ALL) { + throw new ValidationException("can only use expressionForLast in " + + "mode ALL but was " + mode); + } + + String fieldName = getFieldName(); + + Collection<?> col = getCollection(object); + + if (useSensitiveContext) { + c = new WalkerContext(col.size()); + } + + boolean answer; + + boolean pop = false; + + if (!stack.getRoot().contains(object)) { + stack.push(object); + pop = true; + } + + switch (mode) { + case ALL: + answer = validateAllEntries(col); + break; + case AT_LEAST_ONE: + answer = validateAtLeastOneEntry(col); + break; + case EXACTLY_ONE: + answer = validateExtacltyOneEntry(col); + break; + case NONE: + answer = validateNoneEntry(col); + break; + case UNIQUE_KEY: + if (keys == null || keys.length == 0) { + throw new ValidationException("no unique keys defined"); + } + answer = validateUniqueKey(col); + break; + + default: + // should never come here... + answer = false; + } + + if (!answer) { + addFieldError(fieldName, object); + } + if (pop) { + stack.pop(); + } + } + + protected ValueStack stack; + + @Override + public void setValueStack(ValueStack stack) { + super.setValueStack(stack); + this.stack = stack; + } + + @Override + public String getMessage(Object object) { + boolean pop = false; + + if (useSensitiveContext && !stack.getRoot().contains(c)) { + stack.push(c); + pop = true; + } + String message = super.getMessage(object); + + if (pop) { + stack.pop(); + } + return message; + } + + protected Boolean validateAllEntries(Collection<?> col) throws ValidationException { + boolean answer = true; + for (Object entry : col) { + answer = validateOneEntry(entry); + if (!answer) { + // validation on one entry has failed + // no need to continue + break; + } + } + return answer; + } + + protected Boolean validateNoneEntry(Collection<?> col) throws ValidationException { + boolean answer = true; + for (Object entry : col) { + boolean b = validateOneEntry(entry); + if (b) { + // one entry has sucessed, validation has failed + // no need to continue + answer = false; + break; + } + } + return answer; + } + + protected Boolean validateAtLeastOneEntry(Collection<?> col) throws ValidationException { + boolean answer = false; + for (Object entry : col) { + answer = validateOneEntry(entry); + if (answer) { + // one entry was succes, validation is ok, + // no need to continue + break; + } + } + return answer; + } + + protected Boolean validateExtacltyOneEntry(Collection<?> col) throws ValidationException { + int count = 0; + for (Object entry : col) { + boolean answer = validateOneEntry(entry); + if (answer) { + // one entry has succed + count++; + if (count > 1) { + // more than one entriy was successfull + // so validation has failed + break; + } + + } + } + return count == 1; + } + + protected Boolean validateUniqueKey(Collection<?> col) throws ValidationException { + boolean answer = true; + + Set<Integer> hashCodes = new HashSet<Integer>(); + int index = -1; + for (Object entry : col) { + index++; + // construction du hash de la clef d'unicite + Integer hash = getUniqueKeyHashCode(entry); + if (!hashCodes.contains(hash)) { + hashCodes.add(hash); + continue; + } + // une entree avec ce hash a deja ete trouvee + // on est donc en violation sur la clef unique + answer = false; + if (log.isDebugEnabled()) { + log.debug("duplicated uniquekey " + hash + " for entry " + index); + } + } + hashCodes.clear(); + return answer; + } + + protected boolean validateOneEntry(Object object) throws ValidationException { + + Boolean answer = Boolean.FALSE; + + boolean extraExpression = false; + + if (useSensitiveContext) { + c.addCurrent(object); + object = c; + + if (c.isFirst() && useFirst) { + // on valide l'expression sur la premiètre entrée + answer = evaluateExpression(expressionForFirst, object); + extraExpression = true; + } + if (c.isLast() && useLast) { + // on valide l'expression sur la dernière entrée + answer = (!extraExpression || answer) && evaluateExpression(expressionForLast, object); + extraExpression = true; + } + } + + answer = (!extraExpression || answer) && evaluateExpression(getExpression(), object); + + return answer; + } + + protected boolean evaluateExpression(String expression, Object object) throws ValidationException { + Object obj = null; + try { + obj = getFieldValue(expression, object); + } catch (ValidationException e) { + throw e; + } catch (Exception e) { + log.error(e.getMessage(), e); + // let this pass, but it will be logged right below + } + + Boolean answer = Boolean.FALSE; + + if (obj != null && obj instanceof Boolean) { + answer = (Boolean) obj; + } else { + log.warn("Got result of " + obj + " when trying to get Boolean for expression " + expression); + } + return answer; + } + + /** + * @param object the incoming object containing the collection to test + * @return the collection of the incoming object given by the fieldName property + * @throws ValidationException if any pb to retreave the collection + */ + protected Collection<?> getCollection(Object object) throws ValidationException { + String fieldName = getCollectionFieldName(); + if (fieldName == null || fieldName.trim().isEmpty()) { + // on travaille directement sur le fieldName + fieldName = getFieldName(); + } + + Object obj = null; + + // obtain the collection to test + try { + obj = getFieldValue(fieldName, object); + } catch (ValidationException e) { + throw e; + } catch (Exception e) { + // let this pass, but it will be logged right below + } + + if (obj == null) { + // la collection est nulle, donc on renvoie une collection vide + return Collections.emptyList(); + } + + if (!Collection.class.isInstance(obj)) { + throw new ValidationException("field " + fieldName + " is not a collection type! (" + obj.getClass() + ")"); + } + return (Collection<?>) obj; + } + + /** + * Calcule pour une entrée donné, le hash de la clef unique + * + * @param o l'entree de la collection dont on va calculer le hash de la clef unique + * @return le hashCode calclé de la clef unique sur l'entrée donné + * @throws ValidationException if any pb to retreave properties values + */ + protected Integer getUniqueKeyHashCode(Object o) throws ValidationException { + // calcul du hash à la volée + HashCodeBuilder builder = new HashCodeBuilder(); + for (String key : keys) { + Object property = getFieldValue(key, o); + if (log.isDebugEnabled()) { + log.debug("key " + key + " : " + property); + } + builder.append(property); + } + return builder.toHashCode(); + } + + @Override + public String getValidatorType() { + return "collectionFieldExpression"; + } + + public class WalkerContext { + + protected final int size; + + public WalkerContext(int size) { + this.size = size; + } + + protected int index = -1; + + protected Object current; + + protected Object previous; + + public void addCurrent(Object current) { + index++; + previous = this.current; + this.current = current; + } + + public Object getCurrent() { + return current; + } + + public int getIndex() { + return index; + } + + public Object getPrevious() { + return previous; + } + + public int getSize() { + return size; + } + + public boolean isEmpty() { + return size == 0; + } + + public boolean isFirst() { + return index == 0; + } + + public boolean isLast() { + return index == size - 1; + } + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/CollectionUniqueKeyValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/CollectionUniqueKeyValidator.java new file mode 100644 index 0000000..f0a4f8f --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/CollectionUniqueKeyValidator.java @@ -0,0 +1,323 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldExpressionValidator; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Un validateur basé sur {@link FieldExpressionValidator} qui valide une clef + * unique sur une collection. + * <p/> + * Le {@link #fieldName} sert à récupérer la propriété de type de collection du + * bean. + * + * @author tchemit <chemit@codelutin.com> + */ +public class CollectionUniqueKeyValidator extends NuitonFieldValidatorSupport { + + /** + * pour indiquer la propriété qui contient la liste à valider. + * <p/> + * Si cette prorpiété n'est pas renseignée alors on utilise la + * {@link #getFieldName()} pour obtenir la collection. + * <p/> + * Cela permet d'effectuer une validation si une collection mais portant + * en fait sur un autre champs + * + * @since 1.5 + */ + protected String collectionFieldName; + + /** + * la liste des propriétés d'une entrée de la collection qui définit la + * clef unique. + */ + protected String[] keys; + + /** + * Une propriété optionnelle pour valider que l'objet reflétée par cette + * propriété ne viole pas l'intégrité de la clef unique. + * Cela permet de valider l'unicité sans que l'objet soit dans la collection + */ + protected String againstProperty; + + /** + * Une propriété optionnelle pour utiliser l'objet en cours de validation pour + * valider que l'objet reflétée par cette propriété ne viole pas l'intégrité de la clef unique. + * Cela permet de valider l'unicité sans que l'objet soit dans la collection + */ + protected boolean againstMe; + + /** + * Lors de l'utilisation de la againstProperty et qu'un ne peut pas utiliser + * le equals sur l'objet, on peut spécifier une expression pour exclure des + * tests lors de la recherche de la violation de clef unique. + */ + protected String againstIndexExpression; + + /** + * Pour ne pas traiter les valeurs nulles (si positionné à {@code true} les + * valeurs nulles ne sont pas considérée comme unique). + * + * @since 2.2.6 + */ + protected boolean nullValueSkipped; + + public String getCollectionFieldName() { + return collectionFieldName; + } + + public void setCollectionFieldName(String collectionFieldName) { + this.collectionFieldName = collectionFieldName; + } + + public String[] getKeys() { + return keys; + } + + public boolean getAgainstMe() { + return againstMe; + } + + public void setKeys(String[] keys) { + if (keys != null && keys.length == 1 && keys[0].indexOf(',') != -1) { + this.keys = keys[0].split(","); + } else { + this.keys = keys; + } + } + + public String getAgainstProperty() { + return againstProperty; + } + + public void setAgainstProperty(String againstProperty) { + this.againstProperty = againstProperty; + } + + public String getAgainstIndexExpression() { + return againstIndexExpression; + } + + public void setAgainstIndexExpression(String againstIndexExpression) { + this.againstIndexExpression = againstIndexExpression; + } + + public void setAgainstMe(boolean againstMe) { + this.againstMe = againstMe; + } + + public boolean isNullValueSkipped() { + return nullValueSkipped; + } + + public void setNullValueSkipped(boolean nullValueSkipped) { + this.nullValueSkipped = nullValueSkipped; + } + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + if (keys == null || keys.length == 0) { + throw new ValidationException("no unique keys defined"); + } + + String fieldName = getFieldName(); + + Collection<?> col = getCollection(object); + + if (log.isDebugEnabled()) { + log.debug("collection found : " + col); + } + Object againstBean = againstProperty == null ? null : + getFieldValue(againstProperty, object); + + if (log.isDebugEnabled()) { + log.debug("againtBean = " + againstBean); + } + Integer againstIndex = (Integer) (againstIndexExpression == null ? + -1 : + getFieldValue(againstIndexExpression, object)); + if (againstIndex == null) { + againstIndex = -1; + } + if (!againstMe && againstBean == null && col.size() < 2) { + // la liste ne contient pas deux entrées donc c'est valide + return; + } + + if (againstMe) { + // try on this object + againstBean = object; + if (log.isDebugEnabled()) { + log.debug("againtBean from me = " + againstBean); + } + } + + + boolean answer = true; + + Integer againstHashCode = againstBean == null ? + null : getUniqueKeyHashCode(againstBean); + if (log.isDebugEnabled()) { + log.debug("hash for new key " + againstHashCode); + } + + if (againstHashCode == null && nullValueSkipped) { + + // clef nulle, donc pas d'erreur vu que le flag a ete positionne + return; + } + List<Integer> hashCodes = new ArrayList<Integer>(); + + int index = 0; + for (Object o : col) { + Integer hash = getUniqueKeyHashCode(o); + + if (log.isDebugEnabled()) { + log.debug("hash for object " + o + " = " + hash); + } + + if (hash == null && nullValueSkipped) { + + // clef nulle, donc pas d'erreur vu que le flag a ete positionne + continue; + } + + if (againstBean == null) { + if (hashCodes.contains(hash)) { + + // on a deja rencontre cette clef unique, + // donc la validation a echouee + answer = false; + if (log.isDebugEnabled()) { + log.debug("Found same hashcode, not unique!"); + } + break; + } + } else { + // utilisation de againstBean + if (againstIndex != -1) { + if (index != againstIndex && + hash.equals(againstHashCode)) { + // on a deja rencontre cette clef unique, + // donc la validation a echouee + answer = false; + break; + } + } else { + if (!againstBean.equals(o) && + hash.equals(againstHashCode)) { + // on a deja rencontre cette clef unique, + // donc la validation a echouee + answer = false; + break; + } + } + } + // nouveau hashcode enregistre + hashCodes.add(hash); + // index suivant + index++; + } + + if (!answer) { + addFieldError(fieldName, object); + } + } + + /** + * Calcule pour une entrée donné, le hash de la clef unique + * + * @param o l'entree de la collection dont on va calculer le hash de + * la clef unique + * @return le hashCode calclé de la clef unique sur l'entrée donné + * @throws ValidationException if any pb to retreave properties values + */ + protected Integer getUniqueKeyHashCode(Object o) + throws ValidationException { + // calcul du hash à la volée + HashCodeBuilder builder = new HashCodeBuilder(); + for (String key : keys) { + Object property = getFieldValue(key, o); + if (property == null && nullValueSkipped) { + // une valeur nulle a ete trouvee et le flag de skip est positionne + // on retourne alors null comme cas limite + return null; + } + + builder.append(property); + } + return builder.toHashCode(); + } + + /** + * @param object the incoming object containing the collection to test + * @return the collection of the incoming object given by the fieldName + * property + * @throws ValidationException if any pb to retreave the collection + */ + protected Collection<?> getCollection(Object object) + throws ValidationException { + String fieldName = getCollectionFieldName(); + if (fieldName == null || fieldName.trim().isEmpty()) { + // on travaille directement sur le fieldName + fieldName = getFieldName(); + } + + Object obj = null; + + // obtain the collection to test + try { + obj = getFieldValue(fieldName, object); + } catch (ValidationException e) { + throw e; + } catch (Exception e) { + // let this pass, but it will be logged right below + } + + if (obj == null) { + // la collection est nulle, donc on renvoie une collection vide + return Collections.emptyList(); + } + + if (!Collection.class.isInstance(obj)) { + throw new ValidationException("field " + fieldName + + " is not a collection type! (" + obj.getClass() + ')'); + } + return (Collection<?>) obj; + } + + @Override + public String getValidatorType() { + return "collectionUniqueKey"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/EmailFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/EmailFieldValidator.java new file mode 100644 index 0000000..da5b790 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/EmailFieldValidator.java @@ -0,0 +1,66 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.util.StringUtil; + +/** + * Validator for email addresses : + * - Deal with + in addresses + * + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class EmailFieldValidator extends NuitonFieldValidatorSupport { + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + // no value defined + return; + } + if (value instanceof String) { + if (StringUtils.isEmpty((String) value)) { + // no value defined + return; + } + if (!StringUtil.isEmail((String) value)) { + addFieldError(fieldName, object); + } + } else { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "emailNuiton"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/ExistingDirectoryFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/ExistingDirectoryFieldValidator.java new file mode 100644 index 0000000..80fe7c5 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/ExistingDirectoryFieldValidator.java @@ -0,0 +1,95 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * ExistingDirectoryFieldValidator checks that a File field exists and is a directory. + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="existingDirectory"> + * <param name="fieldName">tmp</param> + * <message>tmp is not an existing directory</message> + * </validator> + * + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="existingDirectory"> + * <message>tmp is not an existing directory</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author tchemit <chemit@codelutin.com> + */ +public class ExistingDirectoryFieldValidator extends NuitonFieldValidatorSupport { + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + if (value == null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (!(f.isDirectory() && f.exists())) { + // f is not a directory, nor exists + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "existingDirectory"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/ExistingFileFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/ExistingFileFieldValidator.java new file mode 100644 index 0000000..333a601 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/ExistingFileFieldValidator.java @@ -0,0 +1,95 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * ExistingFileFieldValidator checks that a File field exists. * + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="fileExisting"> + * <param name="fieldName">tmp</param> + * <message>tmp is not an existing file</message> + * </validator> + * + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="fileExisting"> + * <message>tmp is not an existing file</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author tchemit <chemit@codelutin.com> + */ +public class ExistingFileFieldValidator extends NuitonFieldValidatorSupport { + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + if (value == null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (!(f.isFile() && f.exists())) { + // f is not a file nor exists + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "existingFile"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/FieldExpressionWithParamsValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/FieldExpressionWithParamsValidator.java new file mode 100644 index 0000000..145bfa6 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/FieldExpressionWithParamsValidator.java @@ -0,0 +1,223 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldExpressionValidator; +import org.nuiton.util.converter.ConverterUtil; + +import java.util.Map; +import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Extends {@link FieldExpressionValidator} to add some extra parameters available + * in the {@link #getExpression()} + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public class FieldExpressionWithParamsValidator extends NuitonFieldExpressionValidator { + + protected static final Pattern EXTRA_BOOLEAN_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(false|true)"); + + protected static final Pattern EXTRA_SHORT_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(\\d+)"); + + protected static final Pattern EXTRA_INT_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(\\d+)"); + + protected static final Pattern EXTRA_LONG_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(\\d+)"); + + protected static final Pattern EXTRA_DOUBLE_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(\\d+\\.\\d+)"); + + protected static final Pattern EXTRA_STRING_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(.+)"); + + protected ValueStack stack; + + protected String booleanParams; + + protected String shortParams; + + protected String intParams; + + protected String longParams; + + protected String doubleParams; + + protected String stringParams; + + protected Map<String, Boolean> booleans; + + protected Map<String, Short> shorts; + + protected Map<String, Integer> ints; + + protected Map<String, Long> longs; + + protected Map<String, Double> doubles; + + protected Map<String, String> strings; + + public String getBooleanParams() { + return booleanParams; + } + + public void setBooleanParams(String booleanParams) { + this.booleanParams = booleanParams; + } + + public String getDoubleParams() { + return doubleParams; + } + + public void setDoubleParams(String doubleParams) { + this.doubleParams = doubleParams; + } + + public String getIntParams() { + return intParams; + } + + public void setIntParams(String intParams) { + this.intParams = intParams; + } + + public String getLongParams() { + return longParams; + } + + public void setLongParams(String longParams) { + this.longParams = longParams; + } + + public String getShortParams() { + return shortParams; + } + + public void setShortParams(String shortParams) { + this.shortParams = shortParams; + } + + public String getStringParams() { + return stringParams; + } + + public void setStringParams(String stringParams) { + this.stringParams = stringParams; + } + + public Map<String, Boolean> getBooleans() { + return booleans; + } + + public Map<String, Double> getDoubles() { + return doubles; + } + + public Map<String, Integer> getInts() { + return ints; + } + + public Map<String, Long> getLongs() { + return longs; + } + + public Map<String, Short> getShorts() { + return shorts; + } + + public Map<String, String> getStrings() { + return strings; + } + + @Override + public String getValidatorType() { + return "fieldexpressionwithparams"; + } + + @Override + public void setValueStack(ValueStack stack) { + super.setValueStack(stack); + this.stack = stack; + } + + @Override + public void validate(Object object) throws ValidationException { + super.validate(object); + } + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + booleans = initParams(Boolean.class, booleanParams, EXTRA_BOOLEAN_PARAM_ENTRY_PATTERN); + shorts = initParams(Short.class, shortParams, EXTRA_SHORT_PARAM_ENTRY_PATTERN); + ints = initParams(Integer.class, intParams, EXTRA_INT_PARAM_ENTRY_PATTERN); + longs = initParams(Long.class, longParams, EXTRA_LONG_PARAM_ENTRY_PATTERN); + doubles = initParams(Double.class, doubleParams, EXTRA_DOUBLE_PARAM_ENTRY_PATTERN); + strings = initParams(String.class, stringParams, EXTRA_STRING_PARAM_ENTRY_PATTERN); + + boolean pop = false; + if (!stack.getRoot().contains(this)) { + stack.push(this); + pop = true; + } + + try { + super.validateWhenNotSkip(object); + } finally { + if (pop) { + stack.pop(); + } + } + + } + + protected <T> Map<String, T> initParams(Class<T> klass, String extraParams, Pattern pattern) throws ValidationException { + + if (extraParams == null || extraParams.isEmpty()) { + // not using + return null; + } + + StringTokenizer stk = new StringTokenizer(extraParams, "|"); + Map<String, T> result = new TreeMap<String, T>(); + while (stk.hasMoreTokens()) { + String entry = stk.nextToken(); + Matcher matcher = pattern.matcher(entry); + if (!matcher.matches()) { + throw new ValidationException("could not parse for extra params " + extraParams + " for type " + klass.getName()); + } + String paramName = matcher.group(1); + String paramValueStr = matcher.group(2); + T paramValue = ConverterUtil.convert(klass, paramValueStr); + if (log.isDebugEnabled()) { + log.debug("detected extra param : <type:" + klass + ", name:" + paramName + ", value:" + paramValue + ">"); + } + result.put(paramName, paramValue); + } + return result; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/FrenchCityNameFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/FrenchCityNameFieldValidator.java new file mode 100644 index 0000000..ecf4516 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/FrenchCityNameFieldValidator.java @@ -0,0 +1,75 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Validator for French cities names : + * - No number accepted + * - Accept spaces, - and ' + * + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchCityNameFieldValidator extends NuitonFieldValidatorSupport { + + protected static String CITY_NAME_REGEXP = "[^\\d]+"; + + protected static Pattern p = Pattern.compile(CITY_NAME_REGEXP); + + //TODO JC18082011 - Deal with cedex + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + // no value defined + return; + } + if (value instanceof String) { + if ("".equals(value)) { + // no value defined + return; + } + Matcher m = p.matcher((String) value); + if (!m.matches()) { + addFieldError(fieldName, object); + } + } else { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "frenchCityName"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/FrenchFinessFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/FrenchFinessFieldValidator.java new file mode 100644 index 0000000..947b55d --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/FrenchFinessFieldValidator.java @@ -0,0 +1,92 @@ +package org.nuiton.validator.xwork2.field; + +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.opensymphony.xwork2.validator.ValidationException; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Sylvain Bavencoff <bavencoff@codelutin.com> + */ +public class FrenchFinessFieldValidator extends NuitonFieldValidatorSupport { + + protected static final String SIRET_REGEXP = "([0-9]{2}|2A|2B)0([0-9]{6})"; + + protected static final Pattern p = Pattern.compile(SIRET_REGEXP); + + @Override + protected void validateWhenNotSkip(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + // no value defined + return; + } + String finess; + + if (value.getClass().isArray()) { + // le finess est stocker dans un tableau, par exemple un byte[] + finess = ""; + for (int i = 0; i < Array.getLength(value); i++) { + finess += String.valueOf(Array.get(value, i)); + } + } else if (value instanceof Collection<?>) { + // le finess est stocker dans une collection, + // ca doit pas arriver souvent :D, mais autant le gerer + finess = ""; + for (Object o : (Collection<?>) value) { + finess += String.valueOf(o); + } + } else { + // sinon dans tous les autres cas (String, int, long, BigInteger ...) + // on prend le toString + finess = String.valueOf(value); + } + + if (StringUtils.isEmpty(finess)) { + // no value defined + return; + } + + // Remove any space + finess = finess.replaceAll(" ", ""); + + Matcher m = p.matcher(finess); + if (!m.matches()) { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "frenchFiness"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/FrenchLastNameFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/FrenchLastNameFieldValidator.java new file mode 100644 index 0000000..e342dec --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/FrenchLastNameFieldValidator.java @@ -0,0 +1,73 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Validator for French last names : + * - No number accepted + * - Accept spaces, - and ' + * + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchLastNameFieldValidator extends NuitonFieldValidatorSupport { + + protected static String LAST_NAME_REGEXP = "[^\\d]+"; + + protected static Pattern p = Pattern.compile(LAST_NAME_REGEXP); + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + // no value defined + return; + } + if (value instanceof String) { + if ("".equals(value)) { + // no value defined + return; + } + Matcher m = p.matcher((String) value); + if (!m.matches()) { + addFieldError(fieldName, object); + } + } else { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "frenchLastName"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/FrenchPhoneNumberFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/FrenchPhoneNumberFieldValidator.java new file mode 100644 index 0000000..c1f3d09 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/FrenchPhoneNumberFieldValidator.java @@ -0,0 +1,76 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Validator used to validate French phone numbers like : + * - 0000000000 + * - 00.00.00.00.00 + * - 00-00-00-00-00 + * - 00 00 00 00 00 + * + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchPhoneNumberFieldValidator extends NuitonFieldValidatorSupport { + + protected static String PHONE_NUMBER_REGEXP = + "[0-9]{10}|(([0-9]{2}[-\\.\\s]){4})[0-9]{2}"; + + protected static Pattern p = Pattern.compile(PHONE_NUMBER_REGEXP); + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + // no value defined + return; + } + if (value instanceof String) { + if ("".equals(value)) { + // no value defined + return; + } + Matcher m = p.matcher((String) value); + if (!m.matches()) { + addFieldError(fieldName, object); + } + } else { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "frenchPhoneNumber"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/FrenchPostCodeFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/FrenchPostCodeFieldValidator.java new file mode 100644 index 0000000..7555386 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/FrenchPostCodeFieldValidator.java @@ -0,0 +1,76 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Validate post codes for French cities + * <p/> + * - Take into account 2A and 2B + * - Take into account DOMs and TOMs + * - Postcodes starting with 99 are not valid + * + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchPostCodeFieldValidator extends NuitonFieldValidatorSupport { + + protected static String POST_CODE_REGEXP = + "^((0[1-9])|([1-8][0-9])|(9[0-8])|(2A)|(2B))[0-9]{3}$"; + + protected static Pattern p = Pattern.compile(POST_CODE_REGEXP); + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + // no value defined + return; + } + if (value instanceof String) { + if ("".equals(value)) { + // no value defined + return; + } + Matcher m = p.matcher((String) value); + if (!m.matches()) { + addFieldError(fieldName, object); + } + } else { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "frenchPostCode"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/FrenchSiretFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/FrenchSiretFieldValidator.java new file mode 100644 index 0000000..cc495b4 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/FrenchSiretFieldValidator.java @@ -0,0 +1,176 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Validator for French SIRET numbers + * <p/> + * Siret can be in: + * <li>String format: "44211670300038" + * <li>long, int: 44211670300038 + * <li>Array or Collection of something: [4,4,2,1,1,6,7,0,,3,0,0,0,3,8] or ["442","116","703", "0003", "8"] + * + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + * Validation do the Luhn checksum too + */ +public class FrenchSiretFieldValidator extends NuitonFieldValidatorSupport { + + protected static final String SIRET_REGEXP = "[0-9]{14}"; + + protected static final Pattern p = Pattern.compile(SIRET_REGEXP); + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + // no value defined + return; + } + String siret; + + if (value.getClass().isArray()) { + // le siret est stocker dans un tableau, par exemple un byte[] + siret = ""; + for (int i = 0; i < Array.getLength(value); i++) { + siret += String.valueOf(Array.get(value, i)); + } + } else if (value instanceof Collection<?>) { + // le siret est stocker dans une collection, + // ca doit pas arriver souvent :D, mais autant le gerer + siret = ""; + for (Object o : (Collection<?>) value) { + siret += String.valueOf(o); + } + } else { + // sinon dans tous les autres cas (String, int, long, BigInteger ...) + // on prend le toString + siret = String.valueOf(value); + } + + if (StringUtils.isEmpty(siret)) { + // no value defined + return; + } + + // Remove any space + siret = siret.replaceAll(" ", ""); + + Matcher m = p.matcher(siret); + if (!m.matches() || !luhnChecksum(siret)) { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "frenchSiret"; + } + + /** + * Verifie la validite d'un numero en suivant l'algorithme Luhn tel que d'ecrit + * dans <a href="http://fr.wikipedia.org/wiki/Luhn">wikipedia</a> + * <p/> + * Algo: + * en fonction de la position du numero dans la sequence, + * on multiplie pas 1 (pour les impaires) ou par 2 pour les paires + * (1 etant le numero le plus a droite) + * On fait la somme de tous les chiffres qui resulte de ces multiplications + * (si un resultat etait 14, on ne fait pas +14 mais +1+4) + * <p/> + * Si le résultat de cette somme donne un reste de 0 une fois divisé par 10 + * le numero est valide. + * + * @param siret une chaine composer que de chiffre + * @return vrai si on a reussi a valider le numero + */ + public static boolean luhnChecksum(String siret) { + + char[] tab = siret.toCharArray(); + int sum = 0; + for (int i = tab.length - 1; i >= 0; i--) { + // recuperation de la valeur + int n = getDigit(tab[i]); + + // 1ere phase il faut faire la multiplication par 1 ou 2 + + // il faut faire x1 pour les paires et x2 sur les impaires. + // en prenant en compte que le numero siret le plus a droite est le + // 1 et le plus a gauche le 14. + // mais comme en informatique on commence a 0 :D + // il faut faire +1 sur l'indice puis un simple module 2 + 1 + // nous convient + n *= (i + 1) % 2 + 1; + + // 2eme phase il faut faire l'addition + + // si une fois multiplie il est superieur a 9, il faut additionner + // toutes ces constituante, mais comme il ne peut pas etre superieur + // a 18, cela revient a retrancher 9 + if (n > 9) { + n -= 9; + } + + // on peut directement faire la somme + sum += n; + } + + // 3eme phase on verifie que c'est bien un multiple de 10 + boolean result = sum % 10 == 0; + + return result; + } + + + /** + * Converti un char en un entier '0' => 0 et '9' => 9, et 'A' => 10 a 'Z' => 36, + * les autres caractere sont aussi convertis pour que 'a' = 10 et 'z' = 36. + * Pour les autres c'est un indedermine + * + * @param c le caractere qui doit etre converti + * @return le chiffre + */ + public static int getDigit(char c) { + int result = 0; + if (c >= '0' && c <= '9') { + result = c - '0'; + } else if (c >= 'A' && c <= 'Z') { + result = c - 'A' + 10; + } else { + result = c - 'a' + 10; + } + return result; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/NotExistingDirectoryFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/NotExistingDirectoryFieldValidator.java new file mode 100644 index 0000000..b65f731 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/NotExistingDirectoryFieldValidator.java @@ -0,0 +1,94 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * NotExistingDirectoryFieldValidator checks that a File field as a directory does not exist. * + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="notExistingDirectory"> + * <param name="fieldName">tmp</param> + * <message>tmp is an existing directory</message> + * </validator> + * + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="notExistingDirectory"> + * <message>tmp is an existing directory</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author tchemit <chemit@codelutin.com> + */ +public class NotExistingDirectoryFieldValidator extends NuitonFieldValidatorSupport { + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + if (value == null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (f.exists() || f.isFile()) { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "notExistingDirectory"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/NotExistingFileFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/NotExistingFileFieldValidator.java new file mode 100644 index 0000000..f189e52 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/NotExistingFileFieldValidator.java @@ -0,0 +1,95 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * NotExistingFileFieldValidator checks that a File field as a file does not exist. * + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="notExistingFile"> + * <param name="fieldName">tmp</param> + * <message>tmp is an existing file</message> + * </validator> + * + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="notExistingFile"> + * <message>tmp is an existing file</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author tchemit <chemit@codelutin.com> + */ +public class NotExistingFileFieldValidator extends NuitonFieldValidatorSupport { + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + if (value == null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (f.exists() || f.isDirectory()) { + // f is not a file and exist + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "notExistingFile"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/NuitonFieldExpressionValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/NuitonFieldExpressionValidator.java new file mode 100644 index 0000000..971f6b2 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/NuitonFieldExpressionValidator.java @@ -0,0 +1,136 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldExpressionValidator; + +/** + * Nuiton default field validator. + * <p/> + * This validator offers a {@link #skip} property that can be used to skip or + * not the validator, this property is a OGNL expression. + * <p/> + * To use this new field validator support, just now implements the method + * {@link #validateWhenNotSkip(Object)}. This method will be invoked only if the skip + * parameter is evaluated to {@code false}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.3 + */ +public class NuitonFieldExpressionValidator extends FieldExpressionValidator { + + /** + * extra parameter at the very beginning of the + * {@link #validate(Object)} method to be able to skip (or not) the + * validator execution. + * <p/> + * by default the value is {@code false} : it seems fair to want to + * validate if the validator is used :D... + */ + protected String skip = "false"; + + /** + * Sets the value of the {@link #skip} parameter. + * + * @param skip the new value of the {@link #skip} parameter + */ + public void setSkip(String skip) { + this.skip = skip; + } + + /** + * Method to be invoked when skip parameter was not evaludated to {@code true}. + * + * @param object the object to be validated. + * @throws ValidationException is thrown if there is validation error(s). + */ + + protected void validateWhenNotSkip(Object object) throws ValidationException { + super.validate(object); + } + + @Override + public void validate(Object object) throws ValidationException { + + // evaluate the skip parameter + boolean mustSkip = evaluateSkipParameter(object); + + if (mustSkip) { + + // skip is set to true, so skip the validation + if (log.isDebugEnabled()) { + log.debug("Skip the validation from " + this + + ", due to skip parameter evaluated to true"); + } + return; + } + + // must validate + validateWhenNotSkip(object); + } + + /** + * Evaluate the skip parameter value against the object to validate. + * <p/> + * This parameter can be an OGNL expression. + * + * @param object the object to validate + * @return the evaluation of the skip parameter. + * @throws ValidationException if could not evaluate the parameter + */ + protected boolean evaluateSkipParameter(Object object) throws ValidationException { + + skip = skip.trim(); + + if ("false".equals(skip)) { + + return false; + } + + if ("true".equals(skip)) { + + return true; + } + + try { + Boolean answer = Boolean.FALSE; + Object obj; + obj = getFieldValue(skip, object); + if (obj != null && obj instanceof Boolean) { + answer = (Boolean) obj; + } + return answer; + } catch (ValidationException e) { + throw e; + } catch (Exception e) { + // let this pass, but it will be logged right below + throw new ValidationException( + "Can not evaluate boolean expression [" + skip + + "] for reason " + e.getMessage()); + } + + } + +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/NuitonFieldValidatorSupport.java b/src/main/java/org/nuiton/validator/xwork2/field/NuitonFieldValidatorSupport.java new file mode 100644 index 0000000..a486686 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/NuitonFieldValidatorSupport.java @@ -0,0 +1,139 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; + +/** + * Nuiton default field validator. + * <p/> + * This validator offers a {@link #skip} property that can be used to skip or + * not the validator, this property is a OGNL expression. + * <p/> + * To use this new field validator support, just now implements the method + * {@link #validateWhenNotSkip(Object)}. This method will be invoked only if the skip + * parameter is evaluated to {@code false}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.3 + */ +public abstract class NuitonFieldValidatorSupport extends FieldValidatorSupport { + + /** + * extra parameter at the very beginning of the + * {@link #validate(Object)} method to be able to skip (or not) the + * validator execution. + * <p/> + * by default the value is {@code false} : it seems fair to want to + * validate if the validator is used :D... + */ + protected String skip = "false"; + + /** + * Sets the value of the {@link #skip} parameter. + * + * @param skip the new value of the {@link #skip} parameter + */ + public void setSkip(String skip) { + this.skip = skip; + } + + /** + * Method to be invoked when skip parameter was not evaludated to {@code true}. + * + * @param object the object to be validated. + * @throws ValidationException is thrown if there is validation error(s). + */ + + protected abstract void validateWhenNotSkip(Object object) throws ValidationException; + + @Override + public void validate(Object object) throws ValidationException { + + // evaluate the skip parameter + boolean mustSkip = evaluateSkipParameter(object); + + if (mustSkip) { + + // skip is set to true, so skip the validation + if (log.isDebugEnabled()) { + log.debug("Skip the validation from " + this + + ", due to skip parameter evaluated to true"); + } + return; + } + + // must validate + validateWhenNotSkip(object); + } + + /** + * Evaluate the skip parameter value against the object to validate. + * <p/> + * This parameter can be an OGNL expression. + * + * @param object the object to validate + * @return the evaluation of the skip parameter. + * @throws ValidationException if could not evaluate the parameter + */ + protected boolean evaluateSkipParameter(Object object) throws ValidationException { + + skip = skip.trim(); + + if ("false".equals(skip)) { + + return false; + } + + if ("true".equals(skip)) { + + return true; + } + + try { + Boolean answer = Boolean.FALSE; + Object obj; + obj = getFieldValue(skip, object); + if (obj != null && obj instanceof Boolean) { + answer = (Boolean) obj; + } + return answer; + } catch (ValidationException e) { + throw e; + } catch (Exception e) { + // let this pass, but it will be logged right below + throw new ValidationException( + "Can not evaluate boolean expression [" + skip + + "] for reason " + e.getMessage()); + } + + } + + @Override + public Object getFieldValue(String name, + Object object) throws ValidationException { + return super.getFieldValue(name, object); + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/RequiredFileFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/RequiredFileFieldValidator.java new file mode 100644 index 0000000..a6135ae --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/RequiredFileFieldValidator.java @@ -0,0 +1,95 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * RequiredFileFieldValidator checks that a File field is not null nor have an empty filename. + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="requiredFile"> + * <param name="fieldName">tmp</param> + * <message>tmp is required</message> + * </validator> + * + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="requiredFile"> + * <message>tmp is required</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author tchemit <chemit@codelutin.com> + */ +public class RequiredFileFieldValidator extends NuitonFieldValidatorSupport { + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + if (value == null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (f.getPath().trim().isEmpty()) { + // f is not a directory nor exists + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "requiredFile"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/SkipableRequiredFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/SkipableRequiredFieldValidator.java new file mode 100644 index 0000000..c89a153 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/SkipableRequiredFieldValidator.java @@ -0,0 +1,43 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class SkipableRequiredFieldValidator extends NuitonFieldValidatorSupport { + + @Override + protected void validateWhenNotSkip(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + addFieldError(fieldName, object); + } + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/SkipableRequiredStringFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/SkipableRequiredStringFieldValidator.java new file mode 100644 index 0000000..9564d51 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/SkipableRequiredStringFieldValidator.java @@ -0,0 +1,43 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class SkipableRequiredStringFieldValidator extends NuitonFieldValidatorSupport { + + @Override + protected void validateWhenNotSkip(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null || !(value instanceof String) || "".equals(value)) { + addFieldError(fieldName, object); + } + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/VATIdentificationNumberFieldValidator.java b/src/main/java/org/nuiton/validator/xwork2/field/VATIdentificationNumberFieldValidator.java new file mode 100644 index 0000000..68d8946 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/VATIdentificationNumberFieldValidator.java @@ -0,0 +1,78 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import com.opensymphony.xwork2.validator.ValidationException; +import org.apache.commons.lang3.StringUtils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Validator for EU VAT number. + * + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class VATIdentificationNumberFieldValidator extends NuitonFieldValidatorSupport { + + protected static String VAT_INTRA_REGEXP = "^(RO\\d{2,10}|GB\\d{5}|(ATU|DK|FI|HU|LU|MT|CZ|SI)\\d{8}|IE[A-Z\\d]{8}|(DE|BG|EE|EL|LT|BE0|PT|CZ)\\d{9}|CY\\d{8}[A-Z]|(ES|GB)[A-Z\\d]{9}|(BE0|PL|SK|CZ)\\d{10}|(FR|IT|LV)\\d{11}|(LT|SE)\\d{12}|(NL|GB)[A-Z\\d]{12})$"; + + protected static Pattern p = Pattern.compile(VAT_INTRA_REGEXP); + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + String fieldName = getFieldName(); + Object value = getFieldValue(fieldName, object); + + if (value == null) { + // no value defined + return; + } + if (value instanceof String) { + + String vatNumber = (String) value; + if (StringUtils.isEmpty(vatNumber)) { + // no value defined + return; + } + + // Remove any space + vatNumber = vatNumber.replaceAll(" ", ""); + + Matcher m = p.matcher(vatNumber); + if (!m.matches()) { + addFieldError(fieldName, object); + } + } else { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "VATIdentificationNumber"; + } +} diff --git a/src/main/java/org/nuiton/validator/xwork2/field/package-info.java b/src/main/java/org/nuiton/validator/xwork2/field/package-info.java new file mode 100644 index 0000000..d788651 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/field/package-info.java @@ -0,0 +1,31 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/** + * Package of extra xworks2 field validators. + * + * <strong>To be continued...</strong> + * + * @since 2.0 + */ +package org.nuiton.validator.xwork2.field; diff --git a/src/main/java/org/nuiton/validator/xwork2/package-info.java b/src/main/java/org/nuiton/validator/xwork2/package-info.java new file mode 100644 index 0000000..e45bb25 --- /dev/null +++ b/src/main/java/org/nuiton/validator/xwork2/package-info.java @@ -0,0 +1,31 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/** + * Package of xworks2 implementation of the Nuiton-validator api. + * + * <strong>To be continued...</strong> + * + * @since 2.0 + */ +package org.nuiton.validator.xwork2; diff --git a/src/main/resources/META-INF/services/org.nuiton.validator.NuitonValidatorProvider b/src/main/resources/META-INF/services/org.nuiton.validator.NuitonValidatorProvider new file mode 100644 index 0000000..02c867d --- /dev/null +++ b/src/main/resources/META-INF/services/org.nuiton.validator.NuitonValidatorProvider @@ -0,0 +1 @@ +org.nuiton.validator.xwork2.XWork2NuitonValidatorProvider \ No newline at end of file diff --git a/src/main/resources/i18n/nuiton-validator_en_GB.properties b/src/main/resources/i18n/nuiton-validator_en_GB.properties new file mode 100644 index 0000000..5770128 --- /dev/null +++ b/src/main/resources/i18n/nuiton-validator_en_GB.properties @@ -0,0 +1,4 @@ +validator.scope.error.label=Error +validator.scope.fatal.label=Fatal error +validator.scope.info.label=Information +validator.scope.warning.label=Warning diff --git a/src/main/resources/i18n/nuiton-validator_es_ES.properties b/src/main/resources/i18n/nuiton-validator_es_ES.properties new file mode 100644 index 0000000..db00e32 --- /dev/null +++ b/src/main/resources/i18n/nuiton-validator_es_ES.properties @@ -0,0 +1,4 @@ +validator.scope.error.label=Error +validator.scope.fatal.label=Fatal Error +validator.scope.info.label=Información +validator.scope.warning.label=Advertencias diff --git a/src/main/resources/i18n/nuiton-validator_fr_FR.properties b/src/main/resources/i18n/nuiton-validator_fr_FR.properties new file mode 100644 index 0000000..eccfedd --- /dev/null +++ b/src/main/resources/i18n/nuiton-validator_fr_FR.properties @@ -0,0 +1,4 @@ +validator.scope.error.label=Erreur +validator.scope.fatal.label=Erreur fatale +validator.scope.info.label=Information +validator.scope.warning.label=Avertissement diff --git a/src/site/apt/index.apt b/src/site/apt/index.apt new file mode 100644 index 0000000..1ae8431 --- /dev/null +++ b/src/site/apt/index.apt @@ -0,0 +1,98 @@ +~~~ +~~ #%L +~~ Nuiton Validator +~~ $Id$ +~~ $HeadURL$ +~~ %% +~~ Copyright (C) 2011 CodeLutin +~~ %% +~~ This program is free software: you can redistribute it and/or modify +~~ it under the terms of the GNU Lesser General Public License as +~~ published by the Free Software Foundation, either version 3 of the +~~ License, or (at your option) any later version. +~~ +~~ This program is distributed in the hope that it will be useful, +~~ but WITHOUT ANY WARRANTY; without even the implied warranty of +~~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +~~ GNU General Lesser Public License for more details. +~~ +~~ You should have received a copy of the GNU General Lesser Public +~~ License along with this program. If not, see +~~ <http://www.gnu.org/licenses/lgpl-3.0.html>. +~~ #L% +~~~ + ---- + Nuiton Validator + ---- + ---- + 2011-01-27 + ---- + + + +Présentation + + La librairie <Nuiton-validator> propose une api neutre de validation intégrant + la notion de niveau de validation. + +Note + + <<Nuiton-validator>> quitte le projet <nuiton-utils> pour devenir un projet autonome. + + Voici quelques liens sur le nouveau projet: + + * {{{http://svn.nuiton.org/svn/nuiton-validator}svn}} + + * {{{http://nuiton.org/projects/nuiton-validator}forge}} + + * {{{http://maven-site.nuiton.org/nuiton-validator}site}} + + [] + + A noter que le GAV de l'artefact ne change pas (<org.nuiton:nuiton-validator>). + + La dernière version stable dans nuiton-utils est la 2.7; vous pouvez dès à + présent utiliser la version 3.0-alpha-1 de nuiton-validator. + + Pour plus de détails sur les changements importants entre chaque version, + vous pouvez consulter les {{{./versions.html}Notes de versions}}. + +Implantation (xwork2) + + Actuellement la seule implantation disponible se base sur XWork2. + +* Configuration + + La configuration des validateurs se font via des fichier xml. + +* Ajout d'un validateur + + Pour enregister un nouveau validateur sur un bean, il suffit de placer dans + le même paquetage que le bean un fichier <XXX[-context]-scope-validation.xml> où + XXX est le nom non qualifié du bean. + + Le context optionel permet de définir plusieurs contexts de validation. + + Le scope parmi les suivants : fatal, error, warning, info donne le niveau de + validation. + +* Ajout d'un nouveau type de validateur + + Il est aussi possible de définir de nouveau type de validateurs : + + * créer une classe qui étend FieldValidator + + * ajouter un fichier <validators.xml> (ou ajouter dans un tel fichier la + définition du nouveau validator) à la racine du class-path. + +* I18n + + Afin de rendre le mécanisme multi-langue, on propose dans les fichiers de + validations d'utiliser des clef i18n pour les messages. + + Un nouveau parseur dans notre plugin i18n a été ajouté pour détecter ces + clefs. (<i18n:parserValidation>) + + + <Veuillez consulter la JavaDoc pour de plus ample détails sur les différentes + librairies.> diff --git a/src/site/apt/versions.apt b/src/site/apt/versions.apt new file mode 100644 index 0000000..88f986b --- /dev/null +++ b/src/site/apt/versions.apt @@ -0,0 +1,33 @@ +~~~ +~~ #%L +~~ Nuiton Config +~~ $Id$ +~~ $HeadURL$ +~~ %% +~~ Copyright (C) 2013 CodeLutin +~~ %% +~~ This program is free software: you can redistribute it and/or modify +~~ it under the terms of the GNU Lesser General Public License as +~~ published by the Free Software Foundation, either version 3 of the +~~ License, or (at your option) any later version. +~~ +~~ This program is distributed in the hope that it will be useful, +~~ but WITHOUT ANY WARRANTY; without even the implied warranty of +~~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +~~ GNU General Lesser Public License for more details. +~~ +~~ You should have received a copy of the GNU General Lesser Public +~~ License along with this program. If not, see +~~ <http://www.gnu.org/licenses/lgpl-3.0.html>. +~~ #L% +~~~ + ---- + Nuiton config + ---- + ---- + 2013-07-23 + ---- + +Utilisation de la version 3.0 + + * Pas de migration (pour le moment). \ No newline at end of file diff --git a/src/site/site_fr.xml b/src/site/site_fr.xml new file mode 100644 index 0000000..8428c9e --- /dev/null +++ b/src/site/site_fr.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2013 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<project name="${project.name}"> + + <skin> + <groupId>org.apache.maven.skins</groupId> + <artifactId>maven-fluido-skin</artifactId> + <version>1.3.0</version> + </skin> + + <custom> + <fluidoSkin> + <topBarEnabled>false</topBarEnabled> + <googleSearch/> + <sideBarEnabled>true</sideBarEnabled> + <searchEnabled>true</searchEnabled> + <sourceLineNumbersEnabled>true</sourceLineNumbersEnabled> + </fluidoSkin> + </custom> + + <bannerLeft> + <name>${project.name}</name> + <href>index.html</href> + </bannerLeft> + + <bannerRight> + <src>http://www.codelutin.com/images/lutinorange-codelutin.png</src> + <href>http://www.codelutin.com</href> + </bannerRight> + + <publishDate position="right" /> + <version position="right" /> + + <poweredBy> + + <logo href="http://maven.apache.org" name="Maven" + img="http://maven-site.chorem.org/public/images/logos/maven-feather.png"/> + + </poweredBy> + + <body> + + <head> + <script type="text/javascript" + src="http://maven-site.chorem.org/public/js/mavenpom-site.js"> + </script> + + <link rel="stylesheet" type="text/css" + href="http://maven-site.chorem.org/public/css/mavenpom-site.css"/> + </head> + + <links> + <item name="Nuiton.org" href="http://nuiton.org"/> + <item name="Code Lutin" href="http://www.codelutin.com"/> + <item name="Libre entreprise" href="http://www.libre-entreprise.org"/> + </links> + + <breadcrumbs> + <item name="${project.name}" + href="${project.url}/index.html"/> + </breadcrumbs> + + <menu name="Utilisateur"> + <item name="Accueil" href="index.html"/> + <item name="Note de versions" href="versions.html"/> + </menu> + + <menu ref="reports"/> + + <footer> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}' locale='fr'> + </div> + </footer> + </body> +</project> diff --git a/src/test/java/org/nuiton/validator/AbstractValidatorDetectorTest.java b/src/test/java/org/nuiton/validator/AbstractValidatorDetectorTest.java new file mode 100644 index 0000000..b7f6d72 --- /dev/null +++ b/src/test/java/org/nuiton/validator/AbstractValidatorDetectorTest.java @@ -0,0 +1,159 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; + +import java.io.File; +import java.util.Iterator; +import java.util.SortedSet; +import java.util.regex.Pattern; + +/** + * Abstract test to detects and test your validators. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public abstract class AbstractValidatorDetectorTest { + + protected final String providerName; + + protected File rootDirectory; + + public AbstractValidatorDetectorTest(String providerName) { + this.providerName = providerName; + } + + protected NuitonValidatorProvider provider; + + protected abstract File getRootDirectory(File basedir); + + @Before + public void setUp() throws Exception { + provider = NuitonValidatorFactory.getProvider(providerName); + rootDirectory = getRootDirectory(ValidatorTestHelper.getBasedir()); + } + + @After + public void tearDown() throws Exception { + provider = null; + } + + protected SortedSet<NuitonValidator<?>> detectValidators(Class<?>... types) { + return detectValidators(null, NuitonValidatorScope.values(), types); + } + + protected SortedSet<NuitonValidator<?>> detectValidators(Pattern context, Class<?>... types) { + return detectValidators(context, NuitonValidatorScope.values(), types); + } + + protected SortedSet<NuitonValidator<?>> detectValidators(Pattern context, NuitonValidatorScope[] scopes, Class<?>... types) { + SortedSet<NuitonValidator<?>> validators = + provider.detectValidators(rootDirectory, context, scopes, types); + return validators; + } + + public void assertValidatorModel(NuitonValidator<?> validator, + String expectedContext, + Class<?> expectedType, + NuitonValidatorScope... expectedScopes) { + ValidatorTestHelper.assertValidatorModel( + validator, + expectedContext, + expectedType, + expectedScopes + ); + } + + public void assertValidatorEffectiveScopes(NuitonValidator<?> validator, + NuitonValidatorScope... expectedScopes) { + ValidatorTestHelper.assertValidatorEffectiveScopes(validator, + expectedScopes + ); + } + + public void assertValidatorEffectiveFields(NuitonValidator<?> validator, + String... expectedFields) { + + ValidatorTestHelper.assertValidatorEffectiveFields(validator, + expectedFields); + } + + public void assertValidatorEffectiveFields(NuitonValidator<?> validator, + NuitonValidatorScope scope, + String... expectedFields) { + ValidatorTestHelper.assertValidatorEffectiveFields(validator, + scope, + expectedFields); + } + + public void assertValidatorSetWithMultiContextName(SortedSet<NuitonValidator<?>> result, + Object... contextThenClass) { + + Assert.assertNotNull(result); + Assert.assertEquals(contextThenClass.length / 2, result.size()); + + Iterator<NuitonValidator<?>> itr = result.iterator(); + int index = 0; + + NuitonValidatorScope[] scopes = NuitonValidatorScope.values(); + + while (itr.hasNext()) { + NuitonValidator<?> next = itr.next(); + ValidatorTestHelper.assertValidatorModel(next, + (String) contextThenClass[2 * index], + (Class<?>) contextThenClass[2 * index + 1], + scopes); + index++; + } + + } + + public void assertValidatorSetWithSameContextName(SortedSet<NuitonValidator<?>> result, + String context, + Class<?>... contextThenClass) { + + Assert.assertNotNull(result); + Assert.assertEquals(contextThenClass.length, result.size()); + + Iterator<NuitonValidator<?>> itr = result.iterator(); + int index = 0; + + NuitonValidatorScope[] scopes = NuitonValidatorScope.values(); + + while (itr.hasNext()) { + NuitonValidator<?> next = itr.next(); + ValidatorTestHelper.assertValidatorModel(next, + context, + contextThenClass[index++], + scopes); + } + + } + + +} diff --git a/src/test/java/org/nuiton/validator/NuitonValidatorFactoryTest.java b/src/test/java/org/nuiton/validator/NuitonValidatorFactoryTest.java new file mode 100644 index 0000000..232c338 --- /dev/null +++ b/src/test/java/org/nuiton/validator/NuitonValidatorFactoryTest.java @@ -0,0 +1,59 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.validator.model.Person; +import org.nuiton.validator.xwork2.XWork2NuitonValidatorProvider; + +import java.util.Map; + +/** + * To test {@link NuitonValidatorFactory}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class NuitonValidatorFactoryTest { + + @Test + public void testGetProviders() throws Exception { + Map<String, NuitonValidatorProvider> providers = NuitonValidatorFactory.getProviders(); + Assert.assertNotNull(providers); + Assert.assertEquals(1, providers.size()); + Assert.assertTrue(providers.containsKey(XWork2NuitonValidatorProvider.PROVIDER_NAME)); + Assert.assertTrue(providers.get(XWork2NuitonValidatorProvider.PROVIDER_NAME) instanceof XWork2NuitonValidatorProvider); + } + + @Test + public void testNewValidator() throws Exception { + + NuitonValidator<Person> validator = + NuitonValidatorFactory.newValidator(Person.class); + + ValidatorTestHelper.testPerson(validator); + } + +} diff --git a/src/test/java/org/nuiton/validator/ValidatorTestHelper.java b/src/test/java/org/nuiton/validator/ValidatorTestHelper.java new file mode 100644 index 0000000..0556e9f --- /dev/null +++ b/src/test/java/org/nuiton/validator/ValidatorTestHelper.java @@ -0,0 +1,173 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator; + +import org.junit.Assert; +import org.nuiton.validator.model.Person; +import org.nuiton.validator.model.Pet; + +import java.io.File; +import java.util.List; +import java.util.Set; + +/** + * Helper methods to test the validator api. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class ValidatorTestHelper { + + public static File getBasedir() { + + // Search basedir from maven environment + String basedirPath = System.getenv("basedir"); + if (basedirPath == null) { + + // hope the tests are running from the root of the module :) + basedirPath = new File("").getAbsolutePath(); + } + return new File(basedirPath); + } + + public static void assertValidatorModel(NuitonValidator<?> validator, + String expectedContext, + Class<?> expectedType, + NuitonValidatorScope... expectedScopes) { + Assert.assertNotNull(validator); + NuitonValidatorModel<?> model = validator.getModel(); + Assert.assertNotNull(model); + Assert.assertEquals(expectedContext, model.getContext()); + Assert.assertEquals(expectedType, model.getType()); + Set<NuitonValidatorScope> scopes = model.getScopes(); + for (NuitonValidatorScope expectedScope : expectedScopes) { + Assert.assertTrue(scopes.contains(expectedScope)); + } + } + + public static void assertValidatorEffectiveScopes(NuitonValidator<?> validator, + NuitonValidatorScope... expectedScopes) { + Assert.assertNotNull(validator); + Set<NuitonValidatorScope> effectiveScopes = validator.getEffectiveScopes(); + Assert.assertEquals(expectedScopes.length, effectiveScopes.size()); + for (NuitonValidatorScope expectedScope : expectedScopes) { + Assert.assertTrue(effectiveScopes.contains(expectedScope)); + } + } + + public static void assertValidatorEffectiveFields(NuitonValidator<?> validator, + String... expectedFields) { + Assert.assertNotNull(validator); + Set<String> effectiveFields = validator.getEffectiveFields(); + Assert.assertEquals(expectedFields.length, effectiveFields.size()); + for (String expectedField : expectedFields) { + Assert.assertTrue(effectiveFields.contains(expectedField)); + } + } + + public static void assertValidatorEffectiveFields(NuitonValidator<?> validator, + NuitonValidatorScope scope, + String... expectedFields) { + Assert.assertNotNull(validator); + Set<String> effectiveFields = validator.getEffectiveFields(scope); + Assert.assertEquals(expectedFields.length, effectiveFields.size()); + for (String expectedField : expectedFields) { + Assert.assertTrue(effectiveFields.contains(expectedField)); + } + } + + public static void testPerson(NuitonValidator<Person> validator) { + Assert.assertNotNull(validator); + + Person person = new Person(); + + NuitonValidatorResult result; + + result = validator.validate(person); + + // two errors : no name, no firstname + // one warning : no pet + Assert.assertFalse(result.isValid()); + assertFieldMessages(result, NuitonValidatorScope.ERROR, Person.PROPERTY_FIRSTNAME, "person.firstname.required"); + assertFieldMessages(result, NuitonValidatorScope.ERROR, Person.PROPERTY_NAME, "person.name.required"); + assertFieldMessages(result, NuitonValidatorScope.WARNING, Person.PROPERTY_PET, "person.with.no.pet"); + + person.setFirstname("Joe"); + result = validator.validate(person); + + // one error : no name + // one warning : no pet + Assert.assertFalse(result.isValid()); + assertFieldMessages(result, NuitonValidatorScope.ERROR, Person.PROPERTY_FIRSTNAME); + assertFieldMessages(result, NuitonValidatorScope.ERROR, Person.PROPERTY_NAME, "person.name.required"); + assertFieldMessages(result, NuitonValidatorScope.WARNING, Person.PROPERTY_PET, "person.with.no.pet"); + + person.setName("Black"); + result = validator.validate(person); + + // no error + // one warning : no pet + Assert.assertTrue(result.isValid()); + assertFieldMessages(result, NuitonValidatorScope.ERROR, Person.PROPERTY_FIRSTNAME); + assertFieldMessages(result, NuitonValidatorScope.ERROR, Person.PROPERTY_NAME); + assertFieldMessages(result, NuitonValidatorScope.WARNING, Person.PROPERTY_PET, "person.with.no.pet"); + + person.addPet(new Pet()); + result = validator.validate(person); + + // no error + // no warning + Assert.assertTrue(result.isValid()); + assertFieldMessages(result, NuitonValidatorScope.ERROR, Person.PROPERTY_FIRSTNAME); + assertFieldMessages(result, NuitonValidatorScope.ERROR, Person.PROPERTY_NAME); + assertFieldMessages(result, NuitonValidatorScope.WARNING, Person.PROPERTY_PET); + + } + + public static void assertFieldMessages(NuitonValidatorResult result, + NuitonValidatorScope scope, + String field, + String... expectedMessages) { + + if (expectedMessages.length == 0) { + + // no messages + boolean hasMessages = result.hasMessagesForScope(field, scope); + Assert.assertFalse(hasMessages); + + } else { + + // with messages + boolean hasMessages = result.hasMessagesForScope(field, scope); + Assert.assertTrue(hasMessages); + + List<String> messages = result.getMessagesForScope(field, scope); + Assert.assertNotNull(hasMessages); + Assert.assertEquals(expectedMessages.length, messages.size()); + for (String expectedMessage : expectedMessages) { + Assert.assertTrue(messages.contains(expectedMessage)); + } + } + } +} diff --git a/src/test/java/org/nuiton/validator/bean/SimpleBean.java b/src/test/java/org/nuiton/validator/bean/SimpleBean.java new file mode 100644 index 0000000..d2568d2 --- /dev/null +++ b/src/test/java/org/nuiton/validator/bean/SimpleBean.java @@ -0,0 +1,78 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.bean; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public class SimpleBean { + + protected int intValue; + + protected String stringValue; + + final PropertyChangeSupport p; + + public SimpleBean() { + p = new PropertyChangeSupport(this); + } + + public int getIntValue() { + return intValue; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + String old = this.stringValue; + this.stringValue = stringValue; + p.firePropertyChange("stringValue", old, stringValue); + } + + public void setIntValue(int intValue) { + int old = this.intValue; + this.intValue = intValue; + p.firePropertyChange("intValue", old, intValue); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } +} diff --git a/src/test/java/org/nuiton/validator/bean/list/BeanListValidatorTest.java b/src/test/java/org/nuiton/validator/bean/list/BeanListValidatorTest.java new file mode 100644 index 0000000..6aad00e --- /dev/null +++ b/src/test/java/org/nuiton/validator/bean/list/BeanListValidatorTest.java @@ -0,0 +1,528 @@ +package org.nuiton.validator.bean.list; +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.ArrayListMultimap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.SimpleBean; + +import java.util.Arrays; +import java.util.List; + +/** + * To test the {@link BeanListValidator}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public class BeanListValidatorTest { + + /** Logger */ + private static final Log log = + LogFactory.getLog(BeanListValidatorTest.class); + + protected BeanListValidator<SimpleBean> validator; + + protected SimpleBean bean; + + protected SimpleBean bean2; + + BeanValidatorListenerImpl fatalListener; + + BeanValidatorListenerImpl errorListener; + + BeanValidatorListenerImpl warningListener; + + BeanValidatorListenerImpl infoListener; + + @Before + public void setUp() { + + bean = new SimpleBean(); + bean2 = new SimpleBean(); + } + + protected void prepareValidator(String context) { + + validator = BeanListValidator.newValidator(SimpleBean.class, context); + + validator.addBeanListValidatorListener(fatalListener = new BeanValidatorListenerImpl(NuitonValidatorScope.FATAL)); + validator.addBeanListValidatorListener(errorListener = new BeanValidatorListenerImpl(NuitonValidatorScope.ERROR)); + validator.addBeanListValidatorListener(warningListener = new BeanValidatorListenerImpl(NuitonValidatorScope.WARNING)); + validator.addBeanListValidatorListener(infoListener = new BeanValidatorListenerImpl(NuitonValidatorScope.INFO)); + } + + @After + public void tearDown() { + bean = null; + bean2 = null; + if (validator != null) { + validator.removeAllBeans(); + validator = null; + } + } + + private static final String STRING_VALUE_FATAL = "stringValue.fatal"; + + private static final String STRING_VALUE_ERROR = "stringValue.error"; + + private static final String STRING_VALUE_WARNING = "stringValue.warning"; + + private static final String INT_VALUE_FATAL = "intValue.fatal"; + + private static final String INT_VALUE_ERROR = "intValue.error"; + + private static final String INT_VALUE_INFO = "intValue.info"; + + @Test(expected = IllegalStateException.class) + public void testValidateWithBad() { + + // with marchepo context, there is a unknown field in scope error + + prepareValidator("marchepo"); + } + + @Test + public void addBean() { + prepareValidator(null); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + validator.addBean(bean); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + validator.addBean(bean2); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + assertMessages(fatalListener, bean2, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean2, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean2, STRING_VALUE_WARNING); + assertMessages(infoListener, bean2, INT_VALUE_INFO); + + } + + @Test + public void addAllBean() { + prepareValidator(null); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + assertMessages(fatalListener, bean2); + assertMessages(errorListener, bean2); + assertMessages(warningListener, bean2); + assertMessages(infoListener, bean2); + + validator.addAllBeans(Arrays.asList(bean, bean2)); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + assertMessages(fatalListener, bean2, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean2, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean2, STRING_VALUE_WARNING); + assertMessages(infoListener, bean2, INT_VALUE_INFO); + + } + + @Test + public void removeBean() { + prepareValidator(null); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + assertMessages(fatalListener, bean2); + assertMessages(errorListener, bean2); + assertMessages(warningListener, bean2); + assertMessages(infoListener, bean2); + + validator.addBean(bean); + validator.addBean(bean2); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + assertMessages(fatalListener, bean2, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean2, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean2, STRING_VALUE_WARNING); + assertMessages(infoListener, bean2, INT_VALUE_INFO); + + validator.removeBean(bean); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + validator.removeBean(bean2); + + assertMessages(fatalListener, bean2); + assertMessages(errorListener, bean2); + assertMessages(warningListener, bean2); + assertMessages(infoListener, bean2); + } + + @Test + public void removeAllBeans() { + prepareValidator(null); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + assertMessages(fatalListener, bean2); + assertMessages(errorListener, bean2); + assertMessages(warningListener, bean2); + assertMessages(infoListener, bean2); + + validator.addBean(bean); + validator.addBean(bean2); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + assertMessages(fatalListener, bean2, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean2, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean2, STRING_VALUE_WARNING); + assertMessages(infoListener, bean2, INT_VALUE_INFO); + + validator.removeAllBeans(Arrays.asList(bean, bean2)); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + assertMessages(fatalListener, bean2); + assertMessages(errorListener, bean2); + assertMessages(warningListener, bean2); + assertMessages(infoListener, bean2); + } + + @Test + public void removeAllBeans2() { + prepareValidator(null); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + assertMessages(fatalListener, bean2); + assertMessages(errorListener, bean2); + assertMessages(warningListener, bean2); + assertMessages(infoListener, bean2); + + validator.addBean(bean); + validator.addBean(bean2); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + assertMessages(fatalListener, bean2, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean2, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean2, STRING_VALUE_WARNING); + assertMessages(infoListener, bean2, INT_VALUE_INFO); + + validator.removeAllBeans(); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + assertMessages(fatalListener, bean2); + assertMessages(errorListener, bean2); + assertMessages(warningListener, bean2); + assertMessages(infoListener, bean2); + } + + @Test + public void validate() { + + prepareValidator(null); + + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + if (log.isDebugEnabled()) { + log.debug("- bean 1 ----------------------------------------------"); + } + validator.addBean(bean); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("- bean 1 ----------------------------------------------"); + } + bean.setStringValue("one"); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("- bean 1 ----------------------------------------------"); + } + bean.setStringValue("oneone"); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, INT_VALUE_ERROR); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("- bean 1 ----------------------------------------------"); + } + bean.setIntValue(1); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("- bean 1 ----------------------------------------------"); + } + bean.setIntValue(10); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + if (log.isDebugEnabled()) { + log.debug("- bean 1 ----------------------------------------------"); + } + + bean.setStringValue(null); + bean.setIntValue(0); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + + if (log.isDebugEnabled()) { + log.debug("- bean 1 ----------------------------------------------"); + } + + bean.setStringValue("5"); + bean.setIntValue(5); + assertMessages(fatalListener, bean); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("- bean 2 ----------------------------------------------"); + } + validator.addBean(bean2); + + assertMessages(fatalListener, bean2, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean2, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean2, STRING_VALUE_WARNING); + assertMessages(infoListener, bean2, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("- bean 2 ----------------------------------------------"); + } + bean2.setStringValue("one"); + + assertMessages(fatalListener, bean2, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean2, INT_VALUE_ERROR); + assertMessages(warningListener, bean2, STRING_VALUE_WARNING); + assertMessages(infoListener, bean2, INT_VALUE_INFO); + + } + + @Test + public void convert() { + + prepareValidator(null); + + assertMessages(errorListener, bean); + assertMessages(warningListener, bean); + assertMessages(infoListener, bean); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + validator.addBean(bean); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + Object value = validator.convert(bean, "intValue", "abc", Class.class); + + Assert.assertNull(value); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, STRING_VALUE_ERROR, "error.convertor.class"); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + bean.setStringValue("one"); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, "error.convertor.class"); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + value = validator.convert(bean, "intValue", "3", Integer.class); + + bean.setIntValue((Integer) value); + + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + bean.setIntValue(-1); + assertMessages(fatalListener, bean, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, bean, INT_VALUE_ERROR); + assertMessages(warningListener, bean, STRING_VALUE_WARNING); + assertMessages(infoListener, bean, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + } + + void assertMessages(BeanValidatorListenerImpl listener, + Object bean, + String... expected) { + List<String> actual = listener.getMessages(bean); + Assert.assertEquals(" shoudl have " + + Arrays.toString(expected) + " but had " + actual, + expected.length, actual.size()); + for (String m : expected) { + Assert.assertEquals("could not find " + m + " in " + actual, + true, actual.contains(m)); + } + } + + class BeanValidatorListenerImpl implements BeanListValidatorListener { + + private final NuitonValidatorScope scope; + + private final ArrayListMultimap<Object, String> messages; + + public BeanValidatorListenerImpl(NuitonValidatorScope scope) { + this.scope = scope; + messages = ArrayListMultimap.create(); + } + + + public ArrayListMultimap<Object, String> getMessages() { + return messages; + } + + public List<String> getMessages(Object bean) { + return messages.get(bean); + } + + + @Override + public void onFieldChanged(BeanListValidatorEvent event) { + if (scope != event.getScope()) { + return; + } + Object bean = event.getBean(); + String[] messagesToDelete = event.getMessagesToDelete(); + if (messagesToDelete != null && messagesToDelete.length > 0) { + if (log.isDebugEnabled()) { + log.debug(scope + "[" + bean + "] messages to delete : " + Arrays.toString(messagesToDelete)); + } + for (String m : messagesToDelete) { + messages.remove(bean, m); + } + } + String[] messagesToAdd = event.getMessagesToAdd(); + if (messagesToAdd != null && messagesToAdd.length > 0) { + if (log.isDebugEnabled()) { + log.debug(scope + "[" + bean + "] messages to add : " + Arrays.toString(messagesToAdd)); + } + messages.putAll(bean, Arrays.asList(messagesToAdd)); + } + } + } +} diff --git a/src/test/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorTest.java b/src/test/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorTest.java new file mode 100644 index 0000000..13bb37c --- /dev/null +++ b/src/test/java/org/nuiton/validator/bean/simple/SimpleBeanValidatorTest.java @@ -0,0 +1,313 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.bean.simple; + +import com.google.common.collect.Lists; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.SimpleBean; + +import java.util.Arrays; +import java.util.List; + +/** + * To test the {@link SimpleBeanValidator}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.5.2 + */ +public class SimpleBeanValidatorTest { + + /** Logger */ + private static final Log log = + LogFactory.getLog(SimpleBeanValidatorTest.class); + + protected SimpleBeanValidator<SimpleBean> validator; + + protected SimpleBean bean; + + ValidatorListenerImpl fatalListener; + + ValidatorListenerImpl errorListener; + + ValidatorListenerImpl warningListener; + + ValidatorListenerImpl infoListener; + + @Before + public void setUp() { + + bean = new SimpleBean(); + } + + protected void prepareValidator(String context) { + + validator = SimpleBeanValidator.newValidator(SimpleBean.class, context); + + validator.addSimpleBeanValidatorListener(fatalListener = new ValidatorListenerImpl(NuitonValidatorScope.FATAL)); + validator.addSimpleBeanValidatorListener(errorListener = new ValidatorListenerImpl(NuitonValidatorScope.ERROR)); + validator.addSimpleBeanValidatorListener(warningListener = new ValidatorListenerImpl(NuitonValidatorScope.WARNING)); + validator.addSimpleBeanValidatorListener(infoListener = new ValidatorListenerImpl(NuitonValidatorScope.INFO)); + } + + @After + public void tearDown() { + bean = null; + if (validator != null) { + validator.setBean(null); + validator = null; + } + } + + private static final String STRING_VALUE_FATAL = "stringValue.fatal"; + + private static final String STRING_VALUE_ERROR = "stringValue.error"; + + private static final String STRING_VALUE_WARNING = "stringValue.warning"; + + private static final String INT_VALUE_FATAL = "intValue.fatal"; + + private static final String INT_VALUE_ERROR = "intValue.error"; + + private static final String INT_VALUE_INFO = "intValue.info"; + + @Test(expected = IllegalStateException.class) + public void testValidateWithBad() { + + // with marchepo context, there is a unknown field in scope error + + prepareValidator("marchepo"); + } + + @Test + public void validate() { + + prepareValidator(null); + + assertMessages(fatalListener); + assertMessages(errorListener); + assertMessages(warningListener); + assertMessages(infoListener); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + validator.setBean(bean); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + bean.setStringValue("one"); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, INT_VALUE_ERROR); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + bean.setStringValue("oneone"); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, INT_VALUE_ERROR); + assertMessages(warningListener); + assertMessages(infoListener, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + bean.setIntValue(1); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener); + assertMessages(warningListener); + assertMessages(infoListener, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + bean.setIntValue(10); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener); + assertMessages(warningListener); + assertMessages(infoListener); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + bean.setStringValue(null); + bean.setIntValue(0); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + bean.setStringValue("5"); + bean.setIntValue(5); + assertMessages(fatalListener); + assertMessages(errorListener); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + } + + @Test + public void convert() { + + prepareValidator(null); + + assertMessages(errorListener); + assertMessages(warningListener); + assertMessages(infoListener); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + validator.setBean(bean); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, STRING_VALUE_ERROR, INT_VALUE_ERROR); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + Object value = validator.convert("intValue", "abc", Class.class); + + Assert.assertNull(value); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, STRING_VALUE_ERROR, "error.convertor.class"); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + bean.setStringValue("one"); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, "error.convertor.class"); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + value = validator.convert("intValue", "3", Integer.class); + + bean.setIntValue((Integer) value); + + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + + bean.setIntValue(-1); + assertMessages(fatalListener, STRING_VALUE_FATAL, INT_VALUE_FATAL); + assertMessages(errorListener, INT_VALUE_ERROR); + assertMessages(warningListener, STRING_VALUE_WARNING); + assertMessages(infoListener, INT_VALUE_INFO); + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------"); + } + } + + void assertMessages(ValidatorListenerImpl listener, + String... expected) { + List<String> actual = listener.getMessages(); + Assert.assertEquals(" shoudl have " + + Arrays.toString(expected) + " but had " + actual, + expected.length, actual.size()); + for (String m : expected) { + Assert.assertEquals("could not find " + m + " in " + actual, + true, actual.contains(m)); + } + } + + static class ValidatorListenerImpl implements SimpleBeanValidatorListener { + + final NuitonValidatorScope scope; + + public ValidatorListenerImpl(NuitonValidatorScope scope) { + this.scope = scope; + } + + List<String> messages = Lists.newArrayList(); + + public List<String> getMessages() { + return messages; + } + + @Override + public void onFieldChanged(SimpleBeanValidatorEvent event) { + if (scope == event.getScope()) { + String[] messagesToDelete = event.getMessagesToDelete(); + if (messagesToDelete != null && messagesToDelete.length > 0) { + if (log.isDebugEnabled()) { + log.debug(event.getScope() + " messages to delete : " + Arrays.toString(messagesToDelete)); + } + for (String m : messagesToDelete) { + messages.remove(m); + } + } + String[] messagesToAdd = event.getMessagesToAdd(); + if (messagesToAdd != null && messagesToAdd.length > 0) { + if (log.isDebugEnabled()) { + log.debug(event.getScope() + " messages to add : " + Arrays.toString(messagesToAdd)); + } + messages.addAll(Arrays.asList(messagesToAdd)); + } + } + } + } +} diff --git a/src/test/java/org/nuiton/validator/model/Company.java b/src/test/java/org/nuiton/validator/model/Company.java new file mode 100644 index 0000000..75ab5da --- /dev/null +++ b/src/test/java/org/nuiton/validator/model/Company.java @@ -0,0 +1,55 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.model; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class Company { + + public static final String PROPERTY_VAT_NUMBER = "vat"; + + public static final String PROPERTY_SIRET = "siret"; + + protected String vat; + + protected String siret; + + public String getVat() { + return vat; + } + + public void setVat(String vat) { + this.vat = vat; + } + + public String getSiret() { + return siret; + } + + public void setSiret(String siret) { + this.siret = siret; + } +} diff --git a/src/test/java/org/nuiton/validator/model/Contact.java b/src/test/java/org/nuiton/validator/model/Contact.java new file mode 100644 index 0000000..b0884ee --- /dev/null +++ b/src/test/java/org/nuiton/validator/model/Contact.java @@ -0,0 +1,91 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.model; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class Contact { + + public static final String PROPERTY_LAST_NAME = "name"; + + public static final String PROPERTY_EMAIL = "email"; + + public static final String PROPERTY_PHONE = "phone"; + + public static final String PROPERTY_POSTCODE = "postCode"; + + public static final String PROPERTY_CITY = "city"; + + protected String name; + + protected String email; + + protected String phone; + + protected String postCode; + + protected String city; + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getPostCode() { + return postCode; + } + + public void setPostCode(String postCode) { + this.postCode = postCode; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/test/java/org/nuiton/validator/model/HealthEstablishment.java b/src/test/java/org/nuiton/validator/model/HealthEstablishment.java new file mode 100644 index 0000000..5d12c1d --- /dev/null +++ b/src/test/java/org/nuiton/validator/model/HealthEstablishment.java @@ -0,0 +1,44 @@ +package org.nuiton.validator.model; + +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * @author Sylvain Bavencoff <bavencoff@codelutin.com> + */ +public class HealthEstablishment { + + public static final String PROPERTY_FINESS = "finess"; + + protected String finess; + + public String getFiness() { + return finess; + } + + public void setFiness(String finess) { + this.finess = finess; + } + +} diff --git a/src/test/java/org/nuiton/validator/model/ModelValidatorDetectorTestImpl.java b/src/test/java/org/nuiton/validator/model/ModelValidatorDetectorTestImpl.java new file mode 100644 index 0000000..fc904ff --- /dev/null +++ b/src/test/java/org/nuiton/validator/model/ModelValidatorDetectorTestImpl.java @@ -0,0 +1,186 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.model; + +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.validator.AbstractValidatorDetectorTest; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.xwork2.XWork2NuitonValidatorProvider; + +import java.io.File; +import java.util.Iterator; +import java.util.SortedSet; +import java.util.regex.Pattern; + +/** + * Tests the validators defined for the test model. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class ModelValidatorDetectorTestImpl extends AbstractValidatorDetectorTest { + + public static final String CONTEXT = "context"; + + public ModelValidatorDetectorTestImpl() { + super(XWork2NuitonValidatorProvider.PROVIDER_NAME); + } + + @Override + protected File getRootDirectory(File basedir) { + File testResourcesDir = new File(basedir, "src" + File.separator + "test" + File.separator + "resources"); + return testResourcesDir; + } + + @Test + public void detectAllValidators() { + SortedSet<NuitonValidator<?>> result; + NuitonValidator<?> validator; + Iterator<NuitonValidator<?>> iterator; + + // test with all context and all scopes : 3 validators (Person + Pet + Pet (context)) + + result = detectValidators(Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertEquals(3, result.size()); + + iterator = result.iterator(); + validator = iterator.next(); + + assertValidatorModel(validator, null, Person.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING); + assertValidatorEffectiveFields(validator, NuitonValidatorScope.ERROR, Person.PROPERTY_NAME, Person.PROPERTY_FIRSTNAME); + assertValidatorEffectiveFields(validator, NuitonValidatorScope.WARNING, Person.PROPERTY_PET); + + validator = iterator.next(); + assertValidatorModel(validator, null, Pet.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR); + assertValidatorEffectiveFields(validator, NuitonValidatorScope.ERROR, Pet.PROPERTY_NAME); + + validator = iterator.next(); + assertValidatorModel(validator, CONTEXT, Pet.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.INFO); + assertValidatorEffectiveFields(validator, NuitonValidatorScope.INFO, Pet.PROPERTY_NAME); + } + + @Test + public void detectValidatorsWithFilteredScopes() { + + SortedSet<NuitonValidator<?>> result; + NuitonValidator<?> validator; + Iterator<NuitonValidator<?>> iterator; + + // test with no context and only scope warning : one validator (Person) + + result = detectValidators(null, new NuitonValidatorScope[]{NuitonValidatorScope.WARNING}, Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertEquals(1, result.size()); + + iterator = result.iterator(); + + validator = iterator.next(); + assertValidatorModel(validator, null, Person.class, NuitonValidatorScope.WARNING); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.WARNING); + assertValidatorEffectiveFields(validator, NuitonValidatorScope.WARNING, Person.PROPERTY_PET); + + // test with no context and only fatal scope : no validator + + result = detectValidators(null, + new NuitonValidatorScope[]{NuitonValidatorScope.FATAL}, Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } + + @Test + public void detectValidatorsWithFilteredContext() { + + SortedSet<NuitonValidator<?>> result; + NuitonValidator<?> validator; + Iterator<NuitonValidator<?>> iterator; + + + // test with context 'context' and all scopes : one validator (Pet) + + result = detectValidators(Pattern.compile(CONTEXT), Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertEquals(1, result.size()); + + iterator = result.iterator(); + + validator = iterator.next(); + assertValidatorModel(validator, CONTEXT, Pet.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.INFO); + assertValidatorEffectiveFields(validator, NuitonValidatorScope.INFO, Pet.PROPERTY_NAME); + + + // test with specific context fake and all scopes : no validator + + result = detectValidators(Pattern.compile(".*-fake"), + Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } + + @Test + public void detectValidatorsWithFilteredContextAndFilteredScope() { + + SortedSet<NuitonValidator<?>> result; + NuitonValidator<?> validator; + Iterator<NuitonValidator<?>> iterator; + + // test with context 'context' and info-fatal scopes : one validator (Pet) + + result = detectValidators(Pattern.compile(CONTEXT), + new NuitonValidatorScope[]{NuitonValidatorScope.INFO, NuitonValidatorScope.FATAL}, + Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertEquals(1, result.size()); + + iterator = result.iterator(); + + validator = iterator.next(); + assertValidatorModel(validator, CONTEXT, Pet.class, NuitonValidatorScope.FATAL, NuitonValidatorScope.INFO); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.INFO); + assertValidatorEffectiveFields(validator, NuitonValidatorScope.INFO, Pet.PROPERTY_NAME); + + // test with specific context fake and fatal scope : no validator + + result = detectValidators(Pattern.compile(".*-fake"), + new NuitonValidatorScope[]{NuitonValidatorScope.FATAL}, + Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } + + +} diff --git a/src/test/java/org/nuiton/validator/model/Person.java b/src/test/java/org/nuiton/validator/model/Person.java new file mode 100644 index 0000000..da8deff --- /dev/null +++ b/src/test/java/org/nuiton/validator/model/Person.java @@ -0,0 +1,93 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class Person { + + public static final String PROPERTY_NAME = "name"; + + public static final String PROPERTY_FIRSTNAME = "firstname"; + + public static final String PROPERTY_PET = "pet"; + + protected String name; + + protected String firstname; + + protected Collection<Pet> pet; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFirstname() { + return firstname; + } + + public void setFirstname(String firstname) { + this.firstname = firstname; + } + + public Collection<Pet> getPet() { + return pet; + } + + public void setPet(Collection<Pet> pet) { + this.pet = pet; + } + + public void addPet(Pet pet) { + if (this.pet == null) { + this.pet = new ArrayList<Pet>(); + } + + pet.setPerson(this); + + this.pet.add(pet); + } + + @Override + public String toString() { + String result = new ToStringBuilder(this). + append(PROPERTY_NAME, name). + append(PROPERTY_FIRSTNAME, firstname). + toString(); + return result; + } +} diff --git a/src/test/java/org/nuiton/validator/model/Pet.java b/src/test/java/org/nuiton/validator/model/Pet.java new file mode 100644 index 0000000..bc62879 --- /dev/null +++ b/src/test/java/org/nuiton/validator/model/Pet.java @@ -0,0 +1,98 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class Pet { + + public static final String PROPERTY_NAME = "name"; + + public static final String PROPERTY_TYPE = "type"; + + public static final String PROPERTY_PERSON = "person"; + + public static final String PROPERTY_RACE = "race"; + + protected String name; + + protected String type; + + protected Person person; + + protected Race race; + + + public void setName(String name) { + + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + + public String getType() { + return type; + } + + public void setPerson(Person person) { + this.person = person; + } + + + public Person getPerson() { + return person; + } + + public void setRace(Race race) { + this.race = race; + } + + public Race getRace() { + return race; + } + + @Override + public String toString() { + String result = new ToStringBuilder(this). + append(PROPERTY_NAME, this.name). + append(PROPERTY_TYPE, this.type). + append(PROPERTY_RACE, this.race). + toString(); + return result; + } + +} diff --git a/src/test/java/org/nuiton/validator/model/Race.java b/src/test/java/org/nuiton/validator/model/Race.java new file mode 100644 index 0000000..96ef660 --- /dev/null +++ b/src/test/java/org/nuiton/validator/model/Race.java @@ -0,0 +1,55 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class Race { + + public static final String PROPERTY_NAME = "name"; + + protected String name; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + String result = new ToStringBuilder(this). + append(PROPERTY_NAME, this.name). + toString(); + return result; + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorProviderTest.java b/src/test/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorProviderTest.java new file mode 100644 index 0000000..0ed9e0d --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorProviderTest.java @@ -0,0 +1,167 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorModel; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.ValidatorTestHelper; +import org.nuiton.validator.model.Person; +import org.nuiton.validator.model.Pet; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.SortedSet; +import java.util.regex.Pattern; + +/** + * To test {@link XWork2NuitonValidatorProvider}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class XWork2NuitonValidatorProviderTest { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(XWork2NuitonValidatorProviderTest.class); + + protected XWork2NuitonValidatorProvider provider; + + @Before + public void setUp() { + provider = new XWork2NuitonValidatorProvider(); + } + + @Test + public void testGetModel() throws Exception { + + NuitonValidatorModel<Person> model = + provider.getModel(Person.class, null); + + Assert.assertNotNull(model); + Assert.assertNull(model.getContext()); + Assert.assertEquals(Person.class, model.getType()); + Set<NuitonValidatorScope> scopes = new HashSet<NuitonValidatorScope>( + Arrays.asList(NuitonValidatorScope.values())); + Assert.assertEquals(scopes, model.getScopes()); + } + + @Test + public void testNewValidator() throws Exception { + + + NuitonValidatorModel<Person> model = + provider.getModel(Person.class, null); + + NuitonValidator<Person> validator = provider.newValidator(model); + + Assert.assertNotNull(validator); + } + + @Test + public void testDetectValidators() { + + String context = "context"; + + File basedir = ValidatorTestHelper.getBasedir(); + File testResourcesDir = new File(basedir, "src" + File.separator + "test" + File.separator + "resources"); + + SortedSet<NuitonValidator<?>> result; + NuitonValidator<?> validator; + Iterator<NuitonValidator<?>> iterator; + + // test with all context and all scopes : two validators (Person + Pet + Pet (context)) + + result = provider.detectValidators(testResourcesDir, null, null, Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertEquals(3, result.size()); + + + iterator = result.iterator(); + validator = iterator.next(); + + ValidatorTestHelper.assertValidatorModel(validator, null, Person.class, NuitonValidatorScope.values()); + ValidatorTestHelper.assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING); + + validator = iterator.next(); + ValidatorTestHelper.assertValidatorModel(validator, null, Pet.class, NuitonValidatorScope.values()); + ValidatorTestHelper.assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR); + + validator = iterator.next(); + ValidatorTestHelper.assertValidatorModel(validator, context, Pet.class, NuitonValidatorScope.values()); + ValidatorTestHelper.assertValidatorEffectiveScopes(validator, NuitonValidatorScope.INFO); + + // test with no context and only scope warning : one validator (Person) + + result = provider.detectValidators(testResourcesDir, null, new NuitonValidatorScope[]{NuitonValidatorScope.WARNING}, Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertEquals(1, result.size()); + + iterator = result.iterator(); + + validator = iterator.next(); + ValidatorTestHelper.assertValidatorModel(validator, null, Person.class, NuitonValidatorScope.WARNING); + ValidatorTestHelper.assertValidatorEffectiveScopes(validator, NuitonValidatorScope.WARNING); + + // test with context 'context' and all scopes : one validator (Pet) + + result = provider.detectValidators(testResourcesDir, Pattern.compile(context), null, Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertEquals(1, result.size()); + + iterator = result.iterator(); + + validator = iterator.next(); + ValidatorTestHelper.assertValidatorModel(validator, context, Pet.class, NuitonValidatorScope.values()); + ValidatorTestHelper.assertValidatorEffectiveScopes(validator, NuitonValidatorScope.INFO); + + // test with no context and only scope fatal : no validator + result = provider.detectValidators(testResourcesDir, null, + new NuitonValidatorScope[]{NuitonValidatorScope.FATAL}, Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + + // test with specific context fake and all scopes : no validator + + result = provider.detectValidators(testResourcesDir, Pattern.compile(".*-fake"), + null, Person.class, Pet.class); + + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } + +} diff --git a/src/test/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorTest.java new file mode 100644 index 0000000..cffd5d1 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/XWork2NuitonValidatorTest.java @@ -0,0 +1,59 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2; + +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorModel; +import org.nuiton.validator.ValidatorTestHelper; +import org.nuiton.validator.model.Person; + +/** + * To test {@link XWork2NuitonValidator}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class XWork2NuitonValidatorTest { + + @Test + public void testNewValidator() throws Exception { + + XWork2NuitonValidatorProvider provider = + new XWork2NuitonValidatorProvider(); + + + NuitonValidatorModel<Person> model = + provider.getModel(Person.class, null); + + NuitonValidator<Person> validator = provider.newValidator(model); + + Assert.assertNotNull(validator); + + ValidatorTestHelper.testPerson(validator); + + } + +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/AbstractFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/AbstractFieldValidatorTest.java new file mode 100644 index 0000000..d7767ae --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/AbstractFieldValidatorTest.java @@ -0,0 +1,132 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorFactory; +import org.nuiton.validator.NuitonValidatorResult; + +import java.io.File; +import java.util.List; + +/** + * Abstract class to test a specific validator. + * <p/> + * To implements a test on a new validator, just extends this class + * and implements the method {@link #testValidator()}. + * + * @param <B> the type of bean to validate. + * @author tchemit <chemit@codelutin.com> + */ +public abstract class AbstractFieldValidatorTest<B> extends Assert { + + /** Logger */ + private static final Log log = + LogFactory.getLog(AbstractFieldValidatorTest.class); + + protected static NuitonValidator<?> cacheValidator; + + protected static File basedir; + + protected final Class<B> type; + + protected NuitonValidator<B> validator; + + protected B bean; + + public AbstractFieldValidatorTest(Class<B> type) { + this.type = type; + } + + /** + * the method to test the given validator on the given bean. + * <p/> + * When coming here a validator and bean were instanciated and the bean was + * setted into validator via setBean method. + * + * @throws Exception if any error ? + */ + public abstract void testValidator() throws Exception; + + @Before + @SuppressWarnings("unchecked") + public void setUp() throws Exception { + log.debug("start test " + getClass().getSimpleName()); + bean = type.newInstance(); + if (cacheValidator == null) { + validator = NuitonValidatorFactory.newValidator(type); + cacheValidator = validator; + } else { + validator = (NuitonValidator<B>) cacheValidator; + } + } + + @After + @SuppressWarnings("unchecked") + public void tearDown() { + } + + @AfterClass + public static void afterclass() throws Exception { + cacheValidator = null; + } + + @BeforeClass + public static void initValidator() throws Exception { + + String b = System.getenv("basedir"); + if (b == null) { + b = new File("").getAbsolutePath(); + } + basedir = new File(b); + } + + @SuppressWarnings("unchecked") + protected void assertFieldInError(String fieldName, String error, boolean required) { + + NuitonValidatorResult result = validator.validate(bean); + + List<String> errorMessages = result.getErrorMessages(fieldName); + + boolean errorFound = errorMessages.contains(error); + + if (required) { + + // must have this error + + assertTrue("error " + error + " should not exist but was found.", errorFound); + } else { + + // must not have this error + assertFalse("error " + error + " should exist but was not found.", errorFound); + } + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/AbstractValidatorBeanFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/AbstractValidatorBeanFieldValidatorTest.java new file mode 100644 index 0000000..f137984 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/AbstractValidatorBeanFieldValidatorTest.java @@ -0,0 +1,37 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +/** + * Abstract class to test a specific validator for the {@link ValidatorBean}. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public abstract class AbstractValidatorBeanFieldValidatorTest extends AbstractFieldValidatorTest<ValidatorBean> { + + public AbstractValidatorBeanFieldValidatorTest() { + super(ValidatorBean.class); + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/CollectionFieldExpressionValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/CollectionFieldExpressionValidatorTest.java new file mode 100644 index 0000000..6b2e7e5 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/CollectionFieldExpressionValidatorTest.java @@ -0,0 +1,265 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.xwork2.field.ValidatorBean.ValidatorBeanEntry; + +import java.util.Arrays; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class CollectionFieldExpressionValidatorTest extends AbstractValidatorBeanFieldValidatorTest { + + protected static final String PROPERTY = "entries"; + + static protected ValidatorBeanEntry beanEntry0 = new ValidatorBeanEntry(0, "stringValue"); + + static protected ValidatorBeanEntry beanEntry0Bis = new ValidatorBeanEntry(0, "fake"); + + static protected ValidatorBeanEntry beanEntry1 = new ValidatorBeanEntry(1, "fake"); + + static protected ValidatorBeanEntry beanEntry3 = new ValidatorBeanEntry(3, "fake"); + + static protected ValidatorBeanEntry beanEntry5 = new ValidatorBeanEntry(5, "fake"); + + @Test + @Override + public void testValidator() throws Exception { + assertNull(bean.getEntries()); + + // no entry + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", false); + + + // add a matching etry + bean.setEntries(Arrays.asList(beanEntry0)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", true); + + // two matching etries + bean.setEntries(Arrays.asList(beanEntry0, beanEntry0)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", true); + + // add a none matching etry + bean.setEntries(Arrays.asList(beanEntry0Bis)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", false); + + // add a none matching etry and a matching entry + bean.setEntries(Arrays.asList(beanEntry0Bis, beanEntry0)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", true); + } + + @Test + public void testValidatorWithContext() throws Exception { + assertNull(bean.getEntries()); + + // no entry + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + // add a matching etry + bean.setEntries(Arrays.asList(beanEntry0)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + // add a none matching etry + bean.setEntries(Arrays.asList(beanEntry0Bis)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + // add a none matching etry and a matching entry + bean.setEntries(Arrays.asList(beanEntry0Bis, beanEntry0)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry0)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3, beanEntry5)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry3, beanEntry1)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + } + + @Test + public void testValidatorWithContextAndFirst() throws Exception { + assertNull(bean.getEntries()); + String message = "collectionFieldExpression.all.useFirst"; + + // no entry + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0)); + assertFieldInError(PROPERTY, message, false); + + + bean.setEntries(Arrays.asList(beanEntry0Bis)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3, beanEntry5)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry3, beanEntry1)); + assertFieldInError(PROPERTY, message, true); + } + + @Test + public void testValidatorWithContextAndLast() throws Exception { + assertNull(bean.getEntries()); + String message = "collectionFieldExpression.all.useLast"; + + // no entry + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + + bean.setEntries(Arrays.asList(beanEntry0Bis)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry1)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3, beanEntry5)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry3, beanEntry1)); + assertFieldInError(PROPERTY, message, true); + } + + @Test + public void testValidatorWithContextAndFirstAndLast() throws Exception { + assertNull(bean.getEntries()); + + String message = "collectionFieldExpression.all.useFirstAndLast"; + // no entry + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + + bean.setEntries(Arrays.asList(beanEntry0Bis)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry1)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3, beanEntry5)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry3, beanEntry1)); + assertFieldInError(PROPERTY, message, true); + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/CollectionUniqueKeyValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/CollectionUniqueKeyValidatorTest.java new file mode 100644 index 0000000..48855fe --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/CollectionUniqueKeyValidatorTest.java @@ -0,0 +1,114 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.xwork2.field.ValidatorBean.ValidatorBeanEntry; + +import java.util.Arrays; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class CollectionUniqueKeyValidatorTest extends AbstractValidatorBeanFieldValidatorTest { + + static protected ValidatorBeanEntry beanEntry = new ValidatorBeanEntry(0, "stringValue"); + + static protected ValidatorBeanEntry beanEntry2 = new ValidatorBeanEntry(0, "fake"); + + static protected ValidatorBeanEntry beanEntry3 = new ValidatorBeanEntry(0, "stringValue", "stringValue2"); + + @Test + @Override + public void testValidator() throws Exception { + assertNull(bean.getEntries()); + + // no entry + assertFieldInError("entries", "collectionUniqueKey.one.failed", false); + assertFieldInError("entries", "collectionUniqueKey.two.failed", false); + assertFieldInError("entries", "collectionUniqueKey.three.failed", false); + assertFieldInError("entries", "collectionUniqueKey.four.failed", false); + assertFieldInError("entries", "collectionUniqueKey.five.failed", false); + + // add a entry + bean.setEntries(Arrays.asList(beanEntry)); + + assertFieldInError("entries", "collectionUniqueKey.one.failed", false); + assertFieldInError("entries", "collectionUniqueKey.two.failed", false); + assertFieldInError("entries", "collectionUniqueKey.three.failed", false); + assertFieldInError("entries", "collectionUniqueKey.four.failed", false); + assertFieldInError("entries", "collectionUniqueKey.five.failed", false); + + // add violating property + bean.setEntry(beanEntry3); + assertFieldInError("entries", "collectionUniqueKey.one.failed", false); + assertFieldInError("entries", "collectionUniqueKey.two.failed", false); + assertFieldInError("entries", "collectionUniqueKey.three.failed", false); + assertFieldInError("entries", "collectionUniqueKey.four.failed", false); + assertFieldInError("entries", "collectionUniqueKey.five.failed", true); + + + // two entries with same key + bean.setEntries(Arrays.asList(beanEntry, beanEntry)); + + assertFieldInError("entries", "collectionUniqueKey.one.failed", true); + assertFieldInError("entries", "collectionUniqueKey.two.failed", true); + assertFieldInError("entries", "collectionUniqueKey.three.failed", true); + assertFieldInError("entries", "collectionUniqueKey.four.failed", true); + + // add a entry + bean.setEntries(Arrays.asList(beanEntry2)); + + assertFieldInError("entries", "collectionUniqueKey.one.failed", false); + assertFieldInError("entries", "collectionUniqueKey.two.failed", false); + assertFieldInError("entries", "collectionUniqueKey.three.failed", false); + assertFieldInError("entries", "collectionUniqueKey.four.failed", false); + + // add two entries (will violated unique key on intValue) + bean.setEntries(Arrays.asList(beanEntry2, beanEntry)); + + assertFieldInError("entries", "collectionUniqueKey.one.failed", true); + assertFieldInError("entries", "collectionUniqueKey.two.failed", false); + assertFieldInError("entries", "collectionUniqueKey.three.failed", false); + assertFieldInError("entries", "collectionUniqueKey.four.failed", false); + + + // two entries with same key (except validator four) + bean.setEntries(Arrays.asList(beanEntry, beanEntry3)); + assertFieldInError("entries", "collectionUniqueKey.one.failed", true); + assertFieldInError("entries", "collectionUniqueKey.two.failed", true); + assertFieldInError("entries", "collectionUniqueKey.three.failed", true); + assertFieldInError("entries", "collectionUniqueKey.four.failed", false); + + beanEntry.setStringValue2("stringValue2"); + // two entries with same key + bean.setEntries(Arrays.asList(beanEntry, beanEntry3)); + assertFieldInError("entries", "collectionUniqueKey.one.failed", true); + assertFieldInError("entries", "collectionUniqueKey.two.failed", true); + assertFieldInError("entries", "collectionUniqueKey.three.failed", true); + assertFieldInError("entries", "collectionUniqueKey.four.failed", true); + + + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/EmailFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/EmailFieldValidatorTest.java new file mode 100644 index 0000000..78e2f3b --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/EmailFieldValidatorTest.java @@ -0,0 +1,68 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.model.Contact; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class EmailFieldValidatorTest extends AbstractFieldValidatorTest<Contact> { + + public EmailFieldValidatorTest() { + super(Contact.class); + } + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getEmail()); + + // Valid email + bean.setEmail("toto@toto.com"); + assertFieldInError(Contact.PROPERTY_EMAIL, "contact.email.format", false); + + // Valid email with + + bean.setEmail("toto+validation@toto.com"); + assertFieldInError(Contact.PROPERTY_EMAIL, "contact.email.format", false); + + // Not valid email + bean.setEmail("toto"); + assertFieldInError(Contact.PROPERTY_EMAIL, "contact.email.format", true); + + // use requiredstring for that case + bean.setEmail(""); + assertFieldInError(Contact.PROPERTY_EMAIL, "contact.email.format", + false); + + // use required for that case + bean.setEmail(null); + assertFieldInError(Contact.PROPERTY_EMAIL, "contact.email.format", + false); + + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/ExistingDirectoryFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/ExistingDirectoryFieldValidatorTest.java new file mode 100644 index 0000000..ec82cdb --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/ExistingDirectoryFieldValidatorTest.java @@ -0,0 +1,57 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; + +import java.io.File; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class ExistingDirectoryFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getExistingDirectory()); + assertFieldInError("existingDirectory", "existingDirectory.required", true); + + bean.setExistingDirectory(new File("")); + assertFieldInError("existingDirectory", "existingDirectory.required", true); + + // existing file + bean.setExistingDirectory(new File(basedir, "pom.xml")); + assertFieldInError("existingDirectory", "existingDirectory.required", false); + assertFieldInError("existingDirectory", "existingDirectory.not.exist", true); + + // existing directory + bean.setExistingDirectory(basedir); + assertFieldInError("existingDirectory", "existingDirectory.required", false); + assertFieldInError("existingDirectory", "existingDirectory.not.exist", false); + + } + +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/ExistingFileFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/ExistingFileFieldValidatorTest.java new file mode 100644 index 0000000..59df3d0 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/ExistingFileFieldValidatorTest.java @@ -0,0 +1,57 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; + +import java.io.File; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class ExistingFileFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getExistingFile()); + assertFieldInError("existingFile", "existingFile.required", true); + + bean.setExistingFile(new File("")); + assertFieldInError("existingFile", "existingFile.required", true); + + // existing directory + bean.setExistingFile(basedir); + assertFieldInError("existingFile", "existingFile.required", false); + assertFieldInError("existingFile", "existingFile.not.exist", true); + + // existing file + bean.setExistingFile(new File(basedir, "pom.xml")); + assertFieldInError("existingFile", "existingFile.required", false); + assertFieldInError("existingFile", "existingFile.not.exist", false); + + } + +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/FieldExpressionBean.java b/src/test/java/org/nuiton/validator/xwork2/field/FieldExpressionBean.java new file mode 100644 index 0000000..f9b0d0c --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/FieldExpressionBean.java @@ -0,0 +1,131 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class FieldExpressionBean { + + protected final PropertyChangeSupport p; + + protected boolean booleanValue; + + protected short shortValue; + + protected int intValue; + + protected long longValue; + + protected double doubleValue; + + protected String stringValue; + + public FieldExpressionBean() { + p = new PropertyChangeSupport(this); + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public double getDoubleValue() { + return doubleValue; + } + + public int getIntValue() { + return intValue; + } + + public long getLongValue() { + return longValue; + } + + public short getShortValue() { + return shortValue; + } + + public String getStringValue() { + return stringValue; + } + + public void setBooleanValue(boolean newValue) { + Object oldValue = booleanValue; + booleanValue = newValue; + firePropertyChange("booleanValue", oldValue, newValue); + } + + public void setDoubleValue(double newValue) { + Object oldValue = doubleValue; + doubleValue = newValue; + firePropertyChange("doubleValue", oldValue, newValue); + } + + public void setIntValue(int newValue) { + Object oldValue = stringValue; + intValue = newValue; + firePropertyChange("intValue", oldValue, newValue); + } + + public void setLongValue(long newValue) { + Object oldValue = longValue; + longValue = newValue; + firePropertyChange("longValue", oldValue, newValue); + } + + public void setShortValue(short newValue) { + Object oldValue = shortValue; + shortValue = newValue; + firePropertyChange("shortValue", oldValue, newValue); + } + + public void setStringValue(String newValue) { + Object oldValue = stringValue; + stringValue = newValue; + firePropertyChange("stringValue", oldValue, newValue); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + p.firePropertyChange(propertyName, oldValue, newValue); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/FieldExpressionWithParamsValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/FieldExpressionWithParamsValidatorTest.java new file mode 100644 index 0000000..06037a1 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/FieldExpressionWithParamsValidatorTest.java @@ -0,0 +1,144 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class FieldExpressionWithParamsValidatorTest extends AbstractFieldValidatorTest<FieldExpressionBean> { + + public static final String MESSAGE = "expression.too.big##100"; + + public static final String MESSAGE2 = "expression.too.big##100##2000"; + + public FieldExpressionWithParamsValidatorTest() { + super(FieldExpressionBean.class); + } + + @Test + @Override + public void testValidator() throws Exception { + + testBooleanType(); + testShortType(); + testIntType(); + testLongType(); + testDoubleType(); + testStringType(); + + + } + + protected void testBooleanType() { + + assertEquals(false, bean.isBooleanValue()); + assertFieldInError("booleanValue", "expression.boolean.not.equals##true", true); + assertFieldInError("booleanValue", "expression.boolean.not.equals##false", false); + + bean.setBooleanValue(true); + assertFieldInError("booleanValue", "expression.boolean.not.equals##true", false); + assertFieldInError("booleanValue", "expression.boolean.not.equals##false", true); + } + + protected void testShortType() { + assertEquals(0, bean.getShortValue()); + assertFieldInError("shortValue", MESSAGE, false); + assertFieldInError("shortValue", MESSAGE2, false); + bean.setShortValue((short) 10); + assertFieldInError("shortValue", MESSAGE, false); + assertFieldInError("shortValue", MESSAGE2, false); + bean.setShortValue((short) 1000); + assertFieldInError("shortValue", MESSAGE, true); + assertFieldInError("shortValue", MESSAGE2, false); + bean.setShortValue((short) 3000); + assertFieldInError("shortValue", MESSAGE, true); + assertFieldInError("shortValue", MESSAGE2, true); + } + + protected void testIntType() { + assertEquals(0, bean.getIntValue()); + assertFieldInError("intValue", MESSAGE, false); + assertFieldInError("intValue", MESSAGE2, false); + bean.setIntValue(10); + assertFieldInError("intValue", MESSAGE, false); + assertFieldInError("intValue", MESSAGE2, false); + bean.setIntValue(1000); + assertFieldInError("intValue", MESSAGE, true); + assertFieldInError("intValue", MESSAGE2, false); + bean.setIntValue(3000); + assertFieldInError("intValue", MESSAGE, true); + assertFieldInError("intValue", MESSAGE2, true); + } + + protected void testLongType() { + assertEquals(0, bean.getLongValue()); + assertFieldInError("longValue", MESSAGE, false); + assertFieldInError("longValue", MESSAGE2, false); + bean.setLongValue(10); + assertFieldInError("longValue", MESSAGE, false); + assertFieldInError("longValue", MESSAGE2, false); + bean.setLongValue(1000); + assertFieldInError("longValue", MESSAGE, true); + assertFieldInError("longValue", MESSAGE2, false); + bean.setLongValue(3000); + assertFieldInError("longValue", MESSAGE, true); + assertFieldInError("longValue", MESSAGE2, true); + } + + protected void testDoubleType() { + assertEquals(0.0, bean.getDoubleValue(), 0); + assertFieldInError("doubleValue", MESSAGE + ".0", false); + assertFieldInError("doubleValue", "expression.too.big##100.0##2000.0", false); + bean.setDoubleValue(10); + assertFieldInError("doubleValue", MESSAGE + ".0", false); + assertFieldInError("doubleValue", "expression.too.big##100.0##2000.0", false); + bean.setDoubleValue(1000); + assertFieldInError("doubleValue", MESSAGE + ".0", true); + assertFieldInError("doubleValue", "expression.too.big##100.0##2000.0", false); + bean.setDoubleValue(3000); + assertFieldInError("doubleValue", MESSAGE + ".0", true); + assertFieldInError("doubleValue", "expression.too.big##100.0##2000.0", true); + } + + protected void testStringType() { + assertEquals(null, bean.getStringValue()); + + assertFieldInError("stringValue", "expression.stringNotValue##1000", true); + assertFieldInError("stringValue", "expression.stringNotValue##1000##3000", true); + bean.setStringValue("100"); + + assertFieldInError("stringValue", "expression.stringNotValue##1000", true); + assertFieldInError("stringValue", "expression.stringNotValue##1000##3000", true); + + bean.setStringValue("1000"); + assertFieldInError("stringValue", "expression.stringNotValue##1000", false); + assertFieldInError("stringValue", "expression.stringNotValue##1000##3000", false); + + bean.setStringValue("3000"); + assertFieldInError("stringValue", "expression.stringNotValue##1000", true); + assertFieldInError("stringValue", "expression.stringNotValue##1000##3000", false); + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/FrenchCityNameFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/FrenchCityNameFieldValidatorTest.java new file mode 100644 index 0000000..f9d9cc9 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/FrenchCityNameFieldValidatorTest.java @@ -0,0 +1,106 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.model.Contact; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchCityNameFieldValidatorTest extends AbstractFieldValidatorTest<Contact> { + + public FrenchCityNameFieldValidatorTest() { + super(Contact.class); + } + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getCity()); + + // Valid city + bean.setCity("Nantes"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + // Valid city + bean.setCity("Couëron"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + // Valid city + bean.setCity("Saint Sébastien Sur Loire"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + // Valid city + bean.setCity("St Sebastien sur Loire"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + // Valid city + bean.setCity("St-Sebastien-sur-Loire"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + // Valid city + bean.setCity("Y"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + // Valid city + bean.setCity("Saint-Remy-en-Bouzemont-Saint-Genest-et-Isson"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + // Not Valid city name + bean.setCity("2Ville"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + true); + + // Not Valid city name + bean.setCity("Ville2Merde"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + true); + + // Not Valid city name + bean.setCity("Ville 2 Merde"); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + true); + + // Use requiredstring validator for this case + bean.setCity(""); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + // Use required validator for this case + bean.setCity(null); + assertFieldInError(Contact.PROPERTY_CITY, "contact.city.format", + false); + + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/FrenchFinessFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/FrenchFinessFieldValidatorTest.java new file mode 100644 index 0000000..df39877 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/FrenchFinessFieldValidatorTest.java @@ -0,0 +1,85 @@ +package org.nuiton.validator.xwork2.field; + +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.junit.Test; +import org.nuiton.validator.model.HealthEstablishment; + +/** + * @author Sylvain Bavencoff <bavencoff@codelutin.com> + */ +public class FrenchFinessFieldValidatorTest extends AbstractFieldValidatorTest<HealthEstablishment> { + + public FrenchFinessFieldValidatorTest() { + super(HealthEstablishment.class); + } + + @Test + @Override + public void testValidator() throws Exception { + assertNull(bean.getFiness()); + + // Valid Finess + bean.setFiness("440123456"); + assertFieldInError(HealthEstablishment.PROPERTY_FINESS, "healthEstablishment.finess.format", + false); + + // Valid Finess + bean.setFiness("2B0483714"); + assertFieldInError(HealthEstablishment.PROPERTY_FINESS, "healthEstablishment.finess.format", + false); + + // not Valid Finess + bean.setFiness("2B01"); + assertFieldInError(HealthEstablishment.PROPERTY_FINESS, "healthEstablishment.finess.format", + true); + + // not Valid Finess + bean.setFiness("4402345636"); + assertFieldInError(HealthEstablishment.PROPERTY_FINESS, "healthEstablishment.finess.format", + true); + + // not Valid Finess + bean.setFiness("CC0123456"); + assertFieldInError(HealthEstablishment.PROPERTY_FINESS, "healthEstablishment.finess.format", + true); + + // not Valid Finess + bean.setFiness("441123456"); + assertFieldInError(HealthEstablishment.PROPERTY_FINESS, "healthEstablishment.finess.format", + true); + + // not Valid Finess + bean.setFiness("441B23456"); + assertFieldInError(HealthEstablishment.PROPERTY_FINESS, "healthEstablishment.finess.format", + true); + + // not Valid Finess + bean.setFiness("4402345F6"); + assertFieldInError(HealthEstablishment.PROPERTY_FINESS, "healthEstablishment.finess.format", + true); + + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/FrenchLastNameFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/FrenchLastNameFieldValidatorTest.java new file mode 100644 index 0000000..4f97926 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/FrenchLastNameFieldValidatorTest.java @@ -0,0 +1,87 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.model.Contact; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchLastNameFieldValidatorTest extends AbstractFieldValidatorTest<Contact> { + + public FrenchLastNameFieldValidatorTest() { + super(Contact.class); + } + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getCity()); + + // Valid name + bean.setName("Couteau"); + assertFieldInError(Contact.PROPERTY_LAST_NAME, "contact.name.format", + false); + + // Valid name + bean.setName("Le Ny"); + assertFieldInError(Contact.PROPERTY_LAST_NAME, "contact.name.format", + false); + + // Valid name + bean.setName("Clémenceau"); + assertFieldInError(Contact.PROPERTY_LAST_NAME, "contact.name.format", + false); + + // Valid name + bean.setName("Couteau--Viney"); + assertFieldInError(Contact.PROPERTY_LAST_NAME, "contact.name.format", + false); + + // Not valid name + bean.setName("2Pac"); + assertFieldInError(Contact.PROPERTY_LAST_NAME, "contact.name.format", + true); + + // Not valid name + bean.setName("Nom2Merde"); + assertFieldInError(Contact.PROPERTY_LAST_NAME, "contact.name.format", + true); + + // Use requiredstring validator for that case + bean.setName(""); + assertFieldInError(Contact.PROPERTY_LAST_NAME, "contact.name.format", + false); + + // Use required validator for that case + bean.setName(null); + assertFieldInError(Contact.PROPERTY_LAST_NAME, "contact.name.format", + false); + + + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/FrenchPhoneNumberFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/FrenchPhoneNumberFieldValidatorTest.java new file mode 100644 index 0000000..879dc0c --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/FrenchPhoneNumberFieldValidatorTest.java @@ -0,0 +1,134 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.model.Contact; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchPhoneNumberFieldValidatorTest extends AbstractFieldValidatorTest<Contact> { + + public FrenchPhoneNumberFieldValidatorTest() { + super(Contact.class); + } + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getPhone()); + + // Valid phone Number + bean.setPhone("0000000000"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + false); + + // Valid phone Number + bean.setPhone("00 00 00 00 00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + false); + + // Valid phone Number + bean.setPhone("00-00-00-00-00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + false); + + // Valid phone Number + bean.setPhone("00.00.00.00.00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + false); + + // Too long phone Number + bean.setPhone("00 00 00 00 00 00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Too long phone Number + bean.setPhone("00-00-00-00-00-00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Too long phone Number + bean.setPhone("000000000000"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Too long phone Number + bean.setPhone("00.00.00.00.00.00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Too short phone Number + bean.setPhone("00.00.00.00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Too short phone Number + bean.setPhone("00000000"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Too short phone Number + bean.setPhone("00-00-00-00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Too short phone Number + bean.setPhone("00 00 00 00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Invalid character in phone Number + bean.setPhone("00 00 ab 00 00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Invalid character in phone Number + bean.setPhone("0000ab0000"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Invalid character in phone Number + bean.setPhone("00.00.ab.00.00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + + // Invalid character in phone Number + bean.setPhone("00-00-ab-00-00"); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + true); + //Use required string validator for this case + bean.setPhone(""); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + false); + //Use required validator for this case + bean.setPhone(null); + assertFieldInError(Contact.PROPERTY_PHONE, "contact.phoneNumber.format", + false); + + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/FrenchPostCodeFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/FrenchPostCodeFieldValidatorTest.java new file mode 100644 index 0000000..707a6e5 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/FrenchPostCodeFieldValidatorTest.java @@ -0,0 +1,92 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.model.Contact; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchPostCodeFieldValidatorTest extends AbstractFieldValidatorTest<Contact> { + + public FrenchPostCodeFieldValidatorTest() { + super(Contact.class); + } + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getPostCode()); + + // Valid postCode + bean.setPostCode("44230"); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + false); + + // Valid postCode for Corsica + bean.setEmail("2A220"); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + false); + + // Valid postCode for DOM + bean.setEmail("97120"); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + false); + + // Valid postCode for TOM + bean.setPostCode("98120"); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + false); + + // Too long postCode + bean.setPostCode("442300"); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + true); + + // Too short postCode + bean.setPostCode("4423"); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + true); + + // postCode cannot start with 99 + bean.setPostCode("99230"); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + true); + + // postCode can be empty (use a requiredstring validator for this check) + bean.setPostCode(""); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + false); + + // postCode can be null (use a requiredstring validator for this check) + bean.setPostCode(null); + assertFieldInError(Contact.PROPERTY_POSTCODE, "contact.postCode.format", + false); + + + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/FrenchSiretFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/FrenchSiretFieldValidatorTest.java new file mode 100644 index 0000000..c68e02b --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/FrenchSiretFieldValidatorTest.java @@ -0,0 +1,103 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.model.Company; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class FrenchSiretFieldValidatorTest extends AbstractFieldValidatorTest<Company> { + + public FrenchSiretFieldValidatorTest() { + super(Company.class); + } + + @Test + public void TestLuhnChecksum() throws Exception { + // verification sur de vrai numero siret (ca doit passer :) + assertTrue(FrenchSiretFieldValidator.luhnChecksum("44211670300038")); + assertTrue(FrenchSiretFieldValidator.luhnChecksum("73282932000074")); + + // verification avec les memes, en ne modifiant que le dernier chiffre + // ca doit failer + assertFalse(FrenchSiretFieldValidator.luhnChecksum("44211670300030")); + assertFalse(FrenchSiretFieldValidator.luhnChecksum("73282932000070")); + } + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getSiret()); + + // Valid siret + bean.setSiret("44211670300038"); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + false); + + // Valid siret + bean.setSiret("73282932000074"); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + false); + + // Not Valid siret, because bad checksum + bean.setSiret("73282932000071"); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + true); + + // Not valid siret + bean.setSiret("4421167030003"); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + true); + + // Not valid siret + bean.setSiret("442116703000389"); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + true); + + // Not valid siret + bean.setSiret("4421bf1670300038"); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + true); + + // Use requiredString for empty siret + bean.setSiret(""); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + false); + + // Use required for null siret + bean.setSiret(null); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + false); + + // Valid siret with spaces + bean.setSiret("535 198 188 00018 "); + assertFieldInError(Company.PROPERTY_SIRET, "company.siret.format", + false); + + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/NotExistingDirectoryFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/NotExistingDirectoryFieldValidatorTest.java new file mode 100644 index 0000000..a2d271b --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/NotExistingDirectoryFieldValidatorTest.java @@ -0,0 +1,60 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; + +import java.io.File; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class NotExistingDirectoryFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { + + @Test + @Override + public void testValidator() throws Exception { + assertNull(bean.getNotExistingDirectory()); + assertFieldInError("notExistingDirectory", "notExistingDirectory.required", true); + + bean.setNotExistingDirectory(new File("")); + assertFieldInError("notExistingDirectory", "notExistingDirectory.required", true); + + // existing directory + bean.setNotExistingDirectory(basedir); + assertFieldInError("notExistingDirectory", "notExistingDirectory.required", false); + assertFieldInError("notExistingDirectory", "notExistingDirectory.exist", true); + + // existing file + bean.setNotExistingDirectory(new File(basedir, "pom.xml")); + assertFieldInError("notExistingDirectory", "notExistingDirectory.required", false); + assertFieldInError("notExistingDirectory", "notExistingDirectory.exist", true); + + // none existing directory + bean.setNotExistingDirectory(new File(basedir, "pom.xml-" + System.currentTimeMillis())); + assertFieldInError("notExistingDirectory", "notEexistingFile.required", false); + assertFieldInError("notExistingDirectory", "notExistingDirectory.exist", false); + } + +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/NotExistingFileFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/NotExistingFileFieldValidatorTest.java new file mode 100644 index 0000000..98e47c5 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/NotExistingFileFieldValidatorTest.java @@ -0,0 +1,63 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; + +import java.io.File; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class NotExistingFileFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getNotExistingFile()); + assertFieldInError("notExistingFile", "notExistingFile.required", true); + + bean.setNotExistingFile(new File("")); + assertFieldInError("notExistingFile", "notExistingFile.required", true); + + // existing directory + bean.setNotExistingFile(basedir); + assertFieldInError("notExistingFile", "notExistingFile.required", false); + assertFieldInError("notExistingFile", "notExistingFile.exist", true); + + // existing file + bean.setNotExistingFile(new File(basedir, "pom.xml")); + assertFieldInError("notExistingFile", "notExistingFile.required", false); + assertFieldInError("notExistingFile", "notExistingFile.exist", true); + + // none existing file + bean.setNotExistingFile(new File(basedir, "pom.xml-" + System.currentTimeMillis())); + assertFieldInError("notExistingFile", "notEexistingFile.required", false); + assertFieldInError("notExistingFile", "notExistingFile.exist", false); + + + } + +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/RequiredFileFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/RequiredFileFieldValidatorTest.java new file mode 100644 index 0000000..234cc77 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/RequiredFileFieldValidatorTest.java @@ -0,0 +1,56 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; + +import java.io.File; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class RequiredFileFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getExistingFile()); + assertFieldInError("existingFile", "existingFile.required", true); + + bean.setExistingFile(new File("")); + assertFieldInError("existingFile", "existingFile.required", true); + + bean.setExistingFile(basedir); + assertFieldInError("existingFile", "existingFile.required", false); + + assertFieldInError("existingFile", "existingFile.not.exist", true); + + bean.setExistingFile(new File(basedir, "pom.xml")); + assertFieldInError("existingFile", "existingFile.required", false); + assertFieldInError("existingFile", "existingFile.not.exist", false); + + } + +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/VATIdentificationNumberFieldValidatorTest.java b/src/test/java/org/nuiton/validator/xwork2/field/VATIdentificationNumberFieldValidatorTest.java new file mode 100644 index 0000000..e6e2581 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/VATIdentificationNumberFieldValidatorTest.java @@ -0,0 +1,80 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import org.junit.Test; +import org.nuiton.validator.model.Company; + +/** + * @author jcouteau <couteau@codelutin.com> + * @since 2.3 + */ +public class VATIdentificationNumberFieldValidatorTest extends AbstractFieldValidatorTest<Company> { + + public VATIdentificationNumberFieldValidatorTest() { + super(Company.class); + } + + @Test + @Override + public void testValidator() throws Exception { + + assertNull(bean.getVat()); + + // Valid vat + bean.setVat("FR57442116703"); + assertFieldInError(Company.PROPERTY_VAT_NUMBER, "company.vat.format", + false); + + // Not valid vat + bean.setVat("FR 57 44211670332"); + assertFieldInError(Company.PROPERTY_VAT_NUMBER, "company.vat.format", + true); + + // Not valid vat + bean.setVat("442116703000389"); + assertFieldInError(Company.PROPERTY_VAT_NUMBER, "company.vat.format", + true); + + // Valid vat, with spaces in it + bean.setVat("FR 57 442116703"); + assertFieldInError(Company.PROPERTY_VAT_NUMBER, "company.vat.format", + false); + + // Real vat, with spaces in it + bean.setVat("FR 39 535 198 188"); + assertFieldInError(Company.PROPERTY_VAT_NUMBER, "company.vat.format", + false); + + // Use required string validator for that + bean.setVat(""); + assertFieldInError(Company.PROPERTY_VAT_NUMBER, "company.vat.format", + false); + + // Use required validator for that + bean.setVat(null); + assertFieldInError(Company.PROPERTY_VAT_NUMBER, "company.vat.format", + false); + } +} diff --git a/src/test/java/org/nuiton/validator/xwork2/field/ValidatorBean.java b/src/test/java/org/nuiton/validator/xwork2/field/ValidatorBean.java new file mode 100644 index 0000000..294f965 --- /dev/null +++ b/src/test/java/org/nuiton/validator/xwork2/field/ValidatorBean.java @@ -0,0 +1,182 @@ +/* + * #%L + * Nuiton Validator + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.validator.xwork2.field; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import java.util.Collection; + +public class ValidatorBean { + + public static class ValidatorBeanEntry { + + protected int intValue; + + protected String stringValue; + + protected String stringValue2; + + public ValidatorBeanEntry(int intValue, String stringValue) { + this.intValue = intValue; + this.stringValue = stringValue; + } + + public ValidatorBeanEntry(int intValue, String stringValue, String stringValue2) { + this.intValue = intValue; + this.stringValue = stringValue; + this.stringValue2 = stringValue2; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public String getStringValue2() { + return stringValue2; + } + + public void setStringValue2(String stringValue2) { + this.stringValue2 = stringValue2; + } + } + + protected File existingFile; + + protected File notExistingFile; + + protected File existingDirectory; + + protected File notExistingDirectory; + + protected Collection<ValidatorBeanEntry> entries; + + protected String stringValue; + + protected ValidatorBeanEntry entry; + + PropertyChangeSupport p; + + public ValidatorBean() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + public String getStringValue() { + return stringValue; + } + + public File getExistingFile() { + return existingFile; + } + + public File getNotExistingFile() { + return notExistingFile; + } + + public File getExistingDirectory() { + return existingDirectory; + } + + public File getNotExistingDirectory() { + return notExistingDirectory; + } + + public ValidatorBeanEntry getEntry() { + return entry; + } + + public Collection<ValidatorBeanEntry> getEntries() { + return entries; + } + + public void setStringValue(String stringValue) { + String old = this.stringValue; + this.stringValue = stringValue; + p.firePropertyChange("stringValue", old, existingFile); + } + + public void setExistingFile(File existingFile) { + File old = this.existingFile; + this.existingFile = existingFile; + p.firePropertyChange("existingFile", old, existingFile); + } + + public void setNotExistingFile(File notExistingFile) { + File old = this.notExistingFile; + this.notExistingFile = notExistingFile; + p.firePropertyChange("notExistingFile", old, notExistingFile); + } + + public void setExistingDirectory(File existingDirectory) { + File old = this.existingDirectory; + this.existingDirectory = existingDirectory; + p.firePropertyChange("existingDirectory", old, existingDirectory); + } + + public void setNotExistingDirectory(File notExistingDirectory) { + File old = this.notExistingDirectory; + this.notExistingDirectory = notExistingDirectory; + p.firePropertyChange("notExistingDirectory", old, notExistingDirectory); + } + + public void setEntries(Collection<ValidatorBeanEntry> entries) { + this.entries = entries; + // set null oldValue to always fire event + // otherwise it could been not sent... + p.firePropertyChange("entries", null, entries); + } + + public void setEntry(ValidatorBeanEntry entry) { + this.entry = entry; + p.firePropertyChange("entry", null, entry); + } +} diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties new file mode 100644 index 0000000..8e98a06 --- /dev/null +++ b/src/test/resources/log4j.properties @@ -0,0 +1,32 @@ +### +# #%L +# Nuiton Validator +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2011 CodeLutin, Tony Chemit +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### + +# Global logging configuration +log4j.rootLogger=ERROR, stdout +# Console output... +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n + +log4j.logger.org.nuiton.validator=INFO diff --git a/src/test/resources/org/nuiton/validator/bean/SimpleBean-error-validation.xml b/src/test/resources/org/nuiton/validator/bean/SimpleBean-error-validation.xml new file mode 100644 index 0000000..8090351 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/bean/SimpleBean-error-validation.xml @@ -0,0 +1,42 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="requiredstring"> + <message>stringValue.error</message> + </field-validator> + </field> + + <field name="intValue"> + <field-validator type="int"> + <param name="min">1</param> + <message>intValue.error</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/bean/SimpleBean-fatal-validation.xml b/src/test/resources/org/nuiton/validator/bean/SimpleBean-fatal-validation.xml new file mode 100644 index 0000000..e6f1cd9 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/bean/SimpleBean-fatal-validation.xml @@ -0,0 +1,46 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="fieldexpression"> + <param name="expression"> + <![CDATA[ stringValue != null && stringValue == "5"]]></param> + <message>stringValue.fatal</message> + </field-validator> + </field> + + + <field name="intValue"> + <field-validator type="int"> + <param name="min">5</param> + <param name="max">5</param> + <message>intValue.fatal</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/bean/SimpleBean-info-validation.xml b/src/test/resources/org/nuiton/validator/bean/SimpleBean-info-validation.xml new file mode 100644 index 0000000..7b94f49 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/bean/SimpleBean-info-validation.xml @@ -0,0 +1,36 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="intValue"> + <field-validator type="int"> + <param name="min">10</param> + <message>intValue.info</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/bean/SimpleBean-marchepo-error-validation.xml b/src/test/resources/org/nuiton/validator/bean/SimpleBean-marchepo-error-validation.xml new file mode 100644 index 0000000..50b82df --- /dev/null +++ b/src/test/resources/org/nuiton/validator/bean/SimpleBean-marchepo-error-validation.xml @@ -0,0 +1,37 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <!-- add a unknown field --> + + <field name="stringValueUnknown"> + <field-validator type="requiredstring"> + <message>stringValue.error.can.not.happen!</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/bean/SimpleBean-simple-validation.xml b/src/test/resources/org/nuiton/validator/bean/SimpleBean-simple-validation.xml new file mode 100644 index 0000000..8d4b2d4 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/bean/SimpleBean-simple-validation.xml @@ -0,0 +1,42 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="requiredstring"> + <message>stringValue.null</message> + </field-validator> + </field> + + <field name="intValue"> + <field-validator type="int"> + <param name="min">1</param> + <message>intValue.null</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/bean/SimpleBean-warning-validation.xml b/src/test/resources/org/nuiton/validator/bean/SimpleBean-warning-validation.xml new file mode 100644 index 0000000..2701f03 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/bean/SimpleBean-warning-validation.xml @@ -0,0 +1,36 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="fieldexpression"> + <param name="expression"><![CDATA[ stringValue != null && stringValue.length() > 5]]></param> + <message>stringValue.warning</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/legacy/SimpleBean-error-validation.xml b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-error-validation.xml new file mode 100644 index 0000000..20b1439 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-error-validation.xml @@ -0,0 +1,42 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="requiredstring"> + <message>stringValue.error</message> + </field-validator> + </field> + + <field name="intValue"> + <field-validator type="int"> + <param name="min">1</param> + <message>intValue.error</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/legacy/SimpleBean-fatal-validation.xml b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-fatal-validation.xml new file mode 100644 index 0000000..e6f1cd9 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-fatal-validation.xml @@ -0,0 +1,46 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="fieldexpression"> + <param name="expression"> + <![CDATA[ stringValue != null && stringValue == "5"]]></param> + <message>stringValue.fatal</message> + </field-validator> + </field> + + + <field name="intValue"> + <field-validator type="int"> + <param name="min">5</param> + <param name="max">5</param> + <message>intValue.fatal</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/legacy/SimpleBean-info-validation.xml b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-info-validation.xml new file mode 100644 index 0000000..7b94f49 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-info-validation.xml @@ -0,0 +1,36 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="intValue"> + <field-validator type="int"> + <param name="min">10</param> + <message>intValue.info</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/legacy/SimpleBean-simple-validation.xml b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-simple-validation.xml new file mode 100644 index 0000000..8d4b2d4 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-simple-validation.xml @@ -0,0 +1,42 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="requiredstring"> + <message>stringValue.null</message> + </field-validator> + </field> + + <field name="intValue"> + <field-validator type="int"> + <param name="min">1</param> + <message>intValue.null</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/legacy/SimpleBean-warning-validation.xml b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-warning-validation.xml new file mode 100644 index 0000000..2701f03 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/legacy/SimpleBean-warning-validation.xml @@ -0,0 +1,36 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="fieldexpression"> + <param name="expression"><![CDATA[ stringValue != null && stringValue.length() > 5]]></param> + <message>stringValue.warning</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/model/Company-error-validation.xml b/src/test/resources/org/nuiton/validator/model/Company-error-validation.xml new file mode 100644 index 0000000..7ac5b3f --- /dev/null +++ b/src/test/resources/org/nuiton/validator/model/Company-error-validation.xml @@ -0,0 +1,41 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="siret"> + <field-validator type="frenchSiret"> + <message>company.siret.format</message> + </field-validator> + </field> + + <field name="vat"> + <field-validator type="vatIdentificationNumber"> + <message>company.vat.format</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/model/Contact-error-validation.xml b/src/test/resources/org/nuiton/validator/model/Contact-error-validation.xml new file mode 100644 index 0000000..5552c3c --- /dev/null +++ b/src/test/resources/org/nuiton/validator/model/Contact-error-validation.xml @@ -0,0 +1,57 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="email"> + <field-validator type="emailNuiton"> + <message>contact.email.format</message> + </field-validator> + </field> + + <field name="postCode"> + <field-validator type="frenchPostCode"> + <message>contact.postCode.format</message> + </field-validator> + </field> + + <field name="city"> + <field-validator type="frenchCityName"> + <message>contact.city.format</message> + </field-validator> + </field> + + <field name="name"> + <field-validator type="frenchLastName"> + <message>contact.name.format</message> + </field-validator> + </field> + + <field name="phone"> + <field-validator type="frenchPhoneNumber"> + <message>contact.phoneNumber.format</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/model/HealthEstablishment-error-validation.xml b/src/test/resources/org/nuiton/validator/model/HealthEstablishment-error-validation.xml new file mode 100644 index 0000000..e3f8f2f --- /dev/null +++ b/src/test/resources/org/nuiton/validator/model/HealthEstablishment-error-validation.xml @@ -0,0 +1,33 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2013 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="finess"> + <field-validator type="frenchFiness"> + <message>healthEstablishment.finess.format</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/model/Person-error-validation.xml b/src/test/resources/org/nuiton/validator/model/Person-error-validation.xml new file mode 100644 index 0000000..dd137ba --- /dev/null +++ b/src/test/resources/org/nuiton/validator/model/Person-error-validation.xml @@ -0,0 +1,41 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="name"> + <field-validator type="requiredstring"> + <message>person.name.required</message> + </field-validator> + </field> + + <field name="firstname"> + <field-validator type="requiredstring"> + <message>person.firstname.required</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/model/Person-warning-validation.xml b/src/test/resources/org/nuiton/validator/model/Person-warning-validation.xml new file mode 100644 index 0000000..bdafeab --- /dev/null +++ b/src/test/resources/org/nuiton/validator/model/Person-warning-validation.xml @@ -0,0 +1,37 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="pet"> + <field-validator type="fieldexpression"> + <param name="expression"> + <![CDATA[ pet!=null || !pet.empty]]></param> + <message>person.with.no.pet</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/model/Pet-context-info-validation.xml b/src/test/resources/org/nuiton/validator/model/Pet-context-info-validation.xml new file mode 100644 index 0000000..ac91ce2 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/model/Pet-context-info-validation.xml @@ -0,0 +1,33 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="name"> + <field-validator type="requiredstring"> + <message>pet.name.required</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/model/Pet-error-validation.xml b/src/test/resources/org/nuiton/validator/model/Pet-error-validation.xml new file mode 100644 index 0000000..ac91ce2 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/model/Pet-error-validation.xml @@ -0,0 +1,33 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="name"> + <field-validator type="requiredstring"> + <message>pet.name.required</message> + </field-validator> + </field> + +</validators> diff --git a/src/test/resources/org/nuiton/validator/xwork2/field/FieldExpressionBean-error-validation.xml b/src/test/resources/org/nuiton/validator/xwork2/field/FieldExpressionBean-error-validation.xml new file mode 100644 index 0000000..fb98fe5 --- /dev/null +++ b/src/test/resources/org/nuiton/validator/xwork2/field/FieldExpressionBean-error-validation.xml @@ -0,0 +1,122 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + +<field name="booleanValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="booleanParams">boolean:true</param> + <param name="expression"><![CDATA[ booleanValue == booleans.boolean]]> + </param> + <message>expression.boolean.not.equals##${booleans.boolean}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="booleanParams">boolean:false</param> + <param name="expression"><![CDATA[ booleanValue == booleans.boolean]]> + </param> + <message>expression.boolean.not.equals##${booleans.boolean}</message> + </field-validator> + </field> + + <field name="shortValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="shortParams">short:100</param> + <param name="expression"><![CDATA[ shortValue < shorts.short]]> + </param> + <message>expression.too.big##${shorts.short}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="shortParams">short:100|short2:2000</param> + <param name="expression"><![CDATA[ shortValue < shorts.short || shortValue < shorts.short2]]> + </param> + <message>expression.too.big##${shorts.short}##${shorts.short2}</message> + </field-validator> + </field> + + <field name="intValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="intParams">int:100</param> + <param name="expression"><![CDATA[ intValue < ints.int]]> + </param> + <message>expression.too.big##${ints.int}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="intParams">int:100|int2:2000</param> + <param name="expression"><![CDATA[ intValue < ints.int || intValue < ints.int2]]> + </param> + <message>expression.too.big##${ints.int}##${ints.int2}</message> + </field-validator> + </field> + + <field name="longValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="longParams">long:100</param> + <param name="expression"><![CDATA[ longValue < longs.long]]> + </param> + <message>expression.too.big##${longs.long}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="longParams">long:100|long2:2000</param> + <param name="expression"><![CDATA[ longValue < longs.long || longValue < longs.long2]]> + </param> + <message>expression.too.big##${longs.long}##${longs.long2}</message> + </field-validator> + </field> + + <field name="doubleValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="doubleParams">double:100.0</param> + <param name="expression"><![CDATA[ doubleValue < doubles.double]]> + </param> + <message>expression.too.big##${doubles.double}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="doubleParams">double:100.0|double2:2000.0</param> + <param name="expression"><![CDATA[ doubleValue < doubles.double || doubleValue < doubles.double2]]> + </param> + <message>expression.too.big##${doubles.double}##${doubles.double2}</message> + </field-validator> + </field> + + <field name="stringValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="stringParams">string:1000</param> + <param name="expression"><![CDATA[ stringValue.equals(strings.string)]]> + </param> + <message>expression.stringNotValue##${strings.string}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="stringParams">string:1000|string2:3000</param> + <param name="expression"><![CDATA[ stringValue.equals(strings.string) || stringValue.equals(strings.string2)]]> + </param> + <message>expression.stringNotValue##${strings.string}##${strings.string2}</message> + </field-validator> + </field> + + + + +</validators> diff --git a/src/test/resources/org/nuiton/validator/xwork2/field/ValidatorBean-error-validation.xml b/src/test/resources/org/nuiton/validator/xwork2/field/ValidatorBean-error-validation.xml new file mode 100644 index 0000000..cc2958b --- /dev/null +++ b/src/test/resources/org/nuiton/validator/xwork2/field/ValidatorBean-error-validation.xml @@ -0,0 +1,177 @@ +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="requiredstring" short-circuit="true"> + <message>stringValue.required</message> + </field-validator> + </field> + + <field name="existingFile"> + <field-validator type="requiredFile" short-circuit="true"> + <message>existingFile.required</message> + </field-validator> + <field-validator type="existingFile" short-circuit="true"> + <message>existingFile.not.exist</message> + </field-validator> + </field> + + <field name="notExistingFile"> + <field-validator type="requiredFile" short-circuit="true"> + <message>notExistingFile.required</message> + </field-validator> + <field-validator type="notExistingFile" short-circuit="true"> + <message>notExistingFile.exist</message> + </field-validator> + </field> + + <field name="existingDirectory"> + <field-validator type="requiredFile" short-circuit="true"> + <message>existingDirectory.required</message> + </field-validator> + + <field-validator type="existingDirectory" short-circuit="true"> + <message>existingDirectory.not.exist</message> + </field-validator> + </field> + + <field name="notExistingDirectory"> + <field-validator type="requiredFile" short-circuit="true"> + <message>notExistingDirectory.required</message> + </field-validator> + + <field-validator type="notExistingDirectory" short-circuit="true"> + <message>notExistingDirectory.exist</message> + </field-validator> + </field> + + <field name="entries"> + + <field-validator type="collectionUniqueKey"> + <param name="keys">intValue</param> + <message>collectionUniqueKey.one.failed</message> + </field-validator> + <field-validator type="collectionUniqueKey"> + <param name="keys">stringValue</param> + <message>collectionUniqueKey.two.failed</message> + </field-validator> + <field-validator type="collectionUniqueKey"> + <param name="keys">intValue,stringValue</param> + <message>collectionUniqueKey.three.failed</message> + </field-validator> + <field-validator type="collectionUniqueKey"> + <param name="keys">intValue,stringValue,stringValue2</param> + <message>collectionUniqueKey.four.failed</message> + </field-validator> + <field-validator type="collectionUniqueKey"> + <param name="keys">stringValue</param> + <param name="againstProperty">entry</param> + <message>collectionUniqueKey.five.failed</message> + </field-validator> + + <field-validator type="collectionFieldExpression"> + <param name="mode">AT_LEAST_ONE</param> + <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]> + </param> + <message>collectionFieldExpression.atLeastOne</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">EXACTLY_ONE</param> + <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]> + </param> + <message>collectionFieldExpression.exactlyOne</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]> + </param> + <message>collectionFieldExpression.all</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">NONE</param> + <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]> + </param> + <message>collectionFieldExpression.none</message> + </field-validator> + + <!-- useContext --> + <field-validator type="collectionFieldExpression"> + <param name="mode">AT_LEAST_ONE</param> + <param name="useSensitiveContext">true</param> + <param name="expression"><![CDATA[ size > 1 && previous != null && previous.intValue < current.intValue]]></param> + <message>collectionFieldExpression.atLeastOne.useSensitiveContext</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">EXACTLY_ONE</param> + <param name="useSensitiveContext">true</param> + <param name="expression"><![CDATA[ size > 1 && previous != null && ( previous.intValue == 2 + current.intValue || current.intValue == 2 + previous.intValue) ]]></param> + <message>collectionFieldExpression.exactlyOne.useSensitiveContext</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="useSensitiveContext">true</param> + <param name="expression"><![CDATA[ size > 1 && (previous == null || previous.intValue < current.intValue)]]></param> + <message>collectionFieldExpression.all.useSensitiveContext</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">NONE</param> + <param name="useSensitiveContext">true</param> + <param name="expression"><![CDATA[ size > 1 && previous != null && ( current.intValue == 2 + previous.intValue)]]></param> + <message>collectionFieldExpression.none.useSensitiveContext</message> + </field-validator> + + <!-- useFirst --> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="useSensitiveContext">true</param> + <param name="expressionForFirst"><![CDATA[ current.intValue == 0]]></param> + <param name="expression"><![CDATA[ previous == null || previous.intValue < current.intValue]]></param> + <message>collectionFieldExpression.all.useFirst</message> + </field-validator> + + <!-- useLast --> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="useSensitiveContext">true</param> + <param name="expressionForLast"><![CDATA[ current.intValue > 0]]></param> + <param name="expression"><![CDATA[ previous == null || previous.intValue < current.intValue]]></param> + <message>collectionFieldExpression.all.useLast</message> + </field-validator> + + <!-- useFirstAndLast --> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="useSensitiveContext">true</param> + <param name="expressionForFirst"><![CDATA[ current.intValue == 0]]></param> + <param name="expressionForLast"><![CDATA[ current.intValue > 0]]></param> + <param name="expression"><![CDATA[ previous == null || previous.intValue < current.intValue]]></param> + <message>collectionFieldExpression.all.useFirstAndLast</message> + </field-validator> + + </field> + +</validators> diff --git a/src/test/resources/validators.xml b/src/test/resources/validators.xml new file mode 100644 index 0000000..83c3b73 --- /dev/null +++ b/src/test/resources/validators.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + Nuiton Validator + $Id$ + $HeadURL$ + %% + Copyright (C) 2011 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator Config 1.0//EN" + "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd"> +<validators> + <!-- default validators from XWork framework --> + <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/> + <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/> + <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/> + <validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/> + <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/> + <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/> + <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/> + <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/> + <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/> + <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/> + <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/> + <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/> + <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/> + <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/> + <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/> + <validator name="conditionalvisitor" + class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/> + + <!-- default nuiton-validator validators --> + <validator name="collectionFieldExpression" class="org.nuiton.validator.xwork2.field.CollectionFieldExpressionValidator"/> + <validator name="collectionUniqueKey" class="org.nuiton.validator.xwork2.field.CollectionUniqueKeyValidator"/> + + <!-- io validators --> + <validator name="requiredFile" class="org.nuiton.validator.xwork2.field.RequiredFileFieldValidator"/> + <validator name="existingFile" class="org.nuiton.validator.xwork2.field.ExistingFileFieldValidator"/> + <validator name="notExistingFile" class="org.nuiton.validator.xwork2.field.NotExistingFileFieldValidator"/> + <validator name="existingDirectory" class="org.nuiton.validator.xwork2.field.ExistingDirectoryFieldValidator"/> + <validator name="notExistingDirectory" class="org.nuiton.validator.xwork2.field.NotExistingDirectoryFieldValidator"/> + <validator name="fieldexpressionwithparams" class="org.nuiton.validator.xwork2.field.FieldExpressionWithParamsValidator"/> + + <!-- much much better email validator :) --> + <validator name="emailNuiton" class="org.nuiton.validator.xwork2.field.EmailFieldValidator"/> + + <!-- french specific validators --> + <validator name="frenchPhoneNumber" class="org.nuiton.validator.xwork2.field.FrenchPhoneNumberFieldValidator"/> + <validator name="frenchCityName" class="org.nuiton.validator.xwork2.field.FrenchCityNameFieldValidator"/> + <validator name="frenchLastName" class="org.nuiton.validator.xwork2.field.FrenchLastNameFieldValidator"/> + <validator name="frenchPostCode" class="org.nuiton.validator.xwork2.field.FrenchPostCodeFieldValidator"/> + <validator name="frenchSiret" class="org.nuiton.validator.xwork2.field.FrenchSiretFieldValidator"/> + <validator name="frenchFiness" class="org.nuiton.validator.xwork2.field.FrenchFinessFieldValidator"/> + + <!-- eu specific validators --> + <validator name="vatIdentificationNumber" class="org.nuiton.validator.xwork2.field.VATIdentificationNumberFieldValidator"/> + +</validators> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
participants (1)
-
nuiton.org scm