branch
git-svn-id: https://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/prepare_r3@922981 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/2_0_3_prepare/assembly/pom.xml b/2_0_3_prepare/assembly/pom.xml
new file mode 100644
index 0000000..bc0d5e2
--- /dev/null
+++ b/2_0_3_prepare/assembly/pom.xml
@@ -0,0 +1,201 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>myfaces-extval-assembly12</artifactId>
+ <packaging>pom</packaging>
+ <name>Apache MyFaces Extensions Validator Assembly</name>
+ <description>MyFaces Extensions Validator Assembly is used to generate
+ .zip and .tar.gz distributions </description>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-parent</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/assembly</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/assembly</developerConnection>
+ <url>http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/1_2_2_rc/assembly</url>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>dependency-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-javadoc</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-core</artifactId>
+ <version>${core.version}</version>
+ <classifier>javadoc</classifier>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>myfaces-extval-generic-support</artifactId>
+ <version>${generic-support.version}</version>
+ <classifier>javadoc</classifier>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>myfaces-extval-trinidad-support</artifactId>
+ <version>${trinidad-support.version}</version>
+ <classifier>javadoc</classifier>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>myfaces-extval-property-validation</artifactId>
+ <version>${property-validation.version}</version>
+ <classifier>javadoc</classifier>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>myfaces-extval-bean-validation</artifactId>
+ <version>${bean-validation.version}</version>
+ <classifier>javadoc</classifier>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${project.build.directory}/javadoc</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>copy-source</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-core</artifactId>
+ <version>${core.version}</version>
+ <classifier>sources</classifier>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>myfaces-extval-generic-support</artifactId>
+ <version>${generic-support.version}</version>
+ <classifier>sources</classifier>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>myfaces-extval-trinidad-support</artifactId>
+ <version>${trinidad-support.version}</version>
+ <classifier>sources</classifier>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>myfaces-extval-property-validation</artifactId>
+ <version>${property-validation.version}</version>
+ <classifier>sources</classifier>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>myfaces-extval-bean-validation</artifactId>
+ <version>${bean-validation.version}</version>
+ <classifier>sources</classifier>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${project.build.directory}/src</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <!-- EXECUTE mvn package to generate assembly files -->
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>make_assembly_src</id>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/coresrc.xml</descriptor>
+ </descriptors>
+ <finalName>myfaces-extval12-${version}-src</finalName>
+ <appendAssemblyId>false</appendAssemblyId>
+ <outputDirectory>target/assembly/out</outputDirectory>
+ <workDirectory>target/assembly/work</workDirectory>
+ </configuration>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>make_assembly_bin</id>
+ <configuration>
+ <descriptors>
+ <descriptor>${basedir}/src/main/assembly/corebin.xml</descriptor>
+ </descriptors>
+ <finalName>myfaces-extval12-${version}-bin</finalName>
+ <appendAssemblyId>false</appendAssemblyId>
+ <outputDirectory>target/assembly/out</outputDirectory>
+ <workDirectory>target/assembly/work</workDirectory>
+ </configuration>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-core</artifactId>
+ <version>${core.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>myfaces-extval-property-validation</artifactId>
+ <version>${property-validation.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>myfaces-extval-bean-validation</artifactId>
+ <version>${bean-validation.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>myfaces-extval-trinidad-support</artifactId>
+ <version>${trinidad-support.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>myfaces-extval-generic-support</artifactId>
+ <version>${generic-support.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <!-- Since extval could be async released, an generated assembly could contain different
+ artifact versions -->
+ <properties>
+ <core.version>2.0.3-SNAPSHOT</core.version>
+ <trinidad-support.version>2.0.3-SNAPSHOT</trinidad-support.version>
+ <generic-support.version>2.0.3-SNAPSHOT</generic-support.version>
+ <property-validation.version>2.0.3-SNAPSHOT</property-validation.version>
+ <bean-validation.version>2.0.3-SNAPSHOT</bean-validation.version>
+ </properties>
+</project>
diff --git a/2_0_3_prepare/assembly/src/main/assembly/corebin.xml b/2_0_3_prepare/assembly/src/main/assembly/corebin.xml
new file mode 100644
index 0000000..0f712f0
--- /dev/null
+++ b/2_0_3_prepare/assembly/src/main/assembly/corebin.xml
@@ -0,0 +1,32 @@
+<assembly>
+ <id>corebin</id>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>lib</outputDirectory>
+ <scope>runtime</scope>
+ </dependencySet>
+ </dependencySets>
+ <fileSets>
+ <fileSet>
+ <directory>src/main/resources</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>README*</include>
+ <include>LICENSE*</include>
+ <include>NOTICE*</include>
+ <include>RELEASE*</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/javadoc</directory>
+ <outputDirectory>javadoc</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/2_0_3_prepare/assembly/src/main/assembly/coresrc.xml b/2_0_3_prepare/assembly/src/main/assembly/coresrc.xml
new file mode 100644
index 0000000..7d1ece1
--- /dev/null
+++ b/2_0_3_prepare/assembly/src/main/assembly/coresrc.xml
@@ -0,0 +1,27 @@
+<assembly>
+ <id>coresrc</id>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>src/main/resources</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>README*</include>
+ <include>LICENSE*</include>
+ <include>NOTICE*</include>
+ <include>RELEASE*</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/src</directory>
+ <outputDirectory>src</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
+
diff --git a/2_0_3_prepare/assembly/src/main/resources/LICENSE.txt b/2_0_3_prepare/assembly/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/2_0_3_prepare/assembly/src/main/resources/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/2_0_3_prepare/assembly/src/main/resources/NOTICE.txt b/2_0_3_prepare/assembly/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/2_0_3_prepare/assembly/src/main/resources/NOTICE.txt
@@ -0,0 +1,9 @@
+Apache MyFaces Extensions Validator
+Copyright 2007-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+------------------------------------------------------------------------
+See the file LICENSE.txt
+------------------------------------------------------------------------
\ No newline at end of file
diff --git a/2_0_3_prepare/component-support/generic-support/pom.xml b/2_0_3_prepare/component-support/generic-support/pom.xml
new file mode 100644
index 0000000..acd80e4
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/pom.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>jar</packaging>
+
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>myfaces-extval-generic-support</artifactId>
+
+ <name>MyFaces Extensions-Validator Generic Support Module</name>
+ <version>2.0.3-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>component-support-modules-project</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1.1</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <version>2.1_3</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/config</directory>
+ <includes>
+ <include>**/*xml</include>
+ </includes>
+ <targetPath>/META-INF</targetPath>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ </includes>
+ <targetPath>/META-INF</targetPath>
+ </resource>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*properties</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/2_0_3_prepare/component-support/generic-support/src/main/config/faces-config.xml b/2_0_3_prepare/component-support/generic-support/src/main/config/faces-config.xml
new file mode 100644
index 0000000..e2605f3
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/src/main/config/faces-config.xml
@@ -0,0 +1,28 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
+ version="2.0">
+ <lifecycle>
+ <phase-listener>
+ org.apache.myfaces.extensions.validator.generic.startup.GenericModuleStartupListener
+ </phase-listener>
+ </lifecycle>
+</faces-config>
\ No newline at end of file
diff --git a/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/ExtValGenericRenderKit.java b/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/ExtValGenericRenderKit.java
new file mode 100644
index 0000000..7dbed7b
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/ExtValGenericRenderKit.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.generic.renderkit;
+
+import org.apache.myfaces.extensions.validator.core.renderkit.ExtValRenderKit;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import javax.faces.render.RenderKit;
+import javax.faces.render.Renderer;
+import java.lang.reflect.Method;
+
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.MethodProxy;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValGenericRenderKit extends ExtValRenderKit implements MethodInterceptor
+{
+ public static RenderKit newInstance(RenderKit renderKit)
+ {
+ Class currentClass = renderKit.getClass();
+
+ //it's not possible to wrap the converter again - occurs e.g. under solaris + bea weblogic
+ if (ProxyUtils.isProxiedClass(currentClass))
+ {
+ return renderKit;
+ }
+
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(renderKit.getClass());
+ enhancer.setCallback(new ExtValGenericRenderKit(renderKit));
+ enhancer.setClassLoader(Thread.currentThread().getContextClassLoader());
+
+ return (RenderKit) enhancer.create();
+ }
+
+ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable
+ {
+ if(method.getName().equals("getRenderer"))
+ {
+ return getRenderer((String)args[0], (String)args[1]);
+ }
+ else if(method.getName().equals("addRenderer"))
+ {
+ addRenderer((String)args[0], (String)args[1], (Renderer)args[2]);
+ }
+ else
+ {
+ return proxy.invokeSuper(obj, args);
+ }
+
+ return null;
+ }
+
+ public ExtValGenericRenderKit(RenderKit wrapped)
+ {
+ super(wrapped);
+ }
+
+ @Override
+ protected Renderer createWrapper(Renderer renderer)
+ {
+ return ExtValGenericRendererWrapper.newInstance(renderer);
+ }
+}
diff --git a/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/ExtValGenericRendererWrapper.java b/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/ExtValGenericRendererWrapper.java
new file mode 100644
index 0000000..2165575
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/ExtValGenericRendererWrapper.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.generic.renderkit;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.renderkit.ExtValRendererWrapper;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.render.Renderer;
+import java.lang.reflect.Method;
+
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.MethodProxy;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public final class ExtValGenericRendererWrapper extends ExtValRendererWrapper implements MethodInterceptor
+{
+ public static Renderer newInstance(Renderer renderer)
+ {
+ Class currentClass = renderer.getClass();
+
+ //to avoid re-wrapping - occurs e.g. under solaris + bea weblogic
+ if (ProxyUtils.isProxiedClass(currentClass))
+ {
+ return renderer;
+ }
+
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(renderer.getClass());
+ enhancer.setCallback(new ExtValGenericRendererWrapper(renderer));
+ enhancer.setClassLoader(Thread.currentThread().getContextClassLoader());
+
+ return (Renderer) enhancer.create();
+ }
+
+ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable
+ {
+ if (method.getName().equals("getConvertedValue") && args[1] instanceof UIComponent)
+ {
+ return getConvertedValue((FacesContext)args[0], (UIComponent)args[1], args[2]);
+ }
+ else if (method.getName().equals("decode") && args[1] instanceof UIComponent)
+ {
+ decode((FacesContext)args[0], (UIComponent)args[1]);
+ }
+ else if (method.getName().equals("encodeBegin") && args[1] instanceof UIComponent)
+ {
+ encodeBegin((FacesContext)args[0], (UIComponent)args[1]);
+ }
+ else if (method.getName().equals("encodeChildren") && args[1] instanceof UIComponent)
+ {
+ encodeChildren((FacesContext)args[0], (UIComponent)args[1]);
+ }
+ else if (method.getName().equals("encodeEnd") && args[1] instanceof UIComponent)
+ {
+ encodeEnd((FacesContext)args[0], (UIComponent)args[1]);
+ }
+ else if (method.getName().equals("convertClientId") && args[1] instanceof String)
+ {
+ return convertClientId((FacesContext)args[0], (String)args[1]);
+ }
+ else if (method.getName().equals("getRendersChildren"))
+ {
+ return getRendersChildren();
+ }
+ else
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("method " + method.getName() + " called without rendering-interceptors");
+ }
+
+ return proxy.invokeSuper(obj, args);
+ }
+ return null;
+ }
+
+ public ExtValGenericRendererWrapper(Renderer wrapped)
+ {
+ super(wrapped);
+ }
+}
diff --git a/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/GenericRenderKitWrapperFactory.java b/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/GenericRenderKitWrapperFactory.java
new file mode 100644
index 0000000..6d917e6
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/renderkit/GenericRenderKitWrapperFactory.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.generic.renderkit;
+
+import org.apache.myfaces.extensions.validator.core.renderkit.AbstractRenderKitWrapperFactory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.render.RenderKit;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class GenericRenderKitWrapperFactory extends AbstractRenderKitWrapperFactory
+{
+ protected RenderKit createWrapper(RenderKit renderKit)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("extval renderkit wrapper created for " + renderKit.getClass().getName() + " via cglib");
+ }
+
+ return ExtValGenericRenderKit.newInstance(renderKit);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/startup/GenericModuleStartupListener.java b/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/startup/GenericModuleStartupListener.java
new file mode 100644
index 0000000..a573314
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/src/main/java/org/apache/myfaces/extensions/validator/generic/startup/GenericModuleStartupListener.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.generic.startup;
+
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.factory.FactoryNames;
+import org.apache.myfaces.extensions.validator.core.renderkit.AbstractRenderKitWrapperFactory;
+import org.apache.myfaces.extensions.validator.core.startup.AbstractStartupListener;
+import org.apache.myfaces.extensions.validator.generic.renderkit.GenericRenderKitWrapperFactory;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class GenericModuleStartupListener extends AbstractStartupListener
+{
+ private static final long serialVersionUID = 4392156032877519556L;
+
+ protected void init()
+ {
+ ExtValContext.getContext().getFactoryFinder().getFactory(FactoryNames.RENDERKIT_WRAPPER_FACTORY,
+ AbstractRenderKitWrapperFactory.class).addRenderKitWrapperFactory(new GenericRenderKitWrapperFactory());
+ }
+}
diff --git a/2_0_3_prepare/component-support/generic-support/src/main/resources/LICENSE.txt b/2_0_3_prepare/component-support/generic-support/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/src/main/resources/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/2_0_3_prepare/component-support/generic-support/src/main/resources/NOTICE.txt b/2_0_3_prepare/component-support/generic-support/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/src/main/resources/NOTICE.txt
@@ -0,0 +1,9 @@
+Apache MyFaces Extensions Validator
+Copyright 2007-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+------------------------------------------------------------------------
+See the file LICENSE.txt
+------------------------------------------------------------------------
\ No newline at end of file
diff --git a/2_0_3_prepare/component-support/generic-support/src/site/apt/index.apt b/2_0_3_prepare/component-support/generic-support/src/site/apt/index.apt
new file mode 100644
index 0000000..659a8e8
--- /dev/null
+++ b/2_0_3_prepare/component-support/generic-support/src/site/apt/index.apt
@@ -0,0 +1,9 @@
+ ------
+Apache MyFaces Extensions Validator Generic Support Module
+ ------
+
+Apache MyFaces Extensions Validator Generic Support Module Overview
+
+ MyFaces Extensions Validator Generic Support Module provides generic Support for JSF component frameworks which have special requirements (e.g. RichFaces, MyFaces Tobago, ...).
+
+ MyFaces Extensions Validator is compatible with JSF 1.1.x and JSF 1.2.x. Both versions require Java 1.5+
\ No newline at end of file
diff --git a/2_0_3_prepare/component-support/pom.xml b/2_0_3_prepare/component-support/pom.xml
new file mode 100644
index 0000000..87854dd
--- /dev/null
+++ b/2_0_3_prepare/component-support/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <packaging>pom</packaging>
+
+ <groupId>org.apache.myfaces.extensions.validator.component-support-modules</groupId>
+ <artifactId>component-support-modules-project</artifactId>
+
+ <name>MyFaces Extensions-Validator Component-Support Modules</name>
+ <version>2.0.3-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-parent</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/component-support</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/component-support</developerConnection>
+ <url>http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/1_2_2_rc/component-support</url>
+ </scm>
+
+ <modules>
+ <!--module>trinidad-support</module-->
+ <module>generic-support</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-core</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <trinidad.version>1.2.9</trinidad.version>
+ </properties>
+</project>
diff --git a/2_0_3_prepare/core/pom.xml b/2_0_3_prepare/core/pom.xml
new file mode 100644
index 0000000..c7ac02e
--- /dev/null
+++ b/2_0_3_prepare/core/pom.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-parent</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-core</artifactId>
+ <name>MyFaces Extensions-Validator Core</name>
+ <version>2.0.3-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/core</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/core</developerConnection>
+ <url>http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/1_2_2_rc/core</url>
+ </scm>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1.1</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.el</groupId>
+ <artifactId>el-api</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/config</directory>
+ <includes>
+ <include>**/*xml</include>
+ </includes>
+ <targetPath>/META-INF</targetPath>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ </includes>
+ <targetPath>/META-INF</targetPath>
+ </resource>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*properties</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/2_0_3_prepare/core/src/main/config/faces-config.xml b/2_0_3_prepare/core/src/main/config/faces-config.xml
new file mode 100644
index 0000000..6dc7f47
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/config/faces-config.xml
@@ -0,0 +1,31 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+
+<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
+ version="2.0">
+ <factory>
+ <render-kit-factory>org.apache.myfaces.extensions.validator.core.renderkit.ExtValRenderKitFactory</render-kit-factory>
+ </factory>
+
+ <lifecycle>
+ <phase-listener>org.apache.myfaces.extensions.validator.core.startup.ExtValStartupListener</phase-listener>
+ </lifecycle>
+</faces-config>
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/ExtValInformation.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/ExtValInformation.java
new file mode 100644
index 0000000..77d5d1c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/ExtValInformation.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+
+/**
+ * dont't move to an other package!!!
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface ExtValInformation
+{
+ static final String EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME = ExtValInformation.class.getPackage().getName();
+ static final String WEBXML_PARAM_PREFIX = ExtValInformation.class.getPackage().getName();
+ static final String VERSION = ClassUtils.getJarVersion(ExtValInformation.class);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/CustomInformation.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/CustomInformation.java
new file mode 100644
index 0000000..62da39e
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/CustomInformation.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.API})
+public enum CustomInformation
+{
+ BASE_PACKAGE,
+
+ COMPONENT_META_DATA_EXTRACTOR,
+ VALIDATION_PARAMETER_EXTRACTOR,
+
+ VALIDATION_STRATEGY_POSTFIX,
+ VALIDATION_ERROR_MESSAGE_RESOLVER_POSTFIX,
+ META_DATA_TRANSFORMER_POSTFIX,
+
+ VALIDATION_STRATEGY_TO_MSG_RESOLVER_NAME_MAPPER,
+ META_DATA_TO_VALIDATION_STRATEGY_NAME_MAPPER,
+ VALIDATION_STRATEGY_TO_META_DATA_TRANSFORMER_NAME_MAPPER,
+
+ STARTUP_LISTENER,
+ COMPONENT_INITIALIZER,
+ VALIDATION_EXCEPTION_INTERCEPTOR,
+ PROPERTY_VALIDATION_INTERCEPTOR,
+ META_DATA_EXTRACTION_INTERCEPTOR,
+
+ MESSAGE_RESOLVER_FACTORY,
+ VALIDATION_STRATEGY_FACTORY,
+ COMPONENT_META_DATA_EXTRACTOR_FACTORY,
+ VALIDATION_PARAMETER_EXTRACTOR_FACTORY,
+ VALIDATION_PARAMETER_FACTORY,
+ META_DATA_TRANSFORMER_FACTORY,
+ FACES_MESSAGE_FACTORY,
+ STORAGE_MANAGER_FACTORY,
+
+ MESSAGE_BUNDLE_NAME,
+ STATIC_STRATEGY_MAPPING_SOURCE,
+
+ META_DATA_STORAGE_FILTER
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/DefaultProjectStageResolver.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/DefaultProjectStageResolver.java
new file mode 100644
index 0000000..034d10a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/DefaultProjectStageResolver.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultProjectStageResolver implements ProjectStageResolver
+{
+ public ProjectStage getCurrentProjectStage()
+ {
+ //don't use the default extval mechanism to avoid too early evaluation with mojarra
+ String result;
+ try
+ {
+ result = FacesContext.getCurrentInstance().getApplication().getProjectStage().toString();
+ }
+ catch (Throwable t)
+ {
+ return createProjectStage(getDefaultProjectStage());
+ }
+
+ if(result == null || "".equals(result))
+ {
+ return createProjectStage(getDefaultProjectStage());
+ }
+ return createProjectStage(ProjectStage.createStageName(result.trim()));
+ }
+
+ protected ProjectStage createProjectStage(ProjectStageName projectStageName)
+ {
+ return ProjectStage.createStage(projectStageName);
+ }
+
+ private ProjectStageName getDefaultProjectStage()
+ {
+ return ExtValUtils.getDefaultStageName();
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContext.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContext.java
new file mode 100644
index 0000000..52895bf
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContext.java
@@ -0,0 +1,412 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.core.factory.DefaultFactoryFinder;
+import org.apache.myfaces.extensions.validator.core.factory.FactoryFinder;
+import org.apache.myfaces.extensions.validator.core.initializer.component.ComponentInitializer;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
+import org.apache.myfaces.extensions.validator.core.interceptor.MetaDataExtractionInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.PropertyValidationInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.RendererInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.ValidationExceptionInterceptor;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.recorder.ProcessedInformationRecorder;
+import org.apache.myfaces.extensions.validator.core.validation.SkipValidationEvaluator;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverityInterpreter;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public class ExtValContext
+{
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private static ExtValContext extValContext;
+
+ //don't try to resolve it dynamically e.g. via InformationProviderBean - there's a mojarra issue
+ private static final String CUSTOM_EXTVAL_CONTEXT_CLASS_NAME =
+ ExtValContext.class.getName().replace(".core.", ".custom.");
+
+ private ViolationSeverityInterpreter violationSeverityInterpreter;
+ private FactoryFinder factoryFinder = DefaultFactoryFinder.getInstance();
+ private Map<String, RendererInterceptor> rendererInterceptors = new HashMap<String, RendererInterceptor>();
+ private List<String> deniedInterceptors = new ArrayList<String>();
+ private List<ProcessedInformationRecorder> processedInformationRecorders =
+ new ArrayList<ProcessedInformationRecorder>();
+
+ private SkipValidationEvaluator skipValidationEvaluator;
+
+ private Map<String, Object> globalProperties = new HashMap<String, Object>();
+
+ private Map<StaticConfigurationNames, List<StaticConfiguration<String, String>>> staticConfigMap
+ = new HashMap<StaticConfigurationNames, List<StaticConfiguration<String, String>>>();
+
+ private ExtValContextInternals contextHelper;
+ private ExtValContextInvocationOrderAwareInternals invocationOrderAwareContextHelper;
+
+ protected ExtValContext()
+ {
+ this.contextHelper = new ExtValContextInternals();
+ this.invocationOrderAwareContextHelper = new ExtValContextInvocationOrderAwareInternals(this.contextHelper);
+ }
+
+ public static ExtValContext getContext()
+ {
+ if (extValContext == null)
+ {
+ extValContext = new ExtValContext();
+
+ tryToCreateCustomExtValContext();
+ }
+ return extValContext;
+ }
+
+ private static void tryToCreateCustomExtValContext()
+ {
+ Object customExtValContext = ClassUtils.tryToInstantiateClassForName(CUSTOM_EXTVAL_CONTEXT_CLASS_NAME);
+
+ if (customExtValContext instanceof ExtValContext)
+ {
+ extValContext = (ExtValContext) customExtValContext;
+ }
+ }
+
+ public void setViolationSeverityInterpreter(ViolationSeverityInterpreter violationSeverityInterpreter)
+ {
+ setViolationSeverityInterpreter(violationSeverityInterpreter, true);
+ }
+
+ public void setViolationSeverityInterpreter(
+ ViolationSeverityInterpreter violationSeverityInterpreter, boolean forceOverride)
+ {
+ if (this.violationSeverityInterpreter == null || forceOverride)
+ {
+ if (this.logger.isInfoEnabled() && violationSeverityInterpreter != null)
+ {
+ this.logger.info(violationSeverityInterpreter.getClass() + " is used");
+ }
+ this.violationSeverityInterpreter = violationSeverityInterpreter;
+ }
+ }
+
+ public ViolationSeverityInterpreter getViolationSeverityInterpreter()
+ {
+ ViolationSeverityInterpreter requestScopedInterpreter = this.contextHelper
+ .getRequestScopedViolationSeverityInterpreter();
+
+ if(requestScopedInterpreter != null)
+ {
+ return requestScopedInterpreter;
+ }
+
+ return this.violationSeverityInterpreter;
+ }
+
+ /*
+ * FactoryFinder
+ */
+ public FactoryFinder getFactoryFinder()
+ {
+ return this.factoryFinder;
+ }
+
+ public void setFactoryFinder(FactoryFinder factoryFinder)
+ {
+ if (factoryFinder != null)
+ {
+ this.factoryFinder = factoryFinder;
+ }
+ }
+
+ /*
+ * SkipValidationEvaluator
+ */
+ public void setSkipValidationEvaluator(SkipValidationEvaluator skipValidationEvaluator)
+ {
+ setSkipValidationEvaluator(skipValidationEvaluator, true);
+ }
+
+ public void setSkipValidationEvaluator(SkipValidationEvaluator skipValidationEvaluator, boolean forceOverride)
+ {
+ if (this.skipValidationEvaluator == null || forceOverride)
+ {
+ if (this.logger.isInfoEnabled() && skipValidationEvaluator != null)
+ {
+ this.logger.info(skipValidationEvaluator.getClass() + " is used");
+ }
+ this.skipValidationEvaluator = skipValidationEvaluator;
+ }
+ }
+
+ public SkipValidationEvaluator getSkipValidationEvaluator()
+ {
+ if (this.skipValidationEvaluator == null)
+ {
+ return new SkipValidationEvaluator()
+ {
+ public boolean skipValidation(FacesContext facesContext, UIComponent uiComponent,
+ ValidationStrategy validationStrategy, MetaDataEntry entry)
+ {
+ return false;
+ }
+ };
+ }
+
+ return this.skipValidationEvaluator;
+ }
+
+ /*
+ * RendererInterceptors
+ */
+ public List<RendererInterceptor> getRendererInterceptors()
+ {
+ return new ArrayList<RendererInterceptor>(this.rendererInterceptors.values());
+ }
+
+ public boolean registerRendererInterceptor(RendererInterceptor rendererInterceptor)
+ {
+ synchronized (ExtValContext.class)
+ {
+ if (this.deniedInterceptors.contains(rendererInterceptor.getInterceptorId()))
+ {
+ return false;
+ }
+
+ this.rendererInterceptors.put(rendererInterceptor.getInterceptorId(), rendererInterceptor);
+ }
+ return true;
+ }
+
+ public void deregisterRendererInterceptor(Class<? extends RendererInterceptor> rendererInterceptorClass)
+ {
+ RendererInterceptor rendererInterceptor = ClassUtils.tryToInstantiateClass(rendererInterceptorClass);
+
+ synchronized (ExtValContext.class)
+ {
+ this.rendererInterceptors.remove(rendererInterceptor.getInterceptorId());
+ }
+ }
+
+ //if an interceptor hasn't been registered so far, it should be denied at future registrations
+ public void denyRendererInterceptor(Class<? extends RendererInterceptor> rendererInterceptorClass)
+ {
+ RendererInterceptor rendererInterceptor = ClassUtils.tryToInstantiateClass(rendererInterceptorClass);
+
+ synchronized (ExtValContext.class)
+ {
+ if (!this.deniedInterceptors.contains(rendererInterceptor.getInterceptorId()))
+ {
+ this.deniedInterceptors.add(rendererInterceptor.getInterceptorId());
+ }
+ }
+ deregisterRendererInterceptor(rendererInterceptorClass);
+ }
+
+ /*
+ * ComponentInitializers
+ */
+ public void addComponentInitializer(ComponentInitializer componentInitializer)
+ {
+ this.invocationOrderAwareContextHelper.lazyInitComponentInitializers();
+ this.invocationOrderAwareContextHelper.addComponentInitializer(componentInitializer);
+ }
+
+ public List<ComponentInitializer> getComponentInitializers()
+ {
+ this.invocationOrderAwareContextHelper.lazyInitComponentInitializers();
+ return this.invocationOrderAwareContextHelper.getComponentInitializers();
+ }
+
+ /*
+ * ValidationExceptionInterceptors
+ */
+ public void addValidationExceptionInterceptor(ValidationExceptionInterceptor validationExceptionInterceptor)
+ {
+ this.invocationOrderAwareContextHelper.lazyInitValidationExceptionInterceptors();
+ this.invocationOrderAwareContextHelper.addValidationExceptionInterceptor(validationExceptionInterceptor);
+ }
+
+ public List<ValidationExceptionInterceptor> getValidationExceptionInterceptors()
+ {
+ this.invocationOrderAwareContextHelper.lazyInitValidationExceptionInterceptors();
+ return this.invocationOrderAwareContextHelper.getValidationExceptionInterceptors();
+ }
+
+ /*
+ * PropertyValidationInterceptors
+ */
+ public void addPropertyValidationInterceptor(PropertyValidationInterceptor propertyValidationInterceptor)
+ {
+ this.invocationOrderAwareContextHelper.lazyInitPropertyValidationInterceptors();
+ this.invocationOrderAwareContextHelper.addPropertyValidationInterceptor(propertyValidationInterceptor);
+ }
+
+ /**
+ * @return all global validation interceptors
+ */
+ public List<PropertyValidationInterceptor> getPropertyValidationInterceptors()
+ {
+ this.invocationOrderAwareContextHelper.lazyInitPropertyValidationInterceptors();
+ return this.invocationOrderAwareContextHelper.getPropertyValidationInterceptors();
+ }
+
+ public List<PropertyValidationInterceptor> getPropertyValidationInterceptorsFor(Class moduleKey)
+ {
+ this.invocationOrderAwareContextHelper.lazyInitPropertyValidationInterceptors();
+ return this.invocationOrderAwareContextHelper.getPropertyValidationInterceptorsFor(moduleKey);
+ }
+
+ /*
+ * MetaDataExtractionInterceptors
+ */
+ public void addMetaDataExtractionInterceptor(MetaDataExtractionInterceptor metaDataExtractionInterceptor)
+ {
+ this.invocationOrderAwareContextHelper.lazyInitMetaDataExtractionInterceptors();
+ this.invocationOrderAwareContextHelper.addMetaDataExtractionInterceptor(metaDataExtractionInterceptor);
+ }
+
+ /**
+ * @return all global meta-data extraction interceptors
+ */
+ public List<MetaDataExtractionInterceptor> getMetaDataExtractionInterceptors()
+ {
+ this.invocationOrderAwareContextHelper.lazyInitMetaDataExtractionInterceptors();
+ return this.invocationOrderAwareContextHelper.getMetaDataExtractionInterceptors();
+ }
+
+ public List<MetaDataExtractionInterceptor> getMetaDataExtractionInterceptorsFor(Class moduleKey)
+ {
+ Map<String, Object> properties = new HashMap<String, Object>();
+
+ if(moduleKey != null)
+ {
+ properties.put(ValidationModuleKey.class.getName(), moduleKey);
+ }
+ return getMetaDataExtractionInterceptorsWith(properties);
+ }
+
+ public List<MetaDataExtractionInterceptor> getMetaDataExtractionInterceptorsWith(Map<String, Object> properties)
+ {
+ this.invocationOrderAwareContextHelper.lazyInitMetaDataExtractionInterceptors();
+ return this.invocationOrderAwareContextHelper.getMetaDataExtractionInterceptorsWith(properties);
+ }
+
+ /*
+ * ProcessedInformationRecorders
+ */
+ public List<ProcessedInformationRecorder> getProcessedInformationRecorders()
+ {
+ return this.processedInformationRecorders;
+ }
+
+ public void addProcessedInformationRecorder(ProcessedInformationRecorder processedInformationRecorder)
+ {
+ this.processedInformationRecorders.add(processedInformationRecorder);
+ }
+
+ /*
+ * InformationProviderBean
+ */
+ public InformationProviderBean getInformationProviderBean()
+ {
+ return this.contextHelper.getInformationProviderBean();
+ }
+
+ /*
+ * StaticConfiguration
+ */
+ public List<StaticConfiguration<String, String>> getStaticConfiguration(StaticConfigurationNames name)
+ {
+ if (!this.staticConfigMap.containsKey(name))
+ {
+ List<StaticConfiguration<String, String>> staticConfigList =
+ new ArrayList<StaticConfiguration<String, String>>();
+ this.staticConfigMap.put(name, staticConfigList);
+ }
+ return this.staticConfigMap.get(name);
+ }
+
+ public void addStaticConfiguration(StaticConfigurationNames name, StaticConfiguration<String, String> staticConfig)
+ {
+ synchronized (this)
+ {
+ List<StaticConfiguration<String, String>> staticConfigList;
+ if (!this.staticConfigMap.containsKey(name))
+ {
+ staticConfigList = new ArrayList<StaticConfiguration<String, String>>();
+ this.staticConfigMap.put(name, staticConfigList);
+ }
+ this.staticConfigMap.get(name).add(staticConfig);
+ }
+ }
+
+ /*
+ * Global properties
+ */
+ public boolean addGlobalProperty(String name, Object value)
+ {
+ return addGlobalProperty(name, value, true);
+ }
+
+ public boolean addGlobalProperty(String name, Object value, boolean forceOverride)
+ {
+ if (this.globalProperties.containsKey(name))
+ {
+ if (!forceOverride)
+ {
+ return false;
+ }
+
+ if (this.logger.isInfoEnabled())
+ {
+ this.logger.info("override global property '" + name + "'");
+ }
+ }
+
+ if(JsfProjectStage.is(JsfProjectStage.Development) && this.logger.isInfoEnabled())
+ {
+ this.logger.info("global property [" + name + "] added");
+ }
+
+ this.globalProperties.put(name, value);
+ return true;
+ }
+
+ public Object getGlobalProperty(String name)
+ {
+ return this.globalProperties.get(name);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContextInternals.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContextInternals.java
new file mode 100644
index 0000000..d2cfd5c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContextInternals.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.core.storage.ViolationSeverityInterpreterStorage;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverityInterpreter;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.context.FacesContext;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class ExtValContextInternals
+{
+ boolean isComponentInitializationActivated()
+ {
+ return !"true".equalsIgnoreCase(WebXmlParameter.DEACTIVATE_COMPONENT_INITIALIZATION);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ InformationProviderBean initInformationProviderBean(Map applicationMap)
+ {
+ List<String> informationProviderBeanClassNames = new ArrayList<String>();
+
+ informationProviderBeanClassNames.add(WebXmlParameter.CUSTOM_INFORMATION_PROVIDER_BEAN);
+ informationProviderBeanClassNames.add(InformationProviderBean.CUSTOM_BEAN);
+
+ InformationProviderBean informationProviderBean;
+ for (String className : informationProviderBeanClassNames)
+ {
+ informationProviderBean = (InformationProviderBean) ClassUtils.tryToInstantiateClassForName(className);
+
+ if (informationProviderBean != null)
+ {
+ applicationMap.put(InformationProviderBean.BEAN_NAME, informationProviderBean);
+ return informationProviderBean;
+ }
+ }
+
+ tryToInitCustomConfiguredInformationProviderBeanClassName(applicationMap);
+
+ if (applicationMap.containsKey(InformationProviderBean.BEAN_NAME))
+ {
+ return (InformationProviderBean) applicationMap.get(InformationProviderBean.BEAN_NAME);
+ }
+ return new InformationProviderBean();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ void tryToInitCustomConfiguredInformationProviderBeanClassName(Map applicationMap)
+ {
+ InformationProviderBean bean = (InformationProviderBean) ExtValUtils.getELHelper()
+ .getBean(InformationProviderBean.CUSTOM_BEAN.replace(".", "_"));
+
+ if (bean != null)
+ {
+ applicationMap.put(InformationProviderBean.BEAN_NAME, bean);
+ }
+ }
+
+ InformationProviderBean getInformationProviderBean()
+ {
+ Map applicationMap = FacesContext.getCurrentInstance().getExternalContext().getApplicationMap();
+ InformationProviderBean bean = (InformationProviderBean) applicationMap.get(InformationProviderBean.BEAN_NAME);
+
+ if (bean == null)
+ {
+ return initInformationProviderBean(applicationMap);
+ }
+ return bean;
+ }
+
+ ViolationSeverityInterpreter getRequestScopedViolationSeverityInterpreter()
+ {
+ return ExtValUtils.getStorage(
+ ViolationSeverityInterpreterStorage.class, ViolationSeverityInterpreterStorage.class.getName())
+ .getViolationSeverityInterpreter();
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContextInvocationOrderAwareInternals.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContextInvocationOrderAwareInternals.java
new file mode 100644
index 0000000..e19366c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValContextInvocationOrderAwareInternals.java
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.core.initializer.component.ComponentInitializer;
+import org.apache.myfaces.extensions.validator.core.interceptor.MetaDataExtractionInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.PropertyValidationInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.ValidationExceptionInterceptor;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Collections;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class ExtValContextInvocationOrderAwareInternals
+{
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private List<MetaDataExtractionInterceptor> metaDataExtractionInterceptors = null;
+ private Map<Class, List<MetaDataExtractionInterceptor>> moduleSpecificMetaDataExtractionInterceptors = null;
+ private List<ValidationExceptionInterceptor> validationExceptionInterceptors = null;
+ private List<PropertyValidationInterceptor> propertyValidationInterceptors = null;
+ private Map<Class, List<PropertyValidationInterceptor>> moduleSpecificPropertyValidationInterceptors = null;
+ private List<ComponentInitializer> componentInitializers = null;
+
+ private ExtValContextInternals contextHelper;
+
+ ExtValContextInvocationOrderAwareInternals(ExtValContextInternals contextHelper)
+ {
+ this.contextHelper = contextHelper;
+ }
+
+ /*
+ * ComponentInitializers
+ */
+ void addComponentInitializer(ComponentInitializer componentInitializer)
+ {
+ this.componentInitializers.add(componentInitializer);
+ sortComponentInitializers();
+ }
+
+ List<ComponentInitializer> getComponentInitializers()
+ {
+ return this.contextHelper.isComponentInitializationActivated() ?
+ this.componentInitializers : new ArrayList<ComponentInitializer>();
+ }
+
+ /*
+ * ValidationExceptionInterceptors
+ */
+ void addValidationExceptionInterceptor(ValidationExceptionInterceptor validationExceptionInterceptor)
+ {
+ this.validationExceptionInterceptors.add(validationExceptionInterceptor);
+ sortValidationExceptionInterceptors();
+ }
+
+ List<ValidationExceptionInterceptor> getValidationExceptionInterceptors()
+ {
+ return this.validationExceptionInterceptors;
+ }
+
+ /*
+ * PropertyValidationInterceptors
+ */
+ void addPropertyValidationInterceptor(PropertyValidationInterceptor propertyValidationInterceptor)
+ {
+ if (propertyValidationInterceptor instanceof ValidationModuleAware)
+ {
+ addPropertyValidationInterceptorForModules(propertyValidationInterceptor);
+ sortModuleSpecificPropertyValidationInterceptors();
+ }
+ else
+ {
+ addPropertyValidationInterceptorForModule(null, propertyValidationInterceptor);
+ sortPropertyValidationInterceptors();
+ }
+ }
+
+ List<PropertyValidationInterceptor> getPropertyValidationInterceptors()
+ {
+ return this.propertyValidationInterceptors;
+ }
+
+ List<PropertyValidationInterceptor> getPropertyValidationInterceptorsFor(Class moduleKey)
+ {
+ List<PropertyValidationInterceptor> result = new ArrayList<PropertyValidationInterceptor>();
+
+ result.addAll(getPropertyValidationInterceptors());
+
+ if (moduleKey != null && this.moduleSpecificPropertyValidationInterceptors.containsKey(moduleKey))
+ {
+ result.addAll(this.moduleSpecificPropertyValidationInterceptors.get(moduleKey));
+ }
+ return sortPropertyValidationInterceptorList(result);
+ }
+
+ private void addPropertyValidationInterceptorForModules(PropertyValidationInterceptor propertyValidationInterceptor)
+ {
+ Class moduleKey;
+ for (String currentModuleKey : ((ValidationModuleAware) propertyValidationInterceptor).getModuleKeys())
+ {
+ moduleKey = ClassUtils.tryToLoadClassForName(currentModuleKey);
+
+ if (moduleKey == null)
+ {
+ continue;
+ }
+
+ addPropertyValidationInterceptorForModule(moduleKey, propertyValidationInterceptor);
+ }
+ }
+
+ private void addPropertyValidationInterceptorForModule(
+ Class moduleKey, PropertyValidationInterceptor propertyValidationInterceptor)
+ {
+ if (moduleKey == null)
+ {
+ this.propertyValidationInterceptors.add(propertyValidationInterceptor);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace(propertyValidationInterceptor.getClass().getName() + " added as global interceptor");
+ }
+ }
+ else
+ {
+ List<PropertyValidationInterceptor> propertyValidationInterceptorList;
+ if (this.moduleSpecificPropertyValidationInterceptors.containsKey(moduleKey))
+ {
+ propertyValidationInterceptorList = this.moduleSpecificPropertyValidationInterceptors.get(moduleKey);
+ }
+ else
+ {
+ propertyValidationInterceptorList = new ArrayList<PropertyValidationInterceptor>();
+ this.moduleSpecificPropertyValidationInterceptors.put(moduleKey, propertyValidationInterceptorList);
+ }
+ propertyValidationInterceptorList.add(propertyValidationInterceptor);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace(propertyValidationInterceptor.getClass().getName() + " added for " + moduleKey.getName());
+ }
+ }
+ }
+
+ /*
+ * MetaDataExtractionInterceptors
+ */
+ void addMetaDataExtractionInterceptor(MetaDataExtractionInterceptor metaDataExtractionInterceptor)
+ {
+ if(metaDataExtractionInterceptor instanceof ValidationModuleAware)
+ {
+ addMetaDataExtractionInterceptorForModules(metaDataExtractionInterceptor);
+ sortModuleSpecificMetaDataExtractionInterceptors();
+ }
+ else
+ {
+ addMetaDataExtractionInterceptorForModule(null, metaDataExtractionInterceptor);
+ sortMetaDataExtractionInterceptors();
+ }
+ }
+
+ private void addMetaDataExtractionInterceptorForModules(MetaDataExtractionInterceptor metaDataExtractionInterceptor)
+ {
+ Class moduleKey;
+ for (String currentModuleKey : ((ValidationModuleAware) metaDataExtractionInterceptor).getModuleKeys())
+ {
+ moduleKey = ClassUtils.tryToLoadClassForName(currentModuleKey);
+
+ if (moduleKey == null)
+ {
+ continue;
+ }
+
+ addMetaDataExtractionInterceptorForModule(moduleKey, metaDataExtractionInterceptor);
+ }
+ }
+
+ private void addMetaDataExtractionInterceptorForModule(
+ Class moduleKey, MetaDataExtractionInterceptor metaDataExtractionInterceptor)
+ {
+ if (moduleKey == null)
+ {
+ this.metaDataExtractionInterceptors.add(metaDataExtractionInterceptor);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace(metaDataExtractionInterceptor.getClass().getName() + " added as global interceptor");
+ }
+ }
+ else
+ {
+ List<MetaDataExtractionInterceptor> metaDataExtractionInterceptorList;
+ if (this.moduleSpecificMetaDataExtractionInterceptors.containsKey(moduleKey))
+ {
+ metaDataExtractionInterceptorList = this.moduleSpecificMetaDataExtractionInterceptors.get(moduleKey);
+ }
+ else
+ {
+ metaDataExtractionInterceptorList = new ArrayList<MetaDataExtractionInterceptor>();
+ this.moduleSpecificMetaDataExtractionInterceptors.put(moduleKey, metaDataExtractionInterceptorList);
+ }
+ metaDataExtractionInterceptorList.add(metaDataExtractionInterceptor);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace(metaDataExtractionInterceptor.getClass().getName() + " added for " + moduleKey.getName());
+ }
+ }
+ }
+
+ List<MetaDataExtractionInterceptor> getMetaDataExtractionInterceptors()
+ {
+ return this.metaDataExtractionInterceptors;
+ }
+
+ List<MetaDataExtractionInterceptor> getMetaDataExtractionInterceptorsWith(Map<String, Object> properties)
+ {
+ List<MetaDataExtractionInterceptor> result = new ArrayList<MetaDataExtractionInterceptor>();
+
+ result.addAll(getMetaDataExtractionInterceptors());
+
+ Class moduleKey = tryToResolveModuleKey(properties);
+ if(moduleKey != null && this.moduleSpecificMetaDataExtractionInterceptors.containsKey(moduleKey))
+ {
+ result.addAll(this.moduleSpecificMetaDataExtractionInterceptors.get(moduleKey));
+ }
+
+ return sortMetaDataExtractionInterceptorList(result);
+ }
+
+ private Class tryToResolveModuleKey(Map<String, Object> properties)
+ {
+ Class moduleKey = null;
+ if(properties != null && properties.containsKey(ValidationModuleKey.class.getName()))
+ {
+ Object foundValue = properties.get(ValidationModuleKey.class.getName());
+ if(foundValue instanceof Class)
+ {
+ moduleKey = (Class)foundValue;
+ }
+ }
+ return moduleKey;
+ }
+
+ /*
+ * init
+ */
+
+ void lazyInitValidationExceptionInterceptors()
+ {
+ if (validationExceptionInterceptors != null)
+ {
+ return;
+ }
+
+ validationExceptionInterceptors = new ArrayList<ValidationExceptionInterceptor>();
+ List<String> validationExceptionInterceptorClassNames = new ArrayList<String>();
+
+ validationExceptionInterceptorClassNames
+ .add(WebXmlParameter.CUSTOM_VALIDATION_EXCEPTION_INTERCEPTOR);
+ validationExceptionInterceptorClassNames
+ .add(this.contextHelper.getInformationProviderBean().get(
+ CustomInformation.VALIDATION_EXCEPTION_INTERCEPTOR));
+
+ ValidationExceptionInterceptor validationExceptionInterceptor;
+ for (String validationExceptionInterceptorName : validationExceptionInterceptorClassNames)
+ {
+ validationExceptionInterceptor =
+ (ValidationExceptionInterceptor)
+ ClassUtils.tryToInstantiateClassForName(validationExceptionInterceptorName);
+
+ if (validationExceptionInterceptor != null)
+ {
+ validationExceptionInterceptors.add(validationExceptionInterceptor);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace(validationExceptionInterceptor.getClass().getName() + " added");
+ }
+ }
+ }
+ }
+
+ void lazyInitMetaDataExtractionInterceptors()
+ {
+ if (metaDataExtractionInterceptors != null)
+ {
+ return;
+ }
+
+ metaDataExtractionInterceptors = new ArrayList<MetaDataExtractionInterceptor>();
+ moduleSpecificMetaDataExtractionInterceptors = new HashMap<Class, List<MetaDataExtractionInterceptor>>();
+
+ List<String> metaDataExtractionInterceptorClassNames = new ArrayList<String>();
+
+ metaDataExtractionInterceptorClassNames
+ .add(WebXmlParameter.CUSTOM_META_DATA_EXTRACTION_INTERCEPTOR);
+ metaDataExtractionInterceptorClassNames
+ .add(this.contextHelper.getInformationProviderBean().get(
+ CustomInformation.META_DATA_EXTRACTION_INTERCEPTOR));
+
+ MetaDataExtractionInterceptor metaDataExtractionInterceptor;
+ for (String validationExceptionInterceptorName : metaDataExtractionInterceptorClassNames)
+ {
+ metaDataExtractionInterceptor =
+ (MetaDataExtractionInterceptor)
+ ClassUtils.tryToInstantiateClassForName(validationExceptionInterceptorName);
+
+ if (metaDataExtractionInterceptor != null)
+ {
+ addMetaDataExtractionInterceptor(metaDataExtractionInterceptor);
+ }
+ }
+ }
+
+ void lazyInitComponentInitializers()
+ {
+ if (componentInitializers != null)
+ {
+ return;
+ }
+
+ componentInitializers = new ArrayList<ComponentInitializer>();
+ List<String> componentInitializerClassNames = new ArrayList<String>();
+ componentInitializerClassNames
+ .add(WebXmlParameter.CUSTOM_COMPONENT_INITIALIZER);
+ componentInitializerClassNames
+ .add(this.contextHelper.getInformationProviderBean().get(CustomInformation.COMPONENT_INITIALIZER));
+
+ ComponentInitializer componentInitializer;
+ for (String componentInitializerName : componentInitializerClassNames)
+ {
+ componentInitializer =
+ (ComponentInitializer) ClassUtils.tryToInstantiateClassForName(componentInitializerName);
+
+ if (componentInitializer != null)
+ {
+ componentInitializers.add(componentInitializer);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace(componentInitializer.getClass().getName() + " added");
+ }
+ }
+ }
+ }
+
+ void lazyInitPropertyValidationInterceptors()
+ {
+ if (propertyValidationInterceptors != null)
+ {
+ return;
+ }
+
+ propertyValidationInterceptors = new ArrayList<PropertyValidationInterceptor>();
+ moduleSpecificPropertyValidationInterceptors = new HashMap<Class, List<PropertyValidationInterceptor>>();
+
+ List<String> validationInterceptorClassNames = new ArrayList<String>();
+
+ validationInterceptorClassNames
+ .add(WebXmlParameter.CUSTOM_PROPERTY_VALIDATION_INTERCEPTOR);
+ validationInterceptorClassNames
+ .add(this.contextHelper.getInformationProviderBean().get(
+ CustomInformation.PROPERTY_VALIDATION_INTERCEPTOR));
+
+ PropertyValidationInterceptor propertyValidationInterceptor;
+ for (String validationInterceptorName : validationInterceptorClassNames)
+ {
+ propertyValidationInterceptor =
+ (PropertyValidationInterceptor)
+ ClassUtils.tryToInstantiateClassForName(validationInterceptorName);
+
+ if (propertyValidationInterceptor != null)
+ {
+ if (propertyValidationInterceptor instanceof ValidationModuleAware)
+ {
+ addPropertyValidationInterceptorForModules(propertyValidationInterceptor);
+ }
+ else
+ {
+ addPropertyValidationInterceptorForModule(null, propertyValidationInterceptor);
+ }
+ }
+ }
+ }
+
+ /*
+ * sort
+ */
+ private void sortComponentInitializers()
+ {
+ Collections.sort(this.componentInitializers, new InvocationOrderComparator<ComponentInitializer>());
+ }
+
+ private void sortPropertyValidationInterceptors()
+ {
+ Collections.sort(this.propertyValidationInterceptors,
+ new InvocationOrderComparator<PropertyValidationInterceptor>());
+ }
+
+ //sort all - it isn't a huge overhead since it's just done during the init-phase
+ private void sortModuleSpecificPropertyValidationInterceptors()
+ {
+ for(List<PropertyValidationInterceptor> propertyValidationInterceptorList :
+ this.moduleSpecificPropertyValidationInterceptors.values())
+ {
+ sortPropertyValidationInterceptorList(propertyValidationInterceptorList);
+ }
+ }
+
+ private List<PropertyValidationInterceptor> sortPropertyValidationInterceptorList(
+ List<PropertyValidationInterceptor> propertyValidationInterceptorList)
+ {
+ Collections.sort(propertyValidationInterceptorList,
+ new InvocationOrderComparator<PropertyValidationInterceptor>());
+
+ return propertyValidationInterceptorList;
+ }
+
+ private void sortValidationExceptionInterceptors()
+ {
+ Collections.sort(this.validationExceptionInterceptors,
+ new InvocationOrderComparator<ValidationExceptionInterceptor>());
+ }
+
+ private void sortMetaDataExtractionInterceptors()
+ {
+ Collections.sort(this.metaDataExtractionInterceptors,
+ new InvocationOrderComparator<MetaDataExtractionInterceptor>());
+ }
+
+ //sort all - it isn't a huge overhead since it's just done during the init-phase
+ private void sortModuleSpecificMetaDataExtractionInterceptors()
+ {
+ for(List<MetaDataExtractionInterceptor> metaDataExtractionInterceptorList :
+ this.moduleSpecificMetaDataExtractionInterceptors.values())
+ {
+ sortMetaDataExtractionInterceptorList(metaDataExtractionInterceptorList);
+ }
+ }
+
+ private List<MetaDataExtractionInterceptor> sortMetaDataExtractionInterceptorList(
+ List<MetaDataExtractionInterceptor> metaDataExtractionInterceptorList)
+ {
+ Collections.sort(metaDataExtractionInterceptorList,
+ new InvocationOrderComparator<MetaDataExtractionInterceptor>());
+
+ return metaDataExtractionInterceptorList;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InformationProviderBean.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InformationProviderBean.java
new file mode 100644
index 0000000..65587a5
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InformationProviderBean.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.ExtValInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * centralized in order that these information aren't spread over the complete code base
+ * + some of them can be customized within a custom impl. of the bean
+ * (extend this class and provide it via convention or web.xml)
+ * <p/>
+ * the static api should only be used
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.API, UsageCategory.CUSTOMIZABLE})
+public class InformationProviderBean
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public static final String BEAN_NAME = ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME
+ + "." + InformationProviderBean.class.getSimpleName();
+ //custom class which is an optional replacement for this class (has to extend this class)
+ public static final String CUSTOM_BEAN = (ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME
+ + ".custom." + InformationProviderBean.class.getSimpleName());
+
+ public InformationProviderBean()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+
+ setupCustomizableInformation();
+ applyCustomValues(this.customizableInfos);
+ }
+
+ private Map<CustomInformation, String> customizableInfos = new HashMap<CustomInformation, String>();
+
+ private void setupCustomizableInformation()
+ {
+ String basePackage = WebXmlParameter.CUSTOM_BASE_PACKAGE;
+
+ if (basePackage == null)
+ {
+ basePackage = ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME + ".custom.";
+ }
+ if (!basePackage.endsWith("."))
+ {
+ basePackage = basePackage + ".";
+ }
+
+ customizableInfos.put(CustomInformation.BASE_PACKAGE, basePackage);
+
+ customizableInfos.put(CustomInformation.COMPONENT_META_DATA_EXTRACTOR,
+ "ComponentMetaDataExtractor");
+ customizableInfos.put(CustomInformation.VALIDATION_PARAMETER_EXTRACTOR,
+ "ValidationParameterExtractor");
+
+ customizableInfos.put(CustomInformation.VALIDATION_STRATEGY_POSTFIX,
+ "ValidationStrategy");
+ customizableInfos.put(CustomInformation.META_DATA_TRANSFORMER_POSTFIX,
+ "MetaDataTransformer");
+ customizableInfos.put(CustomInformation.VALIDATION_ERROR_MESSAGE_RESOLVER_POSTFIX,
+ "ValidationErrorMessageResolver");
+
+ customizableInfos.put(CustomInformation.COMPONENT_INITIALIZER,
+ "ComponentInitializer");
+ customizableInfos.put(CustomInformation.VALIDATION_EXCEPTION_INTERCEPTOR,
+ "ValidationExceptionInterceptor");
+ customizableInfos.put(CustomInformation.PROPERTY_VALIDATION_INTERCEPTOR,
+ "PropertyValidationInterceptor");
+ customizableInfos.put(CustomInformation.META_DATA_EXTRACTION_INTERCEPTOR,
+ "MetaDataExtractionInterceptor");
+
+ customizableInfos.put(CustomInformation.VALIDATION_STRATEGY_TO_MSG_RESOLVER_NAME_MAPPER,
+ "ValidationStrategyToMsgResolverNameMapper");
+ customizableInfos.put(CustomInformation.META_DATA_TO_VALIDATION_STRATEGY_NAME_MAPPER,
+ "MetaDataToValidationStrategyNameMapper");
+ customizableInfos.put(CustomInformation.VALIDATION_STRATEGY_TO_META_DATA_TRANSFORMER_NAME_MAPPER,
+ "ValidationStrategyToMetaDataTransformerNameMapper");
+
+ customizableInfos.put(CustomInformation.STARTUP_LISTENER,
+ "StartupListener");
+
+ customizableInfos.put(CustomInformation.MESSAGE_RESOLVER_FACTORY,
+ "MessageResolverFactory");
+ customizableInfos.put(CustomInformation.VALIDATION_STRATEGY_FACTORY,
+ "ValidationStrategyFactory");
+ customizableInfos.put(CustomInformation.COMPONENT_META_DATA_EXTRACTOR_FACTORY,
+ "ComponentMetaDataExtractorFactory");
+ customizableInfos.put(CustomInformation.VALIDATION_PARAMETER_EXTRACTOR_FACTORY,
+ "ValidationParameterExtractorFactory");
+ customizableInfos.put(CustomInformation.VALIDATION_PARAMETER_FACTORY,
+ "ValidationParameterFactory");
+ customizableInfos.put(CustomInformation.META_DATA_TRANSFORMER_FACTORY,
+ "MetaDataTransformerFactory");
+ customizableInfos.put(CustomInformation.FACES_MESSAGE_FACTORY,
+ "FacesMessageFactory");
+ customizableInfos.put(CustomInformation.STORAGE_MANAGER_FACTORY,
+ "StorageManagerFactory");
+
+ //conventions (the rest of the conventions are built with the help of name mappers,...
+ customizableInfos.put(CustomInformation.MESSAGE_BUNDLE_NAME,
+ "validation_messages");
+ //static strategy mappings (name of property files)
+ customizableInfos.put(CustomInformation.STATIC_STRATEGY_MAPPING_SOURCE,
+ "strategy_mappings");
+
+ customizableInfos.put(CustomInformation.META_DATA_STORAGE_FILTER,
+ "MetaDataStorageFilter");
+ }
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ protected void applyCustomValues(Map<CustomInformation, String> map)
+ {
+ //override to customize information
+ }
+
+ public final String get(CustomInformation customInformation)
+ {
+ String value = customizableInfos.get(customInformation);
+
+ switch (customInformation)
+ {
+ case BASE_PACKAGE:
+ return value;
+
+ /*
+ * postfix used by the SimpleAnnotationToValidationStrategyNameMapper
+ * the SimpleAnnotationToValidationStrategyNameMapper is for custom strategies only
+ * (not for public validation modules)
+ * so it's fine to customize it
+ */
+ case VALIDATION_STRATEGY_POSTFIX:
+ return value;
+
+ case VALIDATION_ERROR_MESSAGE_RESOLVER_POSTFIX:
+ return value;
+
+ case META_DATA_TRANSFORMER_POSTFIX:
+ return value;
+
+ default:
+ return customizableInfos.get(CustomInformation.BASE_PACKAGE) + value;
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InternalConventionProvider.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InternalConventionProvider.java
new file mode 100644
index 0000000..8d9f869
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InternalConventionProvider.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class InternalConventionProvider
+{
+ public static String getModuleMessageBundleName(String packageName)
+ {
+ String newPackageName;
+ if (packageName.endsWith(".resolver"))
+ {
+ newPackageName = packageName.replace(".resolver", ".bundle");
+ }
+ else
+ {
+ newPackageName = packageName.replace(".resolver.", ".bundle.");
+ }
+
+ return newPackageName + ".validation_messages";
+ }
+
+ /**
+ * use a custom name mapper to implement custom conventions
+ */
+ @ToDo(value = Priority.MEDIUM, description = "logging")
+ public static String getMessageResolverClassName(
+ Class<? extends ValidationStrategy> validationStrategyClass, String targetClassName)
+ {
+ return getValidationStrategyBasedName(validationStrategyClass, ".message.resolver.", targetClassName);
+ }
+
+ public static String getMetaDataTransformerClassName(
+ Class<? extends ValidationStrategy> validationStrategyClass, String targetClassName)
+ {
+ return getValidationStrategyBasedName(validationStrategyClass, ".metadata.transformer.", targetClassName);
+ }
+
+ private static String getValidationStrategyBasedName(Class<? extends ValidationStrategy> validationStrategyClass,
+ String targetPackageName, String targetClassName)
+ {
+ String validationStrategyClassName = validationStrategyClass.getName();
+
+ validationStrategyClassName = validationStrategyClassName.replace(".strategy.", targetPackageName);
+
+ if (targetClassName == null || validationStrategyClassName.lastIndexOf(".") == -1)
+ {
+ return null;
+ }
+ return validationStrategyClassName
+ .substring(0, validationStrategyClassName.lastIndexOf(".")) + "." + targetClassName;
+ }
+
+ /**
+ * use a custom name mapper to implement custom conventions
+ */
+ public static String getMessageResolverClassName(String validationStrategyName)
+ {
+ return getValidationStrategyBasedName(validationStrategyName, "ValidationErrorMessageResolver");
+ }
+
+ /**
+ * use a custom name mapper to implement custom conventions
+ */
+ public static String getValidationStrategyClassName(String metaDataKey)
+ {
+ return metaDataKey.replace(".annotation.", ".strategy.") + "Strategy";
+ }
+
+ public static String getMetaDataTransformerClassName(String validationStrategyName)
+ {
+ return getValidationStrategyBasedName(validationStrategyName, "MetaDataTransformer");
+ }
+
+ public static String getValidationStrategyBasedName(String validationStrategyName, String targetPostfix)
+ {
+ if (validationStrategyName.endsWith("ValidationStrategy"))
+ {
+ return validationStrategyName.substring(0, validationStrategyName.length() - 18) + targetPostfix;
+ }
+ else if (validationStrategyName.endsWith("Strategy"))
+ {
+ return validationStrategyName.substring(0, validationStrategyName.length() - 8) + targetPostfix;
+ }
+ return validationStrategyName + targetPostfix;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrder.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrder.java
new file mode 100644
index 0000000..cdffad8
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrder.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+/**
+ * allowed to use for classes which implement interfaces which have the marker @InvocationOrderSupport
+ *
+ * suggested ranges (mainly for name-mappers):
+ * negative values for "extreme" cases
+ *
+ * 0-49 for custom artifacts which should have the highest priority
+ * 50-99 for add-ons which provide artifacts which should have a higher priority than the default artifacts
+ * 100-999 internal artifacts
+ * 1000+ for custom artifacts
+ *
+ * suggested ranges for artifacts like interceptors,...
+ * 1xx ... artifacts of the core
+ * 2xx ... artifacts of validation modules
+ * 3xx ... artifacts of component support modules
+ *
+ * a priority should be unique within one artifact-type - that means
+ * if a name-mapper has priority 100, it's ok that an exception-interceptor also has priority 100.
+ * but a 2nd name-mapper shouldn't have priority 100
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public @interface InvocationOrder
+{
+ /**
+ * default priority for custom artifacts (if they should get added after the internal versions
+ * @return the priority of an artifact annotated with this annotation
+ */
+ int value() default 1000;
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrderComparator.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrderComparator.java
new file mode 100644
index 0000000..818071e
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrderComparator.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.Comparator;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class InvocationOrderComparator<T> implements Comparator<T>
+{
+ public int compare(T nm1, T nm2)
+ {
+ if (hasPriority(nm1) && hasPriority(nm2))
+ {
+ return isPriorityHigher(nm1.getClass().getAnnotation(InvocationOrder.class),
+ nm2.getClass().getAnnotation(InvocationOrder.class));
+ }
+ if (!hasPriority(nm1) && !hasPriority(nm2))
+ {
+ return 0;
+ }
+ return hasPriority(nm1) ? -1 : 1;
+ }
+
+ private int isPriorityHigher(InvocationOrder priority1, InvocationOrder priority2)
+ {
+ if (priority1.value() == priority2.value())
+ {
+ return 0;
+ }
+
+ return priority1.value() < priority2.value() ? -1 : 1;
+ }
+
+ private boolean hasPriority(Object nm)
+ {
+ return nm.getClass().isAnnotationPresent(InvocationOrder.class);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrderSupport.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrderSupport.java
new file mode 100644
index 0000000..bd34e79
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/InvocationOrderSupport.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.TYPE;
+
+@Target(TYPE)
+@Documented
+/**
+ * marker annotation for easier usage
+ * it marks interfaces - instances of classes implementing these interfaces will be sorted
+ * @see InvocationOrderComparator
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public @interface InvocationOrderSupport
+{
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/JsfProjectStage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/JsfProjectStage.java
new file mode 100644
index 0000000..d2b30ba
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/JsfProjectStage.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * project stage equivalent to jsf 2.0
+ * extval 2.x has a special resolver which redirects the call to the new jsf api
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public enum JsfProjectStage
+{
+ Development(ProjectStage.createStageName("Development")),
+ UnitTest(ProjectStage.createStageName("UnitTest")),
+ SystemTest(ProjectStage.createStageName("SystemTest")),
+ Production(ProjectStage.createStageName("Production"));
+
+ private final ProjectStageName value;
+
+ JsfProjectStage(ProjectStageName value)
+ {
+ this.value = value;
+ }
+
+ public static boolean is(JsfProjectStage jsfProjectStage)
+ {
+ return ProjectStage.is(jsfProjectStage.getValue());
+ }
+
+ public ProjectStageName getValue()
+ {
+ return this.value;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/Nested.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/Nested.java
new file mode 100644
index 0000000..00691e8
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/Nested.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+
+/**
+ * marker annotation e.g. to mark sub-name-mappers
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface Nested
+{
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/PhaseIdRecordingPhaseListener.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/PhaseIdRecordingPhaseListener.java
new file mode 100644
index 0000000..0695542
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/PhaseIdRecordingPhaseListener.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.core.storage.FacesInformationStorage;
+
+import javax.faces.event.PhaseListener;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+
+/**
+ * e.g. to allow in metadata extraction interceptors to know if they are invoked during validation or
+ * component initialization (if needed)
+ * example: client-side validation - some functionality shouldn't be processed during rendering
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class PhaseIdRecordingPhaseListener implements PhaseListener
+{
+ private static final long serialVersionUID = 2791240514014867457L;
+
+ public void afterPhase(PhaseEvent phaseEvent)
+ {
+ }
+
+ public void beforePhase(PhaseEvent phaseEvent)
+ {
+ FacesInformationStorage facesInformationStorage = ExtValUtils
+ .getStorage(FacesInformationStorage.class, FacesInformationStorage.class.getName());
+
+ facesInformationStorage.setCurrentPhaseId(phaseEvent.getPhaseId());
+ }
+
+ public PhaseId getPhaseId()
+ {
+ return PhaseId.ANY_PHASE;
+ }
+
+ /*
+ * generated
+ */
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (!(o instanceof PhaseIdRecordingPhaseListener))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStage.java
new file mode 100644
index 0000000..9ba444d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStage.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+/**
+ * extensible project stage implementation
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ProjectStage
+{
+ private ProjectStageName value;
+
+ private ProjectStage(ProjectStageName value)
+ {
+ this.value = value;
+ }
+
+ public static ProjectStageName createStageName(String name)
+ {
+ return ExtValUtils.createProjectStageName(name);
+ }
+
+ public static ProjectStage createStage(ProjectStageName name)
+ {
+ return new ProjectStage(name);
+ }
+
+ public static boolean is(ProjectStageName projectStage)
+ {
+ return getCurrentProjectStage().equals(projectStage);
+ }
+
+ private static ProjectStageName getCurrentProjectStage()
+ {
+ //set ProjectStageResolver to null to tweak the performance
+ Object projectStageResolver = ExtValContext.getContext()
+ .getGlobalProperty(ProjectStageResolver.class.getName());
+
+ if(projectStageResolver instanceof ProjectStageResolver)
+ {
+ return ((ProjectStageResolver)projectStageResolver).getCurrentProjectStage().getValue();
+ }
+ return ExtValUtils.getDefaultStageName();
+ }
+
+ public ProjectStageName getValue()
+ {
+ return this.value;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStageName.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStageName.java
new file mode 100644
index 0000000..1d22b86
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStageName.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface ProjectStageName
+{
+ String getName();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStageResolver.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStageResolver.java
new file mode 100644
index 0000000..144f27a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProjectStageResolver.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface ProjectStageResolver
+{
+ ProjectStage getCurrentProjectStage();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ValidationModuleAware.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ValidationModuleAware.java
new file mode 100644
index 0000000..45420f5
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ValidationModuleAware.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * if an artifact (which supports this concept) should be used just for a/some specific module(s),
+ * the artifact has to implement this interface
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ValidationModuleAware
+{
+ /**
+ * during the registration process the information gets evaluated<br/>
+ * instead of a class array a string array is used so that it's possible to implement
+ * an artifact for different modules. if an add-on restricts an artifact to specific modules,
+ * not all modules have to be used by the webapp. if a module key is unknown, the artifact won't get registered
+ * for this module. if an artifact doesn't implement this interface, it gets registered for all modules
+ *
+ * @return an array of fully qualified class names of the module keys
+ */
+ String[] getModuleKeys();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ValidationModuleKey.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ValidationModuleKey.java
new file mode 100644
index 0000000..805340d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/ValidationModuleKey.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+/**
+ * marker annotation for module keys
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public @interface ValidationModuleKey
+{
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/WebXmlParameter.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/WebXmlParameter.java
new file mode 100644
index 0000000..f18a179
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/WebXmlParameter.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.WebXmlUtils;
+
+/**
+ * centralized in order that these information aren't spread over the complete code base
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface WebXmlParameter
+{
+ /*
+ * misc
+ */
+ static final String CUSTOM_MESSAGE_BUNDLE = WebXmlUtils
+ .getInitParameter("CUSTOM_MESSAGE_BUNDLE");
+
+ static final String CUSTOM_BASE_PACKAGE = WebXmlUtils
+ .getInitParameter("CUSTOM_BASE_PACKAGE");
+
+ static final String CUSTOM_INFORMATION_PROVIDER_BEAN = WebXmlUtils
+ .getInitParameter("CUSTOM_INFORMATION_PROVIDER_BEAN");
+
+ static final String CUSTOM_COMPONENT_META_DATA_EXTRACTOR = WebXmlUtils
+ .getInitParameter("CUSTOM_COMPONENT_META_DATA_EXTRACTOR");
+
+ static final String CUSTOM_VALIDATION_PARAMETER_EXTRACTOR = WebXmlUtils
+ .getInitParameter("CUSTOM_VALIDATION_PARAMETER_EXTRACTOR");
+
+ static final String CUSTOM_VALIDATION_PARAMETER_FACTORY = WebXmlUtils
+ .getInitParameter("CUSTOM_VALIDATION_PARAMETER_FACTORY");
+
+ static final String CUSTOM_STATIC_VALIDATION_STRATEGY_MAPPING = WebXmlUtils
+ .getInitParameter("CUSTOM_STATIC_VALIDATION_STRATEGY_MAPPING");
+
+ static final String CUSTOM_COMPONENT_INITIALIZER = WebXmlUtils
+ .getInitParameter("CUSTOM_COMPONENT_INITIALIZER");
+
+ static final String CUSTOM_VALIDATION_EXCEPTION_INTERCEPTOR = WebXmlUtils
+ .getInitParameter("CUSTOM_VALIDATION_EXCEPTION_INTERCEPTOR");
+
+ static final String CUSTOM_PROPERTY_VALIDATION_INTERCEPTOR = WebXmlUtils
+ .getInitParameter("CUSTOM_PROPERTY_VALIDATION_INTERCEPTOR");
+
+ static final String CUSTOM_META_DATA_EXTRACTION_INTERCEPTOR = WebXmlUtils
+ .getInitParameter("CUSTOM_META_DATA_EXTRACTION_INTERCEPTOR");
+
+ static final String CUSTOM_PROXY_HELPER = WebXmlUtils
+ .getInitParameter("CUSTOM_PROXY_HELPER");
+
+ /*
+ * name mapper
+ */
+ static final String CUSTOM_VALIDATION_STRATEGY_TO_MESSAGE_RESOLVER_NAME_MAPPER = WebXmlUtils
+ .getInitParameter("CUSTOM_VALIDATION_STRATEGY_TO_MESSAGE_RESOLVER_NAME_MAPPER");
+
+ static final String CUSTOM_META_DATA_TO_VALIDATION_STRATEGY_NAME_MAPPER = WebXmlUtils
+ .getInitParameter("CUSTOM_META_DATA_TO_VALIDATION_STRATEGY_NAME_MAPPER");
+
+ static final String CUSTOM_VALIDATION_STRATEGY_TO_META_DATA_TRANSFORMER_NAME_MAPPER = WebXmlUtils
+ .getInitParameter("CUSTOM_VALIDATION_STRATEGY_TO_META_DATA_TRANSFORMER_NAME_MAPPER");
+
+ /*
+ * filter
+ */
+ static final String CUSTOM_META_DATA_STORAGE_FILTER = WebXmlUtils
+ .getInitParameter("CUSTOM_META_DATA_STORAGE_FILTER");
+
+ /*
+ * factories
+ */
+ static final String CUSTOM_VALIDATION_STRATEGY_FACTORY = WebXmlUtils
+ .getInitParameter("CUSTOM_VALIDATION_STRATEGY_FACTORY");
+
+ static final String CUSTOM_MESSAGE_RESOLVER_FACTORY = WebXmlUtils
+ .getInitParameter("CUSTOM_MESSAGE_RESOLVER_FACTORY");
+
+ static final String CUSTOM_COMPONENT_META_DATA_EXTRACTOR_FACTORY = WebXmlUtils
+ .getInitParameter("CUSTOM_COMPONENT_META_DATA_EXTRACTOR_FACTORY");
+
+ static final String CUSTOM_VALIDATION_PARAMETER_EXTRACTOR_FACTORY = WebXmlUtils
+ .getInitParameter("CUSTOM_VALIDATION_PARAMETER_EXTRACTOR_FACTORY");
+
+ static final String CUSTOM_META_DATA_TRANSFORMER_FACTORY = WebXmlUtils
+ .getInitParameter("CUSTOM_META_DATA_TRANSFORMER_FACTORY");
+
+ static final String CUSTOM_STORAGE_MANAGER_FACTORY = WebXmlUtils
+ .getInitParameter("CUSTOM_STORAGE_MANAGER_FACTORY");
+
+ static final String CUSTOM_FACES_MESSAGE_FACTORY = WebXmlUtils
+ .getInitParameter("CUSTOM_FACES_MESSAGE_FACTORY");
+
+ /*
+ * activate
+ */
+ static final String ACTIVATE_REQUIRED_INITIALIZATION = WebXmlUtils
+ .getInitParameter("ACTIVATE_REQUIRED_INITIALIZATION");
+
+ /*
+ * deactivate
+ */
+ @Deprecated
+ static final String DEACTIVATE_RENDERKIT = WebXmlUtils
+ .getInitParameter("DEACTIVATE_RENDERKIT");
+
+ //currently just used by AbstractValidationErrorMessageResolver
+ static final String DEACTIVATE_DEFAULT_CONVENTION = WebXmlUtils
+ .getInitParameter("DEACTIVATE_DEFAULT_CONVENTION");
+
+ static final String DEACTIVATE_DEFAULT_NAME_MAPPERS = WebXmlUtils
+ .getInitParameter("DEACTIVATE_DEFAULT_NAME_MAPPERS");
+
+ static final String DEACTIVATE_EL_RESOLVER = WebXmlUtils
+ .getInitParameter("DEACTIVATE_EL_RESOLVER");
+
+ static final String DEACTIVATE_COMPONENT_INITIALIZATION = WebXmlUtils
+ .getInitParameter("DEACTIVATE_COMPONENT_INITIALIZATION");
+
+ static final String DEACTIVATE_VALIDATION_PARAMETERS = WebXmlUtils
+ .getInitParameter("DEACTIVATE_VALIDATION_PARAMETERS");
+
+ static final String DEACTIVATE_RENDER_KIT_FACTORY = WebXmlUtils
+ .getInitParameter("DEACTIVATE_RENDER_KIT_FACTORY");
+
+ //there is nothing like DEACTIVATE_DEFAULT_VALIDATION_INTERCEPTOR
+ //use ExtValContext.getContext().denyRendererInterceptor(...) within an extval-StartupListener
+
+ /*
+ * spec parameters
+ */
+ static final String INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL = WebXmlUtils
+ .getInitParameter("javax.faces", "INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL");
+
+ static final String VALIDATE_EMPTY_FIELDS = WebXmlUtils
+ .getInitParameter("javax.faces", "VALIDATE_EMPTY_FIELDS");
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/AbstractELHelperFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/AbstractELHelperFactory.java
new file mode 100644
index 0000000..4a43f25
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/AbstractELHelperFactory.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.el;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * details
+ * @see DefaultELHelper
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public abstract class AbstractELHelperFactory
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+ protected AbstractELHelperFactory customELHelperFactory;
+
+ protected AbstractELHelperFactory()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public void setCustomELHelperFactory(AbstractELHelperFactory elHelperFactory)
+ {
+ this.customELHelperFactory = elHelperFactory;
+ }
+
+ public final ELHelper create()
+ {
+ ELHelper result = null;
+
+ if(this.customELHelperFactory != null)
+ {
+ result = this.customELHelperFactory.createELHelper();
+ }
+
+ if(result == null)
+ {
+ return createELHelper();
+ }
+
+ return result;
+ }
+
+ protected abstract ELHelper createELHelper();
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelper.java
new file mode 100644
index 0000000..43109f0
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelper.java
@@ -0,0 +1,344 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.el;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.el.ValueExpression;
+import javax.el.ELContext;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
+import java.io.Externalizable;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+/**
+ * in order to centralize the jsf version dependency within the core
+ *
+ * this el-helper supports jsp and facelets (tested with 1.1.14)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+/*
+ * there is a special facelets workaround for el-expressions of custom components
+ * it's pluggable in order to support special mechanisms of different technologies (than jsp and facelets)
+ * so you can plug in your own impl. which implements a custom workaround (like the facelets workaround of this impl.)
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultELHelper implements ELHelper
+{
+ private static final String DEACTIVATE_EL_RESOLVER = WebXmlParameter.DEACTIVATE_EL_RESOLVER;
+
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public DefaultELHelper()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public Class getTypeOfExpression(FacesContext facesContext, ValueBindingExpression valueBindingExpression)
+ {
+ //due to a restriction with the ri
+ Object bean = getValueOfExpression(facesContext, valueBindingExpression);
+ return (bean != null) ? ProxyUtils.getUnproxiedClass(bean.getClass()) : null;
+ }
+
+ public Object getBean(String beanName)
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ return facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, beanName);
+ }
+
+ public Object getValueOfExpression(FacesContext facesContext,
+ ValueBindingExpression valueBindingExpression)
+ {
+ return (valueBindingExpression != null) ? facesContext.getApplication().evaluateExpressionGet(
+ facesContext, valueBindingExpression.getExpressionString(), Object.class) : null;
+ }
+
+ public boolean isELTermValid(FacesContext facesContext, String valueBindingExpression)
+ {
+ try
+ {
+ facesContext.getApplication().evaluateExpressionGet(facesContext, valueBindingExpression, Object.class);
+ }
+ catch (Throwable t)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private ValueBindingExpression getValueBindingExpression(UIComponent uiComponent, boolean allowBlankCharacters)
+ {
+ String valueBindingExpression = getOriginalValueBindingExpression(uiComponent);
+
+ //for input components without value-binding
+ //(e.g. for special component libs -> issue with ExtValRendererWrapper#encodeBegin)
+ if(valueBindingExpression == null)
+ {
+ if(this.logger.isTraceEnabled())
+ {
+ this.logger.trace(
+ uiComponent.getClass() + " has no value binding - component id: " + uiComponent.getId());
+ }
+ return null;
+ }
+
+ if(!allowBlankCharacters)
+ {
+ valueBindingExpression = valueBindingExpression.replace(" ", "");
+ }
+
+ if (getTypeOfExpression(FacesContext.getCurrentInstance(),
+ new ValueBindingExpression(valueBindingExpression).getBaseExpression()) == null)
+ {
+ ValueBindingExpression result = FaceletsTaglibExpressionHelper.
+ tryToCreateValueBindingForFaceletsBinding(uiComponent);
+
+ if(result == null)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("couldn't resolve expression: " + valueBindingExpression);
+ }
+ return null;
+ }
+
+ Class entityClass = ExtValUtils.getELHelper()
+ .getTypeOfExpression(FacesContext.getCurrentInstance(), result.getBaseExpression());
+
+ if(entityClass == null)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("couldn't resolve expression: " + result.getExpressionString());
+ }
+
+ return null;
+ }
+ return result;
+ }
+ return new ValueBindingExpression(valueBindingExpression);
+ }
+
+ @ToDo(value = Priority.HIGH, description = "check if it works with nested composite components")
+ public PropertyDetails getPropertyDetailsOfValueBinding(UIComponent uiComponent)
+ {
+ if("true".equalsIgnoreCase(DEACTIVATE_EL_RESOLVER))
+ {
+ return getPropertyDetailsViaReflectionFallback(uiComponent);
+ }
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ ValueExpression valueExpression = uiComponent.getValueExpression("value");
+
+ if(valueExpression == null)
+ {
+ return null;
+ }
+
+ ExtValELResolver elResolver = createWrappedELContext(facesContext);
+ inspectTarget(valueExpression,
+ ExtValELResolver.createContextWrapper(facesContext.getELContext(), elResolver), false);
+
+ ExtValELResolver compositeComponentELResolver = null;
+
+ //re-check to get full key for cross-validation
+ if (elResolver.getCompositeComponentExpression() != null)
+ {
+ ValueExpression compositeExpression = elResolver.getCompositeComponentExpression();
+
+ compositeComponentELResolver = createWrappedELContext(facesContext);
+ inspectTarget(compositeExpression,
+ ExtValELResolver.createContextWrapper(
+ facesContext.getELContext(), compositeComponentELResolver), true);
+ }
+
+ if(elResolver.getPath() == null || elResolver.getBaseObject() == null || elResolver.getProperty() == null)
+ {
+ return null;
+ }
+
+ String key;
+ if(compositeComponentELResolver != null)
+ {
+ key = compositeComponentELResolver.getPath() +
+ elResolver.getPath().substring(elResolver.getPath().indexOf("."));
+ }
+ else
+ {
+ key = elResolver.getPath();
+ }
+
+ return new PropertyDetails(key, elResolver.getBaseObject(), elResolver.getProperty());
+ }
+
+ private void inspectTarget(ValueExpression valueExpression, ELContext elContext, boolean inspectCompositeComponent)
+ {
+ try
+ {
+ valueExpression.setValue(elContext, null);
+ }
+ catch (Throwable t)
+ {
+ if(inspectCompositeComponent)
+ {
+ throw new IllegalStateException(
+ "error at binding: " + valueExpression.getExpressionString() +
+ " -- an el-resolver error occurred! maybe you used an invalid binding.", t);
+ }
+ }
+ }
+
+ private ExtValELResolver createWrappedELContext(FacesContext facesContext)
+ {
+ return new ExtValELResolver(facesContext.getApplication().getELResolver());
+ }
+
+ //keep in sync with DefaultELHelper#getPropertyDetailsOfValueBinding of branch!!!
+ private PropertyDetails getPropertyDetailsViaReflectionFallback(UIComponent uiComponent)
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ ValueBindingExpression valueBindingExpression = getValueBindingExpression(uiComponent, false);
+ ValueBindingExpression currentValueBindingExpression =
+ new ValueBindingExpression(valueBindingExpression.getExpressionString());
+
+ String path = null;
+
+ while(currentValueBindingExpression.getBaseExpression() != null)
+ {
+ if(path == null)
+ {
+ path = getPropertyName(currentValueBindingExpression);
+ }
+ else
+ {
+ path = getPropertyName(currentValueBindingExpression) + "." + path;
+ }
+
+ currentValueBindingExpression = currentValueBindingExpression.getBaseExpression();
+ }
+
+ path = currentValueBindingExpression.getProperty() + "." + path;
+
+ Object baseObject = getValueOfExpression(facesContext, valueBindingExpression.getBaseExpression());
+
+ //in case of e.g.: #{bean[bean.passwordRepeatedPropertyName]}
+ //-> bean.passwordRepeatedPropertyName is not the final property name
+ return new PropertyDetails(path, baseObject, getPropertyName(valueBindingExpression));
+ }
+
+ private String getPropertyName(ValueBindingExpression valueBindingExpression)
+ {
+ String propertyName = valueBindingExpression.getProperty();
+
+ if(propertyName.contains("."))
+ {
+ propertyName = extractPropertyNameOfPropertyPath(propertyName);
+ }
+
+ return propertyName;
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "support for more dynamic bindings - details see inline")
+ private String extractPropertyNameOfPropertyPath(String propertyChain)
+ {
+ String[] properties = propertyChain.split("\\.");
+
+ Object currentPropertyValue = ExtValUtils.getELHelper().getBean(properties[0]);
+
+ Method currentMethod;
+ String currentPropertyName;
+ Class currentClassOfPropertyValue;
+ for(int i = 1; i < properties.length; i++)
+ {
+ currentPropertyName = properties[i];
+ currentClassOfPropertyValue = ProxyUtils.getUnproxiedClass(currentPropertyValue.getClass());
+ currentMethod = ReflectionUtils.tryToGetMethod(currentClassOfPropertyValue,
+ "get" + currentPropertyName.substring(0, 1).toUpperCase() + currentPropertyName.substring(1));
+
+ if(currentMethod == null && currentPropertyValue instanceof Map)
+ {
+ //it's ok for the simple map case - but not for e.g.:
+ //#{bean1[bean2.propertyNameProvider[ bean3.index]]}
+ //or every other complex replacement for bean3.index
+ //it might also require an adjustment at FaceletsTaglibExpressionHelper#tryToTransformToRealBinding
+ ((Map)currentPropertyValue).get(currentPropertyName);
+ }
+ else
+ {
+ currentPropertyValue = ReflectionUtils.tryToInvokeMethod(currentPropertyValue, currentMethod);
+ }
+ }
+
+ if(currentPropertyValue instanceof String)
+ {
+ return (String)currentPropertyValue;
+ }
+ else
+ {
+ if(this.logger.isErrorEnabled())
+ {
+ this.logger.error("unexpected value within map syntax: " + propertyChain +
+ " last property name: " + currentPropertyValue);
+ }
+ return null;
+ }
+ }
+
+ static String getOriginalValueBindingExpression(UIComponent uiComponent)
+ {
+ ValueExpression valueExpression = uiComponent.getValueExpression("value");
+
+ return (valueExpression != null) ? valueExpression.getExpressionString() : null;
+ }
+
+ public boolean isELTermWellFormed(Object o)
+ {
+ if (o instanceof ValueBinding || o instanceof Externalizable)
+ {
+ return false;
+ }
+
+ String s = o.toString();
+ return ((s.contains("#") || s.contains("$")) && s.contains("{") && s.contains("}"));
+ }
+
+ public Object getBindingOfComponent(UIComponent uiComponent, String name)
+ {
+ return uiComponent.getValueExpression(name);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelperFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelperFactory.java
new file mode 100644
index 0000000..2cfe56c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelperFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.el;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultELHelperFactory extends AbstractELHelperFactory
+{
+ private ELHelper elHelper = new DefaultELHelper();
+
+ protected ELHelper createELHelper()
+ {
+ return this.elHelper;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ELHelper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ELHelper.java
new file mode 100644
index 0000000..deb2553
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ELHelper.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.el;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ * in order to centralize the jsf version dependency within the core
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface ELHelper
+{
+ Object getBean(String beanName);
+
+ Object getValueOfExpression(FacesContext facesContext, ValueBindingExpression valueBindingExpression);
+
+ Class getTypeOfExpression(FacesContext facesContext, ValueBindingExpression valueBindingExpression);
+
+ PropertyDetails getPropertyDetailsOfValueBinding(UIComponent uiComponent);
+
+ boolean isELTermValid(FacesContext facesContext, String valueBindingExpression);
+
+ boolean isELTermWellFormed(Object o);
+
+ Object getBindingOfComponent(UIComponent uiComponent, String name);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ExtValELResolver.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ExtValELResolver.java
new file mode 100644
index 0000000..1cb1d58
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ExtValELResolver.java
@@ -0,0 +1,285 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.el;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import javax.el.ELResolver;
+import javax.el.ELContext;
+import javax.el.VariableMapper;
+import javax.el.ValueExpression;
+import javax.el.FunctionMapper;
+import javax.faces.el.CompositeComponentExpressionHolder;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.beans.FeatureDescriptor;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValELResolver extends ELResolver
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private ELResolver wrapped;
+ private Object baseObject;
+ private String property;
+ //forms the id for cross-validation within complex components
+ private String expression;
+ private boolean isPathRecordingStopped = false;
+ private CompositeComponentExpressionHolder compositeComponentExpressionHolder;
+ private String compositeComponentExpressionBase;
+
+ public ExtValELResolver(ELResolver elResolver)
+ {
+ this.wrapped = elResolver;
+ }
+
+ public Object getBaseObject()
+ {
+ return baseObject;
+ }
+
+ public String getProperty()
+ {
+ return property;
+ }
+
+ public String getPath()
+ {
+ if(this.logger.isTraceEnabled())
+ {
+ this.logger.trace("extracted path: " + this.expression);
+ }
+ return this.expression;
+ }
+
+ public void reset()
+ {
+ this.baseObject = null;
+ this.property = null;
+ this.expression = null;
+ }
+
+ /**
+ * path recording is performed to get a key for cross-validation<br/>
+ * every base after the first call which is null stops recording<br/>
+ * with a dynamic map syntax the last property in the middle of an expression has to be a string.
+ * such a string result continues the path recording at the next call for the current expression.
+ * <p/>
+ * example: #{bean[bean.propertyNameProvider['nameOfProperty1']]['dynBean'].property}
+ * <p/>
+ * limitation for cross-validation: nameOfProperty1 has to be of type string.
+ * other key types aren't supported yet
+ *
+ * @param elContext wrapped el-context
+ * @param base current base
+ * @param property property to resolve
+ * @return result of the delegated method call
+ */
+ public Object getValue(ELContext elContext, Object base, Object property)
+ {
+ Object result = this.wrapped.getValue(elContext, base, property);
+
+ if(this.compositeComponentExpressionHolder != null && this.compositeComponentExpressionBase == null)
+ {
+ this.compositeComponentExpressionBase = (String)property;
+ }
+
+ if(this.compositeComponentExpressionHolder == null && result instanceof CompositeComponentExpressionHolder)
+ {
+ this.compositeComponentExpressionHolder = ((CompositeComponentExpressionHolder)result);
+ }
+
+ //very first call for an expression
+ if(this.expression == null)
+ {
+ this.expression = (String)property;
+ }
+ //#{bean[dynBase.propertyName]} -> base of dynBase is null -> stop path recording
+ else if(base == null)
+ {
+ this.isPathRecordingStopped = true;
+ }
+ else
+ {
+ boolean propertyExists = false;
+ String propertyName = (String)property;
+ propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
+
+ try
+ {
+ if(base instanceof Map)
+ {
+ if(((Map)base).containsKey(property))
+ {
+ propertyExists = true;
+ }
+ }
+ else if(ProxyUtils.getUnproxiedClass(base.getClass()).getMethod("get" + propertyName) != null)
+ {
+ propertyExists = true;
+ }
+ }
+ catch (NoSuchMethodException e)
+ {
+ try
+ {
+ if(ProxyUtils.getUnproxiedClass(base.getClass()).getMethod("is" + propertyName) != null)
+ {
+ propertyExists = true;
+ }
+ }
+ catch (NoSuchMethodException e1)
+ {
+ if(this.logger.isTraceEnabled() && !"attrs".equals(property))
+ {
+ this.logger.trace("property: " + property +
+ " isn't used for path - it isn't a property of " + base.getClass());
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ return result;
+ }
+
+ //e.g.: #{bean.subBase.property} -> here we are at subBase
+ if(propertyExists && !this.isPathRecordingStopped)
+ {
+ this.expression += "." + property;
+ }
+ else if(propertyExists && result instanceof String)
+ {
+ this.isPathRecordingStopped = false;
+ }
+ }
+
+ /*
+ if(this.isPathRecordingStopped && result instanceof String)
+ {
+ this.expression += "." + property;
+ }
+ */
+
+ return result;
+ }
+
+ public Class<?> getType(ELContext elContext, Object o, Object o1)
+ {
+ return wrapped.getType(elContext, o, o1);
+ }
+
+ public void setValue(ELContext elContext, Object o, Object o1, Object o2)
+ {
+ expression += "." + o1;
+ property = (String)o1;
+ baseObject = o;
+ elContext.setPropertyResolved(true);
+ }
+
+ public boolean isReadOnly(ELContext elContext, Object o, Object o1)
+ {
+ return wrapped.isReadOnly(elContext, o, o1);
+ }
+
+ public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext elContext, Object o)
+ {
+ return wrapped.getFeatureDescriptors(elContext, o);
+ }
+
+ public Class<?> getCommonPropertyType(ELContext elContext, Object o)
+ {
+ return wrapped.getCommonPropertyType(elContext, o);
+ }
+
+ public static ELContext createContextWrapper(final ELContext context, final ELResolver resolver)
+ {
+ return new ELContext()
+ {
+ @Override
+ public Locale getLocale()
+ {
+ return context.getLocale();
+ }
+
+ @Override
+ public void setPropertyResolved(boolean value)
+ {
+ super.setPropertyResolved(value);
+ context.setPropertyResolved(value);
+ }
+
+ @Override
+ public void putContext(Class clazz, Object object)
+ {
+ super.putContext(clazz, object);
+ context.putContext(clazz, object);
+ }
+
+ @Override
+ public Object getContext(Class clazz)
+ {
+ return context.getContext(clazz);
+ }
+
+ @Override
+ public void setLocale(Locale locale)
+ {
+ super.setLocale(locale);
+ context.setLocale(locale);
+ }
+
+ @Override
+ public ELResolver getELResolver()
+ {
+ return resolver;
+ }
+
+ @Override
+ public FunctionMapper getFunctionMapper()
+ {
+ return context.getFunctionMapper();
+ }
+
+ @Override
+ public VariableMapper getVariableMapper()
+ {
+ return context.getVariableMapper();
+ }
+
+ };
+ }
+
+ public ValueExpression getCompositeComponentExpression()
+ {
+ if(this.compositeComponentExpressionHolder != null)
+ {
+ return this.compositeComponentExpressionHolder.getExpression(this.compositeComponentExpressionBase);
+ }
+ return null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/FaceletsTaglibExpressionHelper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/FaceletsTaglibExpressionHelper.java
new file mode 100644
index 0000000..5f2b89f
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/FaceletsTaglibExpressionHelper.java
@@ -0,0 +1,546 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.el;
+
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Iterator;
+
+/**
+ * Helper class to get the real/full value binding - tested with facelets 1.1.14
+ * The target is to get rid of this impl. - currently it's a workaround to support custom facelets components.
+ * An alternative would be an EL-Resolver - there are still some open issues with such an approach
+ * + It isn't available with JSF 1.1.x
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class FaceletsTaglibExpressionHelper
+{
+ public static ValueBindingExpression tryToCreateValueBindingForFaceletsBinding(UIComponent uiComponent)
+ {
+ String faceletsValueBindingExpression = DefaultELHelper.getOriginalValueBindingExpression(uiComponent);
+
+ try
+ {
+ List<String> foundBindings = extractELTerms(
+ ExtValUtils.getELHelper().getBindingOfComponent(uiComponent, "value"));
+
+ Map<String, String> mappedFaceletsVars = new HashMap<String, String>();
+ ValueBindingExpression vbe= new ValueBindingExpression(faceletsValueBindingExpression
+ .substring(0, 1) + "{" + createBinding(foundBindings, mappedFaceletsVars) + "}");
+
+ Class entityClass = ExtValUtils.getELHelper()
+ .getTypeOfExpression(FacesContext.getCurrentInstance(), vbe.getBaseExpression());
+
+ if(entityClass == null)
+ {
+ return tryToReplaceVars(vbe, mappedFaceletsVars);
+ }
+ return vbe;
+ }
+ catch (Throwable t)
+ {
+ return new ValueBindingExpression(faceletsValueBindingExpression);
+ }
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "logging")
+ private static String createBinding(List<String> expressions, Map<String, String> virtualVars)
+ {
+ String currentBinding;
+
+ int indexOfBindingDetails;
+ String[] foundBindingDetails;
+ String[] bindingDetails;
+
+ Map<String, String> addedVirtualNames = new HashMap<String, String>();
+
+ for (String entry : expressions)
+ {
+ if (entry.startsWith("ValueExpression["))
+ {
+ continue;
+ }
+
+ foundBindingDetails = entry.split(" ");
+ indexOfBindingDetails = findIndexOfBindingDetails(foundBindingDetails);
+
+ if (indexOfBindingDetails == -1)
+ {
+ return null;
+ }
+
+ bindingDetails = foundBindingDetails[indexOfBindingDetails].split("=");
+
+ if (bindingDetails.length < 2)
+ {
+ return null;
+ }
+
+ currentBinding = bindingDetails[1];
+
+ //to support blanks within a binding with map syntax
+ if(currentBinding.contains("{") && !currentBinding.contains("}"))
+ {
+ currentBinding = addFurtherBindingParts(currentBinding, foundBindingDetails, indexOfBindingDetails);
+ }
+
+ if (currentBinding.contains("}"))
+ {
+ //entry for "virtual" facelets beans
+ if(!addedVirtualNames.containsKey(bindingDetails[0]))
+ {
+ addedVirtualNames.put(bindingDetails[0], currentBinding);
+ }
+ }
+ //entry for "virtual" facelets var
+ if(!(currentBinding.contains("{") || currentBinding.contains("}")))
+ {
+ virtualVars.put(bindingDetails[0], bindingDetails[1].substring(1, bindingDetails[1].length()-2));
+ }
+ }
+
+ String originalBinding = addedVirtualNames.get("value");
+ originalBinding = originalBinding.substring(originalBinding.indexOf("{") + 1, originalBinding.indexOf("}"));
+ addedVirtualNames.remove("value");
+ return tryToTransformToRealBinding(originalBinding, addedVirtualNames, virtualVars);
+ }
+
+ private static String tryToTransformToRealBinding(
+ String originalBinding, Map<String, String> addedVirtualNames, Map<String, String> virtualVars)
+ {
+ originalBinding = "#{" + originalBinding + "}";
+ Iterator nameIterator = addedVirtualNames.keySet().iterator();
+
+ String currentKey;
+ String currentValue;
+ while(nameIterator.hasNext())
+ {
+ currentKey = (String) nameIterator.next();
+
+ currentValue = addedVirtualNames.get(currentKey);
+ currentValue = currentValue.substring(currentValue.indexOf("{") + 1, currentValue.indexOf("}"));
+
+ originalBinding = originalBinding.replace("{" + currentKey + ".", "{" + currentValue + ".");
+ //dynamic base and property
+ originalBinding = originalBinding.replace("{" + currentKey + "[", "{" + currentValue + "[");
+
+ originalBinding = originalBinding.replace("." + currentKey + ".", "." + currentValue + ".");
+ //dynamic base and property
+ originalBinding = originalBinding.replace("." + currentKey + "[", "." + currentValue + "[");
+
+ originalBinding = originalBinding.replace("[" + currentKey + "]", "['" + currentValue + "']");
+ //dynamic base and property
+ originalBinding = originalBinding.replace("[" + currentKey + "[", "[" + currentValue + "[");
+ originalBinding = originalBinding.replace("[" + currentKey + ".", "[" + currentValue + ".");
+ }
+
+ nameIterator = virtualVars.keySet().iterator();
+
+ while(nameIterator.hasNext())
+ {
+ currentKey = (String) nameIterator.next();
+
+ currentValue = virtualVars.get(currentKey);
+
+ originalBinding = originalBinding.replace("{" + currentKey + ".", "{" + currentValue + ".");
+ //dynamic base and property
+ originalBinding = originalBinding.replace("{" + currentKey + "[", "{" + currentValue + "[");
+
+ originalBinding = originalBinding.replace("." + currentKey + ".", "." + currentValue + ".");
+ //dynamic base and property
+ originalBinding = originalBinding.replace("." + currentKey + "[", "." + currentValue + "[");
+
+ originalBinding = originalBinding.replace("[" + currentKey + "]", "['" + currentValue + "']");
+ //dynamic base and property
+ originalBinding = originalBinding.replace("[" + currentKey + "[", "[" + currentValue + "[");
+ originalBinding = originalBinding.replace("[" + currentKey + ".", "[" + currentValue + ".");
+ }
+
+ return originalBinding.substring(2, originalBinding.length() - 1);
+ }
+
+ //to support blanks - e.g. with map syntax
+ private static String addFurtherBindingParts(String currentBinding, String[] foundBindingDetails,
+ int indexOfBindingDetails)
+ {
+ for(int i = indexOfBindingDetails + 1; i < foundBindingDetails.length; i++)
+ {
+ currentBinding += foundBindingDetails[i];
+ if(foundBindingDetails[i].contains("}"))
+ {
+ return currentBinding;
+ }
+ }
+ return currentBinding;
+ }
+
+ private static int findIndexOfBindingDetails(String[] bindingDetails)
+ {
+ int count = 0;
+ for (String entry : bindingDetails)
+ {
+ if (entry.contains("="))
+ {
+ return count;
+ }
+ count++;
+ }
+ return -1;
+ }
+
+ private static List<String> extractELTerms(Object o)
+ {
+ List<String> foundELTerms = new ArrayList<String>();
+ try
+ {
+ if (resolveELTerms(o, new HashMap<Object, Object>(), foundELTerms, 0) > 0)
+ {
+ return foundELTerms;
+ }
+ }
+ catch (Exception ex)
+ {
+ return null;
+ }
+ return null;
+ }
+
+ private static int resolveELTerms(Object o, Map<Object, Object> visited,
+ List<String> foundELTerms, int count) throws Exception
+ {
+ if (o == null || visited.containsKey(o) || count > 50)
+ {
+ return 0;
+ }
+
+ visited.put(o, null);
+
+ int elCount = 0;
+ Class c = o.getClass();
+
+ //inspect maps
+ if (o instanceof Map)
+ {
+
+ for (Object entry : ((Map) o).values())
+ {
+ //found entry for "virtual" facelets var
+ if(entry.toString().contains("ValueExpression["))
+ {
+ foundELTerms.add(entry.toString());
+ }
+ elCount += resolveELTerms(entry, visited, foundELTerms, count + 1);
+ }
+ return elCount;
+ }
+
+ if (ExtValUtils.getELHelper().isELTermWellFormed(o))
+ {
+ if (foundELTerms != null)
+ {
+ foundELTerms.add(o.toString());
+ }
+ return ++elCount;
+ }
+
+ //analyze arrays
+ if (c.isArray())
+ {
+ int length = Array.getLength(o);
+ //check array [L -> no array of primitive types
+ if (o.toString().startsWith("[L"))
+ {
+ for (int i = 0; i < length; i++)
+ {
+ if (o.toString().startsWith("[Ljava.lang.String"))
+ {
+ if (ExtValUtils.getELHelper().isELTermWellFormed(Array.get(o, i)))
+ {
+ if (foundELTerms != null)
+ {
+ foundELTerms.add(o.toString());
+ }
+ elCount++;
+ }
+ }
+ else
+ {
+ elCount += resolveELTerms(Array.get(o, i), visited, foundELTerms, count + 1);
+ }
+ }
+ }
+ return elCount;
+ }
+
+ List<Field> attributes = findAllAttributes(c, new ArrayList<Field>());
+ Field[] fields = attributes.toArray(new Field[attributes.size()]);
+
+ AccessibleObject.setAccessible(fields, true);
+ for (Field currentField : fields)
+ {
+ if (currentField.get(o) == null)
+ {
+ continue;
+ }
+
+ if (currentField.getType().equals(String.class))
+ {
+ if (currentField.get(o) != null && ExtValUtils.getELHelper().isELTermWellFormed(currentField.get(o)))
+ {
+ if (foundELTerms != null)
+ {
+ foundELTerms.add(o.toString());
+ }
+ elCount++;
+ }
+ }
+ else if (!currentField.getType().isPrimitive())
+ {
+ elCount += resolveELTerms(currentField.get(o), visited, foundELTerms, count + 1);
+ }
+ }
+ return elCount;
+ }
+
+ private static List<Field> findAllAttributes(Class c, List<Field> attributes)
+ {
+ if (c == null)
+ {
+ return attributes;
+ }
+ findAllAttributes(c.getSuperclass(), attributes);
+
+ Field[] fields = c.getDeclaredFields();
+ for (Field currentField : fields)
+ {
+ if (!Modifier.isStatic(currentField.getModifiers()))
+ {
+ attributes.add(currentField);
+ }
+ }
+
+ return attributes;
+ }
+
+ private static ValueBindingExpression tryToReplaceVars(ValueBindingExpression valueBindingExpression,
+ Map<String, String> mappedFaceletsVars)
+ {
+ String property;
+ String result = "";
+ boolean last = false;
+
+ while(true)
+ {
+ if(valueBindingExpression.getBaseExpression() == null)
+ {
+ last = true;
+ }
+
+
+ property = valueBindingExpression.getProperty();
+
+ valueBindingExpression = ValueBindingExpression
+ .replaceProperty(valueBindingExpression, getNewProperty(property, mappedFaceletsVars));
+
+ if(result.length() == 0)
+ {
+ result = valueBindingExpression.getProperty();
+ }
+ else
+ {
+ result = valueBindingExpression.getProperty() + "." + result;
+ }
+
+ valueBindingExpression = valueBindingExpression.getBaseExpression();
+
+ if(last)
+ {
+ break;
+ }
+ }
+ return new ValueBindingExpression(valueBindingExpression.getPrefix() + "{" + result + "}");
+ }
+
+ private static String getNewProperty(String oldProperty, Map<String, String> mappedFaceletsVars)
+ {
+ List<String> virtualVars = getPotentialVirtualVars(oldProperty);
+
+ for(String virtualVar : virtualVars)
+ {
+ if(mappedFaceletsVars.containsKey(virtualVar))
+ {
+ oldProperty = replacePropertyValue(oldProperty, virtualVar, mappedFaceletsVars.get(virtualVar));
+ }
+ }
+ return oldProperty;
+ }
+
+ private static List<String> getPotentialVirtualVars(String oldProperty)
+ {
+ int start = -1;
+ int end = -1;
+
+ List<String> virtualVarList = new ArrayList<String>();
+
+ for(int i = 0; i < oldProperty.length(); i++)
+ {
+ if(start == - 1 && oldProperty.charAt(i) == '[')
+ {
+ start = i + 1;
+ }
+ else if((start != - 1 && oldProperty.charAt(i) == '[') || oldProperty.charAt(i) == ']')
+ {
+ end = i;
+ }
+
+ if(start != -1 && end != -1)
+ {
+ virtualVarList.add(oldProperty.substring(start, end));
+ if(oldProperty.charAt(i) == '[')
+ {
+ start = i + 1;
+ }
+ else
+ {
+ start = -1;
+ }
+ end = -1;
+ }
+ }
+
+ return virtualVarList;
+ }
+
+ private static String replacePropertyValue(String oldProperty, String targetVar, String newValue)
+ {
+ int index = oldProperty.indexOf(targetVar);
+
+ if(index == -1)
+ {
+ return oldProperty;
+ }
+
+ String result = oldProperty.substring(0, index);
+ result += newValue;
+ return result + oldProperty.substring(index + targetVar.length(), oldProperty.length());
+ }
+
+ /*
+ * replace virtual facelets vars (map syntax)
+ * tested styles (simple and nested): test[ix[ix2[ix3]]]
+ */
+ /*
+ private static String _createBinding(List<String> expressions, Map<String, String> virtualVars)
+ {
+ String result = "";
+
+ String prevFaceletsAttributeName = null;
+ String currentBinding;
+ String partOfBinding;
+
+ int indexOfBindingDetails;
+ String[] foundBindingDetails;
+ String[] bindingDetails;
+
+ List<String> addedVirtualNames = new ArrayList<String>();
+
+ for (String entry : expressions)
+ {
+ if (entry.startsWith("ValueExpression["))
+ {
+ continue;
+ }
+
+ foundBindingDetails = entry.split(" ");
+ indexOfBindingDetails = findIndexOfBindingDetails(foundBindingDetails);
+
+ if (indexOfBindingDetails == -1)
+ {
+ return null;
+ }
+
+ bindingDetails = foundBindingDetails[indexOfBindingDetails].split("=");
+
+ if (bindingDetails.length < 2)
+ {
+ return null;
+ }
+
+ currentBinding = bindingDetails[1];
+
+ //to support blanks within a binding with map syntax
+ if(currentBinding.contains("{") && !currentBinding.contains("}"))
+ {
+ currentBinding = addFurtherBindingParts(currentBinding, foundBindingDetails, indexOfBindingDetails);
+ }
+
+ if (prevFaceletsAttributeName != null && currentBinding.contains("}"))
+ {
+ //entry for "virtual" facelets beans
+ if(!addedVirtualNames.contains(bindingDetails[0]))
+ {
+ partOfBinding = currentBinding.substring(currentBinding.indexOf(prevFaceletsAttributeName)
+ + prevFaceletsAttributeName.length(), currentBinding.indexOf("}"));
+
+ addedVirtualNames.add(bindingDetails[0]);
+ result = result + partOfBinding;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ //entry for "virtual" facelets var
+ else if(!(currentBinding.contains("{") || currentBinding.contains("}")))
+ {
+ virtualVars.put(bindingDetails[0], bindingDetails[1].substring(1, bindingDetails[1].length()-2));
+ continue;
+ }
+ else
+ {
+ if(!addedVirtualNames.contains(bindingDetails[0]))
+ {
+ addedVirtualNames.add(bindingDetails[0]);
+ result = currentBinding.substring(currentBinding.indexOf("{") + 1, currentBinding.indexOf("}"));
+ }
+ }
+
+ prevFaceletsAttributeName = bindingDetails[0];
+ }
+ return result;
+ }
+ */
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ValueBindingExpression.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ValueBindingExpression.java
new file mode 100644
index 0000000..d78eb66
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ValueBindingExpression.java
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.el;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@ToDo(value = Priority.MEDIUM, description = "difference between [ and [' - test with more constellations")
+@UsageInformation({UsageCategory.API})
+public class ValueBindingExpression
+{
+ private ValueBindingExpression base;
+ private String value;
+ private String prefix;
+ private String token;
+
+ public static ValueBindingExpression replaceOrAddProperty(ValueBindingExpression valueBindingExpression,
+ String newProperty)
+ {
+ if(valueBindingExpression.getBaseExpression() != null)
+ {
+ return replaceProperty(valueBindingExpression, newProperty);
+ }
+ else
+ {
+ return addProperty(valueBindingExpression, newProperty);
+ }
+ }
+
+ public static ValueBindingExpression replaceProperty(ValueBindingExpression valueBindingExpression,
+ String newProperty)
+ {
+ //TODO adjustments for isDynamicBaseAndProperty
+ if(valueBindingExpression.getProperty().endsWith("']"))
+ {
+ valueBindingExpression = valueBindingExpression.getBaseExpression();
+ }
+
+ if(valueBindingExpression.getBaseExpression() != null)
+ {
+ return addProperty(valueBindingExpression.getBaseExpression(), newProperty);
+ }
+ else
+ {
+ return addProperty(valueBindingExpression, newProperty);
+ }
+ }
+
+ public static ValueBindingExpression addProperty(ValueBindingExpression valueBindingExpression, String newProperty)
+ {
+ String sourceExpression = valueBindingExpression.getExpressionString();
+ String result = sourceExpression.substring(0, sourceExpression.length() - 1);
+
+ //TODO adjustments for isDynamicBaseAndProperty
+ if(newProperty.startsWith("['"))
+ {
+ return new ValueBindingExpression(result + newProperty + "}");
+ }
+ else
+ {
+ return new ValueBindingExpression(result + "." + newProperty + "}");
+ }
+ }
+
+ public ValueBindingExpression(String expression)
+ {
+ if(!ExtValUtils.getELHelper().isELTermWellFormed(expression))
+ {
+ throw new IllegalStateException(expression + " is no valid el-expression");
+ }
+
+ boolean isDynamicBaseAndProperty = expression.lastIndexOf("']") == -1;
+ int index1 = isDynamicBaseAndProperty ? expression.lastIndexOf("]") : expression.lastIndexOf("']");
+ int index2 = expression.lastIndexOf(".");
+
+ if(index1 > index2)
+ {
+ expression = expression.substring(0, index1);
+
+ int index3 = findIndexOfStartingBracket(expression);
+ if(isDynamicBaseAndProperty)
+ {
+ this.value = expression.substring(index3 + 1, index1);
+
+ }
+ else
+ {
+ this.value = expression.substring(index3 + 2, index1);
+ }
+
+ this.base = new ValueBindingExpression(expression.substring(0, index3) + "}");
+ this.token = isDynamicBaseAndProperty ? "[" : "['";
+ }
+ else if( index2 > index1)
+ {
+ this.value = expression.substring(index2 + 1, expression.length() - 1 );
+ this.base = new ValueBindingExpression(expression.substring(0, index2) + "}");
+ this.token = ".";
+ }
+ else
+ {
+ this.value = expression.substring(2, expression.length() - 1);
+ this.prefix = expression.substring(0, 1);
+ }
+ }
+
+ public String getProperty()
+ {
+ this.value = this.value.trim();
+
+ if("[".equals(this.token))
+ {
+ if(this.value.startsWith("'"))
+ {
+ return this.value.substring(1, this.value.length() - 1);
+ }
+ //return this.base.value + this.token + this.value.substring(0, this.value.length()) + "']";
+ }
+ return value;
+ }
+
+ public ValueBindingExpression getBaseExpression()
+ {
+ return base;
+ }
+
+ public String getExpressionString()
+ {
+ if(this.base != null)
+ {
+ String baseExpression = this.base.getExpressionString();
+
+ if("['".equals(this.token))
+ {
+ return baseExpression.substring(0, baseExpression.length() - 1) + this.token + this.value + "']}";
+ }
+ else if("[".equals(this.token))
+ {
+ return baseExpression.substring(0, baseExpression.length() - 1) + this.token + this.value + "]}";
+ }
+ return baseExpression.substring(0, baseExpression.length() - 1) + this.token + this.value + "}";
+ }
+ else
+ {
+ return this.prefix + "{" + this.value + "}";
+ }
+ }
+
+ public String getPrefix()
+ {
+ if(this.base != null)
+ {
+ return this.base.getPrefix();
+ }
+ else
+ {
+ return prefix;
+ }
+ }
+
+ public void setPrefix(String prefix)
+ {
+ if(this.base != null)
+ {
+ this.base.setPrefix(prefix);
+ }
+ else
+ {
+ this.prefix = prefix;
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return getExpressionString();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return getExpressionString().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object target)
+ {
+ return target instanceof ValueBindingExpression && getExpressionString()
+ .equals(((ValueBindingExpression) target).getExpressionString());
+ }
+
+ private int findIndexOfStartingBracket(String expression)
+ {
+ int closeCount = 0;
+ for(int i = expression.length() - 1; i > 0; i--)
+ {
+ if(expression.charAt(i) == '[')
+ {
+ closeCount--;
+ if(closeCount < 0)
+ {
+ return i;
+ }
+ }
+ else if(expression.charAt(i) == ']')
+ {
+ closeCount++;
+ }
+ }
+ return 0;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/AbstractNameMapperAwareFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/AbstractNameMapperAwareFactory.java
new file mode 100644
index 0000000..33100b3
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/AbstractNameMapperAwareFactory.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.factory;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.InvocationOrderComparator;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+@UsageInformation(UsageCategory.API)
+public abstract class AbstractNameMapperAwareFactory<T> implements NameMapperAwareFactory<NameMapper<T>>
+{
+ private List<Class> deniedNameMapperList = new ArrayList<Class>();
+
+ public synchronized void register(NameMapper<T> nameMapper)
+ {
+ if(!deniedNameMapperList.contains(nameMapper.getClass()))
+ {
+ getNameMapperList().add(nameMapper);
+ Collections.sort(getNameMapperList(), getComparator());
+ }
+ }
+
+ protected Comparator<NameMapper<T>> getComparator()
+ {
+ return new InvocationOrderComparator<NameMapper<T>>();
+ }
+
+ public synchronized void deregister(Class<? extends NameMapper> classToDeregister)
+ {
+ Iterator<NameMapper<T>> nameMapperIterator = getNameMapperList().iterator();
+ while(nameMapperIterator.hasNext())
+ {
+ if(nameMapperIterator.next().getClass().getName().equals(classToDeregister.getName()))
+ {
+ nameMapperIterator.remove();
+ //don't break - e.g. to deregister all wrappers...
+ //break;
+ }
+ }
+ }
+
+ public void deny(Class<? extends NameMapper> classToDeny)
+ {
+ deregister(classToDeny);
+
+ synchronized (getClass())
+ {
+ deniedNameMapperList.add(classToDeny);
+ }
+ }
+
+ protected abstract List<NameMapper<T>> getNameMapperList();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/ClassMappingFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/ClassMappingFactory.java
new file mode 100644
index 0000000..d366070
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/ClassMappingFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.factory;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface ClassMappingFactory<P, R>
+{
+ R create(P source);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/DefaultFactoryFinder.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/DefaultFactoryFinder.java
new file mode 100644
index 0000000..c69755f
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/DefaultFactoryFinder.java
@@ -0,0 +1,360 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.factory;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.DefaultComponentMetaDataExtractorFactory;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultStorageManagerFactory;
+import org.apache.myfaces.extensions.validator.core.el.DefaultELHelperFactory;
+import org.apache.myfaces.extensions.validator.core.renderkit.DefaultRenderKitWrapperFactory;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.DefaultMetaDataTransformerFactory;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.DefaultValidationStrategyFactory;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.DefaultMessageResolverFactory;
+import org.apache.myfaces.extensions.validator.core.validation.message.DefaultFacesMessageFactory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.DefaultValidationParameterExtractorFactory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.DefaultValidationParameterFactory;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+//dynamic approach to create the factories during the first request, when a faces-context is available
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultFactoryFinder implements FactoryFinder
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+ protected Map<FactoryNames, Object> factoryMap = new HashMap<FactoryNames, Object>();
+
+ private static FactoryFinder factoryFinder = new DefaultFactoryFinder();
+
+ protected DefaultFactoryFinder()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public static FactoryFinder getInstance()
+ {
+ return factoryFinder;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public final <T> T getFactory(FactoryNames factoryName, Class<T> targetClass)
+ {
+ if(!(factoryMap.containsKey(factoryName)))
+ {
+ initFactory(factoryName);
+ }
+
+ return (T)factoryMap.get(factoryName);
+ }
+
+ private void initFactory(FactoryNames factoryName)
+ {
+ Object factory = null;
+ switch (factoryName)
+ {
+ case COMPONENT_META_DATA_EXTRACTOR_FACTORY:
+ factory = createComponentMetaDataExtractorFactory();
+ break;
+
+ case VALIDATION_STRATEGY_FACTORY:
+ factory = createValidationStrategyFactory();
+ break;
+
+ case MESSAGE_RESOLVER_FACTORY:
+ factory = createMessageResolverFactory();
+ break;
+
+ case META_DATA_TRANSFORMER_FACTORY:
+ factory = createMetaDataTransformerFactory();
+ break;
+
+ case RENDERKIT_WRAPPER_FACTORY:
+ factory = createRenderKitWrapperFactory();
+ break;
+
+ case EL_HELPER_FACTORY:
+ factory = createELHelperFactory();
+ break;
+
+ case FACES_MESSAGE_FACTORY:
+ factory = createFacesMessageFactory();
+ break;
+
+ case VALIDATION_PARAMETER_EXTRACTOR_FACTORY:
+ factory = createValidationParameterExtractorFactory();
+ break;
+
+ case STORAGE_MANAGER_FACTORY:
+ factory = createStorageManagerFactory();
+ break;
+
+ case VALIDATION_PARAMETER_FACTORY:
+ factory = createValidationParameterFactory();
+ break;
+
+ default: //required by checkstyle
+ }
+
+ if(factory == null)
+ {
+ throw new IllegalStateException("not possible to create factory " + factoryName);
+ }
+
+ factoryMap.put(factoryName, factory);
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "add global property extension point")
+ protected Object createComponentMetaDataExtractorFactory()
+ {
+ Object factory = null;
+
+ List<String> metaDataExtractorFactoryClassNames = new ArrayList<String>();
+
+ metaDataExtractorFactoryClassNames.add(WebXmlParameter.CUSTOM_COMPONENT_META_DATA_EXTRACTOR_FACTORY);
+ metaDataExtractorFactoryClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.COMPONENT_META_DATA_EXTRACTOR_FACTORY));
+ metaDataExtractorFactoryClassNames.add(DefaultComponentMetaDataExtractorFactory.class.getName());
+
+ for (String className : metaDataExtractorFactoryClassNames)
+ {
+ factory = ClassUtils.tryToInstantiateClassForName(className);
+
+ if (factory != null)
+ {
+ break;
+ }
+ }
+ return factory;
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "add global property extension point")
+ protected Object createValidationStrategyFactory()
+ {
+ Object factory = null;
+
+ List<String> validationStrategyFactoryClassNames = new ArrayList<String>();
+
+ validationStrategyFactoryClassNames.add(WebXmlParameter.CUSTOM_VALIDATION_STRATEGY_FACTORY);
+ validationStrategyFactoryClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.VALIDATION_STRATEGY_FACTORY));
+ validationStrategyFactoryClassNames.add(DefaultValidationStrategyFactory.class.getName());
+
+ for (String className : validationStrategyFactoryClassNames)
+ {
+ factory = ClassUtils.tryToInstantiateClassForName(className);
+
+ if (factory != null)
+ {
+ break;
+ }
+ }
+
+ return factory;
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "add global property extension point")
+ protected Object createMessageResolverFactory()
+ {
+ Object factory = null;
+ List<String> messageResolverFactoryClassNames = new ArrayList<String>();
+
+ messageResolverFactoryClassNames.add(WebXmlParameter.CUSTOM_MESSAGE_RESOLVER_FACTORY);
+ messageResolverFactoryClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.MESSAGE_RESOLVER_FACTORY));
+ messageResolverFactoryClassNames
+ .add(DefaultMessageResolverFactory.class.getName());
+
+ for (String className : messageResolverFactoryClassNames)
+ {
+ factory = ClassUtils.tryToInstantiateClassForName(className);
+
+ if (factory != null)
+ {
+ break;
+ }
+ }
+
+ return factory;
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "add global property extension point")
+ protected Object createMetaDataTransformerFactory()
+ {
+ Object factory = null;
+ List<String> metaDataTransformerFactoryClassNames = new ArrayList<String>();
+
+ metaDataTransformerFactoryClassNames.add(WebXmlParameter.CUSTOM_META_DATA_TRANSFORMER_FACTORY );
+ metaDataTransformerFactoryClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.META_DATA_TRANSFORMER_FACTORY));
+ metaDataTransformerFactoryClassNames.add(DefaultMetaDataTransformerFactory.class.getName());
+
+ for (String className : metaDataTransformerFactoryClassNames)
+ {
+ factory = ClassUtils.tryToInstantiateClassForName(className);
+
+ if (factory != null)
+ {
+ break;
+ }
+ }
+
+ return factory;
+ }
+
+ protected Object createRenderKitWrapperFactory()
+ {
+ return new DefaultRenderKitWrapperFactory();
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "add global property extension point")
+ protected Object createFacesMessageFactory()
+ {
+ Object factory = null;
+
+ List<String> facesMessageFactoryClassNames = new ArrayList<String>();
+
+ facesMessageFactoryClassNames.add(WebXmlParameter.CUSTOM_FACES_MESSAGE_FACTORY);
+ facesMessageFactoryClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.FACES_MESSAGE_FACTORY));
+
+ Object target = ExtValContext.getContext().getGlobalProperty(CustomInformation.FACES_MESSAGE_FACTORY.name());
+ if(target != null && target instanceof String)
+ {
+ facesMessageFactoryClassNames.add((String)target);
+ }
+ facesMessageFactoryClassNames.add(DefaultFacesMessageFactory.class.getName());
+
+ for (String className : facesMessageFactoryClassNames)
+ {
+ factory = ClassUtils.tryToInstantiateClassForName(className);
+
+ if (factory != null)
+ {
+ break;
+ }
+ }
+
+ return factory;
+ }
+
+ protected Object createELHelperFactory()
+ {
+ return new DefaultELHelperFactory();
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "add global property extension point")
+ protected Object createValidationParameterExtractorFactory()
+ {
+ Object factory = null;
+
+ List<String> validationParameterExtractorFactoryClassNames = new ArrayList<String>();
+
+ validationParameterExtractorFactoryClassNames
+ .add(WebXmlParameter.CUSTOM_VALIDATION_PARAMETER_EXTRACTOR_FACTORY);
+ validationParameterExtractorFactoryClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.VALIDATION_PARAMETER_EXTRACTOR_FACTORY));
+ validationParameterExtractorFactoryClassNames.add(DefaultValidationParameterExtractorFactory.class.getName());
+
+ for (String className : validationParameterExtractorFactoryClassNames)
+ {
+ factory = ClassUtils.tryToInstantiateClassForName(className);
+
+ if (factory != null)
+ {
+ break;
+ }
+ }
+ return factory;
+ }
+
+ protected Object createStorageManagerFactory()
+ {
+ Object factory = null;
+
+ List<String> storageManagerFactoryClassNames = new ArrayList<String>();
+
+ storageManagerFactoryClassNames
+ .add(WebXmlParameter.CUSTOM_STORAGE_MANAGER_FACTORY);
+ storageManagerFactoryClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.STORAGE_MANAGER_FACTORY));
+ storageManagerFactoryClassNames.add(DefaultStorageManagerFactory.class.getName());
+
+ for (String className : storageManagerFactoryClassNames)
+ {
+ factory = ClassUtils.tryToInstantiateClassForName(className);
+
+ if (factory != null)
+ {
+ break;
+ }
+ }
+ return factory;
+ }
+
+ private Object createValidationParameterFactory()
+ {
+ Object factory = null;
+
+ List<String> validationParameterFactoryClassNames = new ArrayList<String>();
+
+ validationParameterFactoryClassNames
+ .add(WebXmlParameter.CUSTOM_VALIDATION_PARAMETER_FACTORY);
+ validationParameterFactoryClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.VALIDATION_PARAMETER_FACTORY));
+ validationParameterFactoryClassNames.add(DefaultValidationParameterFactory.class.getName());
+
+ for (String className : validationParameterFactoryClassNames)
+ {
+ factory = ClassUtils.tryToInstantiateClassForName(className);
+
+ if (factory != null)
+ {
+ break;
+ }
+ }
+ return factory;
+ }
+
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FacesMessageFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FacesMessageFactory.java
new file mode 100644
index 0000000..97bd8a3
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FacesMessageFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.factory;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.application.FacesMessage;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+@UsageInformation(UsageCategory.API)
+public interface FacesMessageFactory
+{
+ FacesMessage convert(FacesMessage facesMessage);
+
+ FacesMessage create(FacesMessage.Severity severity, String summary, String detail);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FactoryFinder.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FactoryFinder.java
new file mode 100644
index 0000000..a4f2625
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FactoryFinder.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.factory;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface FactoryFinder
+{
+ <T> T getFactory(FactoryNames factoryName, Class<T> targetClass);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FactoryNames.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FactoryNames.java
new file mode 100644
index 0000000..912b15e
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/FactoryNames.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.factory;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.API})
+public enum FactoryNames
+{
+ COMPONENT_META_DATA_EXTRACTOR_FACTORY,
+
+ VALIDATION_PARAMETER_EXTRACTOR_FACTORY,
+ VALIDATION_PARAMETER_FACTORY,
+
+ VALIDATION_STRATEGY_FACTORY,
+ MESSAGE_RESOLVER_FACTORY,
+ META_DATA_TRANSFORMER_FACTORY,
+
+ FACES_MESSAGE_FACTORY,
+
+ RENDERKIT_WRAPPER_FACTORY,
+ EL_HELPER_FACTORY,
+
+ STORAGE_MANAGER_FACTORY
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/NameMapperAwareFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/NameMapperAwareFactory.java
new file mode 100644
index 0000000..bd2d1f0
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/factory/NameMapperAwareFactory.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.factory;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+@UsageInformation(UsageCategory.API)
+public interface NameMapperAwareFactory<T extends NameMapper>
+{
+ void register(T classToAdd);
+ void deregister(Class<? extends NameMapper> classToDeregister);
+ void deny(Class<? extends NameMapper> classToDeny);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/component/AbstractHtmlCoreComponentsComponentInitializer.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/component/AbstractHtmlCoreComponentsComponentInitializer.java
new file mode 100644
index 0000000..6f500c3
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/component/AbstractHtmlCoreComponentsComponentInitializer.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.initializer.component;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.component.html.HtmlInputText;
+import javax.faces.component.html.HtmlInputSecret;
+import javax.faces.component.html.HtmlSelectBooleanCheckbox;
+import javax.faces.component.html.HtmlSelectOneListbox;
+import javax.faces.component.html.HtmlSelectOneMenu;
+import javax.faces.component.html.HtmlSelectOneRadio;
+import javax.faces.component.html.HtmlSelectManyCheckbox;
+import javax.faces.component.html.HtmlSelectManyListbox;
+import javax.faces.component.html.HtmlSelectManyMenu;
+import javax.faces.component.html.HtmlInputTextarea;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.REUSE)
+public abstract class AbstractHtmlCoreComponentsComponentInitializer implements ComponentInitializer
+{
+ public void configureComponent(FacesContext facesContext, UIComponent uiComponent, Map<String, Object> metaData)
+ {
+ if(processComponent(uiComponent))
+ {
+ if(validateEmptyFields() && ExtValUtils.isRequiredInitializationActive())
+ {
+ configureRequiredAttribute(facesContext, uiComponent, metaData);
+ }
+
+ configureMaxLengthAttribute(facesContext, uiComponent, metaData);
+ }
+ }
+
+ protected boolean validateEmptyFields()
+ {
+ return ExtValUtils.validateEmptyFields();
+ }
+
+ protected abstract void configureRequiredAttribute(FacesContext facesContext,
+ UIComponent uiComponent,
+ Map<String, Object> metaData);
+
+ protected boolean processComponent(UIComponent uiComponent)
+ {
+ return uiComponent instanceof HtmlInputText ||
+ uiComponent instanceof HtmlInputSecret ||
+ uiComponent instanceof HtmlSelectBooleanCheckbox ||
+ uiComponent instanceof HtmlSelectOneListbox ||
+ uiComponent instanceof HtmlSelectOneMenu ||
+ uiComponent instanceof HtmlSelectOneRadio ||
+ uiComponent instanceof HtmlSelectManyCheckbox ||
+ uiComponent instanceof HtmlSelectManyListbox ||
+ uiComponent instanceof HtmlSelectManyMenu ||
+ uiComponent instanceof HtmlInputTextarea;
+ }
+
+ /**
+ * if there is no special attribute at the component which should overrule
+ * the annotated property return true!
+ *
+ * @param uiComponent component which implements the EditableValueHolder interface
+ * @return false to overrule the annotated property e.g. if component is readonly
+ */
+ @ToDo(value = Priority.MEDIUM, description = "refactor")
+ protected Boolean isComponentRequired(UIComponent uiComponent)
+ {
+ boolean isReadOnly = !Boolean.FALSE.equals(ReflectionUtils.tryToInvokeMethod(
+ uiComponent, ReflectionUtils.tryToGetMethod(uiComponent.getClass(), "isReadonly")));
+ boolean isDisabled = !Boolean.FALSE.equals(ReflectionUtils.tryToInvokeMethod(
+ uiComponent, ReflectionUtils.tryToGetMethod(uiComponent.getClass(), "isDisabled")));
+
+ return !(isReadOnly || isDisabled);
+ }
+
+ protected void configureMaxLengthAttribute(FacesContext facesContext,
+ UIComponent uiComponent,
+ Map<String, Object> metaData)
+ {
+ if(metaData.containsKey(CommonMetaDataKeys.MAX_LENGTH))
+ {
+ Object maxLength = metaData.get(CommonMetaDataKeys.MAX_LENGTH);
+
+ if(!(maxLength instanceof Integer))
+ {
+ return;
+ }
+ if(uiComponent instanceof HtmlInputText)
+ {
+ HtmlInputText htmlInputText = (HtmlInputText)uiComponent;
+ htmlInputText.setMaxlength((Integer)maxLength);
+ }
+ else if(uiComponent instanceof HtmlInputSecret)
+ {
+ HtmlInputSecret htmlInputSecret = (HtmlInputSecret)uiComponent;
+ htmlInputSecret.setMaxlength((Integer)maxLength);
+ }
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/component/ComponentInitializer.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/component/ComponentInitializer.java
new file mode 100644
index 0000000..ec8e355
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/component/ComponentInitializer.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.initializer.component;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrderSupport;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.Map;
+
+/**
+ * Allows to initialize components beforeEncodeBegin.<br/>
+ * e.g.: you can add information for client-side validation mechanisms,...
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrderSupport
+@UsageInformation(UsageCategory.API)
+public interface ComponentInitializer
+{
+ void configureComponent(FacesContext facesContext, UIComponent uiComponent, Map<String, Object> metaData);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfiguration.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfiguration.java
new file mode 100644
index 0000000..359c041
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfiguration.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.initializer.configuration;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import java.util.List;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface StaticConfiguration<T, R>
+{
+ void setSourceOfMapping(String path);
+ List<StaticConfigurationEntry<T, R>> getMapping();
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfigurationEntry.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfigurationEntry.java
new file mode 100644
index 0000000..2b84af5
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfigurationEntry.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.initializer.configuration;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public class StaticConfigurationEntry<T, R>
+{
+ private T source;
+ private R target;
+
+ public T getSource()
+ {
+ return source;
+ }
+
+ public void setSource(T source)
+ {
+ this.source = source;
+ }
+
+ public R getTarget()
+ {
+ return target;
+ }
+
+ public void setTarget(R target)
+ {
+ this.target = target;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfigurationNames.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfigurationNames.java
new file mode 100644
index 0000000..cd75bf4
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticConfigurationNames.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.initializer.configuration;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.API})
+public enum StaticConfigurationNames
+{
+ META_DATA_TO_VALIDATION_STRATEGY_CONFIG,
+ VALIDATION_STRATEGY_TO_MESSAGE_RESOLVER_CONFIG,
+ VALIDATION_STRATEGY_TO_META_DATA_TRANSFORMER_CONFIG,
+ STORAGE_TYPE_TO_STORAGE_MANAGER_CONFIG,
+
+ SKIP_VALIDATION_SUPPORT_CONFIG,
+ VALIDATION_PARAMETER_CONFIG
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticInMemoryConfiguration.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticInMemoryConfiguration.java
new file mode 100644
index 0000000..60cb6f4
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticInMemoryConfiguration.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.initializer.configuration;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.REUSE})
+public class StaticInMemoryConfiguration implements StaticConfiguration<String, String>
+{
+ private List<StaticConfigurationEntry<String, String>> mappings
+ = new ArrayList<StaticConfigurationEntry<String, String>>();
+
+ public void setSourceOfMapping(String path)
+ {
+ }
+
+ public List<StaticConfigurationEntry<String, String>> getMapping()
+ {
+ return mappings;
+ }
+
+ public void addMapping(String source, String target)
+ {
+ StaticConfigurationEntry<String, String> entry = new StaticConfigurationEntry<String, String>();
+ entry.setSource(source);
+ entry.setTarget(target);
+ this.mappings.add(entry);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticResourceBundleConfiguration.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticResourceBundleConfiguration.java
new file mode 100644
index 0000000..81a63c4
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/initializer/configuration/StaticResourceBundleConfiguration.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.initializer.configuration;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.Enumeration;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.REUSE})
+public class StaticResourceBundleConfiguration implements StaticConfiguration<String, String>
+{
+ private String path;
+ private List<StaticConfigurationEntry<String, String>> mappings;
+
+ public void setSourceOfMapping(String path)
+ {
+ this.path = path;
+ //force reload
+ mappings = null;
+ }
+
+ public List<StaticConfigurationEntry<String, String>> getMapping()
+ {
+ if(mappings != null)
+ {
+ return mappings;
+ }
+
+ mappings = new ArrayList<StaticConfigurationEntry<String, String>>();
+
+ ResourceBundle mapping = ResourceBundle.getBundle(path);
+
+ if (mapping == null)
+ {
+ //logging
+ return new ArrayList<StaticConfigurationEntry<String, String>>();
+ }
+
+ Enumeration keys = mapping.getKeys();
+
+ String metaDataKey;
+ String validationStrategyClassName;
+
+ while (keys.hasMoreElements())
+ {
+ metaDataKey = (String) keys.nextElement();
+ validationStrategyClassName = mapping.getString(metaDataKey);
+
+ addMapping(metaDataKey, validationStrategyClassName);
+ }
+ return mappings;
+ }
+
+ private void addMapping(String metaDataKey, String validationStrategyClassName)
+ {
+ StaticConfigurationEntry<String, String> entry = new StaticConfigurationEntry<String, String>();
+ entry.setSource(metaDataKey);
+ entry.setTarget(validationStrategyClassName);
+ this.mappings.add(entry);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/AbstractRendererInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/AbstractRendererInterceptor.java
new file mode 100644
index 0000000..6993968
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/AbstractRendererInterceptor.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipRendererDelegationException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipBeforeInterceptorsException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipAfterInterceptorsException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.convert.ConverterException;
+import javax.faces.render.Renderer;
+import java.io.IOException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public abstract class AbstractRendererInterceptor implements RendererInterceptor
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ protected AbstractRendererInterceptor()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public final String getInterceptorId()
+ {
+ return getClass().getName();
+ }
+
+ public Object getReturnValueOnSkipRendererDelegationException(
+ SkipRendererDelegationException skipRendererDelegationException, Object currentReturnValue)
+ {
+ return currentReturnValue;
+ }
+
+ /*
+ * before
+ */
+ public void beforeDecode(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws SkipBeforeInterceptorsException, SkipRendererDelegationException
+ {
+ }
+
+ public void beforeEncodeBegin(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws IOException, SkipBeforeInterceptorsException, SkipRendererDelegationException
+ {
+ }
+
+ public void beforeEncodeChildren(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws IOException, SkipBeforeInterceptorsException, SkipRendererDelegationException
+ {
+ }
+
+ public void beforeEncodeEnd(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws IOException, SkipBeforeInterceptorsException, SkipRendererDelegationException
+ {
+ }
+
+ public void beforeGetConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object o, Renderer wrapped)
+ throws ConverterException, SkipBeforeInterceptorsException, SkipRendererDelegationException
+ {
+ }
+
+ /*
+ * after
+ */
+ public void afterDecode(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws SkipAfterInterceptorsException
+ {
+ }
+
+ public void afterEncodeBegin(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws IOException, SkipAfterInterceptorsException
+ {
+ }
+
+ public void afterEncodeChildren(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws IOException, SkipAfterInterceptorsException
+ {
+ }
+
+ public void afterEncodeEnd(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws IOException, SkipAfterInterceptorsException
+ {
+ }
+
+ public void afterGetConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object o, Renderer wrapped)
+ throws ConverterException, SkipAfterInterceptorsException
+ {
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/AbstractValidationInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/AbstractValidationInterceptor.java
new file mode 100644
index 0000000..1427129
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/AbstractValidationInterceptor.java
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.ValidationModuleKey;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.MetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.storage.RendererInterceptorPropertyStorage;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipBeforeInterceptorsException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipRendererDelegationException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipAfterInterceptorsException;
+import org.apache.myfaces.extensions.validator.core.recorder.ProcessedInformationRecorder;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.convert.ConverterException;
+import javax.faces.render.Renderer;
+import javax.faces.validator.ValidatorException;
+import javax.el.PropertyNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.REUSE)
+public abstract class AbstractValidationInterceptor extends AbstractRendererInterceptor
+{
+ protected boolean isRequiredInitializationSupported()
+ {
+ return false;
+ }
+
+ @Override
+ public void afterDecode(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws SkipAfterInterceptorsException
+ {
+ /*
+ * component initialization sets a component to required if there are constraints which indicate it
+ * the required flag in a component leads to problems with h:messages (additional message) as well as
+ * incompatibilities with skip validation and severities
+ */
+ if(uiComponent instanceof EditableValueHolder && ExtValUtils.isRequiredResetActivated() &&
+ isRequiredInitializationSupported() && ExtValUtils.isRequiredInitializationActive())
+ {
+ ((EditableValueHolder)uiComponent).setRequired(false);
+ }
+ }
+
+ @Override
+ public void beforeEncodeBegin(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws IOException, SkipBeforeInterceptorsException, SkipRendererDelegationException
+ {
+ if(processComponent(uiComponent) && !isComponentInitializationDeactivated())
+ {
+ initComponent(facesContext, uiComponent);
+ }
+ }
+
+ protected abstract void initComponent(FacesContext facesContext, UIComponent uiComponent);
+
+ @Override
+ public void beforeGetConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object o, Renderer wrapped)
+ throws ConverterException, SkipBeforeInterceptorsException, SkipRendererDelegationException
+ {
+ Object convertedObject;
+
+ try
+ {
+ convertedObject = wrapped.getConvertedValue(facesContext, uiComponent, o);
+ }
+ catch (PropertyNotFoundException r)
+ {
+ if(this.logger.isFatalEnabled())
+ {
+ this.logger.fatal("it seems you are using an invalid binding. " + wrapped.getClass().getName()
+ + ": conversion failed. normally this is >not< a myfaces extval issue!", r);
+ }
+
+ throw r;
+ }
+
+ setRendererInterceptorProperties(uiComponent);
+
+ if(recordProcessedInformation())
+ {
+ //recorde user input e.g. for cross-component validation
+ for(ProcessedInformationRecorder recorder : ExtValContext.getContext().getProcessedInformationRecorders())
+ {
+ recorder.recordUserInput(uiComponent, convertedObject);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(recorder.getClass().getName() + " called");
+ }
+ }
+ }
+
+ try
+ {
+ if(processComponent(uiComponent))
+ {
+ convertedObject = transformValueForValidation(convertedObject);
+
+ if(validateValue(convertedObject) &&
+ processBeforeValidation(facesContext, uiComponent, convertedObject))
+ {
+ processValidation(facesContext, uiComponent, convertedObject);
+ }
+ }
+ }
+ catch (ValidatorException e)
+ {
+ try
+ {
+ //ViolationSeverityInterpreter might decide that it isn't an exception
+ ExtValUtils.tryToThrowValidatorExceptionForComponent(uiComponent, e.getFacesMessage(), e);
+ }
+ catch (ValidatorException finalException)
+ {
+ throw new ConverterException(e.getFacesMessage(), e);
+ }
+ }
+ finally
+ {
+ processAfterValidation(facesContext, uiComponent, convertedObject);
+ resetRendererInterceptorProperties(uiComponent);
+ }
+ }
+
+ protected boolean processBeforeValidation(FacesContext facesContext, UIComponent uiComponent, Object value)
+ {
+ return ExtValUtils.executeGlobalBeforeValidationInterceptors(facesContext, uiComponent, value,
+ PropertyInformation.class.getName(), getPropertyInformation(facesContext, uiComponent), getModuleKey());
+ }
+
+ protected void processAfterValidation(FacesContext facesContext, UIComponent uiComponent, Object value)
+ {
+ ExtValUtils.executeGlobalAfterValidationInterceptors(facesContext, uiComponent, value,
+ PropertyInformation.class.getName(), getPropertyInformation(facesContext, uiComponent), getModuleKey());
+ }
+
+ protected PropertyInformation getPropertyInformation(FacesContext facesContext, UIComponent uiComponent)
+ {
+ Map<String, Object> properties = getPropertiesForComponentMetaDataExtractor(uiComponent);
+
+ MetaDataExtractor metaDataExtractor = getComponentMetaDataExtractor(properties);
+
+ return metaDataExtractor.extract(facesContext, uiComponent);
+ }
+
+ protected Map<String, Object> getPropertiesForComponentMetaDataExtractor(UIComponent uiComponent)
+ {
+ Map<String, Object> properties = new HashMap<String, Object>();
+
+ if(getModuleKey() != null)
+ {
+ properties.put(ValidationModuleKey.class.getName(), getModuleKey());
+ }
+ properties.put(UIComponent.class.getName(), uiComponent);
+ return properties;
+ }
+
+ protected abstract MetaDataExtractor getComponentMetaDataExtractor(Map<String, Object> properties);
+
+ protected Object transformValueForValidation(Object convertedObject)
+ {
+ if ("".equals(convertedObject) && interpretEmptyStringValuesAsNull())
+ {
+ return null;
+ }
+
+ return convertedObject;
+ }
+
+ protected boolean validateValue(Object convertedObject)
+ {
+ if(isValueToValidateEmpty(convertedObject) && !validateEmptyFields())
+ {
+ if(this.logger.isDebugEnabled())
+ {
+ this.logger.debug("empty field validation is deactivated in the web.xml - see: " +
+ "javax.faces.VALIDATE_EMPTY_FIELDS");
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ protected boolean isValueToValidateEmpty(Object convertedObject)
+ {
+ return convertedObject == null || "".equals(convertedObject);
+ }
+
+ protected boolean validateEmptyFields()
+ {
+ return ExtValUtils.validateEmptyFields();
+ }
+
+ protected boolean interpretEmptyStringValuesAsNull()
+ {
+ return ExtValUtils.interpretEmptyStringValuesAsNull();
+ }
+
+ protected abstract void processValidation(
+ FacesContext facesContext, UIComponent uiComponent, Object convertedObject);
+
+ protected boolean processComponent(UIComponent uiComponent)
+ {
+ return uiComponent instanceof EditableValueHolder && isValueBindingOfComponentValid(uiComponent);
+ }
+
+ private boolean isValueBindingOfComponentValid(UIComponent uiComponent)
+ {
+ try
+ {
+ return ExtValUtils.getELHelper().getPropertyDetailsOfValueBinding(uiComponent) != null;
+ }
+ catch (Throwable t)
+ {
+ return false;
+ }
+ }
+
+ private boolean isComponentInitializationDeactivated()
+ {
+ return "true".equalsIgnoreCase(WebXmlParameter.DEACTIVATE_COMPONENT_INITIALIZATION);
+ }
+
+ protected boolean recordProcessedInformation()
+ {
+ //override if needed
+ return false;
+ }
+
+ protected Class getModuleKey()
+ {
+ //override if needed
+ return null;
+ }
+
+ protected Map<String, Object> getInterceptorProperties(UIComponent uiComponent)
+ {
+ Map<String, Object> result = new HashMap<String, Object>();
+
+ if(getModuleKey() != null)
+ {
+ result.put(ValidationModuleKey.class.getName(), getModuleKey());
+ }
+ result.put(UIComponent.class.getName(), uiComponent);
+
+ return result;
+ }
+
+ private void setRendererInterceptorProperties(UIComponent uiComponent)
+ {
+ RendererInterceptorPropertyStorage interceptorPropertyStorage = getRendererInterceptorPropertyStorage();
+
+ Map<String, Object> properties = getInterceptorProperties(uiComponent);
+ for(String key : properties.keySet())
+ {
+ interceptorPropertyStorage.setProperty(key, properties.get(key));
+ }
+ }
+
+ private void resetRendererInterceptorProperties(UIComponent uiComponent)
+ {
+ RendererInterceptorPropertyStorage interceptorPropertyStorage = getRendererInterceptorPropertyStorage();
+
+ for(String key : getInterceptorProperties(uiComponent).keySet())
+ {
+ interceptorPropertyStorage.removeProperty(key);
+ }
+ }
+
+ private RendererInterceptorPropertyStorage getRendererInterceptorPropertyStorage()
+ {
+ return ExtValUtils.getStorage(RendererInterceptorPropertyStorage.class,
+ RendererInterceptorPropertyStorage.class.getName());
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ComponentInitializationAwareMetaDataExtractionInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ComponentInitializationAwareMetaDataExtractionInterceptor.java
new file mode 100644
index 0000000..bdf7118
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ComponentInitializationAwareMetaDataExtractionInterceptor.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrderSupport;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrderSupport
+@UsageInformation(UsageCategory.REUSE)
+public abstract class ComponentInitializationAwareMetaDataExtractionInterceptor implements MetaDataExtractionInterceptor
+{
+ public final void afterExtracting(PropertyInformation propertyInformation)
+ {
+ if(JsfUtils.isRenderResponsePhase())
+ {
+ afterExtractingForComponentInitialization(propertyInformation);
+ }
+ }
+
+ protected abstract void afterExtractingForComponentInitialization(PropertyInformation propertyInformation);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/FacesMessagePropertyValidationInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/FacesMessagePropertyValidationInterceptor.java
new file mode 100644
index 0000000..296b163
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/FacesMessagePropertyValidationInterceptor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.core.storage.FacesMessageStorage;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(900)
+@UsageInformation(UsageCategory.INTERNAL)
+public class FacesMessagePropertyValidationInterceptor implements PropertyValidationInterceptor
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public boolean beforeValidation(
+ FacesContext facesContext, UIComponent uiComponent, Object convertedObject, Map<String, Object> properties)
+ {
+ return true;
+ }
+
+ public void afterValidation(
+ FacesContext facesContext, UIComponent uiComponent, Object convertedObject, Map<String, Object> properties)
+ {
+ FacesMessageStorage facesMessageStorage = ExtValUtils.getStorage(
+ FacesMessageStorage.class, FacesMessageStorage.class.getName());
+
+ if(facesMessageStorage != null)
+ {
+ facesMessageStorage.addAll();
+ ExtValUtils.resetStorage(FacesMessageStorage.class, FacesMessageStorage.class.getName());
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/HtmlCoreComponentsValidationExceptionInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/HtmlCoreComponentsValidationExceptionInterceptor.java
new file mode 100644
index 0000000..ed7c928
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/HtmlCoreComponentsValidationExceptionInterceptor.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.message.LabeledMessage;
+import org.apache.myfaces.extensions.validator.core.validation.exception.RequiredValidatorException;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.html.HtmlInputText;
+import javax.faces.component.html.HtmlInputSecret;
+import javax.faces.component.html.HtmlSelectBooleanCheckbox;
+import javax.faces.component.html.HtmlSelectOneListbox;
+import javax.faces.component.html.HtmlSelectOneMenu;
+import javax.faces.component.html.HtmlSelectOneRadio;
+import javax.faces.component.html.HtmlSelectManyCheckbox;
+import javax.faces.component.html.HtmlSelectManyListbox;
+import javax.faces.component.html.HtmlSelectManyMenu;
+import javax.faces.component.html.HtmlInputTextarea;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import javax.faces.application.FacesMessage;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(100)
+@UsageInformation(UsageCategory.INTERNAL)
+public class HtmlCoreComponentsValidationExceptionInterceptor implements ValidationExceptionInterceptor
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public boolean afterThrowing(UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException validatorException,
+ ValidationStrategy validatorExceptionSource)
+ {
+ if(processComponent(uiComponent))
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ FacesMessage facesMessage = ExtValUtils.convertFacesMessage(validatorException.getFacesMessage());
+
+ tryToUseInlineMessage(uiComponent, validatorException);
+
+ tryToUseLabel(facesContext, uiComponent, metaDataEntry, facesMessage);
+
+ tryToBlocksNavigation(uiComponent, metaDataEntry, facesMessage);
+ }
+ return true;
+ }
+
+ private void tryToUseInlineMessage(UIComponent uiComponent, ValidatorException validatorException)
+ {
+ FacesMessage facesMessage = validatorException.getFacesMessage();
+ String inlineMessage;
+
+ if(validatorException instanceof RequiredValidatorException)
+ {
+ inlineMessage = getInlineRequiredMessage(uiComponent);
+
+ if(inlineMessage != null)
+ {
+ facesMessage.setSummary(inlineMessage);
+ facesMessage.setDetail(inlineMessage);
+ }
+ }
+ else
+ {
+ //
+ inlineMessage = getInlineValidatorMessage(uiComponent);
+
+ if(inlineMessage != null)
+ {
+ facesMessage.setSummary(inlineMessage);
+ facesMessage.setDetail(inlineMessage);
+ }
+ }
+ }
+
+ private void tryToUseLabel(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ FacesMessage facesMessage)
+ {
+ String label = (String) ReflectionUtils.tryToInvokeMethod(uiComponent,
+ ReflectionUtils.tryToGetMethod(uiComponent.getClass(), "getLabel"));
+
+ if(label == null)
+ {
+ label = uiComponent.getClientId(facesContext);
+ }
+
+ //override the label if the annotation provides a label
+ if(metaDataEntry != null && metaDataEntry.getProperty(PropertyInformationKeys.LABEL) != null)
+ {
+ label = metaDataEntry.getProperty(PropertyInformationKeys.LABEL, String.class);
+ }
+
+ if(facesMessage instanceof LabeledMessage)
+ {
+ ((LabeledMessage)facesMessage).setLabelText(label);
+ }
+ //if someone uses a normal faces message
+ else
+ {
+ for(int i = 0; i < 3; i++)
+ {
+ ExtValUtils.tryToPlaceLabel(facesMessage, label, i);
+ }
+ }
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "check if it is still required here")
+ private void tryToBlocksNavigation(UIComponent uiComponent, MetaDataEntry metaDataEntry, FacesMessage facesMessage)
+ {
+ if(metaDataEntry != null && metaDataEntry.getValue() instanceof Annotation)
+ {
+ //correct severity is e.g. provided by ViolationSeverityValidationExceptionInterceptor
+ ExtValUtils.tryToBlocksNavigationForComponent(uiComponent, facesMessage);
+ }
+ }
+
+ private String getInlineRequiredMessage(UIComponent uiComponent)
+ {
+ return (String)ReflectionUtils.tryToInvokeMethod(uiComponent,
+ ReflectionUtils.tryToGetMethod(uiComponent.getClass(), "getRequiredMessage"));
+ }
+
+ private String getInlineValidatorMessage(UIComponent uiComponent)
+ {
+ return (String)ReflectionUtils.tryToInvokeMethod(uiComponent,
+ ReflectionUtils.tryToGetMethod(uiComponent.getClass(), "getValidatorMessage"));
+ }
+
+ protected boolean processComponent(UIComponent uiComponent)
+ {
+ return uiComponent instanceof HtmlInputText ||
+ uiComponent instanceof HtmlInputSecret ||
+ uiComponent instanceof HtmlSelectBooleanCheckbox ||
+ uiComponent instanceof HtmlSelectOneListbox ||
+ uiComponent instanceof HtmlSelectOneMenu ||
+ uiComponent instanceof HtmlSelectOneRadio ||
+ uiComponent instanceof HtmlSelectManyCheckbox ||
+ uiComponent instanceof HtmlSelectManyListbox ||
+ uiComponent instanceof HtmlSelectManyMenu ||
+ uiComponent instanceof HtmlInputTextarea;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/MetaDataExtractionInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/MetaDataExtractionInterceptor.java
new file mode 100644
index 0000000..01d21de
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/MetaDataExtractionInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrderSupport;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+@InvocationOrderSupport
+@UsageInformation(UsageCategory.API)
+public interface MetaDataExtractionInterceptor
+{
+ /**
+ *
+ * @param propertyInformation the information entry which contains information about the property
+ */
+ void afterExtracting(PropertyInformation propertyInformation);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/PropertyValidationInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/PropertyValidationInterceptor.java
new file mode 100644
index 0000000..04cf527
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/PropertyValidationInterceptor.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.InvocationOrderSupport;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrderSupport
+@UsageInformation(UsageCategory.API)
+public interface PropertyValidationInterceptor extends ValidationParameter
+{
+ /**
+ * @return false if the validation process should be bypassed
+ */
+ boolean beforeValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ Map<String, Object> properties);
+
+ /**
+ * processed if validation was executed
+ * in contrast to ValidationExceptionInterceptor it gets executed in any case
+ */
+ void afterValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ Map<String, Object> properties);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/RendererInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/RendererInterceptor.java
new file mode 100644
index 0000000..431f054
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/RendererInterceptor.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipBeforeInterceptorsException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipRendererDelegationException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipAfterInterceptorsException;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.convert.ConverterException;
+import javax.faces.render.Renderer;
+import java.io.IOException;
+
+/**
+ * Allows to intercept renderer methods.<br/>
+ * Base mechanism of extval. It allows to add custom infrastructures.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface RendererInterceptor
+{
+ String getInterceptorId();
+
+ Object getReturnValueOnSkipRendererDelegationException(
+ SkipRendererDelegationException skipRendererDelegationException, Object currentReturnValue);
+
+ /*
+ * before
+ */
+ void beforeDecode(FacesContext facesContext, UIComponent uiComponent, Renderer renderer)
+ throws SkipBeforeInterceptorsException, SkipRendererDelegationException;
+
+ void beforeEncodeBegin(FacesContext facesContext, UIComponent uiComponent, Renderer renderer)
+ throws IOException, SkipBeforeInterceptorsException, SkipRendererDelegationException;
+
+ void beforeEncodeChildren(FacesContext facesContext, UIComponent uiComponent, Renderer renderer)
+ throws IOException, SkipBeforeInterceptorsException, SkipRendererDelegationException;
+
+ void beforeEncodeEnd(FacesContext facesContext, UIComponent uiComponent, Renderer renderer)
+ throws IOException, SkipBeforeInterceptorsException, SkipRendererDelegationException;
+
+ void beforeGetConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object o, Renderer renderer)
+ throws ConverterException, SkipBeforeInterceptorsException, SkipRendererDelegationException;
+
+ /*
+ * after
+ */
+ void afterDecode(FacesContext facesContext, UIComponent uiComponent, Renderer renderer)
+ throws SkipAfterInterceptorsException;
+
+ void afterEncodeBegin(FacesContext facesContext, UIComponent uiComponent, Renderer renderer)
+ throws IOException, SkipAfterInterceptorsException;
+
+ void afterEncodeChildren(FacesContext facesContext, UIComponent uiComponent, Renderer renderer)
+ throws IOException, SkipAfterInterceptorsException;
+
+ void afterEncodeEnd(FacesContext facesContext, UIComponent uiComponent, Renderer renderer)
+ throws IOException, SkipAfterInterceptorsException;
+
+ void afterGetConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object o, Renderer renderer)
+ throws ConverterException, SkipAfterInterceptorsException;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ValidationExceptionInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ValidationExceptionInterceptor.java
new file mode 100644
index 0000000..d4ec3d0
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ValidationExceptionInterceptor.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.InvocationOrderSupport;
+
+import javax.faces.component.UIComponent;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * Allows to intercept validatior exceptions.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrderSupport
+@UsageInformation(UsageCategory.API)
+public interface ValidationExceptionInterceptor
+{
+ /**
+ *
+ * @param uiComponent the current component
+ * @param metaDataEntry the meta data entry which contains the meta data of the property
+ * @param convertedObject the converted user input
+ * @param validatorException the current exception
+ * @param validatorExceptionSource validation strategy which threw the exception
+ * @return false to stop throwing the exception
+ */
+ boolean afterThrowing(UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException validatorException,
+ ValidationStrategy validatorExceptionSource);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ValidationInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ValidationInterceptor.java
new file mode 100644
index 0000000..c2e15e0
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ValidationInterceptor.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.SkipValidationEvaluator;
+import org.apache.myfaces.extensions.validator.core.validation.NullValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.EmptyValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.MetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import java.util.Map;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ValidationInterceptor extends AbstractValidationInterceptor
+{
+ @Override
+ protected boolean isRequiredInitializationSupported()
+ {
+ return true;
+ }
+
+ protected void initComponent(FacesContext facesContext, UIComponent uiComponent)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start to init component " + uiComponent.getClass().getName());
+ }
+
+ Map<String, Object> metaDataResult = ExtValUtils
+ .getTransformedMetaDataFor(facesContext, uiComponent, getModuleKey());
+
+ //get component initializer for the current component and configure it
+ //also in case of skipped validation to reset e.g. the required attribute
+ if(!metaDataResult.isEmpty())
+ {
+ ExtValUtils.configureComponentWithMetaData(facesContext, uiComponent, metaDataResult);
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("init component of " + uiComponent.getClass().getName() + " finished");
+ }
+ }
+
+ protected void processValidation(FacesContext facesContext, UIComponent uiComponent, Object convertedObject)
+ {
+ MetaDataExtractor metaDataExtractor = ExtValUtils
+ .getComponentMetaDataExtractorWith(getPropertiesForComponentMetaDataExtractor(uiComponent));
+
+ PropertyInformation propertyInformation = metaDataExtractor.extract(facesContext, uiComponent);
+
+ try
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start validation");
+ }
+
+ processFieldValidation(facesContext, uiComponent, convertedObject, propertyInformation);
+ }
+ finally
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("validation finished");
+ }
+ }
+ }
+
+ protected MetaDataExtractor getComponentMetaDataExtractor(Map<String, Object> properties)
+ {
+ return ExtValUtils.getComponentMetaDataExtractorWith(properties);
+ }
+
+ protected void processFieldValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ PropertyInformation propertyInformation)
+ {
+ ValidationStrategy validationStrategy;
+ SkipValidationEvaluator skipValidationEvaluator = ExtValContext.getContext().getSkipValidationEvaluator();
+ for (MetaDataEntry entry : propertyInformation.getMetaDataEntries())
+ {
+ validationStrategy = ExtValUtils.getValidationStrategyForMetaData(entry.getKey());
+
+ if (validationStrategy != null &&
+ isValidationStrategyCompatibleWithValue(validationStrategy, convertedObject))
+ {
+ if(skipValidationEvaluator.skipValidation(facesContext, uiComponent, validationStrategy, entry))
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("skip validation of " + entry.getValue() +
+ " with " + validationStrategy.getClass().getName());
+ }
+ //don't break maybe there are constraints which don't support the skip-mechanism
+ continue;
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("validate " + entry.getValue() + " with " + validationStrategy.getClass().getName());
+ }
+
+ try
+ {
+ if(entry.getValue() instanceof Annotation)
+ {
+ if(!ExtValUtils.executeLocalBeforeValidationInterceptors(
+ facesContext, uiComponent, convertedObject,
+ PropertyInformation.class.getName(), propertyInformation,
+ entry.getValue(Annotation.class)))
+ {
+ continue;
+ }
+ }
+
+ /*
+ * validation
+ */
+ validationStrategy.validate(facesContext, uiComponent, entry, convertedObject);
+ }
+ finally
+ {
+ if(entry.getValue() instanceof Annotation)
+ {
+ ExtValUtils.executeLocalAfterValidationInterceptors(
+ facesContext, uiComponent, convertedObject,
+ PropertyInformation.class.getName(), propertyInformation,
+ entry.getValue(Annotation.class));
+ }
+ }
+ }
+ else if(validationStrategy == null && logger.isTraceEnabled())
+ {
+ logger.trace("no validation strategy found for " + entry.getValue());
+ }
+ }
+ }
+
+ protected boolean isValidationStrategyCompatibleWithValue(ValidationStrategy validationStrategy, Object value)
+ {
+ if(value == null)
+ {
+ Class validationStrategyClass = ProxyUtils.getUnproxiedClass(validationStrategy.getClass());
+ return validationStrategyClass.isAnnotationPresent(NullValueAwareValidationStrategy.class);
+ }
+
+ return !"".equals(value) || ProxyUtils.getUnproxiedClass(validationStrategy.getClass())
+ .isAnnotationPresent(EmptyValueAwareValidationStrategy.class);
+ }
+
+ @Override
+ /**
+ * to ensure backward compatibility
+ */
+ protected boolean interpretEmptyStringValuesAsNull()
+ {
+ return false;
+ }
+
+ @Override
+ protected boolean recordProcessedInformation()
+ {
+ return true;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ViolationSeverityValidationExceptionInterceptor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ViolationSeverityValidationExceptionInterceptor.java
new file mode 100644
index 0000000..e934c61
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/interceptor/ViolationSeverityValidationExceptionInterceptor.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.interceptor;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.validator.ValidatorException;
+import javax.faces.application.FacesMessage;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(90)
+@UsageInformation(UsageCategory.INTERNAL)
+public class ViolationSeverityValidationExceptionInterceptor implements ValidationExceptionInterceptor
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public boolean afterThrowing(UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException validatorException,
+ ValidationStrategy validatorExceptionSource)
+ {
+ if(isExtValMetaData(metaDataEntry))
+ {
+ tryToPlaceSeverity(validatorException, metaDataEntry.getValue(Annotation.class));
+ }
+ return true;
+ }
+
+ private boolean isExtValMetaData(MetaDataEntry metaDataEntry)
+ {
+ return metaDataEntry.getValue() instanceof Annotation;
+ }
+
+ private void tryToPlaceSeverity(ValidatorException validatorException, Annotation annotation)
+ {
+ for(FacesMessage.Severity severity : ExtValUtils.getValidationParameterExtractor()
+ .extract(annotation,
+ ExtValUtils.getValidationParameterClassFor(ViolationSeverity.class),
+ FacesMessage.Severity.class))
+ {
+ validatorException.getFacesMessage().setSeverity(severity);
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/AbstractCustomNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/AbstractCustomNameMapper.java
new file mode 100644
index 0000000..47d3865
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/AbstractCustomNameMapper.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.mapper;
+
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A generic implementation. Subclasses just have to now the fully qualified name of the name mapper.
+ *
+ * NameMappers are stateless.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.REUSE)
+public abstract class AbstractCustomNameMapper<T> implements NameMapper<T>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+ private NameMapper<T> customNameMapper;
+
+ protected AbstractCustomNameMapper()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public String createName(T source)
+ {
+ if (customNameMapper == null)
+ {
+ String className = getCustomNameMapperClassName();
+
+ if (className != null)
+ {
+ customNameMapper = (NameMapper<T>) ClassUtils.tryToInstantiateClassForName(className);
+ }
+ }
+
+ return (customNameMapper != null) ? customNameMapper.createName(source) : null;
+ }
+
+ protected abstract String getCustomNameMapperClassName();
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/NameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/NameMapper.java
new file mode 100644
index 0000000..d831cb6
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/NameMapper.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.mapper;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrderSupport;
+
+/**
+ * Interface for name mappers.
+ * A name mapper calculates a name for a given source object.
+ * e.g. Meta-Data Key (e.g.: annotation class name) -> ValidationStrategy
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrderSupport
+@UsageInformation(UsageCategory.API)
+public interface NameMapper<T>
+{
+ String createName(T source);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/SubMapperAwareNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/SubMapperAwareNameMapper.java
new file mode 100644
index 0000000..7e6ddd2
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/SubMapperAwareNameMapper.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.mapper;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * interface for name-mappers which have to delegate to other (sub-)name-mappers
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface SubMapperAwareNameMapper<T> extends NameMapper<T>
+{
+ void addNameMapper(NameMapper<T> nameMapper);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/CommonMetaDataKeys.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/CommonMetaDataKeys.java
new file mode 100644
index 0000000..f1ae637
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/CommonMetaDataKeys.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * helper for frequent meta-data keys
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+/*
+ * placed in core to avoid duplicated information in multiple modules (validation module and component-support module)
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface CommonMetaDataKeys
+{
+ static final String REQUIRED = "required";
+ static final String WEAK_REQUIRED = "weak_required";
+
+ static final String MIN_LENGTH = "min_length";
+ static final String MIN_LENGTH_DEFAULT = "min_length_default";
+
+ static final String MAX_LENGTH = "max_length";
+ static final String MAX_LENGTH_DEFAULT = "max_length_default";
+
+ static final String RANGE_MIN = "range_min";
+ static final String RANGE_MIN_DEFAULT = "range_min_default";
+
+ static final String RANGE_MAX = "range_max";
+ static final String RANGE_MAX_DEFAULT = "range_max_default";
+
+ static final String PATTERN = "pattern";
+ static final String PATTERN_VALIDATION_ERROR_MESSAGE = "pattern_validation_error_message";
+ static final String EMAIL = "email";
+
+ static final String CUSTOM = "custom";
+ static final String SKIP_VALIDATION = "skip_validation";
+ static final String DISABLE_CLIENT_SIDE_VALIDATION = "disable_client_side_validation";
+ //available for add-ons not used internally due to performance reasons
+ static final String DISABLE_SHOW_INDICATION = "disable_show_indication";
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/MetaDataEntry.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/MetaDataEntry.java
new file mode 100644
index 0000000..1e54582
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/MetaDataEntry.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Data holder which stores the meta-data and some information where the meta-data was around.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public class MetaDataEntry
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private String key;
+ private Object value;
+ private Map<String, Object> properties = new HashMap<String, Object>();
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public void setKey(String key)
+ {
+ if(this.logger.isTraceEnabled())
+ {
+ this.logger.trace("setting meta-data key: " + key);
+ }
+
+ this.key = key;
+ }
+
+ public Object getValue()
+ {
+ return value;
+ }
+
+ public <T> T getValue(Class<T> targetClass)
+ {
+ return (T)getValue();
+ }
+
+ public void setValue(Object value)
+ {
+ if(this.logger.isTraceEnabled())
+ {
+ this.logger.trace("setting meta-data value: " + value);
+ }
+
+ this.value = value;
+ }
+
+ public void setProperties(Map<String, Object> properties)
+ {
+ this.properties = properties;
+ }
+
+ public Object getProperty(String key)
+ {
+ return this.properties.get(key);
+ }
+
+ public <T> T getProperty(String key, Class<T> targetClass)
+ {
+ return (T)getProperty(key);
+ }
+
+ public void setProperty(String key, Object value)
+ {
+ if(this.logger.isTraceEnabled())
+ {
+ this.logger.trace("new property added key: " + key + " value: " + value + " for metadata-key: " + this.key);
+ }
+
+ this.properties.put(key, value);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/ComponentMetaDataExtractorFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/ComponentMetaDataExtractorFactory.java
new file mode 100644
index 0000000..f1dc26d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/ComponentMetaDataExtractorFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.extractor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import java.util.Map;
+
+/**
+ * The interface for all factories which create meta-data extractors
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface ComponentMetaDataExtractorFactory
+{
+ MetaDataExtractor create();
+
+ MetaDataExtractor createWith(Map<String, Object> properties);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/DefaultComponentMetaDataExtractor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/DefaultComponentMetaDataExtractor.java
new file mode 100644
index 0000000..452876a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/DefaultComponentMetaDataExtractor.java
@@ -0,0 +1,379 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.extractor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.property.DefaultPropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.storage.MetaDataStorage;
+import org.apache.myfaces.extensions.validator.core.storage.PropertyStorage;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Default implementation which extracts meta-data (e.g. the annotations) of the value binding of a component.
+ * It extracts the meta-data of the field and the property.
+ * (Also the annotations of super classes and interfaces.)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultComponentMetaDataExtractor implements MetaDataExtractor
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public DefaultComponentMetaDataExtractor()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ @ToDo(Priority.MEDIUM)
+ public PropertyInformation extract(FacesContext facesContext, Object object)
+ {
+ PropertyInformation propertyInformation = new DefaultPropertyInformation();
+
+ //should never occur
+ if (!(object instanceof UIComponent))
+ {
+ if (this.logger.isWarnEnabled() && object != null)
+ {
+ this.logger.warn(object.getClass() + " is no valid component");
+ }
+ return propertyInformation;
+ }
+
+ UIComponent uiComponent = (UIComponent) object;
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("start extracting meta-data of " + uiComponent.getClass().getName());
+ }
+
+ PropertyDetails propertyDetails = ExtValUtils.getELHelper().getPropertyDetailsOfValueBinding(uiComponent);
+
+ if (propertyDetails == null)
+ {
+ return propertyInformation;
+ }
+
+ /*
+ * get bean class and property name
+ */
+ Class entityClass = ProxyUtils.getUnproxiedClass(propertyDetails.getBaseObject().getClass());
+
+ //create
+ propertyInformation.setInformation(PropertyInformationKeys.PROPERTY_DETAILS, propertyDetails);
+
+ if (isCached(entityClass, propertyDetails.getProperty()))
+ {
+ for (MetaDataEntry metaDataEntry : getCachedMetaData(entityClass, propertyDetails.getProperty()))
+ {
+ propertyInformation.addMetaDataEntry(metaDataEntry);
+ }
+ }
+ else
+ {
+ extractAnnotations(propertyInformation, propertyDetails, entityClass);
+ cacheMetaData(propertyInformation);
+ }
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("extract finished");
+ }
+
+ return propertyInformation;
+ }
+
+ private boolean isCached(Class entityClass, String property)
+ {
+ return getMetaDataStorage().containsMetaDataFor(entityClass, property);
+ }
+
+ private void cacheMetaData(PropertyInformation propertyInformation)
+ {
+ getMetaDataStorage().storeMetaDataOf(propertyInformation);
+ }
+
+ private MetaDataEntry[] getCachedMetaData(Class entityClass, String property)
+ {
+ return getMetaDataStorage().getMetaData(entityClass, property);
+ }
+
+ private MetaDataStorage getMetaDataStorage()
+ {
+ return ExtValUtils.getStorage(MetaDataStorage.class, MetaDataStorage.class.getName());
+ }
+
+ private boolean isCachedField(Class entity, String property)
+ {
+ return getPropertyStorage().containsField(entity, property);
+ }
+
+ private void tryToCachedField(Class entity, String property, Field field)
+ {
+ PropertyStorage propertyStorage = getPropertyStorage();
+ if (!propertyStorage.containsField(entity, property))
+ {
+ propertyStorage.storeField(entity, property, field);
+ }
+ }
+
+ private Field getCachedField(Class entity, String property)
+ {
+ return getPropertyStorage().getField(entity, property);
+ }
+
+ private boolean isCachedMethod(Class entity, String property)
+ {
+ return getPropertyStorage().containsMethod(entity, property);
+ }
+
+ private void tryToCachedMethod(Class entity, String property, Method method)
+ {
+ PropertyStorage propertyStorage = getPropertyStorage();
+ if (!propertyStorage.containsMethod(entity, property))
+ {
+ propertyStorage.storeMethod(entity, property, method);
+ }
+ }
+
+ private Method getCachedMethod(Class entity, String property)
+ {
+ return getPropertyStorage().getMethod(entity, property);
+ }
+
+ private PropertyStorage getPropertyStorage()
+ {
+ return ExtValUtils.getStorage(PropertyStorage.class, PropertyStorage.class.getName());
+ }
+
+ protected void extractAnnotations(
+ PropertyInformation propertyInformation, PropertyDetails propertyDetails, Class entityClass)
+ {
+ while (!Object.class.getName().equals(entityClass.getName()))
+ {
+ addPropertyAccessAnnotations(entityClass, propertyDetails.getProperty(), propertyInformation);
+ addFieldAccessAnnotations(entityClass, propertyDetails.getProperty(), propertyInformation);
+
+ processInterfaces(entityClass, propertyDetails, propertyInformation);
+
+ entityClass = entityClass.getSuperclass();
+ }
+ }
+
+ private void processInterfaces(
+ Class currentClass, PropertyDetails propertyDetails, PropertyInformation propertyInformation)
+ {
+ for (Class currentInterface : currentClass.getInterfaces())
+ {
+ addPropertyAccessAnnotations(currentInterface, propertyDetails.getProperty(), propertyInformation);
+
+ processInterfaces(currentInterface, propertyDetails, propertyInformation);
+ }
+ }
+
+ protected void addPropertyAccessAnnotations(Class entity, String property,
+ PropertyInformation propertyInformation)
+ {
+ Method method = tryToGetReadMethod(entity, property);
+
+ if (method == null)
+ {
+ method = tryToGetReadMethodManually(entity, property);
+ }
+
+ if (method != null)
+ {
+ tryToCachedMethod(entity, property, method);
+ addAnnotationToAnnotationEntries(Arrays.asList(method.getAnnotations()), propertyInformation);
+ }
+ }
+
+ private Method tryToGetReadMethod(Class entity, String property)
+ {
+ if (isCachedMethod(entity, property))
+ {
+ return getCachedMethod(entity, property);
+ }
+
+ if (useBeanInfo())
+ {
+ try
+ {
+ BeanInfo beanInfo = Introspector.getBeanInfo(entity);
+ for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors())
+ {
+ if (property.equals(propertyDescriptor.getName()) && propertyDescriptor.getReadMethod() != null)
+ {
+ return propertyDescriptor.getReadMethod();
+ }
+ }
+ }
+ catch (IntrospectionException e)
+ {
+ //do nothing
+ }
+ }
+ return null;
+ }
+
+ private boolean useBeanInfo()
+ {
+ return Boolean.TRUE.equals(ExtValContext.getContext().getGlobalProperty(BeanInfo.class.getName()));
+ }
+
+ private Method tryToGetReadMethodManually(Class entity, String property)
+ {
+ property = property.substring(0, 1).toUpperCase() + property.substring(1);
+
+ try
+ {
+ //changed to official bean spec. due to caching there is no performance issue any more
+ return entity.getDeclaredMethod("is" + property);
+ }
+ catch (NoSuchMethodException e)
+ {
+ try
+ {
+ return entity.getDeclaredMethod("get" + property);
+ }
+ catch (NoSuchMethodException e1)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("method not found - class: " + entity.getName()
+ + " - methods: " + "get" + property + " " + "is" + property);
+ }
+
+ return null;
+ }
+ }
+ }
+
+ protected void addFieldAccessAnnotations(Class entity, String property,
+ PropertyInformation propertyInformation)
+ {
+ Field field;
+
+ try
+ {
+ field = getDeclaredField(entity, property);
+ }
+ catch (Exception e)
+ {
+ try
+ {
+ try
+ {
+ field = entity.getDeclaredField("_" + property);
+ }
+ catch (Exception e1)
+ {
+ if (property.length() > 1 &&
+ Character.isUpperCase(property.charAt(0)) &&
+ Character.isUpperCase(property.charAt(1)))
+ {
+ //don't use Introspector#decapitalize here
+ field = entity.getDeclaredField(property.substring(0, 1).toLowerCase() + property.substring(1));
+ }
+ else
+ {
+ field = entity.getDeclaredField(Introspector.decapitalize(property));
+ }
+ }
+ }
+ catch (NoSuchFieldException e1)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("field " + property + " or _" + property + " not found", e1);
+ }
+
+ return;
+ }
+ }
+
+ if (field != null)
+ {
+ tryToCachedField(entity, property, field);
+ addAnnotationToAnnotationEntries(Arrays.asList(field.getAnnotations()), propertyInformation);
+ }
+ }
+
+ @ToDo(value = Priority.HIGH, description = "add support for instances wrapped with cglib")
+ private Field getDeclaredField(Class entity, String property) throws NoSuchFieldException
+ {
+ if (isCachedField(entity, property))
+ {
+ return getCachedField(entity, property);
+ }
+
+ return entity.getDeclaredField(property);
+ }
+
+ protected void addAnnotationToAnnotationEntries(
+ List<Annotation> annotations, PropertyInformation propertyInformation)
+ {
+ for (Annotation annotation : annotations)
+ {
+ propertyInformation.addMetaDataEntry(createMetaDataEntryForAnnotation(annotation));
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace(annotation.getClass().getName() + " found");
+ }
+ }
+ }
+
+ protected MetaDataEntry createMetaDataEntryForAnnotation(Annotation foundAnnotation)
+ {
+ MetaDataEntry entry = new MetaDataEntry();
+
+ entry.setKey(foundAnnotation.annotationType().getName());
+ entry.setValue(foundAnnotation);
+
+ return entry;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/DefaultComponentMetaDataExtractorFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/DefaultComponentMetaDataExtractorFactory.java
new file mode 100644
index 0000000..8f7645b
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/DefaultComponentMetaDataExtractorFactory.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.extractor;
+
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This factory creates a meta-data extractor which extracts the meta-data
+ * of the value binding of a component.
+ * <p/>
+ * order:<br/>
+ * <ol>
+ * <li>configured meta-data extractor (web.xml)</li>
+ * <li>configured meta-data extractor (information provider bean)</li>
+ * <li>default implementation</li>
+ * </ol>
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultComponentMetaDataExtractorFactory implements ComponentMetaDataExtractorFactory
+{
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private static MetaDataExtractor metaDataExtractor = null;
+
+ public DefaultComponentMetaDataExtractorFactory()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "logging")
+ public MetaDataExtractor create()
+ {
+ return createWith(null);
+ }
+
+ public MetaDataExtractor createWith(Map<String, Object> properties)
+ {
+ if (metaDataExtractor == null)
+ {
+ List<String> metaDataExtractorClassNames = new ArrayList<String>();
+
+ metaDataExtractorClassNames.add(WebXmlParameter.CUSTOM_COMPONENT_META_DATA_EXTRACTOR);
+ metaDataExtractorClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.COMPONENT_META_DATA_EXTRACTOR));
+ metaDataExtractorClassNames.add(DefaultComponentMetaDataExtractor.class.getName());
+
+ for (String className : metaDataExtractorClassNames)
+ {
+ metaDataExtractor = (MetaDataExtractor) ClassUtils.tryToInstantiateClassForName(className);
+
+ if (metaDataExtractor != null)
+ {
+ break;
+ }
+ }
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(metaDataExtractor.getClass().getName() + " created");
+ }
+
+ return ExtValUtils.createInterceptedMetaDataExtractorWith(metaDataExtractor, properties);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/MetaDataExtractor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/MetaDataExtractor.java
new file mode 100644
index 0000000..fd4051d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/extractor/MetaDataExtractor.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.extractor;
+
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * An meta-data extractor is responsible to analyze an object
+ * and returns all available meta-data information
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface MetaDataExtractor
+{
+ PropertyInformation extract(FacesContext facesContext, Object object);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/BeanMetaDataTransformerAdapter.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/BeanMetaDataTransformerAdapter.java
new file mode 100644
index 0000000..569912a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/BeanMetaDataTransformerAdapter.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * it's just a helper for proxies - you just need it, if you define the equivalent validation strategy as bean and
+ * e.g. spring creates a proxy for it.
+ *
+ * if there is also a proxy for the extractor you can use the className property to manually repeat the
+ * full qualified class name.
+ *
+ * @see org.apache.myfaces.extensions.validator.core.validation.strategy.BeanValidationStrategyAdapter
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.REUSE})
+public interface BeanMetaDataTransformerAdapter extends MetaDataTransformer
+{
+ String getMetaDataTransformerClassName();
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/BeanMetaDataTransformerAdapterImpl.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/BeanMetaDataTransformerAdapterImpl.java
new file mode 100644
index 0000000..10ea819
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/BeanMetaDataTransformerAdapterImpl.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+
+/**
+ * it's just a helper for proxies - you just need it, if you define the equivalent validation strategy as bean and
+ * e.g. spring creates a proxy for it.
+ *
+ * if there is also a proxy for the transformer you can use the className property to manually repeat the
+ * full qualified class name.
+ *
+ * @see org.apache.myfaces.extensions.validator.core.validation.strategy.BeanValidationStrategyAdapter
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.REUSE})
+public class BeanMetaDataTransformerAdapterImpl implements MetaDataTransformer, BeanMetaDataTransformerAdapter
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private MetaDataTransformer metaDataTransformer;
+ private String metaDataTransformerClassName;
+
+ public Map<String, Object> convertMetaData(MetaDataEntry metaDataEntry)
+ {
+ return this.metaDataTransformer.convertMetaData(metaDataEntry);
+ }
+
+ public String getMetaDataTransformerClassName()
+ {
+ if(metaDataTransformerClassName != null)
+ {
+ return metaDataTransformerClassName;
+ }
+ if(metaDataTransformer.getClass().getPackage() != null)
+ {
+ metaDataTransformer.getClass();
+ }
+
+ return null;
+ }
+
+ /*
+ * generated
+ */
+ public void setMetaDataTransformerClassName(String metaDataTransformerClassName)
+ {
+ this.metaDataTransformerClassName = metaDataTransformerClassName;
+ }
+
+ public MetaDataTransformer getMetaDataTransformer()
+ {
+ return metaDataTransformer;
+ }
+
+ public void setMetaDataTransformer(MetaDataTransformer metaDataTransformer)
+ {
+ this.metaDataTransformer = metaDataTransformer;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/DefaultMetaDataTransformerFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/DefaultMetaDataTransformerFactory.java
new file mode 100644
index 0000000..32c3aee
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/DefaultMetaDataTransformerFactory.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.factory.ClassMappingFactory;
+import org.apache.myfaces.extensions.validator.core.factory.AbstractNameMapperAwareFactory;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.BeanValidationStrategyAdapter;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.IdentifiableValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.mapper.SubMapperAwareNameMapper;
+import org.apache.myfaces.extensions.validator.core.Nested;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationEntry;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper.
+ ValidationStrategyToMetaDataTransformerSubMapperAwareNameMapper;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Factory which creates the MetaDataTransformer for a given ValidationStrategy
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+/*
+ * ValidationStrategy -> MetaDataTransformer instead of Meta-Data -> MetaDataTransformer
+ * to avoid a second static mapping e.g. for jpa annotations
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class DefaultMetaDataTransformerFactory extends AbstractNameMapperAwareFactory<ValidationStrategy>
+ implements ClassMappingFactory<ValidationStrategy, MetaDataTransformer>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Map<String, String> validationStrategyToMetaDataTransformerMapping;
+ private List<NameMapper<ValidationStrategy>> nameMapperList = new ArrayList<NameMapper<ValidationStrategy>>();
+ private List<NameMapper<ValidationStrategy>> subNameMapperList =
+ new ArrayList<NameMapper<ValidationStrategy>>();
+
+ public DefaultMetaDataTransformerFactory()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+
+ //since there is no guarantee that the startup listener of the core gets executed first
+ register(new ValidationStrategyToMetaDataTransformerSubMapperAwareNameMapper());
+ }
+
+ public MetaDataTransformer create(ValidationStrategy validationStrategy)
+ {
+ String validationStrategyName = createValidationStrategyName(validationStrategy);
+
+ tryToInitStaticMappings();
+
+ MetaDataTransformer metaDataTransformer =
+ tryToResolveCachedMetaDataTransformer(validationStrategy, validationStrategyName);
+
+ if(metaDataTransformer != null)
+ {
+ return metaDataTransformer;
+ }
+
+ return createAndCacheMetaDataTransformer(validationStrategy, validationStrategyName);
+ }
+
+ private String createValidationStrategyName(ValidationStrategy validationStrategy)
+ {
+ boolean isProxyDetected = isProxy(validationStrategy);
+ //in case of a proxy and the usage of a BeanValidationStrategyAdapter
+ if (isProxyDetected && validationStrategy instanceof BeanValidationStrategyAdapter)
+ {
+ return ((BeanValidationStrategyAdapter)validationStrategy)
+ .getValidationStrategyClassName();
+ }
+
+ return !isProxyDetected ? ProxyUtils.getClassName(validationStrategy.getClass()) : null;
+ }
+
+ private void tryToInitStaticMappings()
+ {
+ if (validationStrategyToMetaDataTransformerMapping == null)
+ {
+ initStaticMappings();
+ }
+ }
+
+ private boolean isProxy(ValidationStrategy validationStrategy)
+ {
+ return validationStrategy.getClass().getPackage() == null;
+ }
+
+ private MetaDataTransformer createAndCacheMetaDataTransformer(
+ ValidationStrategy validationStrategy, String validationStrategyName)
+ {
+ MetaDataTransformer metaDataTransformer;
+ String transformerName;
+ //null -> use name mappers
+ for (NameMapper<ValidationStrategy> nameMapper : nameMapperList)
+ {
+ transformerName = nameMapper.createName(validationStrategy);
+
+ if (transformerName == null)
+ {
+ continue;
+ }
+
+ metaDataTransformer = tryToCreateAndCacheMetaDataTransformer(
+ validationStrategy, validationStrategyName, transformerName);
+
+ if(metaDataTransformer != null)
+ {
+ return metaDataTransformer;
+ }
+ }
+
+ return null;
+ }
+
+ private MetaDataTransformer tryToResolveCachedMetaDataTransformer(
+ ValidationStrategy validationStrategy, String validationStrategyName)
+ {
+ if (validationStrategyToMetaDataTransformerMapping.containsKey(validationStrategyName))
+ {
+ return (MetaDataTransformer)ClassUtils.tryToInstantiateClassForName(
+ validationStrategyToMetaDataTransformerMapping.get(validationStrategyName));
+ }
+
+ if(validationStrategy instanceof IdentifiableValidationStrategy)
+ {
+ String newValidationStrategyName = validationStrategyName + IdentifiableValidationStrategy.ID_PREFIX +
+ ((IdentifiableValidationStrategy)validationStrategy).getId();
+
+ if (validationStrategyToMetaDataTransformerMapping.containsKey(newValidationStrategyName))
+ {
+ return (MetaDataTransformer)ClassUtils.tryToInstantiateClassForName(
+ validationStrategyToMetaDataTransformerMapping.get(newValidationStrategyName));
+ }
+ }
+
+ return null;
+ }
+
+ private MetaDataTransformer tryToCreateAndCacheMetaDataTransformer(
+ ValidationStrategy validationStrategy, String validationStrategyName, String transformerName)
+ {
+ MetaDataTransformer metaDataTransformer = (MetaDataTransformer)
+ ClassUtils.tryToInstantiateClassForName(transformerName);
+
+ if (metaDataTransformer != null)
+ {
+ if(validationStrategyName != null)
+ {
+ if(validationStrategy instanceof IdentifiableValidationStrategy)
+ {
+ validationStrategyName += IdentifiableValidationStrategy.ID_PREFIX +
+ ((IdentifiableValidationStrategy)validationStrategy).getId();
+ }
+ addMapping(validationStrategyName, transformerName);
+ }
+ return metaDataTransformer;
+ }
+
+ return null;
+ }
+
+ private synchronized void initStaticMappings()
+ {
+ validationStrategyToMetaDataTransformerMapping = new HashMap<String, String>();
+
+ //setup internal static mappings
+ for (StaticConfiguration<String, String> staticConfig :
+ ExtValContext.getContext().getStaticConfiguration(
+ StaticConfigurationNames.VALIDATION_STRATEGY_TO_META_DATA_TRANSFORMER_CONFIG))
+ {
+ setupMappings(staticConfig.getMapping());
+ }
+ }
+
+ private void setupMappings(List<StaticConfigurationEntry<String, String>> mappings)
+ {
+ for(StaticConfigurationEntry<String, String> mapping : mappings)
+ {
+ addMapping(mapping.getSource(), mapping.getTarget());
+ }
+ }
+
+ private synchronized void addMapping(String validationStrategyName, String transformerName)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("adding validation strategy to meta-data transformer mapping: "
+ + validationStrategyName + " -> " + transformerName);
+ }
+
+ validationStrategyToMetaDataTransformerMapping.put(validationStrategyName, transformerName);
+ }
+
+ protected List<NameMapper<ValidationStrategy>> getNameMapperList()
+ {
+ return new SortedNameMapperList<NameMapper<ValidationStrategy>>(this.nameMapperList, this.subNameMapperList);
+ }
+
+ @Override
+ public void register(NameMapper<ValidationStrategy> validationStrategyNameMapper)
+ {
+ tryToInitNameMapperWithExistingSubMappers(validationStrategyNameMapper);
+ super.register(validationStrategyNameMapper);
+ }
+
+ /**
+ * it's a very special case due to the missing order in the execution of startup-listeners (phase listeners)
+ * packaged in faces-config.xml files of jars
+ *
+ * normally the default SubMapperAwareNameMapper should be enough
+ * anyway, if a module adds a new SubMapperAwareNameMapper,
+ * all previous added SubNameMappers have to be added to avoid confusion in special cases.
+ * if a SubMapperAwareNameMapper should be considered as final extend the interface and filter it in addNameMapper
+ *
+ * @param validationStrategyNameMapper which has to be added
+ */
+ private void tryToInitNameMapperWithExistingSubMappers(NameMapper<ValidationStrategy> validationStrategyNameMapper)
+ {
+ if(validationStrategyNameMapper instanceof SubMapperAwareNameMapper)
+ {
+ for(NameMapper<ValidationStrategy> nameMapper : this.subNameMapperList)
+ {
+ if(nameMapper.getClass().isAnnotationPresent(Nested.class))
+ {
+ ((SubMapperAwareNameMapper<ValidationStrategy>)validationStrategyNameMapper)
+ .addNameMapper(nameMapper);
+ }
+ }
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/MetaDataTransformer.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/MetaDataTransformer.java
new file mode 100644
index 0000000..9e504b2
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/MetaDataTransformer.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+
+import java.util.Map;
+
+/**
+ * Allows to transform concrete meta-data to a more abstract form.<br/>
+ * e.g.: @Required, @Column(nullable = false,...), @Length(minimum = 1), ... -> required = true
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+//*Transformer instead of *Converter to avoid naming confusion
+public interface MetaDataTransformer
+{
+ Map<String, Object> convertMetaData(MetaDataEntry metaData);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/SortedNameMapperList.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/SortedNameMapperList.java
new file mode 100644
index 0000000..3bcbb48
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/SortedNameMapperList.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.mapper.SubMapperAwareNameMapper;
+import org.apache.myfaces.extensions.validator.core.Nested;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import java.util.List;
+import java.util.Collections;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation({UsageCategory.INTERNAL})
+class SortedNameMapperList<T extends NameMapper> implements List<T>
+{
+ private List<T> wrapped;
+ private List<T> globalSubNameMapperList;
+
+ SortedNameMapperList(List<T> wrapped, List<T> subNameMapperList)
+ {
+ this.wrapped = wrapped;
+ this.globalSubNameMapperList = subNameMapperList;
+ }
+
+ public boolean add(T t)
+ {
+ if (t != null && t.getClass().isAnnotationPresent(Nested.class))
+ {
+ return addSubNameMapper(t);
+ }
+ else
+ {
+ boolean result = wrapped.add(t);
+
+ Collections.sort(wrapped, new Comparator<T>()
+ {
+ public int compare(T nm1, T nm2)
+ {
+ if (nm1 instanceof SubMapperAwareNameMapper && nm2 instanceof SubMapperAwareNameMapper)
+ {
+ return 0;
+ }
+ return nm1 instanceof SubMapperAwareNameMapper ? 1 : -1;
+ }
+ });
+ return result;
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private boolean addSubNameMapper(T subNameMapper)
+ {
+ boolean result = false;
+ for (NameMapper nameMapper : this.wrapped)
+ {
+ if (nameMapper instanceof SubMapperAwareNameMapper)
+ {
+ ((SubMapperAwareNameMapper) nameMapper).addNameMapper(subNameMapper);
+ result = true;
+ }
+ }
+
+ tryToAddMapperAsGlobalSubNameMapper(subNameMapper);
+ return result;
+ }
+
+ private void tryToAddMapperAsGlobalSubNameMapper(T subNameMapper)
+ {
+ if(!this.globalSubNameMapperList.contains(subNameMapper))
+ {
+ this.globalSubNameMapperList.add(subNameMapper);
+ }
+ }
+
+ /*
+ * generated
+ */
+ public int size()
+ {
+ return wrapped.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return wrapped.isEmpty();
+ }
+
+ public boolean contains(Object o)
+ {
+ return wrapped.contains(o);
+ }
+
+ public Iterator<T> iterator()
+ {
+ return wrapped.iterator();
+ }
+
+ public Object[] toArray()
+ {
+ return wrapped.toArray();
+ }
+
+ @SuppressWarnings({"SuspiciousToArrayCall"})
+ public <T> T[] toArray(T[] a)
+ {
+ return wrapped.toArray(a);
+ }
+
+ public boolean remove(Object o)
+ {
+ return wrapped.remove(o);
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ return wrapped.containsAll(c);
+ }
+
+ public boolean addAll(Collection<? extends T> c)
+ {
+ return wrapped.addAll(c);
+ }
+
+ public boolean addAll(int index, Collection<? extends T> c)
+ {
+ return wrapped.addAll(index, c);
+ }
+
+ public boolean removeAll(Collection<?> c)
+ {
+ return wrapped.removeAll(c);
+ }
+
+ public boolean retainAll(Collection<?> c)
+ {
+ return wrapped.retainAll(c);
+ }
+
+ public void clear()
+ {
+ wrapped.clear();
+ }
+
+ public T get(int index)
+ {
+ return wrapped.get(index);
+ }
+
+ public T set(int index, T element)
+ {
+ return wrapped.set(index, element);
+ }
+
+ public void add(int index, T element)
+ {
+ wrapped.add(index, element);
+ }
+
+ public T remove(int index)
+ {
+ return wrapped.remove(index);
+ }
+
+ public int indexOf(Object o)
+ {
+ return wrapped.indexOf(o);
+ }
+
+ public int lastIndexOf(Object o)
+ {
+ return wrapped.lastIndexOf(o);
+ }
+
+ public ListIterator<T> listIterator()
+ {
+ return wrapped.listIterator();
+ }
+
+ public ListIterator<T> listIterator(int index)
+ {
+ return wrapped.listIterator(index);
+ }
+
+ public List<T> subList(int fromIndex, int toIndex)
+ {
+ return wrapped.subList(fromIndex, toIndex);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/AbstractValidationStrategyToMetaDataTransformerNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/AbstractValidationStrategyToMetaDataTransformerNameMapper.java
new file mode 100644
index 0000000..2dadc16
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/AbstractValidationStrategyToMetaDataTransformerNameMapper.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL})
+public abstract class AbstractValidationStrategyToMetaDataTransformerNameMapper
+ implements NameMapper<ValidationStrategy>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public AbstractValidationStrategyToMetaDataTransformerNameMapper()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/BeanValidationStrategyToMetaDataTransformerNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/BeanValidationStrategyToMetaDataTransformerNameMapper.java
new file mode 100644
index 0000000..e8894d1
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/BeanValidationStrategyToMetaDataTransformerNameMapper.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.BeanValidationStrategyAdapter;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * It's an alternative Mapper - if there is a proxy around the validation strategy.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(500)
+@UsageInformation({UsageCategory.INTERNAL})
+public class BeanValidationStrategyToMetaDataTransformerNameMapper extends
+ AbstractValidationStrategyToMetaDataTransformerNameMapper
+{
+ public String createName(ValidationStrategy validationStrategy)
+ {
+ if(validationStrategy instanceof BeanValidationStrategyAdapter)
+ {
+ return ((BeanValidationStrategyAdapter)validationStrategy).getMetaDataTransformerClassName();
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/CustomConfiguredValidationStrategyToMetaDataTransformerNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/CustomConfiguredValidationStrategyToMetaDataTransformerNameMapper.java
new file mode 100644
index 0000000..e21aaf9
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/CustomConfiguredValidationStrategyToMetaDataTransformerNameMapper.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * To provide a custom NameMapper to map ValidationStrategies to MetaDataTransformers.
+ * (configured via web.xml)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(100)
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class CustomConfiguredValidationStrategyToMetaDataTransformerNameMapper extends
+ AbstractCustomNameMapper<ValidationStrategy>
+{
+ protected String getCustomNameMapperClassName()
+ {
+ return WebXmlParameter.CUSTOM_VALIDATION_STRATEGY_TO_META_DATA_TRANSFORMER_NAME_MAPPER;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/CustomConventionValidationStrategyToMetaDataTransformerNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/CustomConventionValidationStrategyToMetaDataTransformerNameMapper.java
new file mode 100644
index 0000000..cfd080f
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/CustomConventionValidationStrategyToMetaDataTransformerNameMapper.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * To provide a custom NameMapper to map ValidationStrategies to MetaDataTransformers.
+ * (configured via information provider bean)
+ * The bean provides the default name (convention).
+ * It's possible to provide a custom full qualified name. (= customizable convention)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(200)
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class CustomConventionValidationStrategyToMetaDataTransformerNameMapper extends
+ AbstractCustomNameMapper<ValidationStrategy>
+{
+ protected String getCustomNameMapperClassName()
+ {
+ return ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.VALIDATION_STRATEGY_TO_META_DATA_TRANSFORMER_NAME_MAPPER);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/DefaultValidationStrategyToMetaDataTransformerNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/DefaultValidationStrategyToMetaDataTransformerNameMapper.java
new file mode 100644
index 0000000..80e850d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/DefaultValidationStrategyToMetaDataTransformerNameMapper.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.InternalConventionProvider;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+/**
+ * Default implementation which maps ExtVal ValidationStrategies to MetaDataTransformers.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(300)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultValidationStrategyToMetaDataTransformerNameMapper extends
+ AbstractValidationStrategyToMetaDataTransformerNameMapper
+{
+ public String createName(ValidationStrategy validationStrategy)
+ {
+ Class<? extends ValidationStrategy> validationStrategyClass =
+ ProxyUtils.getUnproxiedClass(validationStrategy.getClass(), ValidationStrategy.class);
+
+ return InternalConventionProvider.getMetaDataTransformerClassName(
+ validationStrategyClass,
+ getClassName(validationStrategyClass.getSimpleName()));
+ }
+
+ protected String getClassName(String validationStrategyClassName)
+ {
+ return InternalConventionProvider.getMetaDataTransformerClassName(validationStrategyClassName);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/SimpleValidationStrategyToMetaDataTransformerNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/SimpleValidationStrategyToMetaDataTransformerNameMapper.java
new file mode 100644
index 0000000..4ef175c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/SimpleValidationStrategyToMetaDataTransformerNameMapper.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+/**
+ * It's an alternative Mapper to place ValidationStrategies and MetaDataTransformers in the same package.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(400)
+@UsageInformation({UsageCategory.INTERNAL})
+public class SimpleValidationStrategyToMetaDataTransformerNameMapper extends
+ AbstractValidationStrategyToMetaDataTransformerNameMapper
+{
+ public String createName(ValidationStrategy validationStrategy)
+ {
+ Class<? extends ValidationStrategy> validationStrategyClass =
+ ProxyUtils.getUnproxiedClass(validationStrategy.getClass(), ValidationStrategy.class);
+
+ if(validationStrategyClass.getPackage() == null)
+ {
+ return null;
+ }
+ return getSimpleMetaDataTransformerName(validationStrategyClass.getPackage().getName() + ".",
+ validationStrategyClass.getSimpleName());
+ }
+
+ public String getSimpleMetaDataTransformerName(String validationStrategyPackageName,
+ String validationStrategyClassName)
+ {
+ String postfix = ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.META_DATA_TRANSFORMER_POSTFIX);
+
+ if(validationStrategyClassName.endsWith("ValidationStrategy") ||
+ validationStrategyClassName.endsWith("Strategy"))
+ {
+ return validationStrategyPackageName + validationStrategyClassName
+ .replace(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.VALIDATION_STRATEGY_POSTFIX) ,postfix)
+ .replace("ValidationStrategy", postfix)
+ .replace("Strategy", postfix);
+ }
+
+ //in case of a static validation strategy mapping
+ return validationStrategyPackageName + validationStrategyClassName + postfix;
+ }
+
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/ValidationStrategyToMetaDataTransformerSubMapperAwareNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/ValidationStrategyToMetaDataTransformerSubMapperAwareNameMapper.java
new file mode 100644
index 0000000..56a583b
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/metadata/transformer/mapper/ValidationStrategyToMetaDataTransformerSubMapperAwareNameMapper.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.mapper.SubMapperAwareNameMapper;
+import org.apache.myfaces.extensions.validator.core.Nested;
+import org.apache.myfaces.extensions.validator.core.InvocationOrderComparator;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(100)
+@UsageInformation({UsageCategory.INTERNAL})
+public class ValidationStrategyToMetaDataTransformerSubMapperAwareNameMapper
+ extends AbstractValidationStrategyToMetaDataTransformerNameMapper
+ implements SubMapperAwareNameMapper<ValidationStrategy>
+{
+ private List<NameMapper<ValidationStrategy>> subNameMappers = new ArrayList<NameMapper<ValidationStrategy>>();
+
+ public void addNameMapper(NameMapper<ValidationStrategy> nameMapper)
+ {
+ if(!this.subNameMappers.contains(nameMapper) && nameMapper.getClass().isAnnotationPresent(Nested.class))
+ {
+ this.subNameMappers.add(nameMapper);
+ sortSubNameMappers();
+ }
+ }
+
+ private void sortSubNameMappers()
+ {
+ Collections.sort(this.subNameMappers, new InvocationOrderComparator<NameMapper<ValidationStrategy>>());
+ }
+
+ public String createName(ValidationStrategy source)
+ {
+ String result = null;
+
+ for(NameMapper<ValidationStrategy> mapper : this.subNameMappers)
+ {
+ result = mapper.createName(source);
+
+ if(result != null)
+ {
+ return result;
+ }
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/DefaultPropertyInformation.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/DefaultPropertyInformation.java
new file mode 100644
index 0000000..e45f528
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/DefaultPropertyInformation.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.property;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultPropertyInformation implements PropertyInformation
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Map<String, Object> informationMap = new HashMap<String, Object>();
+ private List<MetaDataEntry> metaDataList = new ArrayList<MetaDataEntry>();
+
+ public boolean containsInformation(String key)
+ {
+ return informationMap.containsKey(key);
+ }
+
+ public Object getInformation(String key)
+ {
+ return informationMap.get(key);
+ }
+
+ public <T> T getInformation(String key, Class<T> targetClass)
+ {
+ return (T) getInformation(key);
+ }
+
+ public void setInformation(String key, Object value)
+ {
+ if(this.logger.isTraceEnabled())
+ {
+ this.logger.trace("new information added key: " + key + " value: " + value);
+ }
+
+ informationMap.put(key, value);
+ }
+
+ public MetaDataEntry[] getMetaDataEntries()
+ {
+ return metaDataList.toArray(new MetaDataEntry[metaDataList.size()]);
+ }
+
+ public void addMetaDataEntry(MetaDataEntry metaDataEntry)
+ {
+ metaDataEntry.setProperties(this.informationMap);
+ this.metaDataList.add(metaDataEntry);
+ }
+
+ public void resetMetaDataEntries()
+ {
+ if(this.logger.isTraceEnabled())
+ {
+ this.logger.trace("resetting meta-data entries");
+ }
+
+ this.metaDataList.clear();
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyDetails.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyDetails.java
new file mode 100644
index 0000000..79037cf
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyDetails.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.property;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+public class PropertyDetails
+{
+ //forms the id for cross-validation within complex components
+ private String key;
+ private Object baseObject;
+ private String property;
+
+ public PropertyDetails(String key, Object baseObject, String property)
+ {
+ this.key = key;
+ this.baseObject = baseObject;
+ this.property = property;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public void setKey(String key)
+ {
+ this.key = key;
+ }
+
+ public Object getBaseObject()
+ {
+ return baseObject;
+ }
+
+ public void setBaseObject(Object baseObject)
+ {
+ this.baseObject = baseObject;
+ }
+
+ public String getProperty()
+ {
+ return property;
+ }
+
+ public void setProperty(String property)
+ {
+ this.property = property;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyInformation.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyInformation.java
new file mode 100644
index 0000000..ad9284f
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyInformation.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.property;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface PropertyInformation
+{
+ boolean containsInformation(String key);
+ Object getInformation(String key);
+ <T> T getInformation(String key, Class<T> targetClass);
+ void setInformation(String key, Object value);
+
+ MetaDataEntry[] getMetaDataEntries();
+ void addMetaDataEntry(MetaDataEntry metaDataEntry);
+ void resetMetaDataEntries();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyInformationKeys.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyInformationKeys.java
new file mode 100644
index 0000000..2fef430
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/property/PropertyInformationKeys.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.property;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface PropertyInformationKeys
+{
+ static final String PROPERTY_DETAILS = "property_details";
+ static final String SKIP_VALIDATION = "skip_validation";
+ static final String LABEL = "label";
+ static final String CUSTOM_PROPERTIES = "custom_properties";
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/proxy/DefaultProxyHelper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/proxy/DefaultProxyHelper.java
new file mode 100644
index 0000000..5785b96
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/proxy/DefaultProxyHelper.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.proxy;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultProxyHelper implements ProxyHelper
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public DefaultProxyHelper()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public <T> Class<T> getUnproxiedClass(Class currentClass, Class<T> targetType)
+ {
+ return (Class<T>)getUnproxiedClass(currentClass);
+ }
+
+ public Class getUnproxiedClass(Class currentClass)
+ {
+ if(isProxiedClass(currentClass))
+ {
+ return currentClass.getSuperclass();
+ }
+ return currentClass;
+ }
+
+ public String getNameOfClass(Class currentClass)
+ {
+ if (isProxiedClass(currentClass))
+ {
+ return currentClass.getSuperclass().getName();
+ }
+ return currentClass.getName();
+ }
+
+ public String getClassNameOfObject(Object object)
+ {
+ if(object != null)
+ {
+ return getNameOfClass(object.getClass());
+ }
+ return null;
+ }
+
+ public boolean isProxiedClass(Class currentClass)
+ {
+ return currentClass.getName().contains("$$EnhancerByCGLIB$$") ||
+ currentClass.getName().contains("$$FastClassByCGLIB$$") ||
+ currentClass.getName().contains("_$$_javassist");
+ }
+
+ public boolean isProxiedObject(Object proxiedObject)
+ {
+ return proxiedObject != null && isProxiedClass(proxiedObject.getClass());
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/proxy/ProxyHelper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/proxy/ProxyHelper.java
new file mode 100644
index 0000000..0ce7e4a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/proxy/ProxyHelper.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.proxy;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ProxyHelper
+{
+ Class getUnproxiedClass(Class currentClass);
+
+ <T> Class<T> getUnproxiedClass(Class currentClass, Class<T> targetType);
+
+ String getNameOfClass(Class proxiedClass);
+
+ String getClassNameOfObject(Object proxiedObject);
+
+ boolean isProxiedClass(Class currentClass);
+
+ boolean isProxiedObject(Object proxiedObject);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/recorder/ProcessedInformationRecorder.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/recorder/ProcessedInformationRecorder.java
new file mode 100644
index 0000000..270f23f
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/recorder/ProcessedInformationRecorder.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.recorder;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+
+/**
+ * Allows to capture converted values.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface ProcessedInformationRecorder
+{
+ void recordUserInput(UIComponent uiComponent, Object value);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/AbstractRenderKitWrapperFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/AbstractRenderKitWrapperFactory.java
new file mode 100644
index 0000000..ac5920c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/AbstractRenderKitWrapperFactory.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.factory.ClassMappingFactory;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.render.RenderKit;
+
+/**
+ * Base for all RenderKitWrapperFactories to force a specific behaviour
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public abstract class AbstractRenderKitWrapperFactory implements ClassMappingFactory<RenderKit, RenderKit>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ protected AbstractRenderKitWrapperFactory wrapped;
+ private boolean deactivated = false;
+
+ protected AbstractRenderKitWrapperFactory()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public void addRenderKitWrapperFactory(AbstractRenderKitWrapperFactory renderKitWrapperFactory)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(renderKitWrapperFactory.getClass().getName() + " added");
+ }
+
+ if(this.wrapped != null)
+ {
+ this.wrapped.addRenderKitWrapperFactory(renderKitWrapperFactory);
+ return;
+ }
+
+ this.wrapped = renderKitWrapperFactory;
+ }
+
+ public void deactivate()
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(getClass().getName() + " deactivated");
+ }
+
+ this.deactivated = true;
+ }
+
+ public boolean isDeactivated()
+ {
+ return deactivated;
+ }
+
+ public final RenderKit create(RenderKit renderKit)
+ {
+ if(isDeactivated())
+ {
+ return null;
+ }
+
+ RenderKit result = null;
+
+ if(this.wrapped != null)
+ {
+ result = this.wrapped.create(renderKit);
+ }
+
+ if(result == null)
+ {
+ return createWrapper(renderKit);
+ }
+
+ return result;
+ }
+
+ protected abstract RenderKit createWrapper(RenderKit renderKit);
+
+ /**
+ * simple test for early config in case of mojarra (incl. the combination with trinidad).
+ * use a custom extval context impl. (see EXTVAL-58) to optimize this check for the target runtime.
+ * this check works for all current implementations since the jsf internals are autom. ready during a request
+ * @return true if the jsf impl. is initialized and it's possible to use it as expected
+ */
+ protected boolean isApplicationInitialized()
+ {
+ return JsfUtils.isApplicationInitialized();
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/DefaultRenderKitWrapperFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/DefaultRenderKitWrapperFactory.java
new file mode 100644
index 0000000..3f26b72
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/DefaultRenderKitWrapperFactory.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+
+import javax.faces.render.RenderKit;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultRenderKitWrapperFactory extends AbstractRenderKitWrapperFactory
+{
+ private RenderKit renderKit;
+ private static final String GENERIC_RENDER_KIT_WRAPPER_FACTORY =
+ "org.apache.myfaces.extensions.validator.generic.renderkit.GenericRenderKitWrapperFactory";
+ private static Boolean useGenericRenderKitWrapperFactory = null;
+
+ protected RenderKit createWrapper(RenderKit renderKit)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("extval renderkit wrapper created for " + renderKit.getClass().getName());
+ }
+
+ //workaround for mojarra (EXTVAL-38)
+ if(useGenericRenderKitWrapperFactory == null)
+ {
+ Class genericFactory = ClassUtils.tryToLoadClassForName(GENERIC_RENDER_KIT_WRAPPER_FACTORY);
+ useGenericRenderKitWrapperFactory = genericFactory != null;
+ }
+
+ if(useGenericRenderKitWrapperFactory)
+ {
+ AbstractRenderKitWrapperFactory renderKitWrapperFactory = (AbstractRenderKitWrapperFactory)ClassUtils
+ .tryToInstantiateClassForName(GENERIC_RENDER_KIT_WRAPPER_FACTORY);
+ return renderKitWrapperFactory.createWrapper(renderKit);
+ }
+
+ if(this.renderKit == null)
+ {
+ this.renderKit = new ExtValRenderKit(renderKit);
+ }
+ return this.renderKit;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValLazyRendererProxy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValLazyRendererProxy.java
new file mode 100644
index 0000000..cb36287
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValLazyRendererProxy.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.render.Renderer;
+import javax.faces.component.UIComponent;
+import javax.faces.convert.ConverterException;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+
+/**
+ * to support a custom proxy
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class ExtValLazyRendererProxy extends Renderer
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Renderer wrapped;
+
+ public ExtValLazyRendererProxy(Renderer renderer)
+ {
+ this.wrapped = renderer;
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("simple proxy created for " + renderer.getClass().getName());
+ }
+ }
+
+ @Override
+ public void decode(FacesContext facesContext, UIComponent uiComponent)
+ {
+ getLazyRenderer().decode(facesContext, uiComponent);
+ }
+
+ @Override
+ public void encodeBegin(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ getLazyRenderer().encodeBegin(facesContext, uiComponent);
+ }
+
+ @Override
+ public void encodeChildren(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ getLazyRenderer().encodeChildren(facesContext, uiComponent);
+ }
+
+ @Override
+ public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ getLazyRenderer().encodeEnd(facesContext, uiComponent);
+ }
+
+ @Override
+ public String convertClientId(FacesContext facesContext, String s)
+ {
+ return getLazyRenderer().convertClientId(facesContext, s);
+ }
+
+ @Override
+ public boolean getRendersChildren()
+ {
+ return getLazyRenderer().getRendersChildren();
+ }
+
+ @Override
+ public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object o)
+ throws ConverterException
+ {
+ return getLazyRenderer().getConvertedValue(facesContext, uiComponent, o);
+ }
+
+ private Renderer getLazyRenderer()
+ {
+ String proxyClassName = (String) ExtValContext.getContext().getGlobalProperty(ExtValRendererProxy.KEY);
+
+ if(proxyClassName != null && !proxyClassName.endsWith(getClass().getName()))
+ {
+ Class targetClass = ClassUtils.tryToLoadClassForName(proxyClassName);
+
+ if(targetClass == null)
+ {
+ throw new IllegalStateException("a custom invalid renderer proxy is configured: " + proxyClassName);
+ }
+
+ Class[] argClasses = new Class[1];
+ argClasses[0] = Renderer.class;
+
+ try
+ {
+ Constructor constructor = targetClass.getConstructor(argClasses);
+ return (Renderer)constructor.newInstance(this.wrapped);
+ }
+ catch (Throwable t)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("couldn't create: " + targetClass.getName());
+ }
+
+ return this.wrapped;
+ }
+ }
+ else
+ {
+ return this.wrapped;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRenderKit.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRenderKit.java
new file mode 100644
index 0000000..547e6f4
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRenderKit.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.ResponseStream;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.RenderKit;
+import javax.faces.render.Renderer;
+import javax.faces.render.ResponseStateManager;
+import javax.faces.render.ClientBehaviorRenderer;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Iterator;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValRenderKit extends RenderKit
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+ protected RenderKit wrapped;
+
+ public ExtValRenderKit(RenderKit wrapped)
+ {
+ this.wrapped = wrapped;
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public void addRenderer(String family, String rendererType, Renderer renderer)
+ {
+ if (renderer instanceof ExtValRendererWrapper)
+ {
+ wrapped.addRenderer(family, rendererType, renderer);
+ }
+ else
+ {
+ wrapped.addRenderer(family, rendererType, createWrapper(renderer));
+ }
+ }
+
+ public Renderer getRenderer(String family, String rendererType)
+ {
+ Renderer renderer = wrapped.getRenderer(family, rendererType);
+
+ if(renderer != null)
+ {
+ return renderer instanceof ExtValRendererWrapper ? renderer : createWrapper(renderer);
+ }
+
+ if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn("no renderer found for family " + family + " and type " + rendererType);
+ }
+
+ return renderer;
+ }
+
+ public ResponseStateManager getResponseStateManager()
+ {
+ return wrapped.getResponseStateManager();
+ }
+
+ public ResponseWriter createResponseWriter(Writer writer, String s, String s1)
+ {
+ return wrapped.createResponseWriter(writer, s, s1);
+ }
+
+ public ResponseStream createResponseStream(OutputStream outputStream)
+ {
+ return wrapped.createResponseStream(outputStream);
+ }
+
+ public Iterator<String> getComponentFamilies()
+ {
+ return wrapped.getComponentFamilies();
+ }
+
+ public Iterator<String> getRendererTypes(String s)
+ {
+ return wrapped.getRendererTypes(s);
+ }
+
+ public void addClientBehaviorRenderer(String s, ClientBehaviorRenderer clientBehaviorRenderer)
+ {
+ wrapped.addClientBehaviorRenderer(s, clientBehaviorRenderer);
+ }
+
+ public ClientBehaviorRenderer getClientBehaviorRenderer(String s)
+ {
+ return wrapped.getClientBehaviorRenderer(s);
+ }
+
+ public Iterator<String> getClientBehaviorRendererTypes()
+ {
+ return wrapped.getClientBehaviorRendererTypes();
+ }
+
+ @UsageInformation(UsageCategory.REUSE)
+ protected Renderer createWrapper(Renderer renderer)
+ {
+ return new ExtValRendererWrapper(renderer);
+ }
+
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRenderKitFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRenderKitFactory.java
new file mode 100644
index 0000000..7376b98
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRenderKitFactory.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.factory.FactoryNames;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.ExtValInformation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.RenderKit;
+import javax.faces.context.FacesContext;
+import java.util.Iterator;
+
+/**
+ * central mechanism which is responsible to create a wrapper for a renderer - starting point of extval.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValRenderKitFactory extends RenderKitFactory
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+ private RenderKitFactory wrapped;
+ private AbstractRenderKitWrapperFactory defaultRenderKitWrapperFactory;
+ private Boolean isDeactivated;
+
+ public ExtValRenderKitFactory(RenderKitFactory renderKitFactory)
+ {
+ this.wrapped = renderKitFactory;
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public void addRenderKit(String s, RenderKit renderKit)
+ {
+ this.wrapped.addRenderKit(s, renderKit);
+ }
+
+ public RenderKit getRenderKit(FacesContext facesContext, String s)
+ {
+ RenderKit renderKit = this.wrapped.getRenderKit(facesContext, s);
+
+ //for mojarra + trinidad
+ if(renderKit == null)
+ {
+ return null;
+ }
+
+ tryToInitDefaultRenderKitWrapperFactory();
+
+ checkRenderKitFactoryDeactivation();
+
+ if(this.isDeactivated)
+ {
+ return renderKit;
+ }
+
+ //test early config in case of mojarra
+ if(!this.defaultRenderKitWrapperFactory.isApplicationInitialized())
+ {
+ return this.defaultRenderKitWrapperFactory.createWrapper(renderKit);
+ }
+
+ return tryToCreateWrapperWithWrapperFactory(renderKit);
+ }
+
+ private void checkRenderKitFactoryDeactivation()
+ {
+ if(this.isDeactivated == null)
+ {
+ if(ExtValUtils.isExtValDeactivated())
+ {
+ this.isDeactivated = true;
+ return;
+ }
+
+ if(this.defaultRenderKitWrapperFactory.isApplicationInitialized())
+ {
+ this.isDeactivated = isRenderKitFactoryDeactivatedViaWebXml();
+ }
+ else
+ {
+ this.isDeactivated = isRenderKitFactoryDeactivatedViaVMParameter();
+ }
+ }
+ }
+
+ private synchronized void tryToInitDefaultRenderKitWrapperFactory()
+ {
+ if(this.defaultRenderKitWrapperFactory == null)
+ {
+ //workaround for mojarra to allow a custom factory during the early config phase
+ //just create the factory with the given name
+ //+it should extend your custom implementation which you register as usual
+ Object customFactory = ClassUtils.tryToInstantiateClassForName(
+ ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME + ".custom.RenderKitWrapperFactory");
+
+ if(customFactory instanceof AbstractRenderKitWrapperFactory)
+ {
+ this.defaultRenderKitWrapperFactory = (AbstractRenderKitWrapperFactory)customFactory;
+ }
+ else
+ {
+ this.defaultRenderKitWrapperFactory = new DefaultRenderKitWrapperFactory();
+ }
+ }
+ }
+
+ private RenderKit tryToCreateWrapperWithWrapperFactory(RenderKit renderKit)
+ {
+ AbstractRenderKitWrapperFactory wrapperFactory = ExtValContext.getContext().getFactoryFinder()
+ .getFactory(FactoryNames.RENDERKIT_WRAPPER_FACTORY, AbstractRenderKitWrapperFactory.class);
+
+ //some component libs e.g. myfaces-trinidad aren't compatible with this clean approach
+ //example see TrinidadModuleStartupListener
+ if(wrapperFactory.isDeactivated())
+ {
+ return renderKit;
+ }
+
+ return wrapperFactory.create(renderKit);
+ }
+
+ public Iterator<String> getRenderKitIds()
+ {
+ return this.wrapped.getRenderKitIds();
+ }
+
+ private boolean isRenderKitFactoryDeactivatedViaWebXml()
+ {
+ return "true".equalsIgnoreCase(WebXmlParameter.DEACTIVATE_RENDER_KIT_FACTORY);
+ }
+
+ private boolean isRenderKitFactoryDeactivatedViaVMParameter()
+ {
+ return "true".equalsIgnoreCase(System
+ .getProperty(ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME +
+ ".DEACTIVATE_RENDER_KIT_FACTORY", "false"));
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRendererProxy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRendererProxy.java
new file mode 100644
index 0000000..ca3613c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRendererProxy.java
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.storage.RendererProxyStorageEntry;
+import org.apache.myfaces.extensions.validator.core.storage.RendererProxyStorage;
+import org.apache.myfaces.extensions.validator.core.JsfProjectStage;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.render.Renderer;
+import javax.faces.component.UIComponent;
+import javax.faces.convert.ConverterException;
+import javax.faces.application.FacesMessage;
+import java.io.IOException;
+
+/**
+ * to avoid multiple calls of renderer methods within renderer interceptors (e.g. for encode, decode,...)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValRendererProxy extends Renderer
+{
+ public static final String KEY = ExtValRendererProxy.class.getName() + ":KEY";
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ protected Renderer wrapped;
+
+ public ExtValRendererProxy(Renderer renderer)
+ {
+ this.wrapped = renderer;
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("proxy created for " + renderer.getClass().getName());
+ }
+ }
+
+ @Override
+ public void decode(FacesContext facesContext, UIComponent uiComponent)
+ {
+ RendererProxyStorageEntry entry = getRendererEntry(facesContext, uiComponent);
+
+ if (!entry.isDecodeCalled())
+ {
+ entry.setDecodeCalled(true);
+
+ try
+ {
+ this.wrapped.decode(facesContext, uiComponent);
+ }
+ catch (RuntimeException r)
+ {
+ resetComponentProxyMapping();
+ throw r;
+ }
+ }
+ else
+ {
+ tryToCreateMessage("decode");
+ }
+ }
+
+ @Override
+ public void encodeBegin(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ RendererProxyStorageEntry entry = getRendererEntry(facesContext, uiComponent);
+
+ if (!entry.isEncodeBeginCalled())
+ {
+ entry.setEncodeBeginCalled(true);
+ try
+ {
+ this.wrapped.encodeBegin(facesContext, uiComponent);
+ }
+ catch (IOException e)
+ {
+ resetComponentProxyMapping();
+ throw e;
+ }
+ catch (RuntimeException r)
+ {
+ resetComponentProxyMapping();
+ throw r;
+ }
+ }
+ else
+ {
+ tryToCreateMessage("encodeBegin");
+ }
+ }
+
+ @Override
+ public void encodeChildren(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ RendererProxyStorageEntry entry = getRendererEntry(facesContext, uiComponent);
+
+ if (!entry.isEncodeChildrenCalled())
+ {
+ entry.setEncodeChildrenCalled(true);
+
+ try
+ {
+ this.wrapped.encodeChildren(facesContext, uiComponent);
+ }
+ catch (IOException e)
+ {
+ resetComponentProxyMapping();
+ throw e;
+ }
+ catch (RuntimeException r)
+ {
+ resetComponentProxyMapping();
+ throw r;
+ }
+ }
+ else
+ {
+ tryToCreateMessage("encodeChildren");
+ }
+ }
+
+ @Override
+ public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ RendererProxyStorageEntry entry = getRendererEntry(facesContext, uiComponent);
+
+ if (!entry.isEncodeEndCalled())
+ {
+ entry.setEncodeEndCalled(true);
+
+ try
+ {
+ this.wrapped.encodeEnd(facesContext, uiComponent);
+ }
+ catch (IOException e)
+ {
+ resetComponentProxyMapping();
+ throw e;
+ }
+ catch (RuntimeException r)
+ {
+ resetComponentProxyMapping();
+ throw r;
+ }
+ }
+ else
+ {
+ tryToCreateMessage("encodeEnd");
+ }
+ }
+
+ @Override
+ public String convertClientId(FacesContext facesContext, String s)
+ {
+ try
+ {
+ return wrapped.convertClientId(facesContext, s);
+ }
+ catch (RuntimeException r)
+ {
+ resetComponentProxyMapping();
+ throw r;
+ }
+ }
+
+ @Override
+ public boolean getRendersChildren()
+ {
+ try
+ {
+ return wrapped.getRendersChildren();
+ }
+ catch (RuntimeException t)
+ {
+ resetComponentProxyMapping();
+ throw t;
+ }
+ }
+
+ @Override
+ public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object o)
+ throws ConverterException
+ {
+ RendererProxyStorageEntry entry = getRendererEntry(facesContext, uiComponent);
+
+ if (entry.getConvertedValue() == null)
+ {
+ try
+ {
+ entry.setConvertedValue(wrapped.getConvertedValue(facesContext, uiComponent, o));
+ }
+ catch (RuntimeException r)
+ {
+ resetComponentProxyMapping();
+ throw r;
+ }
+ }
+ else
+ {
+ tryToCreateMessage("getConvertedValue");
+ }
+ return entry.getConvertedValue();
+ }
+
+ protected RendererProxyStorageEntry getRendererEntry(FacesContext facesContext, UIComponent uiComponent)
+ {
+ String key = uiComponent.getClientId(facesContext);
+
+ key += getOptionalKey(facesContext, uiComponent);
+
+ if (!getRendererStorage().containsEntry(getRendererKey(), key))
+ {
+ getRendererStorage().setEntry(getRendererKey(), key, new RendererProxyStorageEntry());
+ }
+ return getRendererStorage().getEntry(getRendererKey(), key);
+ }
+
+ protected String getOptionalKey(FacesContext facesContext, UIComponent uiComponent)
+ {
+ return "";
+ }
+
+ protected String getRendererKey()
+ {
+ return ProxyUtils.getClassName(this.wrapped.getClass());
+ }
+
+ private RendererProxyStorage getRendererStorage()
+ {
+ return ExtValUtils.getStorage(RendererProxyStorage.class, RendererProxyStorage.class.getName());
+ }
+
+ private void resetComponentProxyMapping()
+ {
+ //reset component proxy mapping
+ ExtValUtils.resetStorage(RendererProxyStorage.class, RendererProxyStorage.class.getName());
+ }
+
+ private void tryToCreateMessage(String methodName)
+ {
+ if(JsfProjectStage.is(JsfProjectStage.Development))
+ {
+ String message = "double call of " + this.wrapped.getClass().getName() + "#" + methodName + " filtered. " +
+ "this optimization might lead to incompatibilities with some component libs. " +
+ "in such a case use the support module for the component lib or use: " +
+ "ExtValContext.getContext().addGlobalProperty(ExtValRendererProxy.KEY, null); " +
+ "in a startup listener";
+
+ FacesContext.getCurrentInstance()
+ .addMessage(null, ExtValUtils.createFacesMessage(FacesMessage.SEVERITY_WARN, message, message));
+
+ if(logger.isWarnEnabled())
+ {
+ logger.warn(message);
+ }
+ }
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("turn on the development mode for further information, if something is displayed wrong.");
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRendererWrapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRendererWrapper.java
new file mode 100644
index 0000000..b7c305e
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/ExtValRendererWrapper.java
@@ -0,0 +1,537 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.interceptor.RendererInterceptor;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipBeforeInterceptorsException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipAfterInterceptorsException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipRendererDelegationException;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.ConverterException;
+import javax.faces.render.Renderer;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+
+/**
+ * Default approach to avoid proxies for converters and the adapter fallback.
+ * It requires that components delegate getConvertedValue to a renderer.<br/>
+ * If it isn't the case for your component lib use:
+ * org.apache.myfaces.extensions.validator.core.proxy.ExtValApplicationFactory<br/>
+ * and<br/>
+ * org.apache.myfaces.extensions.validator.core.proxy.ProxyMappingPhaseListener
+ * <p/>
+ * This wrapper will also implement client-side validation behaviour
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValRendererWrapper extends Renderer
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ protected Renderer wrapped;
+ protected ExtValContext extValContext = ExtValContext.getContext();
+
+ public ExtValRendererWrapper(Renderer renderer)
+ {
+ String proxyClassName = (String)ExtValContext.getContext().getGlobalProperty(ExtValRendererProxy.KEY);
+
+ if(proxyClassName == null)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("no extval renderer proxy configured");
+ }
+
+ this.wrapped = new ExtValLazyRendererProxy(renderer);
+ return;
+ }
+
+ Class targetClass = ClassUtils.tryToLoadClassForName(proxyClassName);
+
+ if(targetClass == null)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("no extval renderer proxy configured");
+ }
+
+ this.wrapped = new ExtValLazyRendererProxy(renderer);
+ return;
+ }
+
+ Class[] argClasses = new Class[1];
+ argClasses[0] = Renderer.class;
+
+ try
+ {
+ Constructor constructor = targetClass.getConstructor(argClasses);
+ this.wrapped = (Renderer)constructor.newInstance(renderer);
+ }
+ catch (Throwable e)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("no extval renderer proxy created for " + renderer.getClass().getName());
+ }
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("extval renderer wrapper created for " + renderer.getClass().getName());
+ }
+ }
+
+ @Override
+ public final void decode(FacesContext facesContext, UIComponent uiComponent)
+ {
+ boolean delegateToWrappedRenderer = true;
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start beforeDecode of " + rendererInterceptor.getClass().getName());
+ }
+
+ try
+ {
+ rendererInterceptor.beforeDecode(facesContext, uiComponent, this.wrapped);
+ }
+ catch (SkipRendererDelegationException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("decode delegation canceled", e);
+ }
+
+ delegateToWrappedRenderer = false;
+
+ if(e.isSkipOtherInterceptors())
+ {
+ break;
+ }
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeDecode of " + rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch(SkipBeforeInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeDecode interceptors canceled", e);
+ }
+ }
+
+ /*
+ * delegate
+ */
+ if(delegateToWrappedRenderer)
+ {
+ wrapped.decode(facesContext, uiComponent);
+ }
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start afterDecode of " + rendererInterceptor.getClass().getName());
+ }
+
+ rendererInterceptor.afterDecode(facesContext, uiComponent, this.wrapped);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterDecode of " + rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipAfterInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterDecode interceptors canceled", e);
+ }
+ }
+ }
+
+ @Override
+ public final void encodeBegin(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ boolean delegateToWrappedRenderer = true;
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start beforeEncodeBegin of " + rendererInterceptor.getClass().getName());
+ }
+
+ try
+ {
+ rendererInterceptor.beforeEncodeBegin(facesContext, uiComponent, this.wrapped);
+ }
+ catch (SkipRendererDelegationException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("encodeBegin delegation canceled", e);
+ }
+
+ delegateToWrappedRenderer = false;
+
+ if(e.isSkipOtherInterceptors())
+ {
+ break;
+ }
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeEncodeBegin of " + rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipBeforeInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeEncodeBegin interceptors canceled", e);
+ }
+ }
+
+ /*
+ * delegate
+ */
+ if(delegateToWrappedRenderer)
+ {
+ wrapped.encodeBegin(facesContext, uiComponent);
+ }
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start afterEncodeBegin of " + rendererInterceptor.getClass().getName());
+ }
+
+ rendererInterceptor.afterEncodeBegin(facesContext, uiComponent, this.wrapped);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterEncodeBegin of " + rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipAfterInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterEncodeBegin interceptors canceled", e);
+ }
+ }
+ }
+
+ @Override
+ public final void encodeChildren(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ boolean delegateToWrappedRenderer = true;
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start beforeEncodeChildren of " + rendererInterceptor.getClass().getName());
+ }
+
+ try
+ {
+ rendererInterceptor.beforeEncodeChildren(facesContext, uiComponent, this.wrapped);
+ }
+ catch (SkipRendererDelegationException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("encodeChildren delegation canceled", e);
+ }
+
+ delegateToWrappedRenderer = false;
+
+ if(e.isSkipOtherInterceptors())
+ {
+ break;
+ }
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeEncodeChildren of " +
+ rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipBeforeInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeEncodeChildren interceptors canceled", e);
+ }
+ }
+
+ /*
+ * delegate
+ */
+ if(delegateToWrappedRenderer)
+ {
+ wrapped.encodeChildren(facesContext, uiComponent);
+ }
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start afterEncodeChildren of " + rendererInterceptor.getClass().getName());
+ }
+
+ rendererInterceptor.afterEncodeChildren(facesContext, uiComponent, this.wrapped);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterEncodeChildren of " + rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipAfterInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterEncodeChildren interceptors canceled", e);
+ }
+ }
+ }
+
+ @Override
+ public final void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
+ throws IOException
+ {
+ boolean delegateToWrappedRenderer = true;
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start beforeEncodeEnd of " + rendererInterceptor.getClass().getName());
+ }
+
+ try
+ {
+ rendererInterceptor.beforeEncodeEnd(facesContext, uiComponent, this.wrapped);
+ }
+ catch (SkipRendererDelegationException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("encodeEnd delegation canceled", e);
+ }
+
+ delegateToWrappedRenderer = false;
+
+ if(e.isSkipOtherInterceptors())
+ {
+ break;
+ }
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeEncodeEnd of " + rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipBeforeInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeEncodeEnd interceptors canceled", e);
+ }
+ }
+
+ /*
+ * delegate
+ */
+ if(delegateToWrappedRenderer)
+ {
+ wrapped.encodeEnd(facesContext, uiComponent);
+ }
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start afterEncodeEnd of " + rendererInterceptor.getClass().getName());
+ }
+
+ rendererInterceptor.afterEncodeEnd(facesContext, uiComponent, this.wrapped);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterEncodeEnd of " + rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipAfterInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterEncodeEnd interceptors canceled", e);
+ }
+ }
+ }
+
+ @Override
+ public final String convertClientId(FacesContext facesContext, String s)
+ {
+ return wrapped.convertClientId(facesContext, s);
+ }
+
+ @Override
+ public final boolean getRendersChildren()
+ {
+ return wrapped.getRendersChildren();
+ }
+
+ @Override
+ public final Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object o)
+ throws ConverterException
+ {
+ boolean delegateToWrappedRenderer = true;
+ Object convertedObject = null;
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start beforeGetConvertedValue of " + rendererInterceptor.getClass().getName());
+ }
+
+ try
+ {
+ rendererInterceptor.beforeGetConvertedValue(facesContext, uiComponent, o, this.wrapped);
+ }
+ catch (SkipRendererDelegationException e)
+ {
+ convertedObject = e.getReturnValueOnException(convertedObject);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("getConvertedValue delegation canceled", e);
+ }
+
+ delegateToWrappedRenderer = false;
+
+ if(e.isSkipOtherInterceptors())
+ {
+ break;
+ }
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeGetConvertedValue of " +
+ rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipBeforeInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("beforeGetConvertedValue interceptors canceled", e);
+ }
+ }
+
+ /*
+ * delegate
+ */
+ if(delegateToWrappedRenderer)
+ {
+ convertedObject = wrapped.getConvertedValue(facesContext, uiComponent, o);
+ }
+
+ try
+ {
+ for(RendererInterceptor rendererInterceptor : extValContext.getRendererInterceptors())
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start afterGetConvertedValue of " + rendererInterceptor.getClass().getName());
+ }
+
+ rendererInterceptor.afterGetConvertedValue(facesContext, uiComponent, o, this.wrapped);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterGetConvertedValue of " + rendererInterceptor.getClass().getName() + " finished");
+ }
+ }
+ }
+ catch (SkipAfterInterceptorsException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("afterGetConvertedValue interceptors canceled", e);
+ }
+ }
+
+ return convertedObject;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipAfterInterceptorsException.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipAfterInterceptorsException.java
new file mode 100644
index 0000000..722ffda
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipAfterInterceptorsException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit.exception;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public class SkipAfterInterceptorsException extends Exception
+{
+ private static final long serialVersionUID = -1472790498766251346L;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipBeforeInterceptorsException.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipBeforeInterceptorsException.java
new file mode 100644
index 0000000..58c20a7
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipBeforeInterceptorsException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit.exception;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public class SkipBeforeInterceptorsException extends Exception
+{
+ private static final long serialVersionUID = -418424051464814888L;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipRendererDelegationException.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipRendererDelegationException.java
new file mode 100644
index 0000000..b920fbe
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/renderkit/exception/SkipRendererDelegationException.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.renderkit.exception;
+
+import org.apache.myfaces.extensions.validator.core.interceptor.RendererInterceptor;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public class SkipRendererDelegationException extends Exception
+{
+ protected RendererInterceptor exceptionSource;
+ protected Object information;
+ boolean skipOtherInterceptors = false;
+ private static final long serialVersionUID = 2343074077532915722L;
+
+ public SkipRendererDelegationException()
+ {
+ }
+
+ public SkipRendererDelegationException(boolean skipOtherInterceptors)
+ {
+ this.skipOtherInterceptors = skipOtherInterceptors;
+ }
+
+ public SkipRendererDelegationException(boolean skipOtherInterceptors, RendererInterceptor rendererInterceptor)
+ {
+ this(skipOtherInterceptors);
+ this.exceptionSource = rendererInterceptor;
+ }
+
+ public void setInformation(Object information)
+ {
+ this.information = information;
+ }
+
+ public Object getInformation()
+ {
+ return information;
+ }
+
+ public boolean isSkipOtherInterceptors()
+ {
+ return skipOtherInterceptors;
+ }
+
+ public Object getReturnValueOnException(Object currentReturnValue)
+ {
+ if (this.exceptionSource != null)
+ {
+ return this.exceptionSource.getReturnValueOnSkipRendererDelegationException(this, currentReturnValue);
+ }
+ return currentReturnValue;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/startup/AbstractStartupListener.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/startup/AbstractStartupListener.java
new file mode 100644
index 0000000..e070a6a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/startup/AbstractStartupListener.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.startup;
+
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+import org.apache.myfaces.extensions.validator.util.WebXmlUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.ProjectStageResolver;
+import org.apache.myfaces.extensions.validator.core.DefaultProjectStageResolver;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * In order to execute logic just once.
+ * e.g. register artifacts via api
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.REUSE)
+public abstract class AbstractStartupListener implements PhaseListener
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ //don't remove - it's a fallback if there is a problem with deregistration
+ //target: don't process init logic more than once
+ private static List<Class> initializedListeners = new ArrayList<Class>();
+
+ private static boolean defaultProjectStageResolverInitialized = false;
+
+ protected AbstractStartupListener()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public void afterPhase(PhaseEvent event)
+ {
+ }
+
+ public void beforePhase(PhaseEvent event)
+ {
+ synchronized (AbstractStartupListener.class)
+ {
+ if (!initializedListeners.contains(getClass()))
+ {
+ try
+ {
+ if(logger.isInfoEnabled())
+ {
+ logger.info("start init of " + getClass().getName());
+ }
+
+ try
+ {
+ if(!isStartupListenerDeactivated())
+ {
+ initProjectStageResolver();
+
+ init();
+ }
+ else
+ {
+ if(logger.isInfoEnabled())
+ {
+ logger.info("init of " + getClass().getName() + " deactivated");
+ }
+ }
+
+ if(logger.isInfoEnabled())
+ {
+ logger.info("init of " + getClass().getName() + " finished");
+ }
+ }
+ finally
+ {
+ JsfUtils.deregisterPhaseListener(this);
+ }
+ }
+ catch (Throwable t)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("an exception occurred while deregistering the phase-listener"
+ + getClass().getName()
+ + " -> there is just a little overhead,"
+ + " but everything else works correctly."
+ + " however, please inform the community about your configuration", t);
+ }
+ }
+ finally
+ {
+ initializedListeners.add(getClass());
+ }
+ }
+ }
+ }
+
+ public PhaseId getPhaseId()
+ {
+ return PhaseId.RESTORE_VIEW;
+ }
+
+ protected boolean isStartupListenerDeactivated()
+ {
+ return ExtValUtils.isExtValDeactivated() ||
+ "true".equalsIgnoreCase(WebXmlUtils.getInitParameter(null, getClass().getName() + ":DEACTIVATED"));
+ }
+
+ protected void initProjectStageResolver()
+ {
+ if(!defaultProjectStageResolverInitialized)
+ {
+ ExtValContext.getContext()
+ .addGlobalProperty(ProjectStageResolver.class.getName(), getProjectStageResolver(), false);
+ defaultProjectStageResolverInitialized = true;
+ }
+ }
+
+ protected ProjectStageResolver getProjectStageResolver()
+ {
+ return new DefaultProjectStageResolver();
+ }
+
+ protected abstract void init();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/startup/ExtValStartupListener.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/startup/ExtValStartupListener.java
new file mode 100644
index 0000000..6ed3281
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/startup/ExtValStartupListener.java
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.startup;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.interceptor.ValidationInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.HtmlCoreComponentsValidationExceptionInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.ViolationSeverityValidationExceptionInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.FacesMessagePropertyValidationInterceptor;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.PhaseIdRecordingPhaseListener;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper
+ .BeanValidationStrategyToMetaDataTransformerNameMapper;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper
+ .SimpleValidationStrategyToMetaDataTransformerNameMapper;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper
+ .DefaultValidationStrategyToMetaDataTransformerNameMapper;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper
+ .CustomConventionValidationStrategyToMetaDataTransformerNameMapper;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper
+ .CustomConfiguredValidationStrategyToMetaDataTransformerNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.mapper
+ .CustomConventionAnnotationToValidationStrategyNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.mapper
+ .DefaultAnnotationToValidationStrategyNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.mapper
+ .CustomConfiguredAnnotationToValidationStrategyNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.mapper
+ .SimpleAnnotationToValidationStrategyNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.mapper
+ .AnnotationToValidationStrategyBeanNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper
+ .CustomConfiguredValidationStrategyToMsgResolverNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper
+ .CustomConventionValidationStrategyToMsgResolverNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper
+ .DefaultValidationStrategyToMsgResolverNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper
+ .DefaultModuleValidationStrategyToMsgResolverNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper
+ .SimpleValidationStrategyToMsgResolverNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.DefaultViolationSeverityInterpreter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.DisableClientSideValidation;
+import org.apache.myfaces.extensions.validator.core.renderkit.ExtValRendererProxy;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+import org.apache.myfaces.extensions.validator.ExtValInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValStartupListener extends AbstractStartupListener
+{
+ private static final long serialVersionUID = -2504826421086572012L;
+
+ protected void init()
+ {
+ if(logger.isInfoEnabled())
+ {
+ if(ExtValInformation.VERSION != null)
+ {
+ logger.info("starting up MyFaces Extensions Validator v" + ExtValInformation.VERSION);
+ }
+ else
+ {
+ logger.info("starting up MyFaces Extensions Validator");
+ }
+ }
+
+ ExtValContext.getContext().registerRendererInterceptor(new ValidationInterceptor());
+
+ ExtValContext.getContext()
+ .addGlobalProperty(ExtValRendererProxy.KEY, ExtValRendererProxy.class.getName(), false);
+
+ initNameMappers();
+ initValidationExceptionInterceptors();
+ initViolationSeverityInterpreter();
+ initPropertyValidationInterceptors();
+ initPhaseListeners();
+ initViolationSeverityKey();
+ initDisableClientSideValidationKey();
+ initRequiredInitialization();
+ executeCustomStartupListener();
+ }
+
+ private void initNameMappers()
+ {
+ String deactivateDefaultNameMappers = WebXmlParameter.DEACTIVATE_DEFAULT_NAME_MAPPERS;
+ if ((deactivateDefaultNameMappers != null && deactivateDefaultNameMappers.equalsIgnoreCase("true")))
+ {
+ return;
+ }
+
+ //register metadata to validation strategy name mapper
+ ExtValUtils.registerMetaDataToValidationStrategyNameMapper(
+ new CustomConfiguredAnnotationToValidationStrategyNameMapper());
+ ExtValUtils.registerMetaDataToValidationStrategyNameMapper(
+ new CustomConventionAnnotationToValidationStrategyNameMapper());
+ ExtValUtils.registerMetaDataToValidationStrategyNameMapper(
+ new DefaultAnnotationToValidationStrategyNameMapper());
+ ExtValUtils.registerMetaDataToValidationStrategyNameMapper(
+ new SimpleAnnotationToValidationStrategyNameMapper());
+
+ ExtValUtils.registerMetaDataToValidationStrategyNameMapper(
+ new AnnotationToValidationStrategyBeanNameMapper(
+ new CustomConfiguredAnnotationToValidationStrategyNameMapper()));
+ ExtValUtils.registerMetaDataToValidationStrategyNameMapper(
+ new AnnotationToValidationStrategyBeanNameMapper(
+ new CustomConventionAnnotationToValidationStrategyNameMapper()));
+ ExtValUtils.registerMetaDataToValidationStrategyNameMapper(
+ new AnnotationToValidationStrategyBeanNameMapper(
+ new DefaultAnnotationToValidationStrategyNameMapper()));
+ ExtValUtils.registerMetaDataToValidationStrategyNameMapper(
+ new AnnotationToValidationStrategyBeanNameMapper(
+ new SimpleAnnotationToValidationStrategyNameMapper()));
+
+ //register validation strategy to message resolver name mapper
+ ExtValUtils.registerValidationStrategyToMessageResolverNameMapper(
+ new CustomConfiguredValidationStrategyToMsgResolverNameMapper());
+ ExtValUtils.registerValidationStrategyToMessageResolverNameMapper(
+ new CustomConventionValidationStrategyToMsgResolverNameMapper());
+ ExtValUtils.registerValidationStrategyToMessageResolverNameMapper(
+ new DefaultValidationStrategyToMsgResolverNameMapper());
+ ExtValUtils.registerValidationStrategyToMessageResolverNameMapper(
+ new DefaultModuleValidationStrategyToMsgResolverNameMapper());
+ ExtValUtils.registerValidationStrategyToMessageResolverNameMapper(
+ new SimpleValidationStrategyToMsgResolverNameMapper());
+
+ //register validation strategy to metadata transformer name mapper
+ ExtValUtils.registerValidationStrategyToMetaDataTransformerNameMapper(
+ new CustomConfiguredValidationStrategyToMetaDataTransformerNameMapper());
+ ExtValUtils.registerValidationStrategyToMetaDataTransformerNameMapper(
+ new CustomConventionValidationStrategyToMetaDataTransformerNameMapper());
+ ExtValUtils.registerValidationStrategyToMetaDataTransformerNameMapper(
+ new DefaultValidationStrategyToMetaDataTransformerNameMapper());
+ ExtValUtils.registerValidationStrategyToMetaDataTransformerNameMapper(
+ new SimpleValidationStrategyToMetaDataTransformerNameMapper());
+ ExtValUtils.registerValidationStrategyToMetaDataTransformerNameMapper(
+ new BeanValidationStrategyToMetaDataTransformerNameMapper());
+ }
+
+ private void executeCustomStartupListener()
+ {
+ String customStartupListenerName = ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.STARTUP_LISTENER);
+ AbstractStartupListener customStartupListener =
+ (AbstractStartupListener)ClassUtils.tryToInstantiateClassForName(customStartupListenerName);
+
+ if(customStartupListener != null)
+ {
+ if(logger.isInfoEnabled())
+ {
+ logger.info("start init of " + customStartupListener.getClass().getName());
+ }
+
+ customStartupListener.init();
+
+ if(logger.isInfoEnabled())
+ {
+ logger.info("init of " + customStartupListener.getClass().getName() + " finished");
+ }
+ }
+ }
+
+ private void initValidationExceptionInterceptors()
+ {
+ ExtValContext.getContext().addValidationExceptionInterceptor(
+ new HtmlCoreComponentsValidationExceptionInterceptor());
+ ExtValContext.getContext().addValidationExceptionInterceptor(
+ new ViolationSeverityValidationExceptionInterceptor());
+ }
+
+ private void initViolationSeverityInterpreter()
+ {
+ ExtValContext.getContext().setViolationSeverityInterpreter(new DefaultViolationSeverityInterpreter(), false);
+ }
+
+ private void initPropertyValidationInterceptors()
+ {
+ ExtValContext.getContext().addPropertyValidationInterceptor(new FacesMessagePropertyValidationInterceptor());
+ }
+
+ private void initPhaseListeners()
+ {
+ JsfUtils.registerPhaseListener(new PhaseIdRecordingPhaseListener());
+ }
+
+ private void initViolationSeverityKey()
+ {
+ ExtValContext.getContext().addGlobalProperty(ViolationSeverity.class.getName(), ViolationSeverity.class, false);
+ }
+
+ private void initDisableClientSideValidationKey()
+ {
+ ExtValContext.getContext().addGlobalProperty(
+ DisableClientSideValidation.class.getName(), DisableClientSideValidation.class, false);
+ }
+
+ private void initRequiredInitialization()
+ {
+ if(WebXmlParameter.ACTIVATE_REQUIRED_INITIALIZATION != null)
+ {
+ boolean requiredInitialization = "true".equalsIgnoreCase(WebXmlParameter.ACTIVATE_REQUIRED_INITIALIZATION);
+
+ ExtValContext.getContext().addGlobalProperty("mode:init:required", requiredInitialization, false);
+
+ if(requiredInitialization)
+ {
+ deactivateRequiredAttributeSupport();
+ }
+ }
+ }
+
+ /**
+ * if it's configured that required init should happen,
+ * it's required to deactivate the support for the required attribute
+ */
+ private void deactivateRequiredAttributeSupport()
+ {
+ ExtValContext.getContext().addGlobalProperty("mode:reset:required", Boolean.TRUE, false);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractApplicationScopeAwareStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractApplicationScopeAwareStorageManager.java
new file mode 100644
index 0000000..1238bdf
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractApplicationScopeAwareStorageManager.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.REUSE;
+
+import javax.faces.context.FacesContext;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * generic storage manager implementation which stores the storage implementations in the application scope
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(REUSE)
+public abstract class AbstractApplicationScopeAwareStorageManager<T> extends AbstractStorageManager<T>
+{
+ protected Map<String, T> resolveStorageMap()
+ {
+ Map applicationMap = FacesContext.getCurrentInstance().getExternalContext().getApplicationMap();
+ Map<String, T> storageMap;
+
+ if(!applicationMap.containsKey(getStorageManagerKey()))
+ {
+ storageMap = new HashMap<String, T>();
+ applicationMap.put(getStorageManagerKey(), storageMap);
+ }
+
+ return (Map<String, T>)applicationMap.get(getStorageManagerKey());
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractRequestScopeAwareStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractRequestScopeAwareStorageManager.java
new file mode 100644
index 0000000..ff6614e
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractRequestScopeAwareStorageManager.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.REUSE;
+
+import javax.faces.context.FacesContext;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * generic storage manager implementation which stores the storage implementations in the request scope
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(REUSE)
+public abstract class AbstractRequestScopeAwareStorageManager<T> extends AbstractStorageManager<T>
+{
+ protected Map<String, T> resolveStorageMap()
+ {
+ Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
+ Map<String, T> storageMap;
+
+ if(!requestMap.containsKey(getStorageManagerKey()))
+ {
+ storageMap = new HashMap<String, T>();
+ requestMap.put(getStorageManagerKey(), storageMap);
+ }
+
+ return (Map<String, T>)requestMap.get(getStorageManagerKey());
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractStorageManager.java
new file mode 100644
index 0000000..5898b97
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/AbstractStorageManager.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.core.factory.AbstractNameMapperAwareFactory;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.REUSE;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * generic storage manager implementation
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(REUSE)
+public abstract class AbstractStorageManager<T> extends AbstractNameMapperAwareFactory<String>
+ implements StorageManager<T>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private List<NameMapper<String>> nameMapperList = new ArrayList<NameMapper<String>>();
+
+ public AbstractStorageManager()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public T create(String storageName)
+ {
+ T storageManager;
+ String storageClassName;
+ //null -> use name mappers
+ for (NameMapper<String> nameMapper : this.nameMapperList)
+ {
+ storageClassName = nameMapper.createName(storageName);
+
+ if (storageClassName == null)
+ {
+ continue;
+ }
+
+ storageManager = resolveStorage(storageName, storageClassName);
+
+ if (storageManager != null)
+ {
+ return storageManager;
+ }
+ }
+ return null;
+ }
+
+ protected T resolveStorage(String storageKey, String storageClassName)
+ {
+ Map<String, T> storageMap = resolveStorageMap();
+
+ if(!storageMap.containsKey(storageKey))
+ {
+ storageMap.put(storageKey, (T)ClassUtils.tryToInstantiateClassForName(storageClassName));
+ }
+ return storageMap.get(storageKey);
+ }
+
+ protected abstract Map<String, T> resolveStorageMap();
+
+ public void reset(String storageKey)
+ {
+ Map<String, T> storageMap = resolveStorageMap();
+
+ if(storageMap != null && storageMap.containsKey(storageKey))
+ {
+ Class storageClass = ProxyUtils.getUnproxiedClass(storageMap.get(storageKey).getClass());
+ storageMap.put(storageKey, (T)ClassUtils.tryToInstantiateClass(storageClass));
+ }
+ }
+
+ protected List<NameMapper<String>> getNameMapperList()
+ {
+ return this.nameMapperList;
+ }
+
+ public abstract String getStorageManagerKey();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesInformationStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesInformationStorage.java
new file mode 100644
index 0000000..47af031
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesInformationStorage.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.event.PhaseId;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultFacesInformationStorage implements FacesInformationStorage
+{
+ private PhaseId currentPhaseId;
+
+ public void setCurrentPhaseId(PhaseId phaseId)
+ {
+ this.currentPhaseId = phaseId;
+ }
+
+ public PhaseId getCurrentPhaseId()
+ {
+ return this.currentPhaseId;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesInformationStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesInformationStorageManager.java
new file mode 100644
index 0000000..da13bdf
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesInformationStorageManager.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.core.storage.mapper.DefaultFacesInformationStorageNameMapper;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * default storage-manager for jsf information not available via jsf-api
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class DefaultFacesInformationStorageManager extends
+ AbstractRequestScopeAwareStorageManager<FacesInformationStorage>
+{
+ DefaultFacesInformationStorageManager()
+ {
+ register(new DefaultFacesInformationStorageNameMapper());
+ }
+
+ public String getStorageManagerKey()
+ {
+ return StorageManager.class.getName() + "_FOR_FACES_INFORMATION_STORAGE:KEY";
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesMessageStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesMessageStorage.java
new file mode 100644
index 0000000..abd6b7c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesMessageStorage.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.core.validation.message.FacesMessageHolder;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@ToDo(value = Priority.LOW, description = "optional parameter to deactivate sorting")
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultFacesMessageStorage implements FacesMessageStorage
+{
+ Map<String, ValidationResult> results = new HashMap<String, ValidationResult>();
+
+ public void addFacesMessage(String clientId, FacesMessage facesMessage)
+ {
+ if(clientId == null)
+ {
+ clientId = "*";
+ }
+
+ if(!this.results.containsKey(clientId))
+ {
+ this.results.put(clientId, new ValidationResult());
+ }
+
+ this.results.get(clientId).addFacesMessageHolder(new FacesMessageHolder(facesMessage, clientId));
+ }
+
+ public List<FacesMessageHolder> getFacesMessages()
+ {
+ List<FacesMessageHolder> result = new ArrayList<FacesMessageHolder>();
+
+ for(ValidationResult validationResult : this.results.values())
+ {
+ result.addAll(validationResult.getFacesMessageHolderList());
+ }
+ return result;
+ }
+
+ public void addAll()
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ List<FacesMessageHolder> facesMessageHolderList;
+
+ for(ValidationResult validationResult : this.results.values())
+ {
+ facesMessageHolderList = validationResult.getFacesMessageHolderList();
+ sortFacesMessageHolderList(facesMessageHolderList);
+
+ for(FacesMessageHolder facesMessageHolder : facesMessageHolderList)
+ {
+ facesContext.addMessage(facesMessageHolder.getClientId(), facesMessageHolder.getFacesMessage());
+ }
+ }
+ }
+
+ private void sortFacesMessageHolderList(List<FacesMessageHolder> facesMessageHolderList)
+ {
+ Collections.sort(facesMessageHolderList, getFacesMessageComparator());
+ }
+
+ protected Comparator<FacesMessageHolder> getFacesMessageComparator()
+ {
+ return new Comparator<FacesMessageHolder>() {
+ public int compare(FacesMessageHolder holder1, FacesMessageHolder holder2)
+ {
+ if(holder1.getFacesMessage().getSeverity() == null)
+ {
+ return 1;
+ }
+ if(isSameSeverity(holder1, holder2))
+ {
+ return compareMessageText(holder1.getFacesMessage(), holder2.getFacesMessage());
+ }
+
+ if(holder1.getFacesMessage().getSeverity().getOrdinal() >
+ holder2.getFacesMessage().getSeverity().getOrdinal())
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ private int compareMessageText(FacesMessage facesMessage1, FacesMessage facesMessage2)
+ {
+ String text1 = facesMessage1.getDetail();
+ String text2 = facesMessage2.getDetail();
+
+ if(text1 == null)
+ {
+ text1 = facesMessage1.getSummary();
+ }
+
+ if(text2 == null)
+ {
+ text2 = facesMessage2.getSummary();
+ }
+
+ if(text1 == null)
+ {
+ return 1;
+ }
+
+ if(text2 == null)
+ {
+ return -1;
+ }
+
+ return text1.compareToIgnoreCase(text2);
+ }
+ };
+ }
+
+ private boolean isSameSeverity(FacesMessageHolder holder1, FacesMessageHolder holder2)
+ {
+ return holder1.getFacesMessage().getSeverity().equals(holder2.getFacesMessage().getSeverity());
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesMessageStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesMessageStorageManager.java
new file mode 100644
index 0000000..312326f
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultFacesMessageStorageManager.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.core.storage.mapper.DefaultFacesMessageStorageNameMapper;
+
+/**
+ * default storage-manager for faces messages
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+class DefaultFacesMessageStorageManager extends AbstractRequestScopeAwareStorageManager<FacesMessageStorage>
+{
+ DefaultFacesMessageStorageManager()
+ {
+ register(new DefaultFacesMessageStorageNameMapper());
+ }
+
+ public String getStorageManagerKey()
+ {
+ return StorageManager.class.getName() + "_FOR_FACES_MESSAGES:KEY";
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultGroupStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultGroupStorage.java
new file mode 100644
index 0000000..16b4d61
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultGroupStorage.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.util.GroupUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+/**
+ * default storage implementation for groups
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultGroupStorage implements GroupStorage
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Map<String, List<Class>> addedGroups = new HashMap<String, List<Class>>();
+
+ private Map<String, List<Class>> restrictedGroups = new HashMap<String, List<Class>>();
+
+ public void addGroup(Class groupClass, String viewId, String clientId)
+ {
+ addGroupToGroupStorage(groupClass, viewId, clientId, this.addedGroups);
+ }
+
+ public void restrictGroup(Class groupClass, String viewId, String clientId)
+ {
+ addGroupToGroupStorage(groupClass, viewId, clientId, this.restrictedGroups);
+ }
+
+ public Class[] getGroups(String viewId, String clientId)
+ {
+ if(this.addedGroups.size() < 1)
+ {
+ return null;
+ }
+
+ //add found groups
+ String key = GroupUtils.getGroupKey(viewId, null);
+ List<Class> resultListForPage = buildGroupList(key, this.addedGroups);
+
+ key = GroupUtils.getGroupKey(viewId, clientId);
+ List<Class> resultListForComponent = buildGroupList(key, this.addedGroups);
+
+ //remove restricted groups
+ Class[] resultsForPage =
+ filterGroupList(GroupUtils.getGroupKey(viewId, null), resultListForPage);
+ Class[] resultsForComponent =
+ filterGroupList(GroupUtils.getGroupKey(viewId, clientId), resultListForComponent);
+
+ if(resultsForPage.length == 0)
+ {
+ if(resultsForComponent.length == 0)
+ {
+ if(this.logger.isDebugEnabled())
+ {
+ this.logger.debug("no groups for group-validation available." +
+ "maybe you restricted all groups or you aren't using groups." +
+ "bean validation will use the default group for validation");
+ }
+ }
+ return resultsForComponent;
+ }
+ else if(resultsForComponent.length == 0)
+ {
+ return resultsForPage;
+ }
+
+ return mergeResults(resultsForPage, resultsForComponent);
+ }
+
+ private void addGroupToGroupStorage(Class groupClass, String viewId, String clientId,
+ Map<String, List<Class>> groupStorage)
+ {
+ List<Class> groupList = groupStorage.get(GroupUtils.getGroupKey(viewId, clientId));
+
+ if(groupList == null)
+ {
+ groupList = new ArrayList<Class>();
+ groupStorage.put(GroupUtils.getGroupKey(viewId, clientId), groupList);
+ }
+
+ if(!groupList.contains(groupClass))
+ {
+ groupList.add(groupClass);
+ }
+ }
+
+ private List<Class> buildGroupList(String key, Map<String, List<Class>> groupStorage)
+ {
+ List<Class> list = groupStorage.get(key);
+ return (list != null) ? list : new ArrayList<Class>();
+ }
+
+ private Class[] filterGroupList(String key, List<Class> addedGroups)
+ {
+ List<Class> restrictedGroups = buildGroupList(key, this.restrictedGroups);
+ List<Class> results = new ArrayList<Class>();
+
+ for(Class currentGroup : addedGroups)
+ {
+ if(!restrictedGroups.contains(currentGroup))
+ {
+ results.add(currentGroup);
+ }
+ }
+
+ return results.toArray(new Class[results.size()]);
+ }
+
+ private Class[] mergeResults(Class[] resultsForPage, Class[] resultsForComponent)
+ {
+ Class[] mergedResult = new Class[resultsForPage.length + resultsForComponent.length];
+
+ System.arraycopy(resultsForPage, 0, mergedResult, 0, resultsForPage.length);
+ System.arraycopy(resultsForComponent, 0, mergedResult, resultsForPage.length, resultsForComponent.length);
+
+ return mergedResult;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultGroupStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultGroupStorageManager.java
new file mode 100644
index 0000000..916b5bc
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultGroupStorageManager.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+/**
+ * default storage-manager for groups
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+class DefaultGroupStorageManager extends AbstractRequestScopeAwareStorageManager<GroupStorage>
+{
+ public String getStorageManagerKey()
+ {
+ return StorageManager.class.getName() + "_FOR_GROUPS:KEY";
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultMetaDataStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultMetaDataStorage.java
new file mode 100644
index 0000000..26d7b58
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultMetaDataStorage.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.property.DefaultPropertyInformation;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultMetaDataStorage implements MetaDataStorage
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Map<String, Map<String, PropertyInformation>> cachedPropertyInformation =
+ new HashMap<String, Map<String, PropertyInformation>>();
+
+ private List<MetaDataStorageFilter> metaDataStorageFilters = new ArrayList<MetaDataStorageFilter>();
+ private List<Class<? extends MetaDataStorageFilter>> deniedMetaDataFilters =
+ new ArrayList<Class<? extends MetaDataStorageFilter>>();
+
+ public DefaultMetaDataStorage()
+ {
+ initFilters();
+ }
+
+ private void initFilters()
+ {
+ List<String> metaDataStorageFilterClassNames = new ArrayList<String>();
+
+ metaDataStorageFilterClassNames
+ .add(WebXmlParameter.CUSTOM_META_DATA_STORAGE_FILTER);
+ metaDataStorageFilterClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean().get(
+ CustomInformation.META_DATA_STORAGE_FILTER));
+
+ MetaDataStorageFilter metaDataStorageFilter;
+ for (String validationExceptionInterceptorName : metaDataStorageFilterClassNames)
+ {
+ metaDataStorageFilter =
+ (MetaDataStorageFilter)ClassUtils.tryToInstantiateClassForName(validationExceptionInterceptorName);
+
+ if (metaDataStorageFilter != null)
+ {
+ this.metaDataStorageFilters.add(metaDataStorageFilter);
+
+ logAddedFilter(metaDataStorageFilter.getClass());
+ }
+ }
+ }
+
+ public void storeMetaDataOf(PropertyInformation propertyInformation)
+ {
+ invokeFilters(propertyInformation);
+
+ PropertyInformation propertyInformationToStore = new DefaultPropertyInformation();
+
+ PropertyDetails propertyDetails = propertyInformation
+ .getInformation(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
+
+ copyMetaData(propertyInformation, propertyInformationToStore);
+
+ getMapForClass(ProxyUtils.getUnproxiedClass(propertyDetails.getBaseObject().getClass()))
+ .put(propertyDetails.getProperty(), propertyInformationToStore);
+ }
+
+ private void invokeFilters(PropertyInformation propertyInformation)
+ {
+ for(MetaDataStorageFilter filter : this.metaDataStorageFilters)
+ {
+ filter.filter(propertyInformation);
+ }
+ }
+
+ public MetaDataEntry[] getMetaData(Class targetClass, String targetProperty)
+ {
+ PropertyInformation propertyInformation = getMapForClass(targetClass).get(targetProperty);
+
+ PropertyInformation clonedPropertyInformation = new DefaultPropertyInformation();
+ copyMetaData(propertyInformation, clonedPropertyInformation);
+
+ return clonedPropertyInformation.getMetaDataEntries();
+ }
+
+ public boolean containsMetaDataFor(Class targetClass, String targetProperty)
+ {
+ return getMapForClass(targetClass).containsKey(targetProperty);
+ }
+
+ public void registerFilter(MetaDataStorageFilter storageFilter)
+ {
+ synchronized (this)
+ {
+ if(!isFilterDenied(storageFilter) && !isFilterAlreadyRegistered(storageFilter))
+ {
+ this.metaDataStorageFilters.add(storageFilter);
+ logAddedFilter(storageFilter.getClass());
+ }
+ }
+ }
+
+ private boolean isFilterDenied(MetaDataStorageFilter storageFilter)
+ {
+ return this.deniedMetaDataFilters.contains(getStorageFilterClass(storageFilter));
+ }
+
+ private boolean isFilterAlreadyRegistered(MetaDataStorageFilter storageFilter)
+ {
+ for(MetaDataStorageFilter filter : this.metaDataStorageFilters)
+ {
+ if(filter.getClass().equals(getStorageFilterClass(storageFilter)))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void deregisterFilter(Class<? extends MetaDataStorageFilter> filterClass)
+ {
+ MetaDataStorageFilter storageFilter = ClassUtils.tryToInstantiateClass(filterClass);
+
+ synchronized (this)
+ {
+ this.metaDataStorageFilters.remove(storageFilter);
+ }
+
+ logRemovedFilter(storageFilter.getClass());
+ }
+
+ public void denyFilter(Class<? extends MetaDataStorageFilter> filterClass)
+ {
+ synchronized (this)
+ {
+ for(Class<? extends MetaDataStorageFilter> filterId : this.deniedMetaDataFilters)
+ {
+ if(filterId.equals(filterClass))
+ {
+ return;
+ }
+ }
+ this.deniedMetaDataFilters.add(filterClass);
+ }
+
+ deregisterFilter(filterClass);
+ }
+
+ @ToDo(Priority.MEDIUM)
+ private void copyMetaData(PropertyInformation source, PropertyInformation target)
+ {
+ MetaDataEntry newMetaDataEntry;
+ for(MetaDataEntry metaDataEntry : source.getMetaDataEntries())
+ {
+ newMetaDataEntry = new MetaDataEntry();
+ newMetaDataEntry.setKey(metaDataEntry.getKey());
+ newMetaDataEntry.setValue(metaDataEntry.getValue());
+
+ target.addMetaDataEntry(newMetaDataEntry);
+ }
+ }
+
+ private void logAddedFilter(Class<? extends MetaDataStorageFilter> filterClass)
+ {
+ if(this.logger.isInfoEnabled())
+ {
+ this.logger.info(filterClass.getName() + " added");
+ }
+ }
+
+ private void logRemovedFilter(Class<? extends MetaDataStorageFilter> filterClass)
+ {
+ if(this.logger.isInfoEnabled())
+ {
+ this.logger.info(filterClass.getName() + " removed");
+ }
+ }
+
+ private Map<String, PropertyInformation> getMapForClass(Class target)
+ {
+ String key = ProxyUtils.getClassName(target);
+ if(!this.cachedPropertyInformation.containsKey(key))
+ {
+ this.cachedPropertyInformation.put(key, new HashMap<String, PropertyInformation>());
+ }
+ return this.cachedPropertyInformation.get(key);
+ }
+
+ private Class<? extends MetaDataStorageFilter> getStorageFilterClass(MetaDataStorageFilter storageFilter)
+ {
+ return ProxyUtils.getUnproxiedClass(storageFilter.getClass(), MetaDataStorageFilter.class);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultMetaDataStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultMetaDataStorageManager.java
new file mode 100644
index 0000000..ecc69be
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultMetaDataStorageManager.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.core.storage.mapper.DefaultMetaDataStorageNameMapper;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * default storage-manager for property information entries
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class DefaultMetaDataStorageManager extends AbstractApplicationScopeAwareStorageManager<MetaDataStorage>
+{
+ DefaultMetaDataStorageManager()
+ {
+ register(new DefaultMetaDataStorageNameMapper());
+ }
+
+ public String getStorageManagerKey()
+ {
+ return StorageManager.class.getName() + "_FOR_META_DATA_CACHE:KEY";
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultPropertyStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultPropertyStorage.java
new file mode 100644
index 0000000..c10a7f0
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultPropertyStorage.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultPropertyStorage implements PropertyStorage
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Map<String, Map<String, Field>> fieldMap = new HashMap<String, Map<String, Field>>();
+ private Map<String, Map<String, Method>> methodMap = new HashMap<String, Map<String, Method>>();
+
+ public void storeField(Class targetClass, String property, Field field)
+ {
+ getFieldMapForClass(targetClass).put(property, field);
+ }
+
+ public void storeMethod(Class targetClass, String property, Method method)
+ {
+ getMethodMapForClass(targetClass).put(property, method);
+ }
+
+ public Field getField(Class targetClass, String property)
+ {
+ return getFieldMapForClass(targetClass).get(property);
+ }
+
+ public Method getMethod(Class targetClass, String property)
+ {
+ return getMethodMapForClass(targetClass).get(property);
+ }
+
+ public boolean containsField(Class targetClass, String property)
+ {
+ return getFieldMapForClass(targetClass).containsKey(property);
+ }
+
+ public boolean containsMethod(Class targetClass, String property)
+ {
+ return getMethodMapForClass(targetClass).containsKey(property);
+ }
+
+ private Map<String, Field> getFieldMapForClass(Class target)
+ {
+ String key = ProxyUtils.getClassName(target);
+ if (!this.fieldMap.containsKey(key))
+ {
+ this.fieldMap.put(key, new HashMap<String, Field>());
+ }
+ return this.fieldMap.get(key);
+ }
+
+ private Map<String, Method> getMethodMapForClass(Class target)
+ {
+ String key = ProxyUtils.getClassName(target);
+ if (!this.methodMap.containsKey(key))
+ {
+ this.methodMap.put(key, new HashMap<String, Method>());
+ }
+ return this.methodMap.get(key);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultPropertyStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultPropertyStorageManager.java
new file mode 100644
index 0000000..9b3010a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultPropertyStorageManager.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.core.storage.mapper.DefaultPropertyStorageNameMapper;
+
+/**
+ * default storage-manager for property information
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+class DefaultPropertyStorageManager extends AbstractApplicationScopeAwareStorageManager<PropertyStorage>
+{
+ DefaultPropertyStorageManager()
+ {
+ register(new DefaultPropertyStorageNameMapper());
+ }
+
+ public String getStorageManagerKey()
+ {
+ return StorageManager.class.getName() + "_FOR_PROPERTY:KEY";
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererInterceptorPropertyStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererInterceptorPropertyStorage.java
new file mode 100644
index 0000000..ee79c62
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererInterceptorPropertyStorage.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultRendererInterceptorPropertyStorage implements RendererInterceptorPropertyStorage
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Map<String, Object> properties = new HashMap<String, Object>();
+
+ public void setProperty(String key, Object value)
+ {
+ this.properties.put(key, value);
+ }
+
+ public Object getProperty(String key)
+ {
+ return this.properties.get(key);
+ }
+
+ public <T> T getProperty(String key, Class<T> targetClass)
+ {
+ return (T)this.properties.get(key);
+ }
+
+ public void removeProperty(String key)
+ {
+ this.properties.remove(key);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererInterceptorPropertyStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererInterceptorPropertyStorageManager.java
new file mode 100644
index 0000000..761b10a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererInterceptorPropertyStorageManager.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.core.storage.mapper.DefaultRendererInterceptorPropertyStorageNameMapper;
+
+/**
+ * default storage-manager for renderer interceptor properties
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+class DefaultRendererInterceptorPropertyStorageManager
+ extends AbstractRequestScopeAwareStorageManager<RendererInterceptorPropertyStorage>
+{
+ DefaultRendererInterceptorPropertyStorageManager()
+ {
+ register(new DefaultRendererInterceptorPropertyStorageNameMapper());
+ }
+
+ public String getStorageManagerKey()
+ {
+ return StorageManager.class.getName() + "_FOR_RENDERER_INTERCEPTOR_PROPERTY:KEY";
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererProxyStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererProxyStorage.java
new file mode 100644
index 0000000..dd27ef8
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererProxyStorage.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * default storage implementation for groups
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultRendererProxyStorage implements RendererProxyStorage
+{
+ Map<String, Map<String, RendererProxyStorageEntry>> proxyStorage =
+ new HashMap<String, Map<String, RendererProxyStorageEntry>>();
+
+ public void setEntry(String rendererKey, String clientId, RendererProxyStorageEntry entry)
+ {
+ getRendererStorage(rendererKey).put(clientId, entry);
+ }
+
+ public boolean containsEntry(String rendererKey, String clientId)
+ {
+ return getRendererStorage(rendererKey).containsKey(clientId);
+ }
+
+ public RendererProxyStorageEntry getEntry(String rendererKey, String clientId)
+ {
+ return getRendererStorage(rendererKey).get(clientId);
+ }
+
+ private Map<String, RendererProxyStorageEntry> getRendererStorage(String rendererKey)
+ {
+ if(!proxyStorage.containsKey(rendererKey))
+ {
+ proxyStorage.put(rendererKey, new HashMap<String, RendererProxyStorageEntry>());
+ }
+
+ return proxyStorage.get(rendererKey);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererProxyStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererProxyStorageManager.java
new file mode 100644
index 0000000..cd81196
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultRendererProxyStorageManager.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.core.renderkit.ExtValRendererProxy;
+import org.apache.myfaces.extensions.validator.core.storage.mapper.DefaultRendererProxyStorageNameMapper;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * default storage-manager for renderer proxy entries
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class DefaultRendererProxyStorageManager
+ extends AbstractRequestScopeAwareStorageManager<RendererProxyStorage>
+{
+ DefaultRendererProxyStorageManager()
+ {
+ register(new DefaultRendererProxyStorageNameMapper());
+ }
+
+ public String getStorageManagerKey()
+ {
+ //for better backward compatibility
+ return ExtValRendererProxy.class.getName() + ":STORAGE";
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultStorageManagerFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultStorageManagerFactory.java
new file mode 100644
index 0000000..05566de
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultStorageManagerFactory.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.core.factory.ClassMappingFactory;
+import org.apache.myfaces.extensions.validator.core.factory.AbstractNameMapperAwareFactory;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationEntry;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * default implementation for storage-manager creation and caching
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultStorageManagerFactory extends AbstractNameMapperAwareFactory<Class>
+ implements ClassMappingFactory<Class, StorageManager>, StorageManagerHolder
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private boolean lazyStaticMappingApplied = false;
+ private List<NameMapper<Class>> nameMapperList = new ArrayList<NameMapper<Class>>();
+ private Map<Class, StorageManager> storageTypeToStorageManagerMap = new HashMap<Class, StorageManager>();
+
+ public DefaultStorageManagerFactory()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+
+ setStorageManager(RendererProxyStorage.class,
+ new DefaultRendererProxyStorageManager(), false);
+ setStorageManager(GroupStorage.class,
+ new DefaultGroupStorageManager(), false);
+ setStorageManager(MetaDataStorage.class,
+ new DefaultMetaDataStorageManager(), false);
+ setStorageManager(FacesMessageStorage.class,
+ new DefaultFacesMessageStorageManager(), false);
+ setStorageManager(PropertyStorage.class,
+ new DefaultPropertyStorageManager(), false);
+ setStorageManager(RendererInterceptorPropertyStorage.class,
+ new DefaultRendererInterceptorPropertyStorageManager(), false);
+ setStorageManager(ViolationSeverityInterpreterStorage.class,
+ new DefaultViolationSeverityInterpreterStorageManager(), false);
+
+ setStorageManager(FacesInformationStorage.class,
+ new DefaultFacesInformationStorageManager(), false);
+ }
+
+ public StorageManager create(Class storageType)
+ {
+ if (!this.lazyStaticMappingApplied)
+ {
+ initStaticMappings();
+ }
+
+ StorageManager storageManager;
+ String storageManagerName;
+ //null -> use name mappers
+ for (NameMapper<Class> nameMapper : this.nameMapperList)
+ {
+ storageManagerName = nameMapper.createName(storageType);
+
+ if (storageManagerName == null)
+ {
+ continue;
+ }
+
+ storageManager = (StorageManager)ClassUtils.tryToInstantiateClassForName(storageManagerName);
+
+ if (storageManager != null)
+ {
+ addMapping(storageType, storageManager);
+ return storageManager;
+ }
+ }
+ return getStorageManager(storageType);
+ }
+
+ private synchronized void addMapping(Class storageType, StorageManager storageManager)
+ {
+ boolean isValidEntry = true;
+ if(storageType == null)
+ {
+ isValidEntry = false;
+ if(this.logger.isErrorEnabled())
+ {
+ this.logger.error("you tried to add an invalid storage type");
+ }
+ }
+
+ if(storageManager == null)
+ {
+ isValidEntry = false;
+ if(this.logger.isErrorEnabled())
+ {
+ this.logger.error("you tried to add an invalid storage manager");
+ }
+ }
+
+ if(!isValidEntry)
+ {
+ return;
+ }
+
+ setStorageManager(storageType, storageManager, true);
+ }
+
+ private void initStaticMappings()
+ {
+ this.lazyStaticMappingApplied = true;
+
+ //setup internal static mappings
+ for (StaticConfiguration<String, String> staticConfig :
+ ExtValContext.getContext().getStaticConfiguration(
+ StaticConfigurationNames.STORAGE_TYPE_TO_STORAGE_MANAGER_CONFIG))
+ {
+ setupMappings(staticConfig.getMapping());
+ }
+ }
+
+ private void setupMappings(List<StaticConfigurationEntry<String, String>> mappings)
+ {
+ for(StaticConfigurationEntry<String, String> mapping : mappings)
+ {
+ addMapping(ClassUtils.tryToLoadClassForName(mapping.getSource()),
+ (StorageManager)ClassUtils.tryToInstantiateClassForName(mapping.getTarget()));
+ }
+ }
+
+ protected List<NameMapper<Class>> getNameMapperList()
+ {
+ return this.nameMapperList;
+ }
+
+ public void setStorageManager(Class storageType, StorageManager storageManager, boolean override)
+ {
+ if(!this.storageTypeToStorageManagerMap.containsKey(storageType) ||
+ (this.storageTypeToStorageManagerMap.containsKey(storageType) && override))
+ {
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("adding type to storage-manager mapping: "
+ + storageType.getName() + " -> " + storageManager.getClass().getName());
+ }
+
+ this.storageTypeToStorageManagerMap.put(storageType, storageManager);
+ }
+ }
+
+ public StorageManager getStorageManager(Class type)
+ {
+ return this.storageTypeToStorageManagerMap.get(type);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultViolationSeverityInterpreterStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultViolationSeverityInterpreterStorage.java
new file mode 100644
index 0000000..007bc3d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultViolationSeverityInterpreterStorage.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverityInterpreter;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultViolationSeverityInterpreterStorage implements ViolationSeverityInterpreterStorage
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private ViolationSeverityInterpreter violationSeverityInterpreter;
+
+ public void setViolationSeverityInterpreter(ViolationSeverityInterpreter violationSeverityInterpreter)
+ {
+ this.violationSeverityInterpreter = violationSeverityInterpreter;
+ }
+
+ public ViolationSeverityInterpreter getViolationSeverityInterpreter()
+ {
+ return this.violationSeverityInterpreter;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultViolationSeverityInterpreterStorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultViolationSeverityInterpreterStorageManager.java
new file mode 100644
index 0000000..5008b53
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/DefaultViolationSeverityInterpreterStorageManager.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.core.storage.mapper.DefaultViolationSeverityInterpreterStorageNameMapper;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * default storage-manager for a custom ViolationSeverityInterpreter
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class DefaultViolationSeverityInterpreterStorageManager extends
+ AbstractRequestScopeAwareStorageManager<ViolationSeverityInterpreterStorage>
+{
+ DefaultViolationSeverityInterpreterStorageManager()
+ {
+ register(new DefaultViolationSeverityInterpreterStorageNameMapper());
+ }
+
+ public String getStorageManagerKey()
+ {
+ return StorageManager.class.getName() + "_FOR_VIOLATIONSEVERITY_INTERPRETER:KEY";
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/FacesInformationStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/FacesInformationStorage.java
new file mode 100644
index 0000000..6601834
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/FacesInformationStorage.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.event.PhaseId;
+
+/**
+ * storage for additional information about the current faces request
+ * for now it just contains information about the current phase of the lifecycle
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface FacesInformationStorage
+{
+ void setCurrentPhaseId(PhaseId phaseId);
+
+ PhaseId getCurrentPhaseId();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/FacesMessageStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/FacesMessageStorage.java
new file mode 100644
index 0000000..7a50f4f
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/FacesMessageStorage.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.message.FacesMessageHolder;
+
+import javax.faces.application.FacesMessage;
+import java.util.List;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface FacesMessageStorage
+{
+ void addFacesMessage(String clientId, FacesMessage facesMessage);
+
+ List<FacesMessageHolder> getFacesMessages();
+
+ void addAll();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/GroupStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/GroupStorage.java
new file mode 100644
index 0000000..4bc014b
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/GroupStorage.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * suggested interface for a group storage
+ * used by the bvi module and add-ons
+ * <p/>
+ * it allows to manage groups for the current request
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface GroupStorage
+{
+ void addGroup(Class groupClass, String viewId, String clientId);
+
+ void restrictGroup(Class groupClass, String viewId, String clientId);
+
+ Class[] getGroups(String viewId, String clientId);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/MetaDataStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/MetaDataStorage.java
new file mode 100644
index 0000000..b9ecebd
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/MetaDataStorage.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface MetaDataStorage
+{
+ void storeMetaDataOf(PropertyInformation propertyInformation);
+
+ MetaDataEntry[] getMetaData(Class targetClass, String targetProperty);
+
+ boolean containsMetaDataFor(Class targetClass, String targetProperty);
+
+ void registerFilter(MetaDataStorageFilter storageFilter);
+
+ void deregisterFilter(Class<? extends MetaDataStorageFilter> filterClass);
+
+ void denyFilter(Class<? extends MetaDataStorageFilter> filterClass);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/MetaDataStorageFilter.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/MetaDataStorageFilter.java
new file mode 100644
index 0000000..eb2fdb6
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/MetaDataStorageFilter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface MetaDataStorageFilter
+{
+ void filter(PropertyInformation propertyInformation);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/PropertyStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/PropertyStorage.java
new file mode 100644
index 0000000..99bed26
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/PropertyStorage.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface PropertyStorage
+{
+ void storeField(Class targetClass, String property, Field field);
+
+ void storeMethod(Class targetClass, String property, Method method);
+
+ Field getField(Class targetClass, String property);
+
+ Method getMethod(Class targetClass, String property);
+
+ boolean containsField(Class targetClass, String property);
+
+ boolean containsMethod(Class targetClass, String property);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererInterceptorPropertyStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererInterceptorPropertyStorage.java
new file mode 100644
index 0000000..6cc8c1d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererInterceptorPropertyStorage.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * a storage which isn't used internally. it's for add-ons to easily store properties of interceptors.
+ * without braking backward compatibility, it's possible to use these properties in custom artifacts.
+ * rendering interception is an internal concept. so properties,... of it won't get into the api.
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface RendererInterceptorPropertyStorage
+{
+ void setProperty(String key, Object value);
+
+ Object getProperty(String key);
+
+ <T> T getProperty(String key, Class<T> targetClass);
+
+ void removeProperty(String key);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererProxyStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererProxyStorage.java
new file mode 100644
index 0000000..d71a75b
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererProxyStorage.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public interface RendererProxyStorage
+{
+ void setEntry(String rendererKey, String clientId, RendererProxyStorageEntry entry);
+
+ boolean containsEntry(String rendererKey, String clientId);
+
+ RendererProxyStorageEntry getEntry(String rendererKey, String clientId);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererProxyStorageEntry.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererProxyStorageEntry.java
new file mode 100644
index 0000000..d934778
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/RendererProxyStorageEntry.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class RendererProxyStorageEntry
+{
+ private boolean decodeCalled = false;
+ private boolean encodeBeginCalled = false;
+ private boolean encodeChildrenCalled = false;
+ private boolean encodeEndCalled = false;
+
+ private Object convertedValue = null;
+
+ public boolean isDecodeCalled()
+ {
+ return decodeCalled;
+ }
+
+ public void setDecodeCalled(boolean decodeCalled)
+ {
+ this.decodeCalled = decodeCalled;
+ }
+
+ public boolean isEncodeBeginCalled()
+ {
+ return encodeBeginCalled;
+ }
+
+ public void setEncodeBeginCalled(boolean encodeBeginCalled)
+ {
+ this.encodeBeginCalled = encodeBeginCalled;
+ }
+
+ public boolean isEncodeChildrenCalled()
+ {
+ return encodeChildrenCalled;
+ }
+
+ public void setEncodeChildrenCalled(boolean encodeChildrenCalled)
+ {
+ this.encodeChildrenCalled = encodeChildrenCalled;
+ }
+
+ public boolean isEncodeEndCalled()
+ {
+ return encodeEndCalled;
+ }
+
+ public void setEncodeEndCalled(boolean encodeEndCalled)
+ {
+ this.encodeEndCalled = encodeEndCalled;
+ }
+
+ public Object getConvertedValue()
+ {
+ return convertedValue;
+ }
+
+ public void setConvertedValue(Object convertedValue)
+ {
+ this.convertedValue = convertedValue;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/StorageManager.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/StorageManager.java
new file mode 100644
index 0000000..50c8397
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/StorageManager.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.API;
+
+/**
+ * manager to create and reset specific storage implementations
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(API)
+public interface StorageManager<T>
+{
+ T create(String key);
+ void reset(String key);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/StorageManagerHolder.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/StorageManagerHolder.java
new file mode 100644
index 0000000..fdf9538
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/StorageManagerHolder.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.API;
+
+/**
+ * interface to manage storage-manager instances
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(API)
+public interface StorageManagerHolder
+{
+ void setStorageManager(Class type, StorageManager storageManager, boolean override);
+ StorageManager getStorageManager(Class type);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/ValidationResult.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/ValidationResult.java
new file mode 100644
index 0000000..f79327c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/ValidationResult.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.core.validation.message.FacesMessageHolder;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@ToDo(value = Priority.LOW, description = "refactor it")
+@UsageInformation(UsageCategory.INTERNAL)
+class ValidationResult
+{
+ private List<FacesMessageHolder> facesMessageHolderList = new ArrayList<FacesMessageHolder>();
+
+ public void addFacesMessageHolder(FacesMessageHolder facesMessageHolder)
+ {
+ this.facesMessageHolderList.add(facesMessageHolder);
+ }
+
+ public List<FacesMessageHolder> getFacesMessageHolderList()
+ {
+ return facesMessageHolderList;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/ViolationSeverityInterpreterStorage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/ViolationSeverityInterpreterStorage.java
new file mode 100644
index 0000000..31669ec
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/ViolationSeverityInterpreterStorage.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverityInterpreter;
+
+/**
+ * suggested interface for a violation-severity-interpreter storage
+ * used by add-ons to change the interpreter for the current request
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ViolationSeverityInterpreterStorage
+{
+ void setViolationSeverityInterpreter(ViolationSeverityInterpreter violationSeverityInterpreter);
+
+ ViolationSeverityInterpreter getViolationSeverityInterpreter();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultFacesInformationStorageNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultFacesInformationStorageNameMapper.java
new file mode 100644
index 0000000..1a10296
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultFacesInformationStorageNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.storage.FacesInformationStorage;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultFacesInformationStorage;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * use a public class to allow optional deregistration
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(100)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultFacesInformationStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String source)
+ {
+ return (FacesInformationStorage.class.getName().equals(source)) ?
+ DefaultFacesInformationStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultFacesMessageStorageNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultFacesMessageStorageNameMapper.java
new file mode 100644
index 0000000..b8e97f2
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultFacesMessageStorageNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultFacesMessageStorage;
+import org.apache.myfaces.extensions.validator.core.storage.FacesMessageStorage;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * use a public class to allow optional deregistration
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(100)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultFacesMessageStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String source)
+ {
+ return (FacesMessageStorage.class.getName().equals(source)) ?
+ DefaultFacesMessageStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultMetaDataStorageNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultMetaDataStorageNameMapper.java
new file mode 100644
index 0000000..45bfe97
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultMetaDataStorageNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.storage.MetaDataStorage;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultMetaDataStorage;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * use a public class to allow optional deregistration
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(100)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultMetaDataStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String source)
+ {
+ return (MetaDataStorage.class.getName().equals(source)) ?
+ DefaultMetaDataStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultPropertyStorageNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultPropertyStorageNameMapper.java
new file mode 100644
index 0000000..27f8623
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultPropertyStorageNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultPropertyStorage;
+import org.apache.myfaces.extensions.validator.core.storage.PropertyStorage;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * use a public class to allow optional deregistration
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(100)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultPropertyStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String source)
+ {
+ return (PropertyStorage.class.getName().equals(source)) ?
+ DefaultPropertyStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultRendererInterceptorPropertyStorageNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultRendererInterceptorPropertyStorageNameMapper.java
new file mode 100644
index 0000000..696841d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultRendererInterceptorPropertyStorageNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.storage.RendererInterceptorPropertyStorage;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultRendererInterceptorPropertyStorage;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * use a public class to allow optional deregistration
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(100)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultRendererInterceptorPropertyStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String source)
+ {
+ return (RendererInterceptorPropertyStorage.class.getName().equals(source)) ?
+ DefaultRendererInterceptorPropertyStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultRendererProxyStorageNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultRendererProxyStorageNameMapper.java
new file mode 100644
index 0000000..c8e9de9
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultRendererProxyStorageNameMapper.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultRendererProxyStorage;
+import org.apache.myfaces.extensions.validator.core.storage.RendererProxyStorage;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * use a public class to allow optional deregistration
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(100)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultRendererProxyStorageNameMapper implements NameMapper<String>
+{
+
+ public String createName(String source)
+ {
+ return (RendererProxyStorage.class.getName().equals(source)) ?
+ DefaultRendererProxyStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultViolationSeverityInterpreterStorageNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultViolationSeverityInterpreterStorageNameMapper.java
new file mode 100644
index 0000000..19496d7
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/storage/mapper/DefaultViolationSeverityInterpreterStorageNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultViolationSeverityInterpreterStorage;
+import org.apache.myfaces.extensions.validator.core.storage.ViolationSeverityInterpreterStorage;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * use a public class to allow optional deregistration
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(100)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultViolationSeverityInterpreterStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String source)
+ {
+ return (ViolationSeverityInterpreterStorage.class.getName().equals(source)) ?
+ DefaultViolationSeverityInterpreterStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/EmptyValueAwareValidationStrategy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/EmptyValueAwareValidationStrategy.java
new file mode 100644
index 0000000..cafbf65
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/EmptyValueAwareValidationStrategy.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface EmptyValueAwareValidationStrategy
+{
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/NullValueAwareValidationStrategy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/NullValueAwareValidationStrategy.java
new file mode 100644
index 0000000..cb750eb
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/NullValueAwareValidationStrategy.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface NullValueAwareValidationStrategy
+{
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/SkipValidationEvaluator.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/SkipValidationEvaluator.java
new file mode 100644
index 0000000..9b4caa4
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/SkipValidationEvaluator.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation;
+
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface SkipValidationEvaluator
+{
+ boolean skipValidation(FacesContext facesContext, UIComponent uiComponent,
+ ValidationStrategy validationStrategy, MetaDataEntry entry);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/exception/RequiredValidatorException.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/exception/RequiredValidatorException.java
new file mode 100644
index 0000000..5fb2bb0
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/exception/RequiredValidatorException.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.exception;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.validator.ValidatorException;
+import javax.faces.application.FacesMessage;
+
+/**
+ * to handle special cases in ValidationExceptionInterceptors
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public class RequiredValidatorException extends ValidatorException
+{
+ private static final long serialVersionUID = -4646331736428495884L;
+
+ public RequiredValidatorException(FacesMessage facesMessage)
+ {
+ super(facesMessage);
+ }
+
+ public RequiredValidatorException(FacesMessage facesMessage, Throwable throwable)
+ {
+ super(facesMessage, throwable);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/DefaultFacesMessageFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/DefaultFacesMessageFactory.java
new file mode 100644
index 0000000..a62510c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/DefaultFacesMessageFactory.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.factory.FacesMessageFactory;
+
+import javax.faces.application.FacesMessage;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultFacesMessageFactory implements FacesMessageFactory
+{
+ public FacesMessage convert(FacesMessage facesMessage)
+ {
+ if(isLabeledFacesMessage(facesMessage))
+ {
+ return facesMessage;
+ }
+ return create(facesMessage.getSeverity(), facesMessage.getSummary(), facesMessage.getDetail());
+ }
+
+ public FacesMessage create(FacesMessage.Severity severity, String summary, String detail)
+ {
+ return new ViolationMessage(severity, summary, detail);
+ }
+
+ protected boolean isLabeledFacesMessage(FacesMessage facesMessage)
+ {
+ //don't use the interface here
+ return facesMessage instanceof ViolationMessage;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/FacesMessageHolder.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/FacesMessageHolder.java
new file mode 100644
index 0000000..a31c367
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/FacesMessageHolder.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.application.FacesMessage;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class FacesMessageHolder
+{
+ private FacesMessage facesMessage;
+ private String clientId;
+
+ public FacesMessageHolder(FacesMessage facesMessage)
+ {
+ this.facesMessage = facesMessage;
+ }
+
+ public FacesMessageHolder(FacesMessage facesMessage, String clientId)
+ {
+ this.facesMessage = facesMessage;
+ setClientId(clientId);
+ }
+
+ public FacesMessage getFacesMessage()
+ {
+ return facesMessage;
+ }
+
+ public String getClientId()
+ {
+ return clientId;
+ }
+
+ public void setClientId(String clientId)
+ {
+ if(!"*".equals(clientId))
+ {
+ this.clientId = clientId;
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/LabeledMessage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/LabeledMessage.java
new file mode 100644
index 0000000..3df7ae7
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/LabeledMessage.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * don't remove *Text - it would lead to an overlap with trinidad
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+@UsageInformation(UsageCategory.API)
+public interface LabeledMessage
+{
+ String getLabelText();
+ void setLabelText(String label);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/ViolationMessage.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/ViolationMessage.java
new file mode 100644
index 0000000..6944c76
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/ViolationMessage.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.application.FacesMessage;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class ViolationMessage extends FacesMessage implements LabeledMessage
+{
+ private static final long serialVersionUID = 6903958942987711231L;
+ private String label;
+ private boolean summaryLabelReplaced = false;
+ private boolean detailLabelReplaced = false;
+
+ public ViolationMessage(String summary, String detail)
+ {
+ this(SEVERITY_ERROR, summary, detail);
+ }
+
+ public ViolationMessage(Severity severity, String summary, String detail)
+ {
+ setSeverity(severity);
+ setSummary(summary);
+ setDetail(detail);
+ }
+
+ public String getLabelText()
+ {
+ return label;
+ }
+
+ public void setLabelText(String label)
+ {
+ this.label = label;
+ }
+
+ @Override
+ public String getSummary()
+ {
+ if(label != null && !this.summaryLabelReplaced)
+ {
+ setSummary(getLabeledMesssage(super.getSummary(), getLabelText()));
+ this.summaryLabelReplaced = true;
+ }
+ return super.getSummary();
+ }
+
+ @Override
+ public String getDetail()
+ {
+ if(label != null && !this.detailLabelReplaced)
+ {
+ setDetail(getLabeledMesssage(super.getDetail(), getLabelText()));
+ this.detailLabelReplaced = true;
+ }
+ return super.getDetail();
+ }
+
+ private String getLabeledMesssage(String message, String label)
+ {
+ for(int i = 0; i < 3; i++)
+ {
+ if(message != null && message.contains("{" + i + "}"))
+ {
+ message = message.replace("{" + i + "}", label);
+ }
+ }
+
+ return message;
+ }
+
+ @Override
+ public void setSummary(String s)
+ {
+ super.setSummary(s);
+ this.summaryLabelReplaced = false;
+ }
+
+ @Override
+ public void setDetail(String s)
+ {
+ super.setDetail(s);
+ this.detailLabelReplaced = false;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/AbstractValidationErrorMessageResolver.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/AbstractValidationErrorMessageResolver.java
new file mode 100644
index 0000000..56396d4
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/AbstractValidationErrorMessageResolver.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver;
+
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * MessageResolver which uses property files.
+ * Subclasses just have to provide the package to look at.
+ * An implementation can also provide a custom name which is e.g. configured via web.xml.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public abstract class AbstractValidationErrorMessageResolver implements MessageResolver
+{
+ public static final String MISSING_RESOURCE_MARKER = "???";
+
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private static String deactivateDefaultConvention = WebXmlParameter.DEACTIVATE_DEFAULT_CONVENTION;
+ private static ResourceBundle defaultBundle = null;
+ private String messageBundleBaseName;
+ //with jsf 1.1 only available if there is a custom bean
+ private String messageBundleVarName;
+
+ protected AbstractValidationErrorMessageResolver()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public String getMessage(String key, Locale locale)
+ {
+ if (key == null || key.equals(""))
+ {
+ return null;
+ }
+
+ if(key.contains(" "))
+ {
+ if(key.endsWith("_detail"))
+ {
+ key = key.substring(0, key.length() - 7);
+ }
+ return key;
+ }
+
+ String customMessage = null;
+
+ try
+ {
+ customMessage = tryToFindCustomMessage(key, locale);
+ }
+ catch (Throwable t)
+ {
+ //do nothing
+ }
+
+ if (customMessage != null)
+ {
+ return customMessage;
+ }
+
+ /*
+ * try to use the convention for the message bundle
+ */
+ try
+ {
+ customMessage = tryToUseMessageBundleConvention(key, locale);
+ }
+ catch (Throwable t)
+ {
+ //do nothing
+ }
+
+ if (customMessage != null)
+ {
+ return customMessage;
+ }
+
+ /*
+ * no message bundle or message found (with the convention)?
+ */
+
+ //try to load custom messages
+ try
+ {
+ customMessage = tryToFindCustomMessageInCustomResourceBundle(key, locale);
+ }
+ catch (Throwable t)
+ {
+ //do nothing - it was just a try
+ }
+
+ return determineMessage(key, locale, customMessage);
+ }
+
+ private String tryToFindCustomMessage(String key, Locale locale)
+ {
+ ResourceBundle resourceBundle;
+ String customMessage = null;
+
+ //only in case of a ValidationErrorMessageResolver which is configured as bean
+ if (this.messageBundleBaseName != null)
+ {
+ resourceBundle = ResourceBundle.getBundle(this.messageBundleBaseName, locale);
+ if (resourceBundle != null)
+ {
+ customMessage = resourceBundle.getString(key);
+ }
+ else
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("message bundle " + this.messageBundleBaseName + " not found");
+ }
+ }
+ }
+
+ //only in case of a ValidationErrorMessageResolver which is configured as bean
+ if (this.messageBundleVarName != null && customMessage == null)
+ {
+ resourceBundle = (ResourceBundle) ExtValUtils.getELHelper().getBean(messageBundleVarName);
+
+ if (resourceBundle != null)
+ {
+ customMessage = resourceBundle.getString(key);
+ }
+ else
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("message bundle var name " + this.messageBundleVarName + " not found");
+ }
+ }
+ }
+
+ return customMessage;
+ }
+
+ private String tryToUseMessageBundleConvention(String key, Locale locale)
+ {
+ if ((deactivateDefaultConvention == null || !deactivateDefaultConvention.equalsIgnoreCase("true"))
+ && isDefaultMessageBundleConventionActive())
+ {
+ if (defaultBundle == null)
+ {
+ try
+ {
+ defaultBundle = ResourceBundle.getBundle(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.MESSAGE_BUNDLE_NAME), locale);
+ }
+ catch (Throwable t)
+ {
+ //do nothing
+ deactivateDefaultConvention = "true";
+ }
+ }
+
+ if (defaultBundle != null)
+ {
+ return defaultBundle.getString(key);
+ }
+ }
+
+ return null;
+ }
+
+ private String tryToFindCustomMessageInCustomResourceBundle(String key, Locale locale)
+ {
+ ResourceBundle resourceBundle = tryToLoadCustomResourceBundle(locale);
+
+ if (resourceBundle != null)
+ {
+ try
+ {
+ return resourceBundle.getString(key);
+ }
+ catch (MissingResourceException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("no custom message for " + key + " within " + getCustomBaseName(), e);
+ }
+ }
+ }
+ return null;
+ }
+
+ private ResourceBundle tryToLoadCustomResourceBundle(Locale locale)
+ {
+ String customBaseName = getCustomBaseName();
+
+ if(customBaseName != null)
+ {
+ return ResourceBundle.getBundle(customBaseName, locale);
+ }
+ return null;
+ }
+
+ private String determineMessage(String key, Locale locale, String customMessage)
+ {
+ //use custom name (if possible) otherwise: fallback to default message (if possible)
+ try
+ {
+ return (customMessage != null) ? customMessage
+ : (getBaseName() != null) ? ResourceBundle.getBundle(getBaseName(), locale).getString(key) : null;
+ }
+ catch (MissingResourceException e)
+ {
+ return MISSING_RESOURCE_MARKER + key + MISSING_RESOURCE_MARKER;
+ }
+ }
+
+ protected boolean isDefaultMessageBundleConventionActive()
+ {
+ return true;
+ }
+
+ protected abstract String getBaseName();
+
+ protected String getCustomBaseName()
+ {
+ return null;
+ }
+
+ public void setMessageBundleBaseName(String messageBundleBaseName)
+ {
+ this.messageBundleBaseName = messageBundleBaseName;
+ }
+
+ public void setMessageBundleVarName(String messageBundleVarName)
+ {
+ this.messageBundleVarName = messageBundleVarName;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultMessageResolverFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultMessageResolverFactory.java
new file mode 100644
index 0000000..1818037
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultMessageResolverFactory.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver;
+
+import org.apache.myfaces.extensions.validator.core.factory.ClassMappingFactory;
+import org.apache.myfaces.extensions.validator.core.factory.AbstractNameMapperAwareFactory;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationEntry;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Factory which creates a MessageResolver for a given ValidationStrategy
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@ToDo(value = Priority.MEDIUM, description = "add generic java api (de-/register mapping)")
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class DefaultMessageResolverFactory extends AbstractNameMapperAwareFactory<ValidationStrategy>
+ implements ClassMappingFactory<ValidationStrategy, MessageResolver>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Map<String, String> strategyMessageResolverMapping;
+ private List<NameMapper<ValidationStrategy>> nameMapperList = new ArrayList<NameMapper<ValidationStrategy>>();
+
+ public DefaultMessageResolverFactory()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public MessageResolver create(ValidationStrategy validationStrategy)
+ {
+ String strategyName = ProxyUtils.getClassName(validationStrategy.getClass());
+
+ if (strategyMessageResolverMapping == null)
+ {
+ initStaticMappings();
+ }
+
+ if (strategyMessageResolverMapping.containsKey(strategyName))
+ {
+ return (MessageResolver) ClassUtils
+ .tryToInstantiateClassForName(strategyMessageResolverMapping.get(strategyName));
+ }
+
+ MessageResolver messageResolver;
+ String resolverName;
+ for (NameMapper<ValidationStrategy> nameMapper : nameMapperList)
+ {
+ //build convention (ValidationErrorMessageResolver)
+ resolverName = nameMapper.createName(validationStrategy);
+
+ //name wasn't mapped
+ if (resolverName == null || ProxyUtils.getClassName(validationStrategy.getClass()).equals(resolverName))
+ {
+ continue;
+ }
+
+ messageResolver = (MessageResolver) ClassUtils.tryToInstantiateClassForName(resolverName);
+
+ if (messageResolver != null)
+ {
+ addMapping(strategyName, resolverName);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(resolverName + " used for " + strategyName);
+ }
+
+ return messageResolver;
+ }
+ }
+
+ addMapping(strategyName, DefaultValidationErrorMessageResolver.class.getName());
+ return new DefaultValidationErrorMessageResolver();
+ }
+
+ private synchronized void initStaticMappings()
+ {
+ strategyMessageResolverMapping = new HashMap<String, String>();
+
+ //setup internal static mappings
+ for (StaticConfiguration<String, String> staticConfig :
+ ExtValContext.getContext().getStaticConfiguration(
+ StaticConfigurationNames.VALIDATION_STRATEGY_TO_MESSAGE_RESOLVER_CONFIG))
+ {
+ setupMappings(staticConfig.getMapping());
+ }
+ }
+
+ private void setupMappings(List<StaticConfigurationEntry<String,String>> mappings)
+ {
+ for(StaticConfigurationEntry<String, String> mapping : mappings)
+ {
+ addMapping(mapping.getSource(), mapping.getTarget());
+ }
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "logging")
+ private synchronized void addMapping(String validationStrategyName, String messageResolverName)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("adding static validation strategy to message resolver mapping: "
+ + validationStrategyName + " -> " + messageResolverName);
+ }
+
+ strategyMessageResolverMapping.put(validationStrategyName, messageResolverName);
+ }
+
+ protected List<NameMapper<ValidationStrategy>> getNameMapperList()
+ {
+ return nameMapperList;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultValidationErrorMessageResolver.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultValidationErrorMessageResolver.java
new file mode 100644
index 0000000..079edc6
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultValidationErrorMessageResolver.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver;
+
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.InternalConventionProvider;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * Default MessageResolver which uses the default convention for the message bundle.
+ * It's possible to provide a custom message bundle via web.xml
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class DefaultValidationErrorMessageResolver extends AbstractValidationErrorMessageResolver
+{
+ private static final String CUSTOM_BUNDLE = WebXmlParameter.CUSTOM_MESSAGE_BUNDLE;
+
+ //not used at the moment - just for a convention
+ protected String getBaseName()
+ {
+ return InternalConventionProvider.getModuleMessageBundleName(getClass().getPackage().getName());
+ }
+
+ protected String getCustomBaseName()
+ {
+ return CUSTOM_BUNDLE;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/MessageResolver.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/MessageResolver.java
new file mode 100644
index 0000000..dcca1c1
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/MessageResolver.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.Locale;
+
+/**
+ * Interface for MessageResolvers independent of the message source.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface MessageResolver
+{
+ String getMessage(String key, Locale locale);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/AbstractValidationStrategyToMsgResolverNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/AbstractValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..10d40b6
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/AbstractValidationStrategyToMsgResolverNameMapper.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public abstract class AbstractValidationStrategyToMsgResolverNameMapper implements NameMapper<ValidationStrategy>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public AbstractValidationStrategyToMsgResolverNameMapper()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConfiguredValidationStrategyToMsgResolverNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConfiguredValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..76c08e8
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConfiguredValidationStrategyToMsgResolverNameMapper.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper;
+
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * To provide a custom NameMapper to map ValidationStrategies to MessageResolvers.
+ * (configured via web.xml)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(100)
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class CustomConfiguredValidationStrategyToMsgResolverNameMapper extends
+ AbstractCustomNameMapper<ValidationStrategy>
+{
+
+ protected String getCustomNameMapperClassName()
+ {
+ return WebXmlParameter.CUSTOM_VALIDATION_STRATEGY_TO_MESSAGE_RESOLVER_NAME_MAPPER;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConventionValidationStrategyToMsgResolverNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConventionValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..343c013
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConventionValidationStrategyToMsgResolverNameMapper.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * To provide a custom NameMapper to map ValidationStrategy to MessageResolver.
+ * (configured via information provider bean)
+ * The bean provides the default name (convention).
+ * It's possible to provide a custom full qualified name. (= customizable convention)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(200)
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class CustomConventionValidationStrategyToMsgResolverNameMapper extends
+ AbstractCustomNameMapper<ValidationStrategy>
+{
+
+ protected String getCustomNameMapperClassName()
+ {
+ return ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.VALIDATION_STRATEGY_TO_MSG_RESOLVER_NAME_MAPPER);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultModuleValidationStrategyToMsgResolverNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultModuleValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..0ebb4d6
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultModuleValidationStrategyToMsgResolverNameMapper.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper;
+
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.DefaultValidationErrorMessageResolver;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * In order to provide a NameMapper per validation module.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(310)
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class DefaultModuleValidationStrategyToMsgResolverNameMapper extends
+ DefaultValidationStrategyToMsgResolverNameMapper
+{
+ @Override
+ protected String getClassName(String strategyClassName)
+ {
+ return DefaultValidationErrorMessageResolver.class.getSimpleName();
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultValidationStrategyToMsgResolverNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..3da477b
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultValidationStrategyToMsgResolverNameMapper.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper;
+
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.InternalConventionProvider;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+/**
+ * Default implementation which maps ExtVal ValidationStrategies to ExtVal MessageResolvers.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(300)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultValidationStrategyToMsgResolverNameMapper extends
+ AbstractValidationStrategyToMsgResolverNameMapper
+{
+ public String createName(ValidationStrategy validationStrategy)
+ {
+ Class<? extends ValidationStrategy> validationStrategyClass = ProxyUtils
+ .getUnproxiedClass(validationStrategy.getClass(), ValidationStrategy.class);
+ return InternalConventionProvider.getMessageResolverClassName(validationStrategyClass,
+ getClassName(validationStrategyClass.getSimpleName()));
+ }
+
+ protected String getClassName(String strategyClassName)
+ {
+ return InternalConventionProvider.getMessageResolverClassName(strategyClassName);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/SimpleValidationStrategyToMsgResolverNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/SimpleValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..d63d970
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/SimpleValidationStrategyToMsgResolverNameMapper.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.message.resolver.mapper;
+
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.InternalConventionProvider;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * It's an alternative Mapper to place ValidationStrategies and MessageResolvers in the same package.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(400)
+@UsageInformation({UsageCategory.INTERNAL})
+public class SimpleValidationStrategyToMsgResolverNameMapper extends
+ DefaultValidationStrategyToMsgResolverNameMapper
+{
+ protected String getClassName(String strategyClassName)
+ {
+ String customPostfix = ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.VALIDATION_ERROR_MESSAGE_RESOLVER_POSTFIX);
+ return InternalConventionProvider.getValidationStrategyBasedName(strategyClassName, customPostfix);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterExtractor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterExtractor.java
new file mode 100644
index 0000000..5d38f54
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterExtractor.java
@@ -0,0 +1,400 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.WildcardType;
+import java.lang.reflect.Modifier;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultValidationParameterExtractor implements ValidationParameterExtractor
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public Map<Object, List<Object>> extract(Annotation annotation)
+ {
+ return extractById(annotation, null);
+ }
+
+ public List<Object> extract(Annotation annotation, Object key)
+ {
+ return extractById(annotation, key, null);
+ }
+
+ public <T> List<T> extract(Annotation annotation, Object key, Class<T> valueType)
+ {
+ return extractById(annotation, key, valueType, null);
+ }
+
+ public <T> T extract(Annotation annotation, Object key, Class<T> valueType, Class valueId)
+ {
+ List<T> results = extractById(annotation, key, valueType, valueId);
+
+ if(results.iterator().hasNext())
+ {
+ return results.iterator().next();
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public <T> List<T> extractById(Annotation annotation, Object key, Class<T> valueType, Class valueId)
+ {
+ List<Object> result = new ArrayList<Object>();
+
+ for(Object entry : extractById(annotation, key, valueId))
+ {
+ if(valueType.isAssignableFrom(entry.getClass()))
+ {
+ result.add(entry);
+ }
+ }
+
+ return (List<T>)result;
+ }
+
+ public List<Object> extractById(Annotation annotation, Object key, Class valueId)
+ {
+ Map<Object, List<Object>> fullResult = extractById(annotation, valueId);
+
+ if(fullResult.containsKey(key))
+ {
+ return fullResult.get(key);
+ }
+
+ return new ArrayList<Object>();
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "add web.xml parameter for performance tuning to deactivate the scan")
+ public Map<Object, List<Object>> extractById(Annotation annotation, Class valueId)
+ {
+ Map<Object, List<Object>> result = new HashMap<Object, List<Object>>();
+
+ for(Method currentAnnotationAttribute : annotation.annotationType().getDeclaredMethods())
+ {
+ try
+ {
+ if(!isValidationParameter(currentAnnotationAttribute.getGenericReturnType()))
+ {
+ continue;
+ }
+
+ Object parameterValue = currentAnnotationAttribute.invoke(annotation);
+
+ if(parameterValue instanceof Class[])
+ {
+ for(Class currentParameterValue : (Class[])parameterValue)
+ {
+ //keep check so that following is true:
+ //if at least one parameter is found which tells that it isn't a blocking error, let it pass
+ processParameterValue(annotation, currentParameterValue, result, valueId);
+ }
+ }
+ else if(parameterValue instanceof Class)
+ {
+ //keep check so that following is true:
+ //if at least one parameter is found which tells that it isn't a blocking error, let it pass
+ processParameterValue(annotation, (Class)parameterValue, result, valueId);
+ }
+ }
+ catch (Throwable e)
+ {
+ if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn(e);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ * don't use the Introspector in this case
+ * if you have a better solution which supports all supported parameter styles (see extval wiki),
+ * you can impl. it and use it (exchange the impls. via the ExtValContext).
+ * furthermore, you can provide the fix for the community
+ */
+ private void processParameterValue(
+ Annotation annotation, Class paramClass, Map<Object, List<Object>> result, Class valueId) throws Exception
+ {
+ Object key = null;
+ List<Object> parameterValues = new ArrayList<Object>();
+
+ if(ValidationParameter.class.isAssignableFrom(paramClass))
+ {
+ List<Field> processedFields = new ArrayList<Field>();
+ List<Method> processedMethods = new ArrayList<Method>();
+
+ Class currentParamClass = paramClass;
+ while (currentParamClass != null && !Object.class.getName().equals(currentParamClass.getName()))
+ {
+ /*
+ * process class
+ */
+ //support pure interface approach e.g. ViolationSeverity.Warn.class
+ for(Field currentField : currentParamClass.getDeclaredFields())
+ {
+ if(!processedFields.contains(currentField))
+ {
+ key = processFoundField(annotation, currentField, parameterValues, key, valueId);
+ processedFields.add(currentField);
+ }
+ }
+
+ //inspect the other methods of the implementing class
+ for(Method currentMethod : currentParamClass.getDeclaredMethods())
+ {
+ if(!processedMethods.contains(currentMethod))
+ {
+ key = processFoundMethod(currentParamClass, currentMethod, parameterValues, key, valueId);
+ processedMethods.add(currentMethod);
+ }
+ }
+
+ /*
+ * process interfaces
+ */
+ for(Class currentInterface : currentParamClass.getInterfaces())
+ {
+ if(!ValidationParameter.class.isAssignableFrom(currentInterface))
+ {
+ continue;
+ }
+
+ //support interface + impl. approach e.g. MyParamImpl.class
+ //(MyParamImpl implements MyParam
+ //MyParam extends ValidationParameter
+ //methods in the interface have to be marked with @ParameterValue and @ParameterKey
+ for(Method currentMethod : currentInterface.getDeclaredMethods())
+ {
+ if(!processedMethods.contains(currentMethod))
+ {
+ key = processFoundMethod(currentParamClass, currentMethod, parameterValues, key, valueId);
+ processedMethods.add(currentMethod);
+ }
+ }
+
+ for(Field currentField : currentInterface.getDeclaredFields())
+ {
+ if(!processedFields.contains(currentField))
+ {
+ key = processFoundField(annotation, currentField, parameterValues, key, valueId);
+ processedFields.add(currentField);
+ }
+ }
+ }
+
+ currentParamClass = currentParamClass.getSuperclass();
+ }
+ }
+
+ key = createDefaultKey(key, paramClass);
+
+ if(parameterValues.isEmpty())
+ {
+ //@ParameterValue is optional as well
+ parameterValues.add(key);
+ }
+
+ if(result.containsKey(key))
+ {
+ result.get(key).addAll(parameterValues);
+ }
+ else
+ {
+ result.put(key, parameterValues);
+ }
+ }
+
+ private Object createDefaultKey(Object key, Class currentClass)
+ {
+ if(key == null)
+ {
+ //check for super-interface (exclude ValidationParameter itself)
+ for(Class interfaceClass : currentClass.getInterfaces())
+ {
+ if(ValidationParameter.class.isAssignableFrom(interfaceClass) &&
+ (!interfaceClass.getName().equals(ValidationParameter.class.getName())))
+ {
+ key = interfaceClass;
+ break;
+ }
+ }
+ }
+
+ if(key == null)
+ {
+ key = currentClass;
+ }
+
+ return key;
+ }
+
+ private Object processFoundField(
+ Object instance, Field currentField, List<Object> paramValues, Object key, Class valueId)
+ {
+ Object newKey = null;
+ if(key == null && currentField.isAnnotationPresent(ParameterKey.class))
+ {
+ try
+ {
+ newKey = currentField.get(instance);
+ }
+ catch (Throwable e)
+ {
+ if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn(e);
+ }
+ }
+ }
+ //no "else if" to allow both at one field
+ if(currentField.isAnnotationPresent(ParameterValue.class))
+ {
+ if(valueId == null || valueId.equals(currentField.getAnnotation(ParameterValue.class).id()))
+ {
+ currentField.setAccessible(true);
+ try
+ {
+ paramValues.add(currentField.get(instance));
+ }
+ catch (Throwable e)
+ {
+ if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn(e);
+ }
+ }
+ }
+ }
+
+ return newKey != null ? newKey : key;
+ }
+
+ private Object processFoundMethod(
+ Class paramClass, Method currentMethod, List<Object> parameterValues, Object key, Class valueId)
+ {
+ Object newKey = null;
+ if(key == null && currentMethod.isAnnotationPresent(ParameterKey.class))
+ {
+ try
+ {
+ if(!(Modifier.isAbstract(paramClass.getModifiers()) || Modifier.isInterface(paramClass.getModifiers())))
+ {
+ newKey = currentMethod.invoke(paramClass.newInstance());
+ }
+ }
+ catch (Throwable e)
+ {
+ if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn(e);
+ }
+ }
+ }
+ //no "else if" to allow both at one field
+ if(currentMethod.isAnnotationPresent(ParameterValue.class))
+ {
+ if(valueId == null || valueId.equals(currentMethod.getAnnotation(ParameterValue.class).id()))
+ {
+ currentMethod.setAccessible(true);
+ try
+ {
+ parameterValues.add(currentMethod.invoke(paramClass.newInstance()));
+ }
+ catch (Throwable e)
+ {
+ //check if it's a none-static inner class -> return this class
+ if(paramClass.getEnclosingClass() != null)
+ {
+ parameterValues.add(paramClass);
+ }
+ else if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn(e);
+ }
+ }
+ }
+ }
+
+ return newKey != null ? newKey : key;
+ }
+
+ private boolean isValidationParameter(Type genericReturnType)
+ {
+ if(genericReturnType instanceof GenericArrayType)
+ {
+ if(((GenericArrayType)genericReturnType).getGenericComponentType() instanceof ParameterizedType)
+ {
+ return analyzeParameterizedType(
+ (ParameterizedType)((GenericArrayType)genericReturnType).getGenericComponentType());
+ }
+ }
+ else if(genericReturnType instanceof ParameterizedType)
+ {
+ return analyzeParameterizedType(
+ (ParameterizedType)genericReturnType);
+ }
+
+ return false;
+ }
+
+ private boolean analyzeParameterizedType(ParameterizedType parameterizedType)
+ {
+ for(Type type : parameterizedType.getActualTypeArguments())
+ {
+ if(type instanceof WildcardType)
+ {
+ for(Type upperBounds : ((WildcardType)type).getUpperBounds())
+ {
+ if(upperBounds instanceof Class &&
+ //for attributes like: Class<? extends InheritedFromValidationParameter> value();
+ ValidationParameter.class.isAssignableFrom((Class)upperBounds))
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterExtractorFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterExtractorFactory.java
new file mode 100644
index 0000000..da2a73c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterExtractorFactory.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultValidationParameterExtractorFactory implements ValidationParameterExtractorFactory
+{
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private static ValidationParameterExtractor validationParameterExtractor = null;
+
+ public DefaultValidationParameterExtractorFactory()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public ValidationParameterExtractor create()
+ {
+ if (validationParameterExtractor == null)
+ {
+ List<String> validationParameterExtractorClassNames = new ArrayList<String>();
+
+ validationParameterExtractorClassNames.add(WebXmlParameter.CUSTOM_VALIDATION_PARAMETER_EXTRACTOR);
+ validationParameterExtractorClassNames
+ .add(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.VALIDATION_PARAMETER_EXTRACTOR));
+ validationParameterExtractorClassNames.add(DefaultValidationParameterExtractor.class.getName());
+
+ for (String className : validationParameterExtractorClassNames)
+ {
+ validationParameterExtractor = (ValidationParameterExtractor)
+ ClassUtils.tryToInstantiateClassForName(className);
+
+ if (validationParameterExtractor != null)
+ {
+ break;
+ }
+ }
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(validationParameterExtractor.getClass().getName() + " created");
+ }
+
+ return validationParameterExtractor;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterFactory.java
new file mode 100644
index 0000000..3d5c8fe
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultValidationParameterFactory.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.factory.ClassMappingFactory;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationEntry;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * maps internal parameters to optionally available custom parameters
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultValidationParameterFactory implements ClassMappingFactory<Class, Class>
+{
+ private Map<Class, Class> parameterMapping = new HashMap<Class, Class>();
+
+ public Class create(Class source)
+ {
+ if (this.parameterMapping.containsKey(source))
+ {
+ return this.parameterMapping.get(source);
+ }
+
+ Class result;
+
+ //it's important to look for the static configs first - global parameters are used internally
+ result = tryToFindStaticConfig(source);
+
+ if (result == null)
+ {
+ result = tryToFindGlobalParameter(source);
+ }
+
+ if (result == null)
+ {
+ result = source;
+ }
+
+ cacheMapping(source, result);
+ return result;
+ }
+
+ private Class tryToFindGlobalParameter(Class source)
+ {
+ Object target = ExtValContext.getContext().getGlobalProperty(source.getName());
+
+ if (target instanceof Class)
+ {
+ return (Class) target;
+ }
+ return null;
+ }
+
+ private Class tryToFindStaticConfig(Class source)
+ {
+ Class result = null;
+ for (StaticConfiguration<String, String> config : ExtValContext.getContext()
+ .getStaticConfiguration(StaticConfigurationNames.VALIDATION_PARAMETER_CONFIG))
+ {
+ result = tryToMap(source, config.getMapping());
+
+ if (result != null)
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ private Class tryToMap(Class source, List<StaticConfigurationEntry<String, String>> mapping)
+ {
+ Class target = null;
+
+ for (StaticConfigurationEntry<String, String> entry : mapping)
+ {
+ if (source.getName().equals(entry.getSource()))
+ {
+ target = ClassUtils.tryToLoadClassForName(entry.getTarget());
+
+ if (target != null)
+ {
+ break;
+ }
+ }
+ }
+
+ return target;
+ }
+
+ private void cacheMapping(Class source, Class target)
+ {
+ this.parameterMapping.put(source, target);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultViolationSeverityInterpreter.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultViolationSeverityInterpreter.java
new file mode 100644
index 0000000..f26c7f1
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DefaultViolationSeverityInterpreter.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.application.FacesMessage;
+
+/**
+ * mechanism to change the default behavior of extval
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultViolationSeverityInterpreter implements ViolationSeverityInterpreter
+{
+ public boolean severityBlocksNavigation(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity)
+ {
+ return FacesMessage.SEVERITY_ERROR.equals(severity) || FacesMessage.SEVERITY_FATAL.equals(severity);
+ }
+
+ public boolean severityCausesValidatorException(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity)
+ {
+ return FacesMessage.SEVERITY_ERROR.equals(severity) || FacesMessage.SEVERITY_FATAL.equals(severity);
+ }
+
+ public boolean severityCausesViolationMessage(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity)
+ {
+ return true;
+ }
+
+ public boolean severityBlocksSubmit(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity)
+ {
+ return FacesMessage.SEVERITY_ERROR.equals(severity) || FacesMessage.SEVERITY_FATAL.equals(severity);
+ }
+
+ public boolean severityShowsIndication(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity)
+ {
+ return FacesMessage.SEVERITY_ERROR.equals(severity) || FacesMessage.SEVERITY_FATAL.equals(severity);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DisableClientSideValidation.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DisableClientSideValidation.java
new file mode 100644
index 0000000..4c0086b
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/DisableClientSideValidation.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface DisableClientSideValidation extends ValidationParameter
+{
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ParameterKey.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ParameterKey.java
new file mode 100644
index 0000000..c302bba
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ParameterKey.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@Target({FIELD, METHOD})
+@Retention(RUNTIME)
+@UsageInformation(UsageCategory.API)
+public @interface ParameterKey
+{
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ParameterValue.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ParameterValue.java
new file mode 100644
index 0000000..3fdc8f3
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ParameterValue.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@Target({FIELD, METHOD})
+@Retention(RUNTIME)
+@UsageInformation(UsageCategory.API)
+public @interface ParameterValue
+{
+ Class id() default ParameterValue.class;
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameter.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameter.java
new file mode 100644
index 0000000..b159c76
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameter.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ValidationParameter
+{
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameterExtractor.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameterExtractor.java
new file mode 100644
index 0000000..9209902
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameterExtractor.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.Map;
+import java.util.List;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ValidationParameterExtractor
+{
+ Map<Object, List<Object>> extract(Annotation annotation);
+ List<Object> extract(Annotation annotation, Object key);
+ <T> List<T> extract(Annotation annotation, Object key, Class<T> valueType);
+ <T> T extract(Annotation annotation, Object key, Class<T> valueType, Class valueId);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameterExtractorFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameterExtractorFactory.java
new file mode 100644
index 0000000..0dcddd2
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ValidationParameterExtractorFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ValidationParameterExtractorFactory
+{
+ ValidationParameterExtractor create();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ViolationSeverity.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ViolationSeverity.java
new file mode 100644
index 0000000..532887c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ViolationSeverity.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.application.FacesMessage;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ViolationSeverity
+{
+ interface Info extends ValidationParameter
+ {
+ @ParameterKey
+ public Class KEY = ViolationSeverity.class;
+
+ @ParameterValue
+ public FacesMessage.Severity SEVERITY = FacesMessage.SEVERITY_INFO;
+
+ //@ParameterValue
+ //MessageType postfix = MessageType.INFO;
+ }
+
+ interface Warn extends ValidationParameter
+ {
+ @ParameterKey
+ public Class KEY = ViolationSeverity.class;
+
+ @ParameterValue
+ FacesMessage.Severity SEVERITY = FacesMessage.SEVERITY_WARN;
+
+ //@ParameterValue
+ //MessageType postfix = MessageType.WARN;
+ }
+
+ interface Error extends ValidationParameter
+ {
+ @ParameterKey
+ public Class KEY = ViolationSeverity.class;
+
+ @ParameterValue
+ FacesMessage.Severity SEVERITY = FacesMessage.SEVERITY_ERROR;
+
+ //@ParameterValue
+ //MessageType postfix = MessageType.ERROR;
+ }
+
+ interface Fatal extends ValidationParameter
+ {
+ @ParameterKey
+ public Class KEY = ViolationSeverity.class;
+
+ @ParameterValue
+ FacesMessage.Severity SEVERITY = FacesMessage.SEVERITY_FATAL;
+
+ //@ParameterValue
+ //MessageType postfix = MessageType.FATAL;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ViolationSeverityInterpreter.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ViolationSeverityInterpreter.java
new file mode 100644
index 0000000..b76bd94
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/parameter/ViolationSeverityInterpreter.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.parameter;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.application.FacesMessage;
+
+/**
+ * mechanism to change the default behavior of extval
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ViolationSeverityInterpreter
+{
+ /**
+ * @param facesContext current faces context
+ * @param uiComponent current component
+ * @param severity jsf severity for faces messages
+ * @return true if the given severity should block the navigation
+ * if #severityCausesValidatorException returns falls validation will be continued for the current property
+ * all messages which don't lead to an exception should be stored in an storage and
+ * added after the first message which gets thrown as exception
+ * a global PropertyValidationInterceptor add the messages of the storage as faces message
+ */
+ boolean severityBlocksNavigation(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity);
+
+ /**
+ * @param facesContext current faces context
+ * @param uiComponent current component
+ * @param severity jsf severity for faces messages
+ * @return true if the given severity should cause a validator exception
+ */
+ boolean severityCausesValidatorException(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity);
+
+ /**
+ *
+ * @param facesContext current faces context
+ * @param uiComponent current component
+ * @param severity jsf severity for faces messages
+ * @return true if a violation message leads to a faces message
+ */
+ boolean severityCausesViolationMessage(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity);
+
+ /**
+ * @param facesContext current faces context
+ * @param uiComponent current component
+ * @param severity jsf severity for faces messages
+ * @return true if the constraint with the given severity should be validated on the client side (if supported)
+ */
+ boolean severityBlocksSubmit(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity);
+
+ /**
+ * available for add-ons - not used internally due to performance reasons
+ *
+ * @param facesContext current faces context
+ * @param uiComponent current component
+ * @param severity jsf severity for faces messages
+ * @return true if the constraint with the given severity
+ * should cause e.g. a required marker independent of client-side validation (if supported)
+ */
+ boolean severityShowsIndication(
+ FacesContext facesContext, UIComponent uiComponent, FacesMessage.Severity severity);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractAnnotationValidationStrategy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractAnnotationValidationStrategy.java
new file mode 100644
index 0000000..159c934
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractAnnotationValidationStrategy.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.validator.ValidatorException;
+import java.lang.annotation.Annotation;
+import java.util.Locale;
+import java.util.MissingResourceException;
+
+/**
+ * Provides the ability of message resolving to ValidationStrategies
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.REUSE})
+public abstract class AbstractAnnotationValidationStrategy<A extends Annotation> extends AbstractValidationStrategy
+{
+ protected static final String DETAIL_MESSAGE_KEY_POSTFIX = "_detail";
+ //e.g. for injecting a message resolver via spring
+ private MessageResolver messageResolver;
+
+ protected String resolveMessage(String key)
+ {
+ Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
+
+ return this.messageResolver != null ? this.messageResolver.getMessage(key, locale) :
+ ExtValUtils.getMessageResolverForValidationStrategy(this).getMessage(key, locale);
+ }
+
+ protected String getErrorMessageSummary(A annotation)
+ {
+ return resolveMessage(getValidationErrorMsgKey(annotation));
+ }
+
+ protected String getErrorMessageDetail(A annotation)
+ {
+ try
+ {
+ String key = getValidationErrorMsgKey(annotation);
+ return (key != null) ? resolveMessage(key + DETAIL_MESSAGE_KEY_POSTFIX) : null;
+ }
+ catch (MissingResourceException e)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("couldn't find key " + getValidationErrorMsgKey(annotation) + DETAIL_MESSAGE_KEY_POSTFIX,
+ e);
+ }
+ }
+ return null;
+ }
+
+ protected FacesMessage getValidationErrorFacesMessage(A annotation)
+ {
+ return ExtValUtils.createFacesMessage(getErrorMessageSummary(annotation), getErrorMessageDetail(annotation));
+ }
+
+ protected abstract String getValidationErrorMsgKey(A annotation);
+
+ public void setMessageResolver(MessageResolver messageResolver)
+ {
+ this.messageResolver = messageResolver;
+ }
+
+ @Override
+ protected boolean processAfterValidatorException(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException validatorException)
+ {
+ metaDataEntry.setProperty(PropertyInformationKeys.LABEL, getLabel(facesContext, uiComponent, metaDataEntry));
+
+ return super.processAfterValidatorException(
+ facesContext, uiComponent, metaDataEntry, convertedObject, validatorException);
+ }
+
+ //e.g. for custom annotations - override if needed
+ protected String getLabel(FacesContext facesContext, UIComponent uiComponent, MetaDataEntry metaDataEntry)
+ {
+ return null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidationStrategy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidationStrategy.java
new file mode 100644
index 0000000..d01f3ed
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidationStrategy.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.exception.RequiredValidatorException;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * Provides the ability to use ValidatorException (as expected by the user) instead of ConverterException.
+ * Furthermore it provides:<br/>
+ * initValidation<br/>
+ * processAfterValidatorException
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.REUSE})
+public abstract class AbstractValidationStrategy implements ValidationStrategy
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ protected AbstractValidationStrategy()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public void validate(FacesContext facesContext, UIComponent uiComponent,
+ MetaDataEntry metaDataEntry, Object convertedObject)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start initValidation of " + getClass().getName());
+ }
+
+ initValidation(facesContext, uiComponent, metaDataEntry, convertedObject);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("initValidation of " + getClass().getName() + " finished");
+ }
+
+ try
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start processValidation of " + getClass().getName());
+ }
+
+ processValidation(facesContext, uiComponent, metaDataEntry, convertedObject);
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("processValidation of " + getClass().getName() + " finished");
+ }
+ }
+ catch (ValidatorException e)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("start processAfterValidatorException of " + getClass().getName());
+ }
+
+ ValidatorException validatorException;
+
+ if(e instanceof RequiredValidatorException)
+ {
+ validatorException = new RequiredValidatorException(
+ ExtValUtils.convertFacesMessage(e.getFacesMessage()), e.getCause());
+ }
+ else
+ {
+ validatorException = new ValidatorException(
+ ExtValUtils.convertFacesMessage(e.getFacesMessage()), e.getCause());
+ }
+
+ if (processAfterValidatorException(
+ facesContext, uiComponent, metaDataEntry, convertedObject, validatorException))
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(getClass().getName() +
+ ": throw original exception after processAfterValidatorException");
+ }
+
+ ExtValUtils.tryToThrowValidatorExceptionForComponent(
+ uiComponent, validatorException.getFacesMessage(), validatorException);
+ }
+
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(getClass().getName() +
+ ": original exception after processAfterValidatorException not thrown");
+ }
+ }
+ }
+
+ protected void initValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject)
+ {
+ //override if needed
+ }
+
+ //override if needed
+ protected boolean processAfterValidatorException(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException validatorException)
+ {
+ return ExtValUtils.executeAfterThrowingInterceptors(
+ uiComponent, metaDataEntry, convertedObject, validatorException, this);
+ }
+
+ protected abstract void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException;
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractVirtualValidationStrategy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractVirtualValidationStrategy.java
new file mode 100644
index 0000000..26a8cfe
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractVirtualValidationStrategy.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+
+/**
+ * to map constraints directly to a meta-data transformer if there is no validation strategy (required by jsr 303)
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.REUSE)
+public abstract class AbstractVirtualValidationStrategy implements IdentifiableValidationStrategy
+{
+ public final void validate(
+ FacesContext facesContext, UIComponent uiComponent, MetaDataEntry metaDataEntry, Object convertedObject)
+ {
+ throw new UnsupportedOperationException("this is just an adapter e.g. for component initialization");
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/BeanValidationStrategyAdapter.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/BeanValidationStrategyAdapter.java
new file mode 100644
index 0000000..6c25e04
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/BeanValidationStrategyAdapter.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * it isn't linked to jsr 303
+ *
+ * it's just a helper for proxies - you just need it, if you define the validation strategy as bean and
+ * e.g. spring creates a proxy for it.
+
+ * adapter to connect validation strategies with meta-data transformers,
+ * if the validation strategy is defined as bean and e.g. spring creates a proxy
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.REUSE})
+public interface BeanValidationStrategyAdapter extends ValidationStrategy
+{
+ //to get back the internal cashing
+ String getValidationStrategyClassName();
+
+ String getMetaDataTransformerClassName();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/BeanValidationStrategyAdapterImpl.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/BeanValidationStrategyAdapterImpl.java
new file mode 100644
index 0000000..4c116f2
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/BeanValidationStrategyAdapterImpl.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.MetaDataTransformer;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.BeanMetaDataTransformerAdapter;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ * it isn't linked to jsr 303
+ *
+ * it's just a helper for proxies - you just need it, if you define the validation strategy as bean and
+ * e.g. spring creates a proxy for it.
+
+ * adapter to connect validation strategies with meta-data transformers,
+ * if the validation strategy is defined as bean and e.g. spring creates a proxy
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.REUSE})
+public class BeanValidationStrategyAdapterImpl implements BeanValidationStrategyAdapter
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private MetaDataTransformer metaDataTransformer;
+ private ValidationStrategy validationStrategy;
+ //optional fallback for internal cashing
+ private String validationStrategyClassName;
+
+ public BeanValidationStrategyAdapterImpl()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public void validate(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject)
+ {
+ this.validationStrategy.validate(facesContext, uiComponent, metaDataEntry, convertedObject);
+ }
+
+ public String getValidationStrategyClassName()
+ {
+ if(validationStrategy.getClass().getPackage() != null)
+ {
+ return validationStrategy.getClass().getName();
+ }
+ return validationStrategyClassName;
+ }
+
+ public String getMetaDataTransformerClassName()
+ {
+ if(metaDataTransformer != null)
+ {
+ if(metaDataTransformer.getClass().getPackage() != null)
+ {
+ return metaDataTransformer.getClass().getName();
+ }
+ else
+ {
+ if(metaDataTransformer instanceof BeanMetaDataTransformerAdapter)
+ {
+ return ((BeanMetaDataTransformerAdapter) metaDataTransformer ).getMetaDataTransformerClassName();
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * generated
+ */
+ public MetaDataTransformer getMetaDataTransformer()
+ {
+ return metaDataTransformer;
+ }
+
+ public void setMetaDataTransformer(MetaDataTransformer metaDataTransformer)
+ {
+ this.metaDataTransformer = metaDataTransformer;
+ }
+
+ public ValidationStrategy getValidationStrategy()
+ {
+ return validationStrategy;
+ }
+
+ public void setValidationStrategy(ValidationStrategy validationStrategy)
+ {
+ this.validationStrategy = validationStrategy;
+ }
+
+ public void setValidationStrategyClassName(String validationStrategyClassName)
+ {
+ this.validationStrategyClassName = validationStrategyClassName;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/DefaultValidationStrategyFactory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/DefaultValidationStrategyFactory.java
new file mode 100644
index 0000000..210a11d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/DefaultValidationStrategyFactory.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.core.factory.ClassMappingFactory;
+import org.apache.myfaces.extensions.validator.core.factory.AbstractNameMapperAwareFactory;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationEntry;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticResourceBundleConfiguration;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.mapper
+ .AnnotationToValidationStrategyBeanNameMapper;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.MissingResourceException;
+
+
+/**
+ * Factory which creates the ValidationStrategy for a given Meta-Data Key
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class DefaultValidationStrategyFactory extends AbstractNameMapperAwareFactory<String>
+ implements ClassMappingFactory<String, ValidationStrategy>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private Map<String, String> metaDataKeyToValidationStrategyMapping = null;
+ private List<NameMapper<String>> nameMapperList = new ArrayList<NameMapper<String>>();
+
+ public DefaultValidationStrategyFactory()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+
+ public ValidationStrategy create(String metaDataKey)
+ {
+ if (metaDataKeyToValidationStrategyMapping == null)
+ {
+ initStaticMappings();
+ }
+
+ if (metaDataKeyToValidationStrategyMapping.containsKey(metaDataKey))
+ {
+ return getValidationStrategyInstance(metaDataKeyToValidationStrategyMapping.get(metaDataKey));
+ }
+
+ ValidationStrategy validationStrategy;
+ String strategyName;
+ //null -> use name mappers
+ for (NameMapper<String> nameMapper : nameMapperList)
+ {
+ strategyName = nameMapper.createName(metaDataKey);
+
+ if (strategyName == null)
+ {
+ continue;
+ }
+
+ validationStrategy = getValidationStrategyInstance(strategyName);
+
+ if (validationStrategy != null)
+ {
+ addMapping(metaDataKey, strategyName);
+ return validationStrategy;
+ }
+ }
+ return null;
+ }
+
+ private ValidationStrategy getValidationStrategyInstance(String validationStrategyName)
+ {
+ if (validationStrategyName
+ .startsWith(AnnotationToValidationStrategyBeanNameMapper.PREFIX_FOR_BEAN_MAPPING))
+ {
+ return (ValidationStrategy) ExtValUtils.getELHelper().getBean(validationStrategyName
+ .substring(AnnotationToValidationStrategyBeanNameMapper.PREFIX_FOR_BEAN_MAPPING.length()));
+ }
+ else
+ {
+ return (ValidationStrategy) ClassUtils.tryToInstantiateClassForName(validationStrategyName);
+ }
+ }
+
+ private synchronized void addMapping(String metaDataKey, String validationStrategyName)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("adding meta-data key to validation strategy mapping: "
+ + metaDataKey + " -> " + validationStrategyName);
+ }
+
+ metaDataKeyToValidationStrategyMapping.put(metaDataKey, validationStrategyName);
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "logging")
+ private synchronized void initStaticMappings()
+ {
+ metaDataKeyToValidationStrategyMapping = new HashMap<String, String>();
+
+ //setup internal static mappings
+ for (StaticConfiguration<String, String> staticConfig :
+ ExtValContext.getContext().getStaticConfiguration(
+ StaticConfigurationNames.META_DATA_TO_VALIDATION_STRATEGY_CONFIG))
+ {
+ setupStrategyMappings(staticConfig.getMapping());
+ }
+
+ StaticConfiguration<String, String> staticConfig = new StaticResourceBundleConfiguration();
+ //try to setup mapping with base name by convention - overrides default mapping
+ try
+ {
+ //build convention (strategy mapping)
+ staticConfig.setSourceOfMapping(ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.STATIC_STRATEGY_MAPPING_SOURCE));
+
+ setupStrategyMappings(staticConfig.getMapping());
+ }
+ catch (Throwable t)
+ {
+ //do nothing - it was just a try
+ }
+
+ //setup custom mapping - overrides all other mappings
+ String customMappingBaseName = WebXmlParameter.CUSTOM_STATIC_VALIDATION_STRATEGY_MAPPING;
+ if (customMappingBaseName != null)
+ {
+ try
+ {
+ staticConfig = new StaticResourceBundleConfiguration();
+ staticConfig.setSourceOfMapping(customMappingBaseName);
+ setupStrategyMappings(staticConfig.getMapping());
+ }
+ catch (MissingResourceException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void setupStrategyMappings(List<StaticConfigurationEntry<String,String>> mappings)
+ {
+ for(StaticConfigurationEntry<String, String> mapping : mappings)
+ {
+ addMapping(mapping.getSource(), mapping.getTarget());
+ }
+ }
+
+ protected List<NameMapper<String>> getNameMapperList()
+ {
+ return this.nameMapperList;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/IdentifiableValidationStrategy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/IdentifiableValidationStrategy.java
new file mode 100644
index 0000000..bf3a2ab
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/IdentifiableValidationStrategy.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * if an adapter is used for several constraints, this interface allows to identify instances
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface IdentifiableValidationStrategy extends ValidationStrategy
+{
+ String ID_PREFIX = ":";
+
+ String getId();
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/ValidationStrategy.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/ValidationStrategy.java
new file mode 100644
index 0000000..b55523d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/ValidationStrategy.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ * Base interface for ValidationStrategies
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+//*ValidationStrategy instead of *Validator to avoid naming confusion
+public interface ValidationStrategy
+{
+ void validate(FacesContext facesContext, UIComponent uiComponent,
+ MetaDataEntry metaDataEntry, Object convertedObject);
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/AbstractMetaDataToValidationStrategyNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/AbstractMetaDataToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..b9b3f0d
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/AbstractMetaDataToValidationStrategyNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public abstract class AbstractMetaDataToValidationStrategyNameMapper implements NameMapper<String>
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public AbstractMetaDataToValidationStrategyNameMapper()
+ {
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(getClass().getName() + " instantiated");
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/AnnotationToValidationStrategyBeanNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/AnnotationToValidationStrategyBeanNameMapper.java
new file mode 100644
index 0000000..d8d94f7
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/AnnotationToValidationStrategyBeanNameMapper.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.beans.Introspector;
+
+/**
+ * Name Mapper which delegates the name mapping, extract the name and convert it to a bean name + prefix
+ * target: configure a validation strategy via a managed bean facility -> allows to inject other beans
+ * instead of api calls + hardcoded bean names
+ * <p/>
+ * allowed bean scopes:
+ * the validation strategy is stateless: application/singleton
+ * the validation strategy is stateful: none/prototype
+ * don't use the session or a conversation scope
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(500)
+@UsageInformation(UsageCategory.INTERNAL)
+public class AnnotationToValidationStrategyBeanNameMapper extends AbstractMetaDataToValidationStrategyNameMapper
+{
+ public static final String PREFIX_FOR_BEAN_MAPPING = "bean:";
+ private NameMapper<String> wrapped;
+
+ public AnnotationToValidationStrategyBeanNameMapper(NameMapper<String> nameMapper)
+ {
+ this.wrapped = nameMapper;
+ }
+
+ public String createName(String source)
+ {
+ String name = wrapped.createName(source);
+
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.substring(name.lastIndexOf(".") + 1);
+ return PREFIX_FOR_BEAN_MAPPING + Introspector.decapitalize(name);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConfiguredAnnotationToValidationStrategyNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConfiguredAnnotationToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..fd03206
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConfiguredAnnotationToValidationStrategyNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy.mapper;
+
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * To provide a custom NameMapper to map Annotations to ValidationStrategies.
+ * (configured via web.xml)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(100)
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class CustomConfiguredAnnotationToValidationStrategyNameMapper extends
+ AbstractCustomNameMapper<String>
+{
+ protected String getCustomNameMapperClassName()
+ {
+ return WebXmlParameter.CUSTOM_META_DATA_TO_VALIDATION_STRATEGY_NAME_MAPPER;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConventionAnnotationToValidationStrategyNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConventionAnnotationToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..d1e8302
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConventionAnnotationToValidationStrategyNameMapper.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * To provide a custom NameMapper to map Annotations to ValidationStrategies.
+ * (configured via information provider bean)
+ * The bean provides the default name (convention).
+ * It's possible to provide a custom full qualified name. (= customizable convention)
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(200)
+@UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
+public class CustomConventionAnnotationToValidationStrategyNameMapper extends
+ AbstractCustomNameMapper<String>
+{
+ protected String getCustomNameMapperClassName()
+ {
+ return ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.META_DATA_TO_VALIDATION_STRATEGY_NAME_MAPPER);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/DefaultAnnotationToValidationStrategyNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/DefaultAnnotationToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..6c38d8f
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/DefaultAnnotationToValidationStrategyNameMapper.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy.mapper;
+
+import org.apache.myfaces.extensions.validator.core.InternalConventionProvider;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * Default implementation which maps ExtVal Annotations to ExtVal ValidationStrategies.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(300)
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultAnnotationToValidationStrategyNameMapper extends AbstractMetaDataToValidationStrategyNameMapper
+{
+ public String createName(String metaDataKey)
+ {
+ return InternalConventionProvider.getValidationStrategyClassName(metaDataKey);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/SimpleAnnotationToValidationStrategyNameMapper.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/SimpleAnnotationToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..9382053
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/SimpleAnnotationToValidationStrategyNameMapper.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.core.validation.strategy.mapper;
+
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * It's an alternative Mapper to place Annotations and ValidationStrategies in the same package.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(400)
+@UsageInformation({UsageCategory.INTERNAL})
+public class SimpleAnnotationToValidationStrategyNameMapper extends AbstractMetaDataToValidationStrategyNameMapper
+{
+ public String createName(String metaDataKey)
+ {
+ return metaDataKey +
+ ExtValContext.getContext().getInformationProviderBean().get(CustomInformation.VALIDATION_STRATEGY_POSTFIX);
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/Priority.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/Priority.java
new file mode 100644
index 0000000..111aa33
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/Priority.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.internal;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+public enum Priority
+{
+ BLOCKING,
+ HIGH,
+ MEDIUM,
+ LOW
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/ToDo.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/ToDo.java
new file mode 100644
index 0000000..9d25a0a
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/ToDo.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.internal;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import java.lang.annotation.Target;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({TYPE, METHOD, FIELD, CONSTRUCTOR})
+public @interface ToDo
+{
+ Priority value();
+ String description() default "";
+
+ @Target({TYPE, METHOD, FIELD})
+ @interface List
+ {
+ ToDo[] value();
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/UsageCategory.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/UsageCategory.java
new file mode 100644
index 0000000..547b385
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/UsageCategory.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.internal;
+
+/**
+ * API:<br/>
+ * parts you might need for custom implementations and which are quite stable in view of changes
+ * <p/>
+ * INTERNAL:<br/>
+ * if you think about referencing an artifact which is marked as internal, ask for support.
+ * there should be a better solution
+ * <p/>
+ * CUSTOMIZABLE:<br/>
+ * a planned extension point which contains logic to customize the framework.
+ * if it isn't also marked as API it might change in future releases.
+ * however, we try to keep it as stable as possible and reasonable.
+ * <p/>
+ * REUSE:<br/>
+ * an artifact which you can reuse for a custom implementation.
+ * if it isn't marked as API it might change in future releases.
+ * however, we try to keep it as stable as possible and reasonable.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+public enum UsageCategory
+{
+ API,
+ INTERNAL,
+ CUSTOMIZABLE,
+ REUSE
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/UsageInformation.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/UsageInformation.java
new file mode 100644
index 0000000..f937ebc
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/internal/UsageInformation.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.internal;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Target;
+
+/**
+ * it's an internal annotation to provide some information concerning usage-categories
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ * @see org.apache.myfaces.extensions.validator.internal.UsageCategory
+ */
+@Target({TYPE, METHOD, FIELD})
+public @interface UsageInformation
+{
+ UsageCategory[] value();
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ClassUtils.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ClassUtils.java
new file mode 100644
index 0000000..c3e2056
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ClassUtils.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.jar.Manifest;
+import java.util.jar.Attributes;
+import java.net.URL;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ClassUtils
+{
+ private static final Log LOG = LogFactory.getLog(ClassUtils.class);
+
+ public static Class tryToLoadClassForName(String name)
+ {
+ try
+ {
+ return loadClassForName(name);
+ }
+ catch (ClassNotFoundException e)
+ {
+ //do nothing - it's just a try
+ return null;
+ }
+ }
+
+ public static Class loadClassForName(String name) throws ClassNotFoundException
+ {
+ try
+ {
+ // Try WebApp ClassLoader first
+ return Class.forName(name, false, // do not initialize for faster startup
+ Thread.currentThread().getContextClassLoader());
+ }
+ catch (ClassNotFoundException ignore)
+ {
+ // fallback: Try ClassLoader for ClassUtils (i.e. the myfaces.jar lib)
+ return Class.forName(name, false, // do not initialize for faster startup
+ ClassUtils.class.getClassLoader());
+ }
+ }
+
+ public static <T> T tryToInstantiateClass(Class<T> targetClass)
+ {
+ try
+ {
+ return targetClass.newInstance();
+ }
+ catch (Throwable t)
+ {
+ //do nothing - it was just a try
+ }
+ return null;
+ }
+
+ public static Object tryToInstantiateClassForName(String className)
+ {
+ try
+ {
+ return instantiateClassForName(className);
+ }
+ catch (Throwable t)
+ {
+ //do nothing - it was just a try
+ }
+ return null;
+ }
+
+ public static Object instantiateClassForName(String className)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException
+ {
+ return loadClassForName(className).newInstance();
+ }
+
+ public static String getJarVersion(Class targetClass)
+ {
+ String classFilePath = targetClass.getCanonicalName().replace('.', '/') + ".class";
+ String manifestFilePath = "/META-INF/MANIFEST.MF";
+
+ String classLocation = targetClass.getResource(targetClass.getSimpleName() + ".class").toString();
+ String manifestFileLocation = classLocation
+ .substring(0, classLocation.indexOf(classFilePath) - 1) + manifestFilePath;
+
+ try
+ {
+ return new Manifest(new URL(manifestFileLocation).openStream())
+ .getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+ }
+ catch (Throwable t)
+ {
+ if (LOG.isTraceEnabled())
+ {
+ LOG.trace("couldn't load version of jar file which contains " + targetClass.getName(), t);
+ }
+ return null;
+ }
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/DefaultProjectName.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/DefaultProjectName.java
new file mode 100644
index 0000000..4fd6399
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/DefaultProjectName.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.core.ProjectStageName;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class DefaultProjectName implements ProjectStageName
+{
+ private final String name;
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ private DefaultProjectName()
+ {
+ this.name = null;
+ }
+
+ private DefaultProjectName(String name)
+ {
+ this.name = name;
+ }
+
+ static ProjectStageName createProjectStageName(String name)
+ {
+ return new DefaultProjectName(name);
+ }
+
+ public String getName()
+ {
+ return this.name;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (!(o instanceof DefaultProjectName))
+ {
+ return false;
+ }
+
+ DefaultProjectName that = (DefaultProjectName) o;
+
+ if (!name.equals(that.name))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return name.hashCode();
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ExtValUtils.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ExtValUtils.java
new file mode 100644
index 0000000..42ee3da
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ExtValUtils.java
@@ -0,0 +1,964 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.ValidationModuleKey;
+import org.apache.myfaces.extensions.validator.core.ProjectStageName;
+import org.apache.myfaces.extensions.validator.core.el.AbstractELHelperFactory;
+import org.apache.myfaces.extensions.validator.core.el.ELHelper;
+import org.apache.myfaces.extensions.validator.core.el.ValueBindingExpression;
+import org.apache.myfaces.extensions.validator.core.factory.ClassMappingFactory;
+import org.apache.myfaces.extensions.validator.core.factory.FacesMessageFactory;
+import org.apache.myfaces.extensions.validator.core.factory.FactoryNames;
+import org.apache.myfaces.extensions.validator.core.factory.NameMapperAwareFactory;
+import org.apache.myfaces.extensions.validator.core.initializer.component.ComponentInitializer;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationEntry;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
+import org.apache.myfaces.extensions.validator.core.interceptor.MetaDataExtractionInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.PropertyValidationInterceptor;
+import org.apache.myfaces.extensions.validator.core.interceptor.ValidationExceptionInterceptor;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.ComponentMetaDataExtractorFactory;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.MetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.MetaDataTransformer;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.storage.FacesMessageStorage;
+import org.apache.myfaces.extensions.validator.core.storage.StorageManager;
+import org.apache.myfaces.extensions.validator.core.validation.SkipValidationEvaluator;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameterExtractor;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameterExtractorFactory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverityInterpreter;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.ExtValInformation;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.MissingResourceException;
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SuppressWarnings({"unchecked"})
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValUtils
+{
+ private static final Log LOGGER = LogFactory.getLog(ExtValUtils.class);
+
+ private static final String JAVAX_FACES_REQUIRED = "javax.faces.component.UIInput.REQUIRED";
+ private static final String JAVAX_FACES_REQUIRED_DETAIL = "javax.faces.component.UIInput.REQUIRED_detail";
+
+ private static final String JAVAX_FACES_MAXIMUM = "javax.faces.validator.LengthValidator.MAXIMUM";
+ private static final String JAVAX_FACES_MAXIMUM_DETAIL = "javax.faces.validator.LengthValidator.MAXIMUM_detail";
+
+ public static ValidationStrategy getValidationStrategyForMetaData(String metaDataKey)
+ {
+ return ((ClassMappingFactory<String, ValidationStrategy>) ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.VALIDATION_STRATEGY_FACTORY, ClassMappingFactory.class))
+ .create(metaDataKey);
+ }
+
+ public static void registerMetaDataToValidationStrategyNameMapper(
+ NameMapper<String> metaDataToValidationStrategyNameMapper)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.VALIDATION_STRATEGY_FACTORY, NameMapperAwareFactory.class))
+ .register(metaDataToValidationStrategyNameMapper);
+ }
+
+ public static void deregisterMetaDataToValidationStrategyNameMapper(
+ Class<? extends NameMapper> metaDataToValidationStrategyNameMapperClass)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.VALIDATION_STRATEGY_FACTORY, NameMapperAwareFactory.class))
+ .deregister(metaDataToValidationStrategyNameMapperClass);
+ }
+
+ public static void denyMetaDataToValidationStrategyNameMapper(
+ Class<? extends NameMapper> metaDataToValidationStrategyNameMapperClass)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.VALIDATION_STRATEGY_FACTORY, NameMapperAwareFactory.class))
+ .deny(metaDataToValidationStrategyNameMapperClass);
+ }
+
+ public static MetaDataTransformer getMetaDataTransformerForValidationStrategy(ValidationStrategy validationStrategy)
+ {
+ return ((ClassMappingFactory<ValidationStrategy, MetaDataTransformer>) ExtValContext
+ .getContext().getFactoryFinder()
+ .getFactory(FactoryNames.META_DATA_TRANSFORMER_FACTORY, ClassMappingFactory.class))
+ .create(validationStrategy);
+ }
+
+ public static void registerValidationStrategyToMetaDataTransformerNameMapper(
+ NameMapper<ValidationStrategy> validationStrategyToMetaDataTransformerNameMapper)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.META_DATA_TRANSFORMER_FACTORY, NameMapperAwareFactory.class))
+ .register(validationStrategyToMetaDataTransformerNameMapper);
+ }
+
+ public static void deregisterValidationStrategyToMetaDataTransformerNameMapper(
+ Class<? extends NameMapper> validationStrategyToMetaDataTransformerNameMapperClass)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.META_DATA_TRANSFORMER_FACTORY, NameMapperAwareFactory.class))
+ .deregister(validationStrategyToMetaDataTransformerNameMapperClass);
+ }
+
+ public static void denyValidationStrategyToMetaDataTransformerNameMapper(
+ Class<? extends NameMapper> validationStrategyToMetaDataTransformerNameMapperClass)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.META_DATA_TRANSFORMER_FACTORY, NameMapperAwareFactory.class))
+ .deny(validationStrategyToMetaDataTransformerNameMapperClass);
+ }
+
+ public static MetaDataExtractor getComponentMetaDataExtractor()
+ {
+ return ExtValContext.getContext().getFactoryFinder()
+ .getFactory(FactoryNames.COMPONENT_META_DATA_EXTRACTOR_FACTORY, ComponentMetaDataExtractorFactory.class)
+ .create();
+ }
+
+ public static MetaDataExtractor getComponentMetaDataExtractorWith(Map<String, Object> properties)
+ {
+ return ExtValContext.getContext().getFactoryFinder()
+ .getFactory(FactoryNames.COMPONENT_META_DATA_EXTRACTOR_FACTORY, ComponentMetaDataExtractorFactory.class)
+ .createWith(properties);
+ }
+
+ public static void configureComponentWithMetaData(FacesContext facesContext,
+ UIComponent uiComponent,
+ Map<String, Object> metaData)
+ {
+ for (ComponentInitializer componentInitializer : ExtValContext.getContext().getComponentInitializers())
+ {
+ componentInitializer.configureComponent(facesContext, uiComponent, metaData);
+ }
+ }
+
+ public static boolean executeAfterThrowingInterceptors(UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException validatorException,
+ ValidationStrategy validatorExceptionSource)
+ {
+ boolean result = true;
+
+ if (metaDataEntry == null)
+ {
+ metaDataEntry = new MetaDataEntry();
+ }
+
+ for (ValidationExceptionInterceptor validationExceptionInterceptor : ExtValContext.getContext()
+ .getValidationExceptionInterceptors())
+ {
+ if (!validationExceptionInterceptor.afterThrowing(
+ uiComponent, metaDataEntry, convertedObject, validatorException, validatorExceptionSource))
+ {
+ result = false;
+ }
+ }
+
+ return result;
+ }
+
+ public static MetaDataExtractor createInterceptedMetaDataExtractor(final MetaDataExtractor metaDataExtractor)
+ {
+ return createInterceptedMetaDataExtractorWith(metaDataExtractor, null);
+ }
+
+ public static MetaDataExtractor createInterceptedMetaDataExtractorFor(
+ final MetaDataExtractor metaDataExtractor, Class moduleKey)
+ {
+ Map<String, Object> properties = new HashMap<String, Object>();
+
+ if(moduleKey != null)
+ {
+ properties.put(ValidationModuleKey.class.getName(), moduleKey);
+ }
+ return createInterceptedMetaDataExtractorWith(metaDataExtractor, properties);
+ }
+
+ public static MetaDataExtractor createInterceptedMetaDataExtractorWith(
+ final MetaDataExtractor metaDataExtractor, final Map<String, Object> properties)
+ {
+ return new MetaDataExtractor()
+ {
+ public PropertyInformation extract(FacesContext facesContext, Object object)
+ {
+ PropertyInformation result = metaDataExtractor.extract(facesContext, object);
+
+ addProperties(result, properties);
+ invokeMetaDataExtractionInterceptors(result, properties);
+
+ return result;
+ }
+ };
+ }
+
+ private static void addProperties(PropertyInformation result, Map<String, Object> properties)
+ {
+ if(properties != null)
+ {
+ Map<String, Object> customProperties = getCustomProperties(result);
+ customProperties.putAll(properties);
+ }
+ }
+
+ private static Map<String, Object> getCustomProperties(PropertyInformation propertyInformation)
+ {
+ if(!propertyInformation.containsInformation(PropertyInformationKeys.CUSTOM_PROPERTIES))
+ {
+ propertyInformation.setInformation(
+ PropertyInformationKeys.CUSTOM_PROPERTIES, new HashMap<String, Object>());
+ }
+
+ return (Map<String, Object>) propertyInformation.getInformation(PropertyInformationKeys.CUSTOM_PROPERTIES);
+ }
+
+ private static void invokeMetaDataExtractionInterceptors(PropertyInformation result, Map<String, Object> properties)
+ {
+ for (MetaDataExtractionInterceptor metaDataExtractionInterceptor :
+ ExtValContext.getContext().getMetaDataExtractionInterceptorsWith(properties))
+ {
+ metaDataExtractionInterceptor.afterExtracting(result);
+ }
+ }
+
+ public static MessageResolver getMessageResolverForValidationStrategy(ValidationStrategy validationStrategy)
+ {
+ return ((ClassMappingFactory<ValidationStrategy, MessageResolver>) ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.MESSAGE_RESOLVER_FACTORY, ClassMappingFactory.class))
+ .create(validationStrategy);
+ }
+
+ public static void registerValidationStrategyToMessageResolverNameMapper(
+ NameMapper<ValidationStrategy> validationStrategyToMsgResolverNameMapper)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.MESSAGE_RESOLVER_FACTORY, NameMapperAwareFactory.class))
+ .register(validationStrategyToMsgResolverNameMapper);
+ }
+
+ public static void deregisterValidationStrategyToMessageResolverNameMapper(
+ Class<? extends NameMapper> validationStrategyToMessageResolverNameMapperClass)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.MESSAGE_RESOLVER_FACTORY, NameMapperAwareFactory.class))
+ .deregister(validationStrategyToMessageResolverNameMapperClass);
+ }
+
+ public static void denyValidationStrategyToMessageResolverNameMapper(
+ Class<? extends NameMapper> validationStrategyToMessageResolverNameMapperClass)
+ {
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.MESSAGE_RESOLVER_FACTORY, NameMapperAwareFactory.class))
+ .deny(validationStrategyToMessageResolverNameMapperClass);
+ }
+
+ public static ELHelper getELHelper()
+ {
+ return ExtValContext.getContext().getFactoryFinder()
+ .getFactory(FactoryNames.EL_HELPER_FACTORY, AbstractELHelperFactory.class).create();
+ }
+
+ public static FacesMessage createFacesMessage(String summary, String detail)
+ {
+ return createFacesMessage(FacesMessage.SEVERITY_ERROR, summary, detail);
+ }
+
+ public static FacesMessage createFacesMessage(FacesMessage.Severity severity, String summary, String detail)
+ {
+ return ExtValContext.getContext().getFactoryFinder()
+ .getFactory(FactoryNames.FACES_MESSAGE_FACTORY, FacesMessageFactory.class)
+ .create(severity, summary, detail);
+ }
+
+ public static FacesMessage convertFacesMessage(FacesMessage facesMessage)
+ {
+ return ExtValContext.getContext().getFactoryFinder()
+ .getFactory(FactoryNames.FACES_MESSAGE_FACTORY, FacesMessageFactory.class)
+ .convert(facesMessage);
+ }
+
+ public static PropertyDetails createPropertyDetailsForNewTarget(MetaDataEntry metaDataEntry,
+ String targetExpression)
+ {
+ Object baseObject;
+ if (getELHelper().isELTermWellFormed(targetExpression))
+ {
+ ValueBindingExpression vbe = new ValueBindingExpression(targetExpression);
+
+ String expression = vbe.getExpressionString();
+ baseObject = getELHelper().getValueOfExpression(FacesContext.getCurrentInstance(), vbe.getBaseExpression());
+ return new PropertyDetails(
+ expression.substring(2, expression.length() - 1), baseObject, vbe.getProperty());
+ }
+
+ PropertyDetails original = metaDataEntry.getProperty(
+ PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
+
+ String newBaseKey = original.getKey().substring(0, original.getKey().lastIndexOf(".") + 1);
+ String newKey = newBaseKey + targetExpression;
+
+ baseObject = ReflectionUtils.getBaseOfPropertyChain(original.getBaseObject(), targetExpression);
+ return new PropertyDetails(
+ newKey, baseObject, targetExpression.substring(targetExpression.lastIndexOf(".") + 1,
+ targetExpression.length()));
+ }
+
+ @UsageInformation(UsageCategory.INTERNAL)
+ public static void tryToPlaceLabel(FacesMessage facesMessage, String label, int index)
+ {
+ if (facesMessage.getSummary() != null && facesMessage.getSummary().contains("{" + index + "}"))
+ {
+ facesMessage.setSummary(facesMessage.getSummary().replace("{" + index + "}", label));
+ }
+
+ if (facesMessage.getDetail() != null && facesMessage.getDetail().contains("{" + index + "}"))
+ {
+ facesMessage.setDetail(facesMessage.getDetail().replace("{" + index + "}", label));
+ }
+ }
+
+ @UsageInformation(UsageCategory.INTERNAL)
+ public static void replaceWithDefaultMaximumMessage(FacesMessage facesMessage, int maxLength)
+ {
+ String facesRequiredMessage = JsfUtils.getMessageFromApplicationMessageBundle(JAVAX_FACES_MAXIMUM);
+ String facesRequiredMessageDetail = facesRequiredMessage;
+
+ //use try/catch for easier sync between trunk/branch
+ try
+ {
+ if (JsfUtils.getMessageFromApplicationMessageBundle(JAVAX_FACES_MAXIMUM_DETAIL) != null)
+ {
+ facesRequiredMessageDetail = JsfUtils
+ .getMessageFromApplicationMessageBundle(JAVAX_FACES_MAXIMUM_DETAIL);
+ }
+ }
+ catch (MissingResourceException missingResourceException)
+ {
+ //jsf 1.2 doesn't have a detail message
+ }
+
+ facesRequiredMessage = facesRequiredMessage.replace("{0}", "" + maxLength);
+ facesRequiredMessageDetail = facesRequiredMessageDetail.replace("{0}", "" + maxLength);
+
+ facesMessage.setSummary(facesRequiredMessage);
+ facesMessage.setDetail(facesRequiredMessageDetail);
+ }
+
+ @UsageInformation(UsageCategory.INTERNAL)
+ public static void replaceWithDefaultRequiredMessage(FacesMessage facesMessage)
+ {
+ String facesRequiredMessage = JsfUtils.getMessageFromApplicationMessageBundle(JAVAX_FACES_REQUIRED);
+ String facesRequiredMessageDetail = facesRequiredMessage;
+
+ //use try/catch for easier sync between trunk/branch
+ try
+ {
+ if (JsfUtils.getMessageFromApplicationMessageBundle(JAVAX_FACES_REQUIRED_DETAIL) != null)
+ {
+ facesRequiredMessageDetail = JsfUtils
+ .getMessageFromApplicationMessageBundle(JAVAX_FACES_REQUIRED_DETAIL);
+ }
+ }
+ catch (MissingResourceException missingResourceException)
+ {
+ //jsf 1.2 doesn't have a detail message
+ }
+
+ facesMessage.setSummary(facesRequiredMessage);
+ facesMessage.setDetail(facesRequiredMessageDetail);
+ }
+
+ public static boolean isSkipableValidationStrategy(Class<? extends ValidationStrategy> targetClass)
+ {
+ for (Class currentClass : getSkipValidationSupportClassList())
+ {
+ if (isSkipValidationSupported(currentClass, targetClass))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean processMetaDataEntryAfterSkipValidation(
+ Class<? extends ValidationStrategy> targetClass, MetaDataEntry entry)
+ {
+ return isSkipableValidationStrategy(targetClass) &&
+ Boolean.TRUE.equals(entry.getProperty(PropertyInformationKeys.SKIP_VALIDATION, Boolean.class));
+ }
+
+ public static List<Class> getSkipValidationSupportClassList()
+ {
+ List<StaticConfiguration<String, String>> staticConfigurationList = ExtValContext.getContext()
+ .getStaticConfiguration(StaticConfigurationNames.SKIP_VALIDATION_SUPPORT_CONFIG);
+
+ List<Class> markerList = new ArrayList<Class>();
+
+ Class currentClass;
+ for (StaticConfiguration<String, String> currentEntry : staticConfigurationList)
+ {
+ for (StaticConfigurationEntry<String, String> currentConfigurationEntry : currentEntry.getMapping())
+ {
+ currentClass = ClassUtils.tryToLoadClassForName(currentConfigurationEntry.getTarget());
+
+ if (currentClass != null)
+ {
+ markerList.add(currentClass);
+ }
+ else
+ {
+ if (LOGGER.isWarnEnabled())
+ {
+ LOGGER.warn("configuration entry provides an invalid entry: "
+ + currentConfigurationEntry.getTarget());
+ }
+ }
+ }
+ }
+
+ return markerList;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public static boolean isSkipValidationSupported(Class currentClass, Class targetClass)
+ {
+ if (currentClass.isAnnotation())
+ {
+ if (targetClass.isAnnotationPresent(currentClass))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if (currentClass.isAssignableFrom(targetClass))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static ValidationParameterExtractor getValidationParameterExtractor()
+ {
+ if(isValidationParameterExtractionDeactivated())
+ {
+ return new ValidationParameterExtractor() {
+
+ public Map<Object, List<Object>> extract(Annotation annotation)
+ {
+ return new HashMap<Object, List<Object>>();
+ }
+
+ public List<Object> extract(Annotation annotation, Object key)
+ {
+ return new ArrayList<Object>();
+ }
+
+ public <T> List<T> extract(Annotation annotation, Object key, Class<T> valueType)
+ {
+ return new ArrayList<T>();
+ }
+
+ public <T> T extract(Annotation annotation, Object key, Class<T> valueType, Class valueId)
+ {
+ return null;
+ }
+ };
+ }
+ return ExtValContext.getContext().getFactoryFinder().getFactory(
+ FactoryNames.VALIDATION_PARAMETER_EXTRACTOR_FACTORY, ValidationParameterExtractorFactory.class)
+ .create();
+ }
+
+ public static Class getValidationParameterClassFor(Class source)
+ {
+ ClassMappingFactory<Class, Class> validationParameterFactory = ExtValContext.getContext().getFactoryFinder()
+ .getFactory(FactoryNames.VALIDATION_PARAMETER_FACTORY, ClassMappingFactory.class);
+
+ return validationParameterFactory.create(source);
+ }
+
+ private static boolean isValidationParameterExtractionDeactivated()
+ {
+ return "true".equalsIgnoreCase(WebXmlParameter.DEACTIVATE_VALIDATION_PARAMETERS);
+ }
+
+ public static boolean executeLocalBeforeValidationInterceptors(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ String propertyKey,
+ Object properties,
+ Annotation annotation)
+ {
+ Map<String, Object> propertyMap = new HashMap<String, Object>();
+ List<PropertyValidationInterceptor> propertyValidationInterceptors = getValidationParameterExtractor().extract(
+ annotation, PropertyValidationInterceptor.class, PropertyValidationInterceptor.class);
+ boolean result = true;
+
+ if (properties != null)
+ {
+ propertyMap.put(propertyKey, properties);
+ }
+ propertyMap.put(Annotation.class.getName(), annotation);
+
+ for (PropertyValidationInterceptor propertyValidationInterceptor : propertyValidationInterceptors)
+ {
+ if (!propertyValidationInterceptor
+ .beforeValidation(facesContext, uiComponent, convertedObject, propertyMap))
+ {
+ result = false;
+ }
+ }
+
+ return result;
+ }
+
+ public static void executeLocalAfterValidationInterceptors(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ String propertyKey,
+ Object properties,
+ Annotation annotation)
+ {
+ Map<String, Object> propertyMap = new HashMap<String, Object>();
+ List<PropertyValidationInterceptor> propertyValidationInterceptors = getValidationParameterExtractor().extract(
+ annotation, PropertyValidationInterceptor.class, PropertyValidationInterceptor.class);
+
+ if (properties != null)
+ {
+ propertyMap.put(propertyKey, properties);
+ propertyMap.put(Annotation.class.getName(), annotation);
+ }
+
+ for (PropertyValidationInterceptor propertyValidationInterceptor : propertyValidationInterceptors)
+ {
+ propertyValidationInterceptor.afterValidation(facesContext, uiComponent, convertedObject, propertyMap);
+ }
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "is renaming ok?")
+ public static boolean executeGlobalBeforeValidationInterceptors(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ String propertyKey,
+ Object properties,
+ Class moduleKey)
+ {
+ Map<String, Object> propertyMap = new HashMap<String, Object>();
+ boolean result = true;
+
+ if (properties != null)
+ {
+ propertyMap.put(propertyKey, properties);
+ }
+
+ List<PropertyValidationInterceptor> propertyValidationInterceptors =
+ ExtValContext.getContext().getPropertyValidationInterceptorsFor(moduleKey);
+
+ for (PropertyValidationInterceptor propertyValidationInterceptor : propertyValidationInterceptors)
+ {
+ if (!propertyValidationInterceptor
+ .beforeValidation(facesContext, uiComponent, convertedObject, propertyMap))
+ {
+ result = false;
+ }
+ }
+
+ return result;
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "is renaming ok?")
+ public static void executeGlobalAfterValidationInterceptors(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ String propertyKey,
+ Object properties,
+ Class moduleKey)
+ {
+ Map<String, Object> propertyMap = new HashMap<String, Object>();
+
+ if (properties != null)
+ {
+ propertyMap.put(propertyKey, properties);
+ }
+
+ List<PropertyValidationInterceptor> propertyValidationInterceptors =
+ ExtValContext.getContext().getPropertyValidationInterceptorsFor(moduleKey);
+
+ for (PropertyValidationInterceptor propertyValidationInterceptor : propertyValidationInterceptors)
+ {
+ propertyValidationInterceptor.afterValidation(facesContext, uiComponent, convertedObject, propertyMap);
+ }
+ }
+
+ public static <T> T getStorage(Class<T> storageType, String storageName)
+ {
+ return (T) getStorageManagerFactory().create(storageType).create(storageName);
+ }
+
+ public static void resetStorage(Class storageType, String storageName)
+ {
+ getStorageManagerFactory().create(storageType).reset(storageName);
+ }
+
+ private static ClassMappingFactory<Class, StorageManager> getStorageManagerFactory()
+ {
+ return (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.STORAGE_MANAGER_FACTORY, ClassMappingFactory.class));
+ }
+
+ public static Map<String, Object> getTransformedMetaData(FacesContext facesContext, UIComponent uiComponent)
+ {
+ return getTransformedMetaDataFor(facesContext, uiComponent, null);
+ }
+
+ public static Map<String, Object> getTransformedMetaDataFor(
+ FacesContext facesContext, UIComponent uiComponent, Class moduleKey)
+ {
+ Map<String, Object> properties = new HashMap<String, Object>();
+
+ if(moduleKey != null)
+ {
+ properties.put(ValidationModuleKey.class.getName(), moduleKey);
+ }
+
+ return getTransformedMetaDataWith(facesContext, uiComponent, properties);
+ }
+
+ public static Map<String, Object> getTransformedMetaDataWith(
+ FacesContext facesContext, UIComponent uiComponent, Map<String, Object> properties)
+ {
+ ValidationStrategy validationStrategy;
+
+ SkipValidationEvaluator skipValidationEvaluator = ExtValContext.getContext().getSkipValidationEvaluator();
+ MetaDataExtractor metaDataExtractor = getComponentMetaDataExtractorWith(properties);
+
+ Map<String, Object> metaData;
+ Map<String, Object> metaDataResult = new HashMap<String, Object>();
+
+ for (MetaDataEntry entry : metaDataExtractor.extract(facesContext, uiComponent).getMetaDataEntries())
+ {
+ metaData = new HashMap<String, Object>();
+ validationStrategy = getValidationStrategyForMetaData(entry.getKey());
+
+ if (validationStrategy != null)
+ {
+ metaData = transformMetaData(
+ facesContext, uiComponent, validationStrategy, skipValidationEvaluator, metaData, entry);
+
+ if (!isComponentInitializationSkipped(metaData, entry, validationStrategy))
+ {
+ //don't break maybe there are constraints which don't support the skip-mechanism
+ metaDataResult.putAll(metaData);
+ }
+ }
+ }
+
+ return metaDataResult;
+ }
+
+ private static Map<String, Object> transformMetaData(FacesContext facesContext,
+ UIComponent uiComponent,
+ ValidationStrategy validationStrategy,
+ SkipValidationEvaluator skipValidationEvaluator,
+ Map<String, Object> metaData, MetaDataEntry entry)
+ {
+ if (!skipValidationEvaluator.skipValidation(facesContext, uiComponent, validationStrategy, entry))
+ {
+ MetaDataTransformer metaDataTransformer = getMetaDataTransformerForValidationStrategy(validationStrategy);
+
+ if (metaDataTransformer != null)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug(metaDataTransformer.getClass().getName() + " instantiated");
+ }
+
+ metaData = metaDataTransformer.convertMetaData(entry);
+ }
+ else
+ {
+ metaData = null;
+ }
+
+ if (metaData == null)
+ {
+ return new HashMap<String, Object>();
+ }
+ }
+ return metaData;
+ }
+
+ private static boolean isComponentInitializationSkipped(Map<String, Object> metaData, MetaDataEntry entry,
+ ValidationStrategy validationStrategy)
+ {
+ return metaData.isEmpty() ||
+ (Boolean.TRUE.equals(entry.getProperty(PropertyInformationKeys.SKIP_VALIDATION, Boolean.class)) &&
+ isSkipableValidationStrategy(ProxyUtils.getUnproxiedClass(
+ validationStrategy.getClass(), ValidationStrategy.class)));
+ }
+
+ public static boolean interpretEmptyStringValuesAsNull()
+ {
+ //to deactivate: the parameter has to be explicitly false
+ return !"false".equalsIgnoreCase(WebXmlParameter.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL);
+ }
+
+ public static boolean validateEmptyFields()
+ {
+ return !"false".equalsIgnoreCase(WebXmlParameter.VALIDATE_EMPTY_FIELDS);
+ }
+
+ public static PropertyDetails getPropertyDetails(PropertyInformation propertyInformation)
+ {
+ return propertyInformation.getInformation(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
+ }
+
+ public static void tryToThrowValidatorExceptionForComponentId(
+ String clientId, FacesMessage facesMessage, Throwable throwable)
+ {
+ UIComponent targetComponent = findComponent(clientId);
+
+ tryToThrowValidatorExceptionForComponent(targetComponent, facesMessage, throwable);
+ }
+
+ public static void tryToThrowValidatorExceptionForComponent(
+ UIComponent uiComponent, FacesMessage facesMessage, Throwable throwable)
+ {
+ ViolationSeverityInterpreter interpreter =
+ ExtValContext.getContext().getViolationSeverityInterpreter();
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ if (interpreter.severityCausesValidatorException(facesContext, uiComponent, facesMessage.getSeverity()))
+ {
+ if (throwable == null)
+ {
+ throw new ValidatorException(facesMessage);
+ }
+ else
+ {
+ throw new ValidatorException(facesMessage, throwable);
+ }
+ }
+ else
+ {
+ tryToAddViolationMessageForComponent(uiComponent, facesMessage);
+ }
+ }
+
+ public static void tryToAddViolationMessageForComponentId(String clientId, FacesMessage facesMessage)
+ {
+ UIComponent targetComponent = findComponent(clientId);
+
+ if (targetComponent == null && clientId != null)
+ {
+ tryToAddViolationMessageForTestClientId(clientId, facesMessage);
+ return;
+ }
+ tryToAddViolationMessageForComponent(targetComponent, facesMessage);
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "required for test frameworks - goal: remove it")
+ private static void tryToAddViolationMessageForTestClientId(String clientId, FacesMessage facesMessage)
+ {
+ ViolationSeverityInterpreter interpreter =
+ ExtValContext.getContext().getViolationSeverityInterpreter();
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ if (interpreter.severityCausesViolationMessage(facesContext, null, facesMessage.getSeverity()))
+ {
+ addFacesMessage(clientId, facesMessage);
+ }
+ tryToBlocksNavigationForComponent(null, facesMessage);
+ }
+
+ public static void tryToAddViolationMessageForComponent(UIComponent uiComponent, FacesMessage facesMessage)
+ {
+ ViolationSeverityInterpreter interpreter =
+ ExtValContext.getContext().getViolationSeverityInterpreter();
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ if (interpreter.severityCausesViolationMessage(facesContext, uiComponent, facesMessage.getSeverity()))
+ {
+ if (uiComponent != null)
+ {
+ addFacesMessage(uiComponent.getClientId(facesContext), facesMessage);
+ }
+ else
+ {
+ addFacesMessage(null, facesMessage);
+ }
+ }
+ tryToBlocksNavigationForComponent(uiComponent, facesMessage);
+ }
+
+ public static void addFacesMessage(FacesMessage facesMessage)
+ {
+ addFacesMessage(null, facesMessage);
+ }
+
+ public static void addFacesMessage(String clientId, FacesMessage facesMessage)
+ {
+ FacesMessageStorage storage = getStorage(FacesMessageStorage.class, FacesMessageStorage.class.getName());
+
+ if (storage != null)
+ {
+ storage.addFacesMessage(clientId, facesMessage);
+ }
+ else
+ {
+ FacesContext.getCurrentInstance().addMessage(clientId, facesMessage);
+ }
+ }
+
+ public static void tryToBlocksNavigationForComponentId(String clientId, FacesMessage facesMessage)
+ {
+ UIComponent targetComponent = findComponent(clientId);
+
+ tryToBlocksNavigationForComponent(targetComponent, facesMessage);
+ }
+
+ public static void tryToBlocksNavigationForComponent(UIComponent uiComponent, FacesMessage facesMessage)
+ {
+ ViolationSeverityInterpreter interpreter =
+ ExtValContext.getContext().getViolationSeverityInterpreter();
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ if (interpreter.severityBlocksNavigation(facesContext, uiComponent, facesMessage.getSeverity()))
+ {
+ FacesContext.getCurrentInstance().renderResponse();
+ }
+ }
+
+ public static boolean severityBlocksSubmitForComponentId(String clientId, FacesMessage facesMessage)
+ {
+ ViolationSeverityInterpreter interpreter =
+ ExtValContext.getContext().getViolationSeverityInterpreter();
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ UIComponent targetComponent = findComponent(clientId);
+
+ return interpreter.severityBlocksSubmit(facesContext, targetComponent, facesMessage.getSeverity());
+ }
+
+ //available for add-ons - not used internally due to performance reasons
+ public static boolean severityShowsIndicationForComponentId(String clientId, FacesMessage facesMessage)
+ {
+ ViolationSeverityInterpreter interpreter =
+ ExtValContext.getContext().getViolationSeverityInterpreter();
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ UIComponent targetComponent = findComponent(clientId);
+
+ return interpreter.severityShowsIndication(facesContext, targetComponent, facesMessage.getSeverity());
+ }
+
+ private static UIComponent findComponent(String clientId)
+ {
+ UIComponent targetComponent = null;
+
+ if (clientId != null)
+ {
+ targetComponent = FacesContext.getCurrentInstance().getViewRoot().findComponent(clientId);
+ }
+ return targetComponent;
+ }
+
+ /**
+ * @return true if component initialization for required validation is activated
+ */
+ public static boolean isRequiredInitializationActive()
+ {
+ return Boolean.TRUE.equals(ExtValContext.getContext().getGlobalProperty("mode:init:required"));
+ }
+
+ /**
+ * needed for some component libs - if required initialization is used e.g. for visual indicators
+ * but features like severity aware validation aren't used.
+ * in such a case it's possible to use the required attribute.
+ *
+ * @return false to deactivate the final reset of the value of the required attribute
+ */
+ public static boolean isRequiredResetActivated()
+ {
+ return Boolean.TRUE.equals(ExtValContext.getContext().getGlobalProperty("mode:reset:required"));
+ }
+
+ public static ProjectStageName getDefaultStageName()
+ {
+ return createProjectStageName("Production");
+ }
+
+ public static ProjectStageName createProjectStageName(String name)
+ {
+ return DefaultProjectName.createProjectStageName(name);
+ }
+
+ public static boolean isExtValDeactivated()
+ {
+ return "true".equalsIgnoreCase(System
+ .getProperty(ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME +
+ ".DEACTIVATE_ALL", "false"));
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/GroupUtils.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/GroupUtils.java
new file mode 100644
index 0000000..585eab3
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/GroupUtils.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class GroupUtils
+{
+ public static String getGroupKey(String viewId, String clientId)
+ {
+ return clientId == null ? viewId : viewId + "@" + clientId;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/JsfUtils.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/JsfUtils.java
new file mode 100644
index 0000000..5e76eca
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/JsfUtils.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.core.storage.FacesInformationStorage;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import javax.faces.FactoryFinder;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.Lifecycle;
+import javax.faces.lifecycle.LifecycleFactory;
+import java.util.Iterator;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class JsfUtils
+{
+ public static void deregisterPhaseListener(PhaseListener phaseListener)
+ {
+ LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
+
+ String currentId;
+ Lifecycle currentLifecycle;
+ Iterator lifecycleIds = lifecycleFactory.getLifecycleIds();
+ while (lifecycleIds.hasNext())
+ {
+ currentId = (String) lifecycleIds.next();
+ currentLifecycle = lifecycleFactory.getLifecycle(currentId);
+ currentLifecycle.removePhaseListener(phaseListener);
+ }
+ }
+
+ public static void registerPhaseListener(PhaseListener phaseListener)
+ {
+ LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
+
+ String currentId;
+ Lifecycle currentLifecycle;
+ Iterator lifecycleIds = lifecycleFactory.getLifecycleIds();
+ while (lifecycleIds.hasNext())
+ {
+ currentId = (String) lifecycleIds.next();
+ currentLifecycle = lifecycleFactory.getLifecycle(currentId);
+ currentLifecycle.addPhaseListener(phaseListener);
+ }
+ }
+
+ public static ResourceBundle getDefaultFacesMessageBundle()
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ return ResourceBundle.getBundle(FacesMessage.FACES_MESSAGES, facesContext.getViewRoot().getLocale());
+ }
+
+ public static ResourceBundle getCustomFacesMessageBundle()
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ String bundleName = facesContext.getApplication().getMessageBundle();
+
+ if (bundleName == null)
+ {
+ return null;
+ }
+
+ return ResourceBundle.getBundle(bundleName, facesContext.getViewRoot().getLocale());
+ }
+
+ public static String getMessageFromApplicationMessageBundle(String messageKey)
+ {
+ ResourceBundle customResourceBundle = getCustomFacesMessageBundle();
+
+ try
+ {
+ if (customResourceBundle != null)
+ {
+ return customResourceBundle.getString(messageKey);
+ }
+ }
+ catch (MissingResourceException e)
+ {
+ //no custom message is available - do nothing
+ }
+
+ return getDefaultFacesMessageBundle().getString(messageKey);
+ }
+
+ public static boolean isRenderResponsePhase()
+ {
+ return PhaseId.RENDER_RESPONSE.equals(getFacesInformationStorage().getCurrentPhaseId());
+ }
+
+ public static PhaseId getCurrentPhaseId()
+ {
+ return getFacesInformationStorage().getCurrentPhaseId();
+ }
+
+ /**
+ * simple test for early config in case of mojarra
+ * @return true if the jsf impl. is initialized and it's possible to use it as expected
+ */
+ public static boolean isApplicationInitialized()
+ {
+ return FacesContext.getCurrentInstance().getClass().getName().startsWith("org.apache.myfaces") ||
+ FacesContext.getCurrentInstance().getExternalContext().getRequestMap() != null &&
+ !FacesContext.getCurrentInstance().getExternalContext().getRequestMap().isEmpty();
+ }
+
+ private static FacesInformationStorage getFacesInformationStorage()
+ {
+ return ExtValUtils.getStorage(FacesInformationStorage.class, FacesInformationStorage.class.getName());
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ProxyUtils.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ProxyUtils.java
new file mode 100644
index 0000000..c75c23e
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ProxyUtils.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.core.proxy.ProxyHelper;
+import org.apache.myfaces.extensions.validator.core.proxy.DefaultProxyHelper;
+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ProxyUtils
+{
+ private static ProxyHelper proxyHelper;
+
+ public static <T> Class<T> getUnproxiedClass(Class currentClass, Class<T> targetType)
+ {
+ return getProxyHelper().getUnproxiedClass(currentClass, targetType);
+ }
+
+ public static Class getUnproxiedClass(Class currentClass)
+ {
+ return getProxyHelper().getUnproxiedClass(currentClass);
+ }
+
+ public static String getClassName(Class proxiedClass)
+ {
+ return getProxyHelper().getNameOfClass(proxiedClass);
+ }
+
+ public static String getClassNameOfObject(Object proxiedObject)
+ {
+ return getProxyHelper().getClassNameOfObject(proxiedObject);
+ }
+
+ public static boolean isProxiedClass(Class currentClass)
+ {
+ return getProxyHelper().isProxiedClass(currentClass);
+ }
+
+ public static boolean isProxiedObject(Object proxiedObject)
+ {
+ return getProxyHelper().isProxiedObject(proxiedObject);
+ }
+
+ private static ProxyHelper getProxyHelper()
+ {
+ if (proxyHelper == null)
+ {
+ //workaround for mojarra
+ if(!JsfUtils.isApplicationInitialized())
+ {
+ return new DefaultProxyHelper();
+ }
+
+ proxyHelper = createProxyHelper();
+ }
+ return proxyHelper;
+ }
+
+ //don't use the default approach (factory finder) - ProxyHelper is called too often...
+ private static ProxyHelper createProxyHelper()
+ {
+ String customProxyHelperClassName = WebXmlParameter.CUSTOM_PROXY_HELPER;
+
+ ProxyHelper result = null;
+ if(customProxyHelperClassName != null && !"".equals(customProxyHelperClassName))
+ {
+ result = (ProxyHelper)ClassUtils.tryToInstantiateClassForName(customProxyHelperClassName);
+ }
+ if(result == null)
+ {
+ result = new DefaultProxyHelper();
+ }
+
+ return result;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ReflectionUtils.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ReflectionUtils.java
new file mode 100644
index 0000000..8e062bf
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/ReflectionUtils.java
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.StringTokenizer;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ReflectionUtils
+{
+ public static Method tryToGetMethod(Class targetClass, String targetMethodName)
+ {
+ return tryToGetMethod(targetClass, targetMethodName, null);
+ }
+
+ public static Method tryToGetMethod(Class targetClass, String targetMethodName, Class... parameterTypes)
+ {
+ try
+ {
+ return getMethod(targetClass, targetMethodName, parameterTypes);
+ }
+ catch (Throwable t)
+ {
+ //do nothing - it's just a try
+ return null;
+ }
+ }
+
+ public static Method getMethod(Class targetClass, String targetMethodName)
+ throws NoSuchMethodException
+ {
+ return getMethod(targetClass, targetMethodName, null);
+ }
+
+ public static Method getMethod(Class targetClass, String targetMethodName, Class... parameterTypes)
+ throws NoSuchMethodException
+ {
+ Class currentClass = targetClass;
+ Method targetMethod = null;
+
+ while (!Object.class.getName().equals(currentClass.getName()))
+ {
+ try
+ {
+ targetMethod = currentClass.getDeclaredMethod(targetMethodName, parameterTypes);
+ break;
+ }
+ catch (NoSuchMethodException e)
+ {
+ currentClass = currentClass.getSuperclass();
+ }
+ }
+
+ if(targetMethod == null)
+ {
+ for (Class currentInterface : targetClass.getInterfaces())
+ {
+ currentClass = currentInterface;
+
+ while (currentClass != null)
+ {
+ try
+ {
+ targetMethod = currentClass.getDeclaredMethod(targetMethodName, parameterTypes);
+ break;
+ }
+ catch (NoSuchMethodException e)
+ {
+ currentClass = currentClass.getSuperclass();
+ }
+ }
+ }
+ }
+
+ if(targetMethod != null)
+ {
+ return targetMethod;
+ }
+
+ throw new NoSuchMethodException("there is no method with the name '" + targetMethodName + "'" +
+ " class: " + targetClass.getName());
+ }
+
+ public static Object tryToInvokeMethod(Object target, Method method)
+ {
+ return tryToInvokeMethod(target, method, null);
+ }
+
+ public static Object tryToInvokeMethodOfClass(Class target, Method method)
+ {
+ return tryToInvokeMethodOfClass(target, method, null);
+ }
+
+ public static Object tryToInvokeMethodOfClass(Class target, Method method, Object[] args)
+ {
+ try
+ {
+ return invokeMethodOfClass(target, method, args);
+ }
+ catch (Throwable e)
+ {
+ //do nothing - it's just a try
+ return null;
+ }
+ }
+
+ public static Object invokeMethodOfClass(Class target, Method method)
+ throws IllegalAccessException, InstantiationException, InvocationTargetException
+ {
+ return invokeMethod(target.newInstance(), method, null);
+ }
+
+ public static Object invokeMethodOfClass(Class target, Method method, Object... args)
+ throws IllegalAccessException, InstantiationException, InvocationTargetException
+ {
+ return invokeMethod(target.newInstance(), method, args);
+ }
+
+ public static Object tryToInvokeMethod(Object target, Method method, Object... args)
+ {
+ try
+ {
+ return invokeMethod(target, method, args);
+ }
+ catch (Throwable t)
+ {
+ //do nothing - it's just a try
+ return null;
+ }
+ }
+
+ public static Object invokeMethod(Object target, Method method)
+ throws InvocationTargetException, IllegalAccessException
+ {
+ return invokeMethod(target, method, null);
+ }
+
+ public static Object invokeMethod(Object target, Method method, Object... args)
+ throws InvocationTargetException, IllegalAccessException
+ {
+ method.setAccessible(true);
+ return method.invoke(target, args);
+ }
+
+ public static Object getBaseOfPropertyChain(Object baseObject, String propertyChain)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(propertyChain, ".");
+
+ Object currentBase = baseObject;
+ String currentProperty;
+ Method currentMethod;
+
+ while(tokenizer.hasMoreTokens())
+ {
+ currentProperty = tokenizer.nextToken();
+
+ //ignore the last property
+ if(!tokenizer.hasMoreTokens())
+ {
+ break;
+ }
+
+ //no is - it's only possible at properties not at bean level
+ currentMethod = tryToGetMethod(ProxyUtils.getUnproxiedClass(currentBase.getClass()),
+ "get" + currentProperty.substring(0, 1).toUpperCase() +
+ currentProperty.substring(1, currentProperty.length()));
+ currentBase = tryToInvokeMethod(currentBase, currentMethod);
+ }
+
+ return currentBase;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/WebXmlUtils.java b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/WebXmlUtils.java
new file mode 100644
index 0000000..db0769c
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/java/org/apache/myfaces/extensions/validator/util/WebXmlUtils.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.ExtValInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class WebXmlUtils
+{
+ public static String getInitParameter(String key)
+ {
+ return getInitParameter(ExtValInformation.WEBXML_PARAM_PREFIX, key);
+ }
+
+ public static String getInitParameter(String prefix, String name)
+ {
+ String parameterName = name;
+ if(prefix != null)
+ {
+ parameterName = prefix + "." + name;
+ }
+ String value = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(parameterName);
+ return (value != null) ? value.replace(" ", "").trim() : null;
+ }
+}
diff --git a/2_0_3_prepare/core/src/main/resources/LICENSE.txt b/2_0_3_prepare/core/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/resources/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/2_0_3_prepare/core/src/main/resources/NOTICE.txt b/2_0_3_prepare/core/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/2_0_3_prepare/core/src/main/resources/NOTICE.txt
@@ -0,0 +1,9 @@
+Apache MyFaces Extensions Validator
+Copyright 2007-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+------------------------------------------------------------------------
+See the file LICENSE.txt
+------------------------------------------------------------------------
\ No newline at end of file
diff --git a/2_0_3_prepare/core/src/site/apt/index.apt b/2_0_3_prepare/core/src/site/apt/index.apt
new file mode 100644
index 0000000..4a201d2
--- /dev/null
+++ b/2_0_3_prepare/core/src/site/apt/index.apt
@@ -0,0 +1,10 @@
+ ------
+Apache MyFaces Extensions Validator Core Module
+ ------
+
+Apache MyFaces Extensions Validator Core Module Overview
+
+ MyFaces Extensions Validator Core Module provides an extensible validation platform to implement validation based on meta-data.
+ Based on this module it is possible to implement validation modules.
+
+ MyFaces Extensions Validator is compatible with JSF 1.1.x and JSF 1.2.x. Both versions require Java 1.5+
\ No newline at end of file
diff --git a/2_0_3_prepare/examples/assembly/pom.xml b/2_0_3_prepare/examples/assembly/pom.xml
new file mode 100644
index 0000000..5d10260
--- /dev/null
+++ b/2_0_3_prepare/examples/assembly/pom.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>pom</packaging>
+ <name>Apache MyFaces Extensions Validator Examples Assembly</name>
+ <groupId>org.apache.myfaces.extensions.validator.examples</groupId>
+ <artifactId>myfaces-extval-examples-assembly12</artifactId>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator.examples</groupId>
+ <artifactId>examples-project</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>dependency-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-war</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.examples</groupId>
+ <artifactId>examples-hello_world</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.examples</groupId>
+ <artifactId>examples-feature-set_01</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${project.build.directory}/war</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>copy-src</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.examples</groupId>
+ <artifactId>examples-hello_world</artifactId>
+ <version>${project.version}</version>
+ <type>java-source</type>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.apache.myfaces.extensions.validator.examples</groupId>
+ <artifactId>examples-feature-set_01</artifactId>
+ <version>${project.version}</version>
+ <type>java-source</type>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${project.build.directory}/src</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <!-- EXECUTE mvn package to generate assembly files -->
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.1</version>
+ <executions>
+ <execution>
+ <id>make_assembly_src</id>
+ <phase>package</phase>
+ <goals>
+ <goal>assembly</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/depsrc.xml</descriptor>
+ </descriptors>
+ <finalName>myfaces-extval-examples-${project.version}-src</finalName>
+ <appendAssemblyId>false</appendAssemblyId>
+ <outputDirectory>${project.build.directory}/out</outputDirectory>
+ <workDirectory>${project.build.directory}/work</workDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>make_assembly_bin</id>
+ <phase>package</phase>
+ <goals>
+ <goal>assembly</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/dep.xml</descriptor>
+ </descriptors>
+ <finalName>myfaces-extval-examples-${project.version}</finalName>
+ <outputDirectory>${project.build.directory}/out</outputDirectory>
+ <workDirectory>${project.build.directory}/work</workDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.myfaces.maven</groupId>
+ <artifactId>wagon-maven-plugin</artifactId>
+ <version>1.0.1</version>
+ <configuration>
+ <id>myfaces-nightly-builds</id>
+ <url>scpexe://minotaur.apache.org/www/people.apache.org/builds/myfaces/nightly</url>
+ <inputDirectory>${project.build.directory}/out</inputDirectory>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+</project>
diff --git a/2_0_3_prepare/examples/assembly/src/main/assembly/dep.xml b/2_0_3_prepare/examples/assembly/src/main/assembly/dep.xml
new file mode 100644
index 0000000..9bb3ec4
--- /dev/null
+++ b/2_0_3_prepare/examples/assembly/src/main/assembly/dep.xml
@@ -0,0 +1,17 @@
+<assembly>
+ <id>bin</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>target/war</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>*.war</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/2_0_3_prepare/examples/assembly/src/main/assembly/depsrc.xml b/2_0_3_prepare/examples/assembly/src/main/assembly/depsrc.xml
new file mode 100644
index 0000000..63a5803
--- /dev/null
+++ b/2_0_3_prepare/examples/assembly/src/main/assembly/depsrc.xml
@@ -0,0 +1,24 @@
+<assembly>
+ <id>src</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>target/src</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>src/main/resources</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>*.txt</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/2_0_3_prepare/examples/assembly/src/main/resources/LICENSE.txt b/2_0_3_prepare/examples/assembly/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/2_0_3_prepare/examples/assembly/src/main/resources/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/2_0_3_prepare/examples/assembly/src/main/resources/NOTICE.txt b/2_0_3_prepare/examples/assembly/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/2_0_3_prepare/examples/assembly/src/main/resources/NOTICE.txt
@@ -0,0 +1,9 @@
+Apache MyFaces Extensions Validator
+Copyright 2007-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+------------------------------------------------------------------------
+See the file LICENSE.txt
+------------------------------------------------------------------------
\ No newline at end of file
diff --git a/2_0_3_prepare/examples/pom.xml b/2_0_3_prepare/examples/pom.xml
new file mode 100644
index 0000000..f852762
--- /dev/null
+++ b/2_0_3_prepare/examples/pom.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <packaging>pom</packaging>
+
+ <groupId>org.apache.myfaces.extensions.validator.examples</groupId>
+ <artifactId>examples-project</artifactId>
+
+ <name>MyFaces Extensions-Validator examples project</name>
+ <version>2.0.3-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-parent</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/examples</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/examples</developerConnection>
+ <url>http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/1_2_2_rc/examples</url>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <!--This plugin allows to run the example using mvn jetty:run -->
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <version>6.1.8</version>
+ <configuration>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <modules>
+ <!--module>hello_world</module-->
+ <!--module>hello_bean-validation</module-->
+ <!--module>feature-set_01</module-->
+ </modules>
+
+ <profiles>
+ <!-- This profile is invoked by -DprepareRelease=true. This allows mvn release:prepare to
+ run successfully on the assembly projects. -->
+ <profile>
+ <id>prepare-release</id>
+ <activation>
+ <property>
+ <name>prepareRelease</name>
+ </property>
+ </activation>
+ <modules>
+ <module>assembly</module>
+ </modules>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <arguments>-DprepareRelease</arguments>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <properties>
+ <trinidad.version>1.2.9</trinidad.version>
+ </properties>
+
+</project>
diff --git a/2_0_3_prepare/parent/LICENSE.txt b/2_0_3_prepare/parent/LICENSE.txt
new file mode 100644
index 0000000..75b5248
--- /dev/null
+++ b/2_0_3_prepare/parent/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/2_0_3_prepare/parent/NOTICE.txt b/2_0_3_prepare/parent/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/2_0_3_prepare/parent/NOTICE.txt
@@ -0,0 +1,9 @@
+Apache MyFaces Extensions Validator
+Copyright 2007-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+------------------------------------------------------------------------
+See the file LICENSE.txt
+------------------------------------------------------------------------
\ No newline at end of file
diff --git a/2_0_3_prepare/parent/pom.xml b/2_0_3_prepare/parent/pom.xml
new file mode 100644
index 0000000..108e3c6
--- /dev/null
+++ b/2_0_3_prepare/parent/pom.xml
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!--
+ - Parent pom of all the myfaces extensions validator subprojects
+ that help to build other myfaces projects.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.myfaces</groupId>
+ <artifactId>myfaces</artifactId>
+ <version>6</version>
+ </parent>
+
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-parent</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Apache MyFaces Extensions-Validator Project Parent</name>
+ <url>http://myfaces.apache.org/extensions/validator12</url>
+
+ <issueManagement>
+ <system>jira</system>
+ <url>http://issues.apache.org/jira/browse/EXTVAL</url>
+ </issueManagement>
+
+ <ciManagement>
+ <system>continuum</system>
+ <url>http://myfaces.zones.apache.org:8080/continuum</url>
+ <notifiers>
+ <notifier>
+ <type>mail</type>
+ <sendOnSuccess>true</sendOnSuccess>
+ <configuration>
+ <address>commits@myfaces.apache.org</address>
+ </configuration>
+ </notifier>
+ </notifiers>
+ </ciManagement>
+
+ <inceptionYear>2008</inceptionYear>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>${basedir}</directory>
+ <targetPath>META-INF</targetPath>
+ <includes>
+ <include>NOTICE.txt</include>
+ <include>LICENSE.txt</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${basedir}/src/main/resources</directory>
+ </resource>
+ </resources>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.2</version>
+ <configuration>
+ <archive>
+ <manifest>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <!--
+ - Copy LICENSE.txt and NOTICE.txt so that they are included
+ - in the -javadoc jar file for the component.
+ -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>javadoc.resources</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <copy todir="${project.build.directory}/apidocs/META-INF">
+ <fileset dir="${basedir}">
+ <include name="LICENSE.txt" />
+ <include name="NOTICE.txt" />
+ </fileset>
+ </copy>
+ </tasks>
+ </configuration>
+ </execution>
+ <execution>
+ <id>javadoc.site.copy</id>
+ <phase>site</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <!-- Copy javadoc to another directory, to keep javadoc of previous versions on site -->
+ <copy todir="${project.build.directory}/site/apidocs-${project.version}" failonerror="false">
+ <fileset dir="${project.build.directory}/site/apidocs"/>
+ </copy>
+ </tasks>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <!--
+ - Make a checkstyle violation a compile error. Note that if a compile error occurs,
+ - further information can be found in target/site/checkstyle.html (present even when
+ - just the compile goal and not the site goal has been run). Note also that child
+ - projects may redeclare this plugin and provide different configuration settings
+ - to use different checks (more or less strict than the default).
+ -->
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.2</version>
+ <executions>
+ <execution>
+ <id>verify-style</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <configLocation>default/myfaces-checks-standard.xml</configLocation>
+ <headerLocation>default/myfaces-header.txt</headerLocation>
+ </configuration>
+ </plugin>
+
+
+ <plugin>
+ <!-- Set compile source at 1.5, since the target JSF impl is 1.2 -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ <optimize>false</optimize>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>maven2-repository.dev.java.net</id>
+ <name>Java.net Repository for Maven</name>
+ <url>http://download.java.net/maven/2/</url>
+ <layout>default</layout>
+ </repository>
+ </repositories>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>2.4.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.0.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>2.3</version>
+ <configuration>
+ <rulesets>
+ <ruleset>/rulesets/basic.xml</ruleset>
+ <ruleset>/rulesets/unusedcode.xml</ruleset>
+ </rulesets>
+ <linkXref>true</linkXref>
+ <minimumTokens>100</minimumTokens>
+ <targetJdk>1.5</targetJdk>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.2</version>
+ <configuration>
+ <configLocation>default/myfaces-checks-standard.xml</configLocation>
+ <headerLocation>default/myfaces-header.txt</headerLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/parent</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/parent</developerConnection>
+ <url>http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/1_2_2_rc/parent</url>
+ </scm>
+
+ <distributionManagement>
+ <snapshotRepository>
+ <uniqueVersion>false</uniqueVersion>
+ <id>apache.snapshots</id>
+ <name>Apache Maven Snapshot Repository</name>
+ <url>scpexe://people.apache.org/www/people.apache.org/repo/m2-snapshot-repository</url>
+ </snapshotRepository>
+ <site>
+ <id>apache-site</id>
+ <url>scpexe://people.apache.org/www/myfaces.apache.org/extensions/validator12</url>
+ </site>
+ </distributionManagement>
+
+ <profiles>
+ <profile>
+ <id>generate-assembly</id>
+ <activation>
+ <property>
+ <name>performRelease</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.3</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <properties>
+ <jsf.version>1.2.4</jsf.version>
+ </properties>
+</project>
diff --git a/2_0_3_prepare/parent/src/site/apt/index.apt b/2_0_3_prepare/parent/src/site/apt/index.apt
new file mode 100644
index 0000000..6287930
--- /dev/null
+++ b/2_0_3_prepare/parent/src/site/apt/index.apt
@@ -0,0 +1,7 @@
+ ------
+Overview
+ ------
+
+Apache MyFaces Extensions Validator for JSF 1.2
+
+ Apache MyFaces Extensions Validator provides versions for JSF 1.1 and 1.2
diff --git a/2_0_3_prepare/parent/src/site/apt/javadoc.apt b/2_0_3_prepare/parent/src/site/apt/javadoc.apt
new file mode 100644
index 0000000..d9fd36f
--- /dev/null
+++ b/2_0_3_prepare/parent/src/site/apt/javadoc.apt
@@ -0,0 +1,15 @@
+ ------
+Javadoc
+ ------
+
+Javadoc
+
+ Here you can find the javadoc of previous extval versions.
+
+ * {{{http://myfaces.apache.org/extensions/validator12/myfaces-extval-core/apidocs-1.2.1/index.html}Myfaces ExtVal Core Version 1.2.1}}
+
+ * {{{http://myfaces.apache.org/extensions/validator12/validation-modules-project/myfaces-extval-property-validation/apidocs-1.2.1/index.html}Myfaces ExtVal Property Validation Version 1.2.1}}
+
+ * {{{http://myfaces.apache.org/extensions/validator12/myfaces-extval-core/apidocs-1.2.2/index.html}Myfaces ExtVal Core Version 1.2.2}}
+
+ * {{{http://myfaces.apache.org/extensions/validator12/validation-modules-project/myfaces-extval-property-validation/apidocs-1.2.2/index.html}Myfaces ExtVal Property Validation Version 1.2.2}}
diff --git a/2_0_3_prepare/parent/src/site/site.xml b/2_0_3_prepare/parent/src/site/site.xml
new file mode 100644
index 0000000..e5a4ff3
--- /dev/null
+++ b/2_0_3_prepare/parent/src/site/site.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<project name="Apache MyFaces Extensions Validator">
+ <bannerLeft>
+ <name>Apache MyFaces ExtVal</name>
+ <src>images/extval_logo.png</src>
+ <href>http://myfaces.apache.org/extensions/validator/index.html</href>
+ </bannerLeft>
+
+ <bannerRight>
+ <name>Apache MyFaces</name>
+ <src>img/banners/MyFaces_logo.jpg</src>
+ <href>http://myfaces.apache.org/index.html</href>
+ </bannerRight>
+
+ <publishDate format="dd MMM yyyy"/>
+
+ <skin>
+ <groupId>org.apache.myfaces.maven</groupId>
+ <artifactId>myfaces-site-skin</artifactId>
+ <version>1-SNAPSHOT</version>
+ </skin>
+
+ <body>
+ <links>
+ <item name="Apache" href="http://www.apache.org"/>
+ <item name="MyFaces" href="http://myfaces.apache.org/index.html"/>
+ <item name="Download Myfaces ExtVal" href="http://myfaces.apache.org/extensions/validator/download.html"/>
+ </links>
+
+ <menu name="Apache MyFaces" inherit="top">
+ <item name="Overview" href="http://myfaces.apache.org/index.html"/>
+ <item name="Download" href="http://myfaces.apache.org/download.html"/>
+ </menu>
+
+ <menu name="Contents" inherit="top">
+ <item name="Main Site" href="http://myfaces.apache.org/extensions/validator/index.html"/>
+ <item name="ExtVal for JSF 1.1" href="http://myfaces.apache.org/extensions/validator11/index.html" collapse="true">
+ <item name="dummy" href="dummy"/>
+ </item>
+ <item name="ExtVal for JSF 1.2" href="http://myfaces.apache.org/extensions/validator12/index.html">
+ <item name="Core Module" href="http://myfaces.apache.org/extensions/validator12/myfaces-extval-core/index.html"/>
+ <item name="Property Validation" href="http://myfaces.apache.org/extensions/validator12/validation-modules-project/myfaces-extval-property-validation/index.html"/>
+ <item name="Trinidad Support" href="http://myfaces.apache.org/extensions/validator12/component-support-modules-project/myfaces-extval-trinidad-support/index.html"/>
+ <item name="Generic Support" href="http://myfaces.apache.org/extensions/validator12/component-support-modules-project/myfaces-extval-generic-support/index.html"/>
+ </item>
+ </menu>
+
+ <menu name="Documentation">
+ <item name="Wiki" href="http://wiki.apache.org/myfaces/Extensions/Validator/"/>
+ <item name="Javadoc" href="http://myfaces.apache.org/extensions/validator12/javadoc.html"/>
+ </menu>
+
+ <menu ref="reports"/>
+
+ <menu name="Foundation" inherit="bottom">
+ <item name="ASF" href="http://www.apache.org/" />
+ <item name="Sponsorship" href="http://www.apache.org/foundation/sponsorship.html" />
+ <item name="Thanks" href="http://www.apache.org/foundation/thanks.html" />
+ </menu>
+ </body>
+</project>
diff --git a/2_0_3_prepare/pom.xml b/2_0_3_prepare/pom.xml
new file mode 100644
index 0000000..fe20ec2
--- /dev/null
+++ b/2_0_3_prepare/pom.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.myfaces</groupId>
+ <artifactId>myfaces</artifactId>
+ <version>6</version>
+ </parent>
+
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-module</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Apache MyFaces Extensions-Validator Module</name>
+ <url>http://myfaces.apache.org/extensions/validator12</url>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/extensions/validator/trunk/</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/extensions/validator/trunk/</developerConnection>
+ <url>http://svn.apache.org/viewvc/myfaces/extensions/validator/trunk/</url>
+ </scm>
+
+ <distributionManagement>
+ <snapshotRepository>
+ <uniqueVersion>false</uniqueVersion>
+ <id>apache.snapshots</id>
+ <name>Apache Maven Snapshot Repository</name>
+ <url>scpexe://people.apache.org/www/people.apache.org/repo/m2-snapshot-repository</url>
+ </snapshotRepository>
+ <site>
+ <id>apache-site</id>
+ <url>scpexe://people.apache.org/www/myfaces.apache.org/extensions/validator12</url>
+ </site>
+ </distributionManagement>
+
+ <!-- WARNING: DO NOT GENERATE SITE FROM HERE DIRECTLY
+ Since this project has an async release procedure (not
+ all modules should be released at once), the parent pom.xml
+ is not this (there is a module for that). Use maven site
+ plugin here cause problems when the site is generated.
+ The procedure must execute site commmand first on parent
+ module and then on each module listed below.
+ -->
+
+ <modules>
+ <module>parent</module>
+ <module>core</module>
+ <module>validation-modules</module>
+ <module>component-support</module>
+ <module>examples</module>
+ </modules>
+
+ <profiles>
+ <!-- This profile is invoked by -DprepareRelease=true. This allows mvn release:prepare to
+ run successfully on the assembly projects. -->
+ <profile>
+ <id>prepare-release</id>
+ <activation>
+ <property>
+ <name>prepareRelease</name>
+ </property>
+ </activation>
+ <modules>
+ <module>assembly</module>
+ </modules>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <arguments>-DprepareRelease</arguments>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <properties>
+ <jsf.version>1.2.4</jsf.version>
+ </properties>
+</project>
diff --git a/2_0_3_prepare/site/pom.xml b/2_0_3_prepare/site/pom.xml
new file mode 100644
index 0000000..bc86435
--- /dev/null
+++ b/2_0_3_prepare/site/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.myfaces</groupId>
+ <artifactId>myfaces</artifactId>
+ <version>6</version>
+ </parent>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-site</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Apache MyFaces Extensions-Validator</name>
+ <url>http://myfaces.apache.org/extensions/validator</url>
+
+ <build>
+ <defaultGoal>site</defaultGoal>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-ssh-external</artifactId>
+ <version>1.0-alpha-5</version>
+ </extension>
+ </extensions>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </reporting>
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/extensions/validator/trunk/site</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/extensions/validator/trunk/site</developerConnection>
+ <url>http://svn.apache.org/viewcvs.cgi/myfaces/extensions/validator/trunk/site</url>
+ </scm>
+ <distributionManagement>
+ <site>
+ <id>apache-site</id>
+ <name>Apache Website</name>
+ <url>scpexe://people.apache.org/www/myfaces.apache.org/extensions/validator</url>
+ </site>
+ </distributionManagement>
+
+</project>
diff --git a/2_0_3_prepare/site/src/site/apt/download.apt b/2_0_3_prepare/site/src/site/apt/download.apt
new file mode 100644
index 0000000..7c514e0
--- /dev/null
+++ b/2_0_3_prepare/site/src/site/apt/download.apt
@@ -0,0 +1,108 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements. See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License. You may obtain a copy of the License at
+ ~~
+ ~~ http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+
+ ------
+Download Apache MyFaces Extensions Validator
+ ------
+
+Download Apache MyFaces Extensions Validator
+
+
+ Use the links below to download a distribution of Apache MyFaces Extensions Validator from
+ one of our mirrors. It is good practice to verify the integrity of the
+ distribution files.
+
+ You will be prompted for a mirror - if the file is not found on yours, please be patient, as it may take 24
+ hours to reach all mirrors.
+
+ Apache MyFaces Extensions Validator is distributed as a <<<zip>>> archive (for Windows) and
+ as a <<<tar.gz>>> archive (for UNIX). The content is the same. Please note
+ that the <<<tar.gz>>> archives contain file names longer than 100 characters and have been
+ created using GNU tar extensions. Thus they must be untarred with a GNU compatible
+ version of tar.
+
+ << Apache MyFaces Extensions Validator 1.0.0 Distribution >>
+
+*-------------------------+---------+----------+-----------+
+| | Mirrors | Checksum | Signature |
+*-------------------------+---------+----------+-----------+
+| MyFaces Extensions Validator for JSF 1.1 1.1.2 (tar.gz) | {{{http://www.apache.org/dyn/closer.cgi/myfaces/binaries/myfaces-extval11-1.1.2-bin.tar.gz} myfaces-extval11-1.1.2-bin.tar.gz}} | {{{http://www.apache.org/dist/myfaces/binaries/myfaces-extval11-1.1.2-bin.tar.gz.md5} myfaces-extval11-1.1.2-bin.tar.gz.md5}} | {{{http://www.apache.org/dist/myfaces/binaries/myfaces-extval11-1.1.2-bin.tar.gz.asc} myfaces-extval11-1.1.2-bin.tar.gz.asc}} |
+*-------------------------+---------+----------+-----------+
+| MyFaces Extensions Validator for JSF 1.1 1.1.2 (zip) | {{{http://www.apache.org/dyn/closer.cgi/myfaces/binaries/myfaces-extval11-1.1.2-bin.zip} myfaces-extval11-1.1.2-bin.zip}} | {{{http://www.apache.org/dist/myfaces/binaries/myfaces-extval11-1.1.2-bin.zip.md5} myfaces-extval11-1.1.2-bin.zip.md5}} | {{{http://www.apache.org/dist/myfaces/binaries/myfaces-extval11-1.1.2-bin.zip.asc} myfaces-extval11-1.1.2-bin.zip.asc}} |
+*-------------------------+---------+----------+-----------+
+| MyFaces Extensions Validator for JSF 1.1 1.1.2 Source (tar.gz) | {{{http://www.apache.org/dyn/closer.cgi/myfaces/source/myfaces-extval11-1.1.2-src.tar.gz} myfaces-extval11-1.1.2-src.tar.gz}} | {{{http://www.apache.org/dist/myfaces/source/myfaces-extval11-1.1.2-src.tar.gz.md5} myfaces-extval11-1.1.2-src.tar.gz.md5}} | {{{http://www.apache.org/dist/myfaces/source/myfaces-extval11-1.1.2-src.tar.gz.asc} myfaces-extval11-1.1.2-src.tar.gz.asc}} |
+*-------------------------+---------+----------+-----------+
+| MyFaces Extensions Validator for JSF 1.1 1.1.2 Source (zip) | {{{http://www.apache.org/dyn/closer.cgi/myfaces/source/myfaces-extval11-1.1.2-src.zip} myfaces-extval11-1.1.2-src.zip}} | {{{http://www.apache.org/dist/myfaces/source/myfaces-extval11-1.1.2-src.zip.md5} myfaces-extval11-1.1.2-src.zip.md5}} | {{{http://www.apache.org/dist/myfaces/source/myfaces-extval11-1.1.2-src.zip.asc} myfaces-extval11-1.1.2-src.zip.asc}} |
+*-------------------------+---------+----------+-----------+
+| MyFaces Extensions Validator for JSF 1.2 1.2.2 (tar.gz) | {{{http://www.apache.org/dyn/closer.cgi/myfaces/binaries/myfaces-extval12-1.2.2-bin.tar.gz} myfaces-extval12-1.2.2-bin.tar.gz}} | {{{http://www.apache.org/dist/myfaces/binaries/myfaces-extval12-1.2.2-bin.tar.gz.md5} myfaces-extval12-1.2.2-bin.tar.gz.md5}} | {{{http://www.apache.org/dist/myfaces/binaries/myfaces-extval12-1.2.2-bin.tar.gz.asc} myfaces-extval12-1.2.2-bin.tar.gz.asc}} |
+*-------------------------+---------+----------+-----------+
+| MyFaces Extensions Validator for JSF 1.2 1.2.2 (zip) | {{{http://www.apache.org/dyn/closer.cgi/myfaces/binaries/myfaces-extval12-1.2.2-bin.zip} myfaces-extval12-1.2.2-bin.zip}} | {{{http://www.apache.org/dist/myfaces/binaries/myfaces-extval12-1.2.2-bin.zip.md5} myfaces-extval12-1.2.2-bin.zip.md5}} | {{{http://www.apache.org/dist/myfaces/binaries/myfaces-extval12-1.2.2-bin.zip.asc} myfaces-extval12-1.2.2-bin.zip.asc}} |
+*-------------------------+---------+----------+-----------+
+| MyFaces Extensions Validator for JSF 1.2 1.2.2 Source (tar.gz) | {{{http://www.apache.org/dyn/closer.cgi/myfaces/source/myfaces-extval12-1.2.2-src.tar.gz} myfaces-extval12-1.2.2-src.tar.gz}} | {{{http://www.apache.org/dist/myfaces/source/myfaces-extval12-1.2.2-src.tar.gz.md5} myfaces-extval12-1.2.2-src.tar.gz.md5}} | {{{http://www.apache.org/dist/myfaces/source/myfaces-extval12-1.2.2-src.tar.gz.asc} myfaces-extval12-1.2.2-src.tar.gz.asc}} |
+*-------------------------+---------+----------+-----------+
+| MyFaces Extensions Validator for JSF 1.2 1.2.2 Source (zip) | {{{http://www.apache.org/dyn/closer.cgi/myfaces/source/myfaces-extval12-1.2.2-src.zip} myfaces-extval12-1.2.2-src.zip}} | {{{http://www.apache.org/dist/myfaces/source/myfaces-extval12-1.2.2-src.zip.md5} myfaces-extval12-1.2.2-src.zip.md5}} | {{{http://www.apache.org/dist/myfaces/source/myfaces-extval12-1.2.2-src.zip.asc} myfaces-extval12-1.2.2-src.zip.asc}} |
+*-------------------------+---------+----------+-----------+
+
+Latest source code from SVN repository
+
+ If you want to use the latest Apache MyFaces Extensions Validator features, the source code is under
+ version control with SVN. Click {{{source-repository.html} here }}
+ for information on how to use the ASF Extensions Validator SVN Repository.
+
+Verifying checksums
+
+ It is essential that you verify the integrity of the downloaded
+ files using the PGP and MD5 signatures. MD5 verification ensures the
+ file was not corrupted during the download process. PGP verification
+ ensures that the file came from a certain person.
+
+ To verify the MD5 signature on the files, you need to use a program
+ called <<<md5>>> or <<<md5sum>>>, which is
+ included in many UNIX distributions. It is also available as part of
+ {{{http://www.gnu.org/software/textutils/textutils.html}GNU Textutils}}.
+ Windows users can get binary md5 programs from {{{http://www.fourmilab.ch/md5/}here}},
+ {{{http://www.pc-tools.net/win32/freeware/console/}here}}, or
+ {{{http://www.slavasoft.com/fsum/}here}}.
+
+Verifying signatures
+
+ PGP verification ensures that the file came from a certain person. We strongly recommend
+ you verify your downloads with both PGP and MD5.
+
+ The PGP signatures can be verified using {{{http://www.pgpi.org/}PGP}} or
+ {{{http://www.gnupg.org/}GPG}}. First download the Apache MyFaces
+ {{{http://www.apache.org/dist/myfaces/KEYS}KEYS}} as well as the <<<asc>>> signature file
+ for the particular distribution. It is important that you get these files from the ultimate
+ trusted source - the main ASF distribution site, rather than from a mirror.
+ Then verify the signatures using ...
+
+ <<<
+ % pgpk -a KEYS
+ % pgpv myfaces-extval11-1.1.2-bin.tar.gz.asc myfaces-extval11-1.1.2-bin.tar.gz
+ >>>
+
+ <or>
+
+ <<<
+ % pgp -ka KEYS
+ % pgp myfaces-extval11-1.1.2-bin.tar.gz.asc myfaces-extval11-1.1.2-bin.tar.gz
+ >>>
+
+ <or>
+
+ <<<
+ % gpg --import KEYS
+ % gpg --verify myfaces-extval11-1.1.2-bin.tar.gz.asc myfaces-extval11-1.1.2-bin.tar.gz
+ >>>
diff --git a/2_0_3_prepare/site/src/site/apt/index.apt b/2_0_3_prepare/site/src/site/apt/index.apt
new file mode 100644
index 0000000..a42539b
--- /dev/null
+++ b/2_0_3_prepare/site/src/site/apt/index.apt
@@ -0,0 +1,14 @@
+ ------
+Apache MyFaces Extensions Validator
+ ------
+
+Apache MyFaces Extensions Validator Overview
+
+ MyFaces Extensions Validator is a JSF centric validation framework.
+
+ It offers powerful and easy to use field based validation based on annotations.
+It has a pluggable architecture, so it is possible to add new validation modules or support for component libraries like Trinidad or other 3rd party frameworks.
+
+ MyFaces Extensions Validator is compatible with JSF 1.1.x and JSF 1.2.x. Both versions require Java 1.5+
+
+ Further information are available at the {{{http://wiki.apache.org/myfaces/Extensions/Validator/}Wiki}}.
\ No newline at end of file
diff --git a/2_0_3_prepare/site/src/site/site.xml b/2_0_3_prepare/site/src/site/site.xml
new file mode 100644
index 0000000..3ebc9ff
--- /dev/null
+++ b/2_0_3_prepare/site/src/site/site.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<project name="Apache Myfaces Extensions Validator">
+ <bannerLeft>
+ <name>Apache MyFaces ExtVal</name>
+ <src>images/extval_logo.png</src>
+ <href>http://myfaces.apache.org/extensions/validator/index.html</href>
+ </bannerLeft>
+
+ <bannerRight>
+ <name>Apache MyFaces</name>
+ <src>img/banners/MyFaces_logo.jpg</src>
+ <href>http://myfaces.apache.org/index.html</href>
+ </bannerRight>
+
+ <publishDate format="dd MMM yyyy"/>
+
+ <skin>
+ <groupId>org.apache.myfaces.maven</groupId>
+ <artifactId>myfaces-site-skin</artifactId>
+ <version>1-SNAPSHOT</version>
+ </skin>
+
+ <body>
+ <links>
+ <item name="Apache" href="http://www.apache.org"/>
+ <item name="MyFaces" href="http://myfaces.apache.org/index.html"/>
+ <item name="Download Myfaces ExtVal" href="download.html"/>
+ </links>
+
+ <menu name="Apache MyFaces" inherit="top">
+ <item name="Overview" href="http://myfaces.apache.org/index.html"/>
+ <item name="Download" href="http://myfaces.apache.org/download.html"/>
+ </menu>
+
+ <menu name="Contents" inherit="top">
+ <item name="Main Site" href="http://myfaces.apache.org/extensions/validator/index.html"/>
+ <item name="ExtVal for JSF 1.1" href="http://myfaces.apache.org/extensions/validator11/index.html" collapse="true">
+ <item name="dummy" href="dummy"/>
+ </item>
+ <item name="ExtVal for JSF 1.2" href="http://myfaces.apache.org/extensions/validator12/index.html" collapse="true">
+ <item name="dummy" href="dummy"/>
+ </item>
+ </menu>
+
+ <menu name="Documentation">
+ <item name="Wiki" href="http://wiki.apache.org/myfaces/Extensions/Validator/"/>
+ </menu>
+
+ <menu ref="reports"/>
+
+ <menu name="Foundation" inherit="top">
+ <item name="ASF" href="http://www.apache.org/" />
+ <item name="Sponsorship" href="http://www.apache.org/foundation/sponsorship.html" />
+ <item name="Thanks" href="http://www.apache.org/foundation/thanks.html" />
+ </menu>
+ </body>
+</project>
diff --git a/2_0_3_prepare/validation-modules/bean-validation/pom.xml b/2_0_3_prepare/validation-modules/bean-validation/pom.xml
new file mode 100644
index 0000000..5a51c11
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/pom.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>jar</packaging>
+
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>myfaces-extval-bean-validation</artifactId>
+
+ <name>MyFaces Extensions-Validator Bean-Validation-Integration-Module (JSR 303)</name>
+ <version>2.0.3-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>validation-modules-project</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <repositories>
+ <repository>
+ <id>jboss</id>
+ <url>http://repository.jboss.com/maven2</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>jboss-snapshot</id>
+ <url>http://snapshots.jboss.org/maven2</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-core</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <version>1.0.0.GA</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.el</groupId>
+ <artifactId>el-api</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1.1</version>
+ <scope>compile</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/config</directory>
+ <includes>
+ <include>**/*xml</include>
+ </includes>
+ <targetPath>/META-INF</targetPath>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ </includes>
+ <targetPath>/META-INF</targetPath>
+ </resource>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*properties</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.4.2</version>
+ <configuration>
+ <excludes>
+ <exclude>**/Abstract*.java</exclude>
+ <exclude>**/TestUtils.java</exclude>
+ <exclude>**/*Bean.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/config/faces-config.xml b/2_0_3_prepare/validation-modules/bean-validation/src/main/config/faces-config.xml
new file mode 100644
index 0000000..1967f44
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/config/faces-config.xml
@@ -0,0 +1,30 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
+ version="2.0">
+ <factory>
+ <application-factory>org.apache.myfaces.extensions.validator.beanval.factory.ExtValApplicationFactory</application-factory>
+ </factory>
+ <lifecycle>
+ <phase-listener>org.apache.myfaces.extensions.validator.beanval.startup.JSF2AwareBeanValidationStartupListener</phase-listener>
+ <phase-listener>org.apache.myfaces.extensions.validator.beanval.startup.BeanValidationStartupListener</phase-listener>
+ </lifecycle>
+</faces-config>
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanAwareConstraintValidatorFactory.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanAwareConstraintValidatorFactory.java
new file mode 100644
index 0000000..27a7404
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanAwareConstraintValidatorFactory.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.ConstraintValidator;
+import java.beans.Introspector;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class BeanAwareConstraintValidatorFactory implements ConstraintValidatorFactory
+{
+ private ConstraintValidatorFactory constraintValidatorFactory;
+
+ public BeanAwareConstraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory)
+ {
+ setConstraintValidatorFactory(constraintValidatorFactory);
+ }
+
+ public void setConstraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory)
+ {
+ if(constraintValidatorFactory == null)
+ {
+ throw new IllegalStateException("null is not allowed here");
+ }
+ this.constraintValidatorFactory = constraintValidatorFactory;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @ToDo(value = Priority.MEDIUM, description = "allow the registration of a custom prefix")
+ public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> targetClass)
+ {
+ String validatorClassName = targetClass.getSimpleName();
+ Object result = ExtValUtils.getELHelper().getBean(createBeanName(validatorClassName));
+
+ if(result != null && targetClass.isAssignableFrom(result.getClass()))
+ {
+ return (T)result;
+ }
+ return this.constraintValidatorFactory.getInstance(targetClass);
+ }
+
+ private String createBeanName(String validatorClassName)
+ {
+ return Introspector.decapitalize(validatorClassName);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanAwareValidatorFactory.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanAwareValidatorFactory.java
new file mode 100644
index 0000000..47d76c6
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanAwareValidatorFactory.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.ValidatorFactory;
+import javax.validation.Validator;
+import javax.validation.ValidatorContext;
+import javax.validation.MessageInterpolator;
+import javax.validation.TraversableResolver;
+import javax.validation.ConstraintValidatorFactory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class BeanAwareValidatorFactory implements ValidatorFactory
+{
+ private ValidatorFactory validatorFactory;
+
+ public BeanAwareValidatorFactory(ValidatorFactory validatorFactory)
+ {
+ setValidatorFactory(validatorFactory);
+ }
+
+ public void setValidatorFactory(ValidatorFactory validatorFactory)
+ {
+ if(validatorFactory == null)
+ {
+ throw new IllegalStateException("null is not allowed here");
+ }
+ this.validatorFactory = validatorFactory;
+ }
+
+ public Validator getValidator()
+ {
+ return validatorFactory.getValidator();
+ }
+
+ public ValidatorContext usingContext()
+ {
+ return validatorFactory.usingContext();
+ }
+
+ public MessageInterpolator getMessageInterpolator()
+ {
+ return validatorFactory.getMessageInterpolator();
+ }
+
+ public TraversableResolver getTraversableResolver()
+ {
+ return validatorFactory.getTraversableResolver();
+ }
+
+ public ConstraintValidatorFactory getConstraintValidatorFactory()
+ {
+ return new BeanAwareConstraintValidatorFactory(validatorFactory.getConstraintValidatorFactory());
+ }
+
+ public <T> T unwrap(Class<T> tClass)
+ {
+ return validatorFactory.unwrap(tClass);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleKey.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleKey.java
new file mode 100644
index 0000000..e453627
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleKey.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.ValidationModuleKey;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@ValidationModuleKey
+@UsageInformation(UsageCategory.API)
+public interface BeanValidationModuleKey
+{
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleValidationInterceptor.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleValidationInterceptor.java
new file mode 100644
index 0000000..a98c910
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleValidationInterceptor.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval;
+
+import org.apache.myfaces.extensions.validator.core.interceptor.AbstractValidationInterceptor;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.MetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.beanval.util.BeanValidationUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.validation.ConstraintViolation;
+import java.util.Set;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class BeanValidationModuleValidationInterceptor extends AbstractValidationInterceptor
+{
+ BeanValidationModuleValidationInterceptorInternals bviUtils =
+ new BeanValidationModuleValidationInterceptorInternals(this.logger);
+
+ @Override
+ protected boolean isRequiredInitializationSupported()
+ {
+ return true;
+ }
+
+ protected void initComponent(FacesContext facesContext, UIComponent uiComponent)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("start to init component " + uiComponent.getClass().getName());
+ }
+
+ PropertyDetails propertyDetails = bviUtils.extractPropertyDetails(
+ facesContext, uiComponent, getPropertiesForComponentMetaDataExtractor(uiComponent));
+
+ if (propertyDetails != null)
+ {
+ initComponentWithPropertyDetails(facesContext, uiComponent, propertyDetails);
+ }
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("init component of " + uiComponent.getClass().getName() + " finished");
+ }
+ }
+
+ protected void initComponentWithPropertyDetails(FacesContext facesContext,
+ UIComponent uiComponent,
+ PropertyDetails propertyDetails)
+ {
+ this.bviUtils.initComponentWithPropertyDetails(facesContext, uiComponent, propertyDetails);
+ }
+
+ protected void processValidation(FacesContext facesContext, UIComponent uiComponent, Object convertedObject)
+ {
+ PropertyInformation propertyInformation = getPropertyInformation(facesContext, uiComponent);
+
+ boolean validateProperty = hasBeanValidationConstraints(propertyInformation);
+ try
+ {
+ if (validateProperty)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("jsr303 start validation");
+ }
+
+ processFieldValidation(facesContext, uiComponent, convertedObject, propertyInformation);
+ }
+ }
+ finally
+ {
+ if (validateProperty)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("jsr303 validation finished");
+ }
+ }
+ }
+ }
+
+ protected MetaDataExtractor getComponentMetaDataExtractor(Map<String, Object> properties)
+ {
+ return bviUtils.getComponentMetaDataExtractor(properties);
+ }
+
+ protected boolean hasBeanValidationConstraints(PropertyInformation propertyInformation)
+ {
+ return this.bviUtils.hasBeanValidationConstraints(propertyInformation);
+ }
+
+ protected void processFieldValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ PropertyInformation propertyInformation)
+ {
+ /*not used yet supportMultipleViolationsPerField()*/
+ Set<ConstraintViolation> violations = this.bviUtils
+ .validate(facesContext, uiComponent, convertedObject, propertyInformation);
+
+ processConstraintViolations(facesContext, uiComponent, convertedObject, violations);
+ }
+
+ protected void processConstraintViolations(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ Set<ConstraintViolation> violations)
+ {
+ if(violations != null && !violations.isEmpty())
+ {
+ BeanValidationUtils.processConstraintViolations(facesContext, uiComponent, convertedObject, violations);
+ }
+ }
+
+ @Override
+ protected Class getModuleKey()
+ {
+ return BeanValidationModuleKey.class;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleValidationInterceptorInternals.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleValidationInterceptorInternals.java
new file mode 100644
index 0000000..e0f8a7b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationModuleValidationInterceptorInternals.java
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval;
+
+import org.apache.commons.logging.Log;
+import org.apache.myfaces.extensions.validator.beanval.validation.strategy.BeanValidationVirtualValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.MetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.MetaDataTransformer;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.validation.ConstraintViolation;
+import javax.validation.ValidatorFactory;
+import javax.validation.groups.Default;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.ElementDescriptor;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class BeanValidationModuleValidationInterceptorInternals
+{
+ private Log logger;
+
+ BeanValidationModuleValidationInterceptorInternals(Log logger)
+ {
+ this.logger = logger;
+ }
+
+ PropertyDetails extractPropertyDetails(
+ FacesContext facesContext, UIComponent uiComponent, Map<String, Object> propertiesForExtraction)
+ {
+ PropertyDetails result = getComponentMetaDataExtractor(propertiesForExtraction)
+ .extract(facesContext, uiComponent)
+ .getInformation(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
+
+ if (result.getBaseObject() == null && this.logger.isWarnEnabled())
+ {
+ this.logger.warn("no base object at " + result.getKey() +
+ " component-id: " + uiComponent.getClientId(facesContext));
+ }
+
+ return result.getBaseObject() != null ? result : null;
+ }
+
+ /*
+ * also invokes meta-data extraction interceptors
+ * (see e.g. ExtValBeanValidationMetaDataExtractionInterceptor)
+ */
+ MetaDataExtractor getComponentMetaDataExtractor(Map<String, Object> properties)
+ {
+ return ExtValUtils.getComponentMetaDataExtractorWith(properties);
+ }
+
+ void initComponentWithPropertyDetails(
+ FacesContext facesContext, UIComponent uiComponent, PropertyDetails propertyDetails)
+ {
+ Class[] foundGroups = resolveGroups(facesContext, uiComponent);
+
+ if (foundGroups == null)
+ {
+ return;
+ }
+ else if (foundGroups.length == 0)
+ {
+ foundGroups = new Class[]{Default.class};
+ }
+
+ Class targetClass = propertyDetails.getBaseObject().getClass();
+
+ targetClass = ProxyUtils.getUnproxiedClass(targetClass);
+
+ ElementDescriptor elementDescriptor = getDescriptorFor(targetClass, propertyDetails.getProperty());
+
+ if (elementDescriptor == null)
+ {
+ return;
+ }
+
+ processElementDescriptor(facesContext, uiComponent, foundGroups, elementDescriptor);
+ }
+
+ void processElementDescriptor(FacesContext facesContext,
+ UIComponent uiComponent,
+ Class[] foundGroups,
+ ElementDescriptor elementDescriptor)
+ {
+ Map<String, Object> metaData;
+
+ for (ConstraintDescriptor<?> constraintDescriptor :
+ elementDescriptor.findConstraints().unorderedAndMatchingGroups(foundGroups).getConstraintDescriptors())
+ {
+ metaData = transformConstraintDescriptorToMetaData(
+ constraintDescriptor, elementDescriptor.getElementClass());
+
+ if (metaData != null && !metaData.isEmpty())
+ {
+ ExtValUtils.configureComponentWithMetaData(facesContext, uiComponent, metaData);
+ }
+ }
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "ConstraintDescriptor#isReportAsSingleViolation")
+ private Map<String, Object> transformConstraintDescriptorToMetaData(
+ ConstraintDescriptor<?> constraintDescriptor, Class elementClass)
+ {
+ Map<String, Object> result = new HashMap<String, Object>();
+ MetaDataTransformer metaDataTransformer;
+
+ metaDataTransformer = ExtValUtils.getMetaDataTransformerForValidationStrategy(
+ new BeanValidationVirtualValidationStrategy(constraintDescriptor, elementClass));
+
+ if (metaDataTransformer != null)
+ {
+ result.putAll(transformMetaData(metaDataTransformer, constraintDescriptor));
+ }
+
+ if (!constraintDescriptor.isReportAsSingleViolation())
+ {
+ Set<ConstraintDescriptor<?>> composingConstraints = constraintDescriptor.getComposingConstraints();
+ if (composingConstraints != null && !composingConstraints.isEmpty())
+ {
+ result.putAll(transformComposingConstraints(composingConstraints, elementClass));
+ }
+ }
+
+ return result;
+ }
+
+ private Map<String, Object> transformComposingConstraints(
+ Set<ConstraintDescriptor<?>> composingConstraints, Class elementClass)
+ {
+ Map<String, Object> result = new HashMap<String, Object>();
+ for (ConstraintDescriptor constraintDescriptor : composingConstraints)
+ {
+ result.putAll(transformConstraintDescriptorToMetaData(constraintDescriptor, elementClass));
+ }
+
+ return result;
+ }
+
+ private Map<String, Object> transformMetaData(
+ MetaDataTransformer metaDataTransformer, ConstraintDescriptor<?> constraintDescriptor)
+ {
+ MetaDataEntry entry;
+ Map<String, Object> result;
+ if (this.logger.isDebugEnabled())
+ {
+ this.logger.debug(metaDataTransformer.getClass().getName() + " instantiated");
+ }
+
+ entry = new MetaDataEntry();
+ entry.setKey(constraintDescriptor.getAnnotation().annotationType().getName());
+ entry.setValue(constraintDescriptor);
+
+ result = metaDataTransformer.convertMetaData(entry);
+ return result;
+ }
+
+ boolean hasBeanValidationConstraints(PropertyInformation propertyInformation)
+ {
+ PropertyDetails propertyDetails = ExtValUtils.getPropertyDetails(propertyInformation);
+
+ Class targetClass = ProxyUtils.getUnproxiedClass(propertyDetails.getBaseObject().getClass());
+
+ return getDescriptorFor(targetClass, propertyDetails.getProperty()) != null;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ Set<ConstraintViolation> validate(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ PropertyInformation propertyInformation)
+ {
+ Class baseBeanClass = getBaseClassType(propertyInformation);
+ String propertyName = getPropertyToValidate(propertyInformation);
+
+ Class[] groups = resolveGroups(facesContext, uiComponent);
+
+ if (groups == null)
+ {
+ return null;
+ }
+
+ ValidatorFactory validatorFactory = ExtValBeanValidationContext.getCurrentInstance().getValidatorFactory();
+ return validatorFactory
+ .usingContext()
+ .messageInterpolator(ExtValBeanValidationContext.getCurrentInstance().getMessageInterpolator())
+ .constraintValidatorFactory(validatorFactory.getConstraintValidatorFactory())
+ .traversableResolver(validatorFactory.getTraversableResolver())
+ .getValidator()
+ .validateValue(baseBeanClass, propertyName, convertedObject, groups);
+ }
+
+ Class getBaseClassType(PropertyInformation propertyInformation)
+ {
+ Class result = ExtValUtils.getPropertyDetails(propertyInformation).getBaseObject().getClass();
+
+ return ProxyUtils.getUnproxiedClass(result);
+ }
+
+ String getPropertyToValidate(PropertyInformation propertyInformation)
+ {
+ return ExtValUtils.getPropertyDetails(propertyInformation).getProperty();
+ }
+
+ Class[] resolveGroups(FacesContext facesContext, UIComponent uiComponent)
+ {
+ return ExtValBeanValidationContext.getCurrentInstance().getGroups(
+ facesContext.getViewRoot().getViewId(),
+ uiComponent.getClientId(facesContext));
+ }
+
+ ElementDescriptor getDescriptorFor(Class targetClass, String property)
+ {
+ BeanDescriptor beanDescriptor = ExtValBeanValidationContext.getCurrentInstance().getValidatorFactory()
+ .getValidator().getConstraintsForClass(targetClass);
+
+ return beanDescriptor.getConstraintsForProperty(property);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/ExtValBeanValidationContext.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/ExtValBeanValidationContext.java
new file mode 100644
index 0000000..78f5bb2
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/ExtValBeanValidationContext.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval;
+
+import org.apache.myfaces.extensions.validator.beanval.validation.message.interpolator.DefaultMessageInterpolator;
+import org.apache.myfaces.extensions.validator.beanval.validation.message.interpolator.ExtValMessageInterpolatorAdapter;
+import org.apache.myfaces.extensions.validator.beanval.validation.strategy.BeanValidationVirtualValidationStrategy;
+import org.apache.myfaces.extensions.validator.beanval.storage.ModelValidationEntry;
+import org.apache.myfaces.extensions.validator.beanval.storage.ModelValidationStorage;
+import org.apache.myfaces.extensions.validator.beanval.annotation.BeanValidation;
+import org.apache.myfaces.extensions.validator.beanval.annotation.ModelValidation;
+import org.apache.myfaces.extensions.validator.beanval.util.BeanValidationUtils;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.storage.GroupStorage;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+import javax.validation.MessageInterpolator;
+import javax.validation.ValidatorFactory;
+import java.util.Map;
+import java.util.List;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public class ExtValBeanValidationContext implements GroupStorage, ModelValidationStorage
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private static final String KEY = ExtValBeanValidationContext.class.getName() + ":KEY";
+
+ private MessageInterpolator defaultMessageInterpolator;
+
+ private MessageResolver messageResolver;
+
+ private GroupStorage groupStorage;
+
+ private ModelValidationStorage modelValidationStorage;
+
+ private ExtValBeanValidationContext()
+ {
+ initGroupStorage();
+ initModelValidationStorage();
+
+ initMessageResolver();
+ initMessageInterpolator();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public static ExtValBeanValidationContext getCurrentInstance()
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ Map requestMap = facesContext.getExternalContext().getRequestMap();
+
+ ExtValBeanValidationContext currentContext = (ExtValBeanValidationContext)requestMap.get(KEY);
+
+ if(currentContext == null)
+ {
+ currentContext = new ExtValBeanValidationContext();
+ requestMap.put(KEY, currentContext);
+ }
+
+ return currentContext;
+ }
+
+ public ValidatorFactory getValidatorFactory()
+ {
+ Object validatorFactory = ExtValContext.getContext().getGlobalProperty(ValidatorFactory.class.getName());
+
+ if(validatorFactory instanceof ValidatorFactory)
+ {
+ return (ValidatorFactory)validatorFactory;
+ }
+
+ if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn("fallback to the default bv validator factory");
+ }
+ return BeanValidationUtils.getDefaultValidatorFactory();
+ }
+
+ public MessageInterpolator getMessageInterpolator()
+ {
+ if(this.messageResolver != null)
+ {
+ return new ExtValMessageInterpolatorAdapter(this.defaultMessageInterpolator, this.messageResolver);
+ }
+
+ return this.defaultMessageInterpolator;
+ }
+
+ public void addGroup(Class groupClass, String viewId, String clientId)
+ {
+ this.groupStorage.addGroup(groupClass, viewId, clientId);
+ }
+
+ public void restrictGroup(Class groupClass, String viewId, String clientId)
+ {
+ this.groupStorage.restrictGroup(groupClass, viewId, clientId);
+ }
+
+ public Class[] getGroups(String viewId, String clientId)
+ {
+ return this.groupStorage.getGroups(viewId, clientId);
+ }
+
+ public void addModelValidationEntry(ModelValidationEntry modelValidationEntry)
+ {
+ this.modelValidationStorage.addModelValidationEntry(modelValidationEntry);
+ }
+
+ public List<ModelValidationEntry> getModelValidationEntriesToValidate()
+ {
+ return this.modelValidationStorage.getModelValidationEntriesToValidate();
+ }
+
+ private void initGroupStorage()
+ {
+ this.groupStorage = ExtValUtils
+ .getStorage(GroupStorage.class, BeanValidation.class.getName());
+ }
+
+ private void initModelValidationStorage()
+ {
+ this.modelValidationStorage = ExtValUtils.
+ getStorage(ModelValidationStorage.class, ModelValidation.class.getName());
+ }
+
+ @ToDo(Priority.HIGH)
+ private void initMessageInterpolator()
+ {
+ Object foundBean = ExtValUtils.getELHelper().getBean(MessageInterpolator.class.getName().replace(".", "_"));
+
+ if(foundBean instanceof MessageInterpolator)
+ {
+ this.defaultMessageInterpolator = (MessageInterpolator)foundBean;
+ }
+ else
+ {
+ this.defaultMessageInterpolator = new DefaultMessageInterpolator(
+ BeanValidationUtils.getDefaultValidatorFactory().getMessageInterpolator());
+ }
+ }
+
+ private void initMessageResolver()
+ {
+ this.messageResolver = ExtValUtils.getMessageResolverForValidationStrategy(getBeanValidationStrategy());
+ }
+
+ private ValidationStrategy getBeanValidationStrategy()
+ {
+ return new BeanValidationVirtualValidationStrategy(null, null);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/HtmlCoreComponentsComponentInitializer.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/HtmlCoreComponentsComponentInitializer.java
new file mode 100644
index 0000000..7ec69d3
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/HtmlCoreComponentsComponentInitializer.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval;
+
+import org.apache.myfaces.extensions.validator.core.initializer.component
+ .AbstractHtmlCoreComponentsComponentInitializer;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(200)
+@UsageInformation(UsageCategory.INTERNAL)
+public class HtmlCoreComponentsComponentInitializer extends AbstractHtmlCoreComponentsComponentInitializer
+{
+ protected void configureRequiredAttribute(FacesContext facesContext,
+ UIComponent uiComponent,
+ Map<String, Object> metaData)
+ {
+ if(!ExtValUtils.interpretEmptyStringValuesAsNull())
+ {
+ return;
+ }
+
+ if(Boolean.TRUE.equals(metaData.get(CommonMetaDataKeys.REQUIRED)) ||
+ Boolean.TRUE.equals(isComponentRequired(uiComponent)))
+ {
+ ((EditableValueHolder)uiComponent).setRequired(true);
+ }
+ else
+ {
+ ((EditableValueHolder)uiComponent).setRequired(false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/BeanValidation.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/BeanValidation.java
new file mode 100644
index 0000000..c6933a9
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/BeanValidation.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.groups.Default;
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.FIELD;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+
+@Target({METHOD, FIELD, TYPE})
+@Retention(RUNTIME)
+@UsageInformation(UsageCategory.API)
+@Documented
+public @interface BeanValidation
+{
+ String[] viewIds() default "*";
+
+ Class[] useGroups() default Default.class;
+
+ Class[] restrictGroups() default {};
+
+ String[] conditions() default "#{true}";
+
+ ModelValidation modelValidation() default @ModelValidation;
+
+ @Retention(RUNTIME) static @interface List
+ {
+ BeanValidation[] value();
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/ModelValidation.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/ModelValidation.java
new file mode 100644
index 0000000..86c78dd
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/ModelValidation.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.FIELD;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+
+@Target({METHOD, FIELD, TYPE})
+@Retention(RUNTIME)
+@UsageInformation(UsageCategory.API)
+@Documented
+public @interface ModelValidation
+{
+ public static final String DEFAULT = "";
+
+ boolean isActive() default false;
+
+ boolean displayInline() default false;
+
+ @ToDo(value = Priority.MEDIUM, description = "support property chain syntax")
+ String[] validationTargets() default DEFAULT;
+
+ String message() default DEFAULT;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/extractor/DefaultGroupControllerScanningExtractor.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/extractor/DefaultGroupControllerScanningExtractor.java
new file mode 100644
index 0000000..216f135
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/extractor/DefaultGroupControllerScanningExtractor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.annotation.extractor;
+
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.DefaultComponentMetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.DefaultPropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@ToDo(value = Priority.MEDIUM, description = "use meta-data storage - but a special impl.")
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultGroupControllerScanningExtractor extends DefaultComponentMetaDataExtractor
+{
+ @Override
+ public PropertyInformation extract(FacesContext facesContext, Object object)
+ {
+ if (!(object instanceof PropertyDetails))
+ {
+ throw new IllegalStateException(object.getClass() + " is not a " + PropertyDetails.class.getName());
+ }
+
+ PropertyDetails propertyDetails = (PropertyDetails)object;
+
+ Class entityClass = ProxyUtils.getUnproxiedClass(propertyDetails.getBaseObject().getClass());
+
+ PropertyInformation propertyInformation = new DefaultPropertyInformation();
+ propertyInformation.setInformation(PropertyInformationKeys.PROPERTY_DETAILS, propertyDetails);
+
+ extractAnnotations(propertyInformation, propertyDetails, entityClass);
+
+ return propertyInformation;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/factory/ExtValApplicationFactory.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/factory/ExtValApplicationFactory.java
new file mode 100644
index 0000000..6f75dca
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/factory/ExtValApplicationFactory.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.factory;
+
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.application.ApplicationFactory;
+import javax.faces.application.Application;
+import javax.faces.application.ApplicationWrapper;
+
+/**
+ * @author Gerhard Petracek
+ * @since 2.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValApplicationFactory extends ApplicationFactory
+{
+ private ApplicationFactory wrapped;
+
+ public ExtValApplicationFactory(ApplicationFactory wrapped)
+ {
+ this.wrapped = wrapped;
+ }
+
+ public ApplicationFactory getWrapped()
+ {
+ return wrapped.getWrapped();
+ }
+
+ @ToDo(value = Priority.HIGH, description = "context param. to deactivate this wrapper")
+ public Application getApplication()
+ {
+ return new ApplicationWrapper() {
+
+ public Application getWrapped()
+ {
+ return wrapped.getApplication();
+ }
+
+ @Override
+ public void addDefaultValidatorId(String s)
+ {
+ if(!"javax.faces.Bean".equals(s))
+ {
+ super.addDefaultValidatorId(s);
+ }
+ }
+ };
+ }
+
+ public void setApplication(Application application)
+ {
+ wrapped.setApplication(application);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidationExceptionInterceptor.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidationExceptionInterceptor.java
new file mode 100644
index 0000000..d3775c7
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidationExceptionInterceptor.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.interceptor.ValidationExceptionInterceptor;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.validator.ValidatorException;
+import javax.faces.context.FacesContext;
+
+/**
+ * extracts and adds the extval bv meta-data (e.g. validation groups) to the ExtValBeanValidationContext
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(200)
+@UsageInformation(UsageCategory.INTERNAL)
+public class BeanValidationExceptionInterceptor implements ValidationExceptionInterceptor
+{
+
+ public boolean afterThrowing(UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException validatorException,
+ ValidationStrategy validatorExceptionSource)
+ {
+ if(uiComponent instanceof EditableValueHolder && isBlockingException(uiComponent, validatorException))
+ {
+ //bv integration doesn't throw exceptions to support multiple messages -> set component state
+ ((EditableValueHolder)uiComponent).setValid(false);
+ }
+ return true;
+ }
+
+ private boolean isBlockingException(UIComponent uiComponent, ValidatorException validatorException)
+ {
+ return ExtValContext.getContext().getViolationSeverityInterpreter().severityCausesValidatorException(
+ FacesContext.getCurrentInstance(),
+ uiComponent,
+ validatorException.getFacesMessage().getSeverity());
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidationTagAwareValidationInterceptor.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidationTagAwareValidationInterceptor.java
new file mode 100644
index 0000000..27c4638
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidationTagAwareValidationInterceptor.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.interceptor;
+
+import org.apache.myfaces.extensions.validator.core.interceptor.PropertyValidationInterceptor;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.beanval.ExtValBeanValidationContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.validator.BeanValidator;
+import javax.faces.validator.Validator;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 2.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class BeanValidationTagAwareValidationInterceptor implements PropertyValidationInterceptor
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public boolean beforeValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ Map<String, Object> properties)
+ {
+ if(uiComponent instanceof EditableValueHolder && //"filter" cross-validation calls
+ properties.containsKey(PropertyInformation.class.getName()))
+ {
+ inspectValidators(facesContext.getViewRoot().getViewId(),
+ (EditableValueHolder)uiComponent,
+ uiComponent.getClientId(facesContext),
+ ((EditableValueHolder)uiComponent).getValidators());
+ }
+
+ return true;
+ }
+
+ public void afterValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ Map<String, Object> properties)
+ {
+ //not used
+ }
+
+ @ToDo.List({@ToDo(value = Priority.HIGH, description = "optimize"),
+ @ToDo(value = Priority.HIGH, description = "use reflection instead of BeanValidator for jsf 1.x versions"),
+ @ToDo(value = Priority.HIGH, description = "test")
+ })
+ private void inspectValidators(String viewId,
+ EditableValueHolder editableValueHolder,
+ String clientId,
+ Validator[] validators)
+ {
+ List<String> validatorsOfTagList = new ArrayList<String>();
+
+ for (Validator validator : validators)
+ {
+ //don't check with instanceof
+ if (validator.getClass().getName().equals(BeanValidator.class.getName()))
+ {
+ validatorsOfTagList.addAll(
+ Arrays.asList(((BeanValidator) validator).getValidationGroups().split(",")));
+
+ //prevent double-validation
+ editableValueHolder.removeValidator(validator);
+ editableValueHolder.addValidator(new BeanValidatorWrapper((BeanValidator)validator));
+ }
+ }
+
+ Class currentClass;
+ for(String groupClassName : validatorsOfTagList)
+ {
+ currentClass = ClassUtils.tryToLoadClassForName(groupClassName);
+
+ if(currentClass != null && currentClass.isInterface())
+ {
+ ExtValBeanValidationContext.getCurrentInstance().addGroup(currentClass, viewId, clientId);
+ }
+ else
+ {
+ if(this.logger.isErrorEnabled())
+ {
+ this.logger.error(groupClassName + " is no valid group - only existing interfaces are allowed");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidatorWrapper.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidatorWrapper.java
new file mode 100644
index 0000000..4fec297
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/BeanValidatorWrapper.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.validator.BeanValidator;
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+
+/**
+ * replacement for BeanValidator which gets added due to f:validateBean
+ *
+ * @author Gerhard Petracek
+ * @since 2.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class BeanValidatorWrapper extends BeanValidator
+{
+ private BeanValidator wrapped;
+
+ BeanValidatorWrapper(BeanValidator wrapped)
+ {
+ this.wrapped = wrapped;
+ }
+
+ public BeanValidator getWrappedBeanValidator()
+ {
+ return this.wrapped;
+ }
+
+ public void setWrapped(BeanValidator wrapped)
+ {
+ this.wrapped = wrapped;
+ }
+
+ public void setValidationGroups(String s)
+ {
+ wrapped.setValidationGroups(s);
+ }
+
+ public String getValidationGroups()
+ {
+ return wrapped.getValidationGroups();
+ }
+
+ public void validate(FacesContext facesContext, UIComponent uiComponent, Object o)
+ {
+ //don't validate - the extval bean-validation adapter will do that
+ }
+
+ /*
+ public Object saveState(FacesContext facesContext)
+ {
+ Object result[] = new Object[1];
+ result[0] = wrapped.getValidationGroups();
+ return result;
+ }
+
+ public void restoreState(FacesContext facesContext, Object state)
+ {
+ this.wrapped = new BeanValidator();
+
+ if (state != null)
+ {
+ Object values[] = (Object[]) state;
+ this.wrapped.setValidationGroups((String) values[0]);
+ }
+ }
+ */
+
+ public void markInitialState()
+ {
+ wrapped.markInitialState();
+ }
+
+ public boolean initialStateMarked()
+ {
+ return wrapped.initialStateMarked();
+ }
+
+ public void clearInitialState()
+ {
+ wrapped.clearInitialState();
+ }
+
+ public boolean isTransient()
+ {
+ return wrapped.isTransient();
+ }
+
+ public void setTransient(boolean b)
+ {
+ wrapped.setTransient(b);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/ExtValBeanValidationMetaDataExtractionInterceptor.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/ExtValBeanValidationMetaDataExtractionInterceptor.java
new file mode 100644
index 0000000..4fcf70f
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/ExtValBeanValidationMetaDataExtractionInterceptor.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.interceptor;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.interceptor.MetaDataExtractionInterceptor;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.ValidationModuleAware;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.beanval.BeanValidationModuleKey;
+import org.apache.myfaces.extensions.validator.beanval.util.BeanValidationUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+
+import javax.faces.component.UIComponent;
+import java.util.Map;
+
+/**
+ * extracts and adds the extval bv meta-data (e.g. validation groups) to the ExtValBeanValidationContext
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(200)
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValBeanValidationMetaDataExtractionInterceptor
+ implements MetaDataExtractionInterceptor, ValidationModuleAware
+{
+ public void afterExtracting(PropertyInformation propertyInformation)
+ {
+ if(propertyInformation.containsInformation(PropertyInformationKeys.CUSTOM_PROPERTIES))
+ {
+ Map properties = propertyInformation.getInformation(PropertyInformationKeys.CUSTOM_PROPERTIES, Map.class);
+
+ if(properties != null && properties.containsKey(UIComponent.class.getName()))
+ {
+ UIComponent uiComponent = (UIComponent)properties.get(UIComponent.class.getName());
+ PropertyDetails propertyDetails = ExtValUtils.getPropertyDetails(propertyInformation);
+
+ processExtValBeanValidationMetaData(uiComponent, propertyDetails);
+ }
+ }
+ }
+
+ /**
+ * adds the extval bv meta-data to the ExtValBeanValidationContext
+ *
+ * @param uiComponent current component
+ * @param propertyDetails property details of the value-binding
+ */
+ private void processExtValBeanValidationMetaData(UIComponent uiComponent, PropertyDetails propertyDetails)
+ {
+ if(JsfUtils.isRenderResponsePhase())
+ {
+ BeanValidationUtils.addMetaDataToContext(uiComponent, propertyDetails, false);
+ }
+ else
+ {
+ BeanValidationUtils.addMetaDataToContext(uiComponent, propertyDetails, true);
+ }
+ }
+
+ public String[] getModuleKeys()
+ {
+ return new String[] {BeanValidationModuleKey.class.getName()};
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/ResetBeanValidationRendererInterceptor.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/ResetBeanValidationRendererInterceptor.java
new file mode 100644
index 0000000..c21d133
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/interceptor/ResetBeanValidationRendererInterceptor.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.interceptor;
+
+import org.apache.myfaces.extensions.validator.core.interceptor.AbstractRendererInterceptor;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipBeforeInterceptorsException;
+import org.apache.myfaces.extensions.validator.core.renderkit.exception.SkipRendererDelegationException;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.render.Renderer;
+import javax.faces.validator.Validator;
+import java.io.IOException;
+
+/**
+ * separated for easier sync
+ *
+ * @author Gerhard Petracek
+ * @since 2.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ResetBeanValidationRendererInterceptor extends AbstractRendererInterceptor
+{
+ @Override
+ public void beforeEncodeBegin(FacesContext facesContext, UIComponent uiComponent, Renderer wrapped)
+ throws IOException, SkipBeforeInterceptorsException, SkipRendererDelegationException
+ {
+ if(uiComponent instanceof EditableValueHolder)
+ {
+ switchBackValidators((EditableValueHolder)uiComponent);
+ }
+ }
+
+ private void switchBackValidators(EditableValueHolder editableValueHolder)
+ {
+ for(Validator validator : editableValueHolder.getValidators())
+ {
+ if(validator instanceof BeanValidatorWrapper)
+ {
+ editableValueHolder.addValidator(((BeanValidatorWrapper)validator).getWrappedBeanValidator());
+ editableValueHolder.removeValidator(validator);
+ }
+ }
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/AbstractBeanValidationMetaDataTransformer.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/AbstractBeanValidationMetaDataTransformer.java
new file mode 100644
index 0000000..1bfda0d
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/AbstractBeanValidationMetaDataTransformer.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.MetaDataTransformer;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.beanval.payload.ViolationSeverity;
+import org.apache.myfaces.extensions.validator.beanval.payload.DisableClientSideValidation;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.Payload;
+import javax.faces.application.FacesMessage;
+import java.util.Map;
+import java.util.Collections;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation({UsageCategory.REUSE})
+public abstract class AbstractBeanValidationMetaDataTransformer<T extends Annotation> implements MetaDataTransformer
+{
+ @SuppressWarnings({"unchecked"})
+ public Map<String, Object> convertMetaData(MetaDataEntry metaDataEntry)
+ {
+ ConstraintDescriptor<? extends T> constraintDescriptor = metaDataEntry.getValue(ConstraintDescriptor.class);
+
+ if(isClientSideValidationEnabled(constraintDescriptor) && isBlockingConstraint(constraintDescriptor))
+ {
+ return transformMetaData((ConstraintDescriptor<T>)constraintDescriptor);
+ }
+ return Collections.emptyMap();
+ }
+
+ protected boolean isClientSideValidationEnabled(ConstraintDescriptor<? extends T> constraintDescriptor)
+ {
+ for(Class<? extends Payload> payload : constraintDescriptor.getPayload())
+ {
+ if(ExtValUtils.getValidationParameterClassFor(DisableClientSideValidation.class).isAssignableFrom(payload))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected boolean isBlockingConstraint(ConstraintDescriptor<?> constraintDescriptor)
+ {
+ FacesMessage testMessage = new FacesMessage();
+ testMessage.setSeverity(ViolationSeverity.Error.VALUE);
+
+ for (Class<? extends Payload> payload : constraintDescriptor.getPayload())
+ {
+ if (ExtValUtils.getValidationParameterClassFor(ViolationSeverity.Warn.class).isAssignableFrom(payload))
+ {
+ testMessage.setSeverity(ViolationSeverity.Warn.VALUE);
+ }
+ else if(ExtValUtils.getValidationParameterClassFor(ViolationSeverity.Info.class).isAssignableFrom(payload))
+ {
+ testMessage.setSeverity(ViolationSeverity.Info.VALUE);
+ }
+ else if(ExtValUtils.getValidationParameterClassFor(ViolationSeverity.Fatal.class).isAssignableFrom(payload))
+ {
+ testMessage.setSeverity(ViolationSeverity.Fatal.VALUE);
+ }
+ }
+ return ExtValUtils.severityBlocksSubmitForComponentId(null, testMessage);
+ }
+ protected abstract Map<String, Object> transformMetaData(ConstraintDescriptor<T> constraintDescriptor);
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/NotNullMetaDataTransformer.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/NotNullMetaDataTransformer.java
new file mode 100644
index 0000000..2008d5a
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/NotNullMetaDataTransformer.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class NotNullMetaDataTransformer extends AbstractBeanValidationMetaDataTransformer<NotNull>
+{
+ protected Map<String, Object> transformMetaData(ConstraintDescriptor<NotNull> constraintDescriptor)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+
+ if(ExtValUtils.interpretEmptyStringValuesAsNull())
+ {
+ results.put(CommonMetaDataKeys.WEAK_REQUIRED, true);
+ }
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/StringSizeMetaDataTransformer.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/StringSizeMetaDataTransformer.java
new file mode 100644
index 0000000..4a9ff58
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/StringSizeMetaDataTransformer.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.constraints.Size;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class StringSizeMetaDataTransformer extends AbstractBeanValidationMetaDataTransformer<Size>
+{
+ protected Map<String, Object> transformMetaData(ConstraintDescriptor<Size> constraintDescriptor)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+ Size annotation = constraintDescriptor.getAnnotation();
+
+ int minimum = annotation.min();
+
+ if(minimum != 0)
+ {
+ results.put(CommonMetaDataKeys.MIN_LENGTH, minimum);
+ }
+ else
+ {
+ results.put(CommonMetaDataKeys.MIN_LENGTH_DEFAULT, minimum);
+ }
+
+ int maximum = annotation.max();
+ if(maximum != Integer.MAX_VALUE)
+ {
+ results.put(CommonMetaDataKeys.MAX_LENGTH, maximum);
+ }
+ else
+ {
+ results.put(CommonMetaDataKeys.MAX_LENGTH_DEFAULT, maximum);
+ }
+
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/AbstractBeanValidationVirtualValidationStrategyToMetaDataTransformerNameMapper.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/AbstractBeanValidationVirtualValidationStrategyToMetaDataTransformerNameMapper.java
new file mode 100644
index 0000000..40e031c
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/AbstractBeanValidationVirtualValidationStrategyToMetaDataTransformerNameMapper.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.mapper
+ .AbstractValidationStrategyToMetaDataTransformerNameMapper;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.beanval.validation.strategy.BeanValidationVirtualValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation({UsageCategory.REUSE})
+public abstract class AbstractBeanValidationVirtualValidationStrategyToMetaDataTransformerNameMapper
+ extends AbstractValidationStrategyToMetaDataTransformerNameMapper
+{
+ public final String createName(ValidationStrategy source)
+ {
+ if(isBeanValidationStrategy(source))
+ {
+ BeanValidationVirtualValidationStrategy beanValidationAdapter =
+ (BeanValidationVirtualValidationStrategy)source;
+
+ return createBeanValidationTransformerName(beanValidationAdapter);
+ }
+ return null;
+ }
+
+ private boolean isBeanValidationStrategy(ValidationStrategy source)
+ {
+ return source instanceof BeanValidationVirtualValidationStrategy;
+ }
+
+ protected abstract String createBeanValidationTransformerName(
+ BeanValidationVirtualValidationStrategy validationStrategy);
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/NotNullNameMapper.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/NotNullNameMapper.java
new file mode 100644
index 0000000..8328786
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/NotNullNameMapper.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.beanval.metadata.transformer.NotNullMetaDataTransformer;
+import org.apache.myfaces.extensions.validator.beanval.validation.strategy.BeanValidationVirtualValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.Nested;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@Nested
+@InvocationOrder(200)
+@UsageInformation({UsageCategory.INTERNAL})
+public class NotNullNameMapper extends AbstractBeanValidationVirtualValidationStrategyToMetaDataTransformerNameMapper
+{
+ protected String createBeanValidationTransformerName(BeanValidationVirtualValidationStrategy adapter)
+ {
+ if(isNotNullConstraint(adapter))
+ {
+ return NotNullMetaDataTransformer.class.getName();
+ }
+ return null;
+ }
+
+ private boolean isNotNullConstraint(BeanValidationVirtualValidationStrategy adapter)
+ {
+ return NotNull.class.getName().equals(
+ adapter.getConstraintDescriptor().getAnnotation().annotationType().getName());
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/SizeNameMapper.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/SizeNameMapper.java
new file mode 100644
index 0000000..1c890c6
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/metadata/transformer/mapper/SizeNameMapper.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.metadata.transformer.mapper;
+
+import org.apache.myfaces.extensions.validator.core.Nested;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.beanval.validation.strategy.BeanValidationVirtualValidationStrategy;
+import org.apache.myfaces.extensions.validator.beanval.metadata.transformer.StringSizeMetaDataTransformer;
+
+import javax.validation.constraints.Size;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@Nested
+@InvocationOrder(210)
+@UsageInformation({UsageCategory.INTERNAL})
+public class SizeNameMapper extends AbstractBeanValidationVirtualValidationStrategyToMetaDataTransformerNameMapper
+{
+ protected String createBeanValidationTransformerName(BeanValidationVirtualValidationStrategy adapter)
+ {
+ if(isStringSizeConstraint(adapter))
+ {
+ return StringSizeMetaDataTransformer.class.getName();
+ }
+ return null;
+ }
+
+ private boolean isStringSizeConstraint(BeanValidationVirtualValidationStrategy adapter)
+ {
+ return Size.class.getName().equals(
+ adapter.getConstraintDescriptor().getAnnotation().annotationType().getName()) &&
+ String.class.getName().equals(adapter.getElementClass().getName());
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/payload/DisableClientSideValidation.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/payload/DisableClientSideValidation.java
new file mode 100644
index 0000000..ab2d22f
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/payload/DisableClientSideValidation.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.payload;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.Payload;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface DisableClientSideValidation extends Payload
+{
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/payload/ViolationSeverity.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/payload/ViolationSeverity.java
new file mode 100644
index 0000000..2388b2d
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/payload/ViolationSeverity.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.payload;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.Payload;
+import javax.faces.application.FacesMessage;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ViolationSeverity
+{
+ interface Info extends Payload
+ {
+ FacesMessage.Severity VALUE = FacesMessage.SEVERITY_INFO;
+ }
+
+ interface Warn extends Payload
+ {
+ FacesMessage.Severity VALUE = FacesMessage.SEVERITY_WARN;
+ }
+
+ interface Error extends Payload
+ {
+ FacesMessage.Severity VALUE = FacesMessage.SEVERITY_ERROR;
+ }
+
+ interface Fatal extends Payload
+ {
+ FacesMessage.Severity VALUE = FacesMessage.SEVERITY_FATAL;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/startup/BeanValidationStartupListener.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/startup/BeanValidationStartupListener.java
new file mode 100644
index 0000000..8d269ef
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/startup/BeanValidationStartupListener.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.startup;
+
+import org.apache.myfaces.extensions.validator.beanval.BeanValidationModuleValidationInterceptor;
+import org.apache.myfaces.extensions.validator.beanval.HtmlCoreComponentsComponentInitializer;
+import org.apache.myfaces.extensions.validator.beanval.BeanAwareValidatorFactory;
+import org.apache.myfaces.extensions.validator.beanval.payload.ViolationSeverity;
+import org.apache.myfaces.extensions.validator.beanval.payload.DisableClientSideValidation;
+import org.apache.myfaces.extensions.validator.beanval.util.BeanValidationUtils;
+import org.apache.myfaces.extensions.validator.beanval.interceptor.ExtValBeanValidationMetaDataExtractionInterceptor;
+import org.apache.myfaces.extensions.validator.beanval.interceptor.BeanValidationExceptionInterceptor;
+import org.apache.myfaces.extensions.validator.beanval.validation.ModelValidationPhaseListener;
+import org.apache.myfaces.extensions.validator.beanval.metadata.transformer.mapper.SizeNameMapper;
+import org.apache.myfaces.extensions.validator.beanval.metadata.transformer.mapper.NotNullNameMapper;
+import org.apache.myfaces.extensions.validator.beanval.storage.DefaultModelValidationStorageManager;
+import org.apache.myfaces.extensions.validator.beanval.storage.ModelValidationStorage;
+import org.apache.myfaces.extensions.validator.beanval.storage.mapper.BeanValidationGroupStorageNameMapper;
+import org.apache.myfaces.extensions.validator.beanval.storage.mapper.ModelValidationStorageNameMapper;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.factory.AbstractNameMapperAwareFactory;
+import org.apache.myfaces.extensions.validator.core.factory.FactoryNames;
+import org.apache.myfaces.extensions.validator.core.startup.AbstractStartupListener;
+import org.apache.myfaces.extensions.validator.core.storage.GroupStorage;
+import org.apache.myfaces.extensions.validator.core.storage.StorageManager;
+import org.apache.myfaces.extensions.validator.core.storage.StorageManagerHolder;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+
+import javax.validation.ValidatorFactory;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class BeanValidationStartupListener extends AbstractStartupListener
+{
+ private static final long serialVersionUID = -5025748399876833394L;
+
+ protected void init()
+ {
+ registerValidatorFactory();
+ registerBeanValidationInterceptor();
+ registerMetaDataTransformerNameMapper();
+ registerGroupStorageNameMapper();
+ registerModelValidationStorageNameMapper();
+ registerComponentInitializers();
+ registerMetaDataExtractionInterceptors();
+ registerPhaseListeners();
+ registerExceptionInterceptor();
+ registerViolationSeverityPayload();
+ registerDisableClientSideValidationPayload();
+ }
+
+ protected void registerValidatorFactory()
+ {
+ ExtValContext.getContext().addGlobalProperty(ValidatorFactory.class.getName(),
+ new BeanAwareValidatorFactory(BeanValidationUtils.getDefaultValidatorFactory()), false);
+ }
+
+ protected void registerBeanValidationInterceptor()
+ {
+ ExtValContext.getContext().registerRendererInterceptor(new BeanValidationModuleValidationInterceptor());
+ }
+
+ protected void registerMetaDataTransformerNameMapper()
+ {
+ ExtValUtils.registerValidationStrategyToMetaDataTransformerNameMapper(new SizeNameMapper());
+ ExtValUtils.registerValidationStrategyToMetaDataTransformerNameMapper(new NotNullNameMapper());
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected void registerGroupStorageNameMapper()
+ {
+ StorageManager storageManager = getStorageManagerHolder().getStorageManager(GroupStorage.class);
+
+ if (storageManager instanceof AbstractNameMapperAwareFactory)
+ {
+ ((AbstractNameMapperAwareFactory<String>) storageManager)
+ .register(new BeanValidationGroupStorageNameMapper());
+ }
+ else
+ {
+ if (this.logger.isWarnEnabled())
+ {
+ this.logger.warn(storageManager.getClass().getName() +
+ " has to implement AbstractNameMapperAwareFactory " + getClass().getName() +
+ " couldn't register " + BeanValidationGroupStorageNameMapper.class.getName());
+ }
+ }
+ }
+
+ protected void registerModelValidationStorageNameMapper()
+ {
+ DefaultModelValidationStorageManager modelValidationStorageManager = new DefaultModelValidationStorageManager();
+ modelValidationStorageManager.register(new ModelValidationStorageNameMapper());
+ getStorageManagerHolder().setStorageManager(ModelValidationStorage.class, modelValidationStorageManager, false);
+ }
+
+ protected void registerComponentInitializers()
+ {
+ ExtValContext.getContext().addComponentInitializer(new HtmlCoreComponentsComponentInitializer());
+ }
+
+ protected StorageManagerHolder getStorageManagerHolder()
+ {
+ return (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.STORAGE_MANAGER_FACTORY, StorageManagerHolder.class));
+ }
+
+ protected void registerMetaDataExtractionInterceptors()
+ {
+ ExtValContext.getContext()
+ .addMetaDataExtractionInterceptor(new ExtValBeanValidationMetaDataExtractionInterceptor());
+ }
+
+ protected void registerPhaseListeners()
+ {
+ JsfUtils.registerPhaseListener(new ModelValidationPhaseListener());
+ JsfUtils.registerPhaseListener(new ModelValidationPhaseListener());
+ }
+
+ protected void registerExceptionInterceptor()
+ {
+ ExtValContext.getContext().addValidationExceptionInterceptor(new BeanValidationExceptionInterceptor());
+ }
+
+ protected void registerViolationSeverityPayload()
+ {
+ ExtValContext extValContext = ExtValContext.getContext();
+
+ extValContext.addGlobalProperty(ViolationSeverity.Info.class.getName(), ViolationSeverity.Info.class, false);
+ extValContext.addGlobalProperty(ViolationSeverity.Warn.class.getName(), ViolationSeverity.Warn.class, false);
+ extValContext.addGlobalProperty(ViolationSeverity.Fatal.class.getName(), ViolationSeverity.Fatal.class, false);
+
+ //no need to register "error" it's the default
+ }
+
+ private void registerDisableClientSideValidationPayload()
+ {
+ ExtValContext.getContext().addGlobalProperty(
+ DisableClientSideValidation.class.getName(), DisableClientSideValidation.class, false);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/startup/JSF2AwareBeanValidationStartupListener.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/startup/JSF2AwareBeanValidationStartupListener.java
new file mode 100644
index 0000000..4a694d9
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/startup/JSF2AwareBeanValidationStartupListener.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.startup;
+
+import org.apache.myfaces.extensions.validator.core.startup.AbstractStartupListener;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.beanval.interceptor.ResetBeanValidationRendererInterceptor;
+import org.apache.myfaces.extensions.validator.beanval.interceptor.BeanValidationTagAwareValidationInterceptor;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 2.x.3
+ */
+@ToDo(value = Priority.HIGH, description = "add optional web.xml param to deactivate")
+@UsageInformation(UsageCategory.INTERNAL)
+public class JSF2AwareBeanValidationStartupListener extends AbstractStartupListener
+{
+ private static final long serialVersionUID = -5025748399876833393L;
+
+ protected void init()
+ {
+ ExtValContext.getContext().registerRendererInterceptor(new ResetBeanValidationRendererInterceptor());
+ ExtValContext.getContext().addPropertyValidationInterceptor(new BeanValidationTagAwareValidationInterceptor());
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultBeanValidationGroupStorage.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultBeanValidationGroupStorage.java
new file mode 100644
index 0000000..b60376e
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultBeanValidationGroupStorage.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.storage;
+
+import org.apache.myfaces.extensions.validator.core.storage.DefaultGroupStorage;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+/**
+ * default storage implementation for bean-validation groups
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultBeanValidationGroupStorage extends DefaultGroupStorage
+{
+ @Override
+ public Class[] getGroups(String viewId, String clientId)
+ {
+ Class[] result = super.getGroups(viewId, clientId);
+
+ if(result == null)
+ {
+ //the default group will be validated automatically
+ return new Class[] {};
+ }
+
+ return result;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultModelValidationStorage.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultModelValidationStorage.java
new file mode 100644
index 0000000..2800f8b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultModelValidationStorage.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.storage;
+
+import org.apache.myfaces.extensions.validator.util.GroupUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+import javax.faces.context.FacesContext;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+/**
+ * storage implementation for model-validation entries
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultModelValidationStorage implements ModelValidationStorage
+{
+ private Map<String, List<ModelValidationEntry>> modelValidationEntries =
+ new HashMap<String, List<ModelValidationEntry>>();
+
+ private List<String> componentsOfRequest = new ArrayList<String>();
+
+ public void addModelValidationEntry(ModelValidationEntry modelValidationEntry)
+ {
+ String clientId = getCurrentClientId(modelValidationEntry);
+
+ List<ModelValidationEntry> modelValidationEntryList = resolveModelValidationEntryList(
+ modelValidationEntry, clientId);
+
+ addModelValidationEntry(modelValidationEntryList, modelValidationEntry);
+ }
+
+ private String getCurrentClientId(ModelValidationEntry modelValidationEntry)
+ {
+ String clientId = null;
+
+ if(modelValidationEntry.getComponent() != null)
+ {
+ clientId = modelValidationEntry.getComponent().getClientId(FacesContext.getCurrentInstance());
+
+ if(!this.componentsOfRequest.contains(clientId))
+ {
+ this.componentsOfRequest.add(clientId);
+ }
+ }
+ return clientId;
+ }
+
+ private List<ModelValidationEntry> resolveModelValidationEntryList(
+ ModelValidationEntry modelValidationEntry, String clientId)
+ {
+ List<ModelValidationEntry> modelValidationEntryList =
+ this.modelValidationEntries.get(GroupUtils.getGroupKey(
+ modelValidationEntry.getViewId(), clientId));
+
+ if(modelValidationEntryList == null)
+ {
+ modelValidationEntryList = new ArrayList<ModelValidationEntry>();
+ this.modelValidationEntries.put(GroupUtils.getGroupKey(
+ modelValidationEntry.getViewId(), clientId), modelValidationEntryList);
+ }
+ return modelValidationEntryList;
+ }
+
+ private void addModelValidationEntry(
+ List<ModelValidationEntry> modelValidationEntryList, ModelValidationEntry modelValidationEntry)
+ {
+ if(!modelValidationEntryList.contains(modelValidationEntry))
+ {
+ modelValidationEntryList.add(modelValidationEntry);
+ }
+ }
+
+ public List<ModelValidationEntry> getModelValidationEntriesToValidate()
+ {
+ String viewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();
+ List<ModelValidationEntry> result = new ArrayList<ModelValidationEntry>();
+
+ addEntriesForComponents(viewId, result);
+
+ addEntriesForPage(viewId, result);
+
+ return result;
+ }
+
+ private void addEntriesForComponents(String viewId, List<ModelValidationEntry> result)
+ {
+ for(String currentClientId : this.componentsOfRequest)
+ {
+ result.addAll(getModelValidationEntries(viewId, currentClientId));
+ }
+ }
+
+ private void addEntriesForPage(String viewId, List<ModelValidationEntry> result)
+ {
+ result.addAll(getModelValidationEntries(viewId));
+ }
+
+ private List<ModelValidationEntry> buildModelValidationEntryList(
+ String key, Map<String, List<ModelValidationEntry>> groupStorage)
+ {
+ List<ModelValidationEntry> list;
+
+ if(key != null && key.endsWith("*"))
+ {
+ list = new ArrayList<ModelValidationEntry>();
+ for(Map.Entry<String,List<ModelValidationEntry>> entry : groupStorage.entrySet())
+ {
+ if(entry.getKey().substring(0, entry.getKey().indexOf("@"))
+ .equals(key.substring(0, key.indexOf("@"))))
+ {
+ list.addAll(entry.getValue());
+ }
+ }
+ return list;
+ }
+
+ list = groupStorage.get(key);
+ return (list != null) ? list : new ArrayList<ModelValidationEntry>();
+ }
+
+ private List<ModelValidationEntry> getModelValidationEntries(String viewId)
+ {
+ return getModelValidationEntries(viewId, null);
+ }
+
+ private List<ModelValidationEntry> getModelValidationEntries(String viewId, String clientId)
+ {
+ if(this.modelValidationEntries.size() < 1)
+ {
+ return new ArrayList<ModelValidationEntry>();
+ }
+
+ //add found groups
+ String key;
+ List<ModelValidationEntry> resultListForPage = null;
+
+ if(!"*".equals(clientId))
+ {
+ key = GroupUtils.getGroupKey(viewId, null);
+ resultListForPage =
+ buildModelValidationEntryList(key, this.modelValidationEntries);
+ }
+
+ key = GroupUtils.getGroupKey(viewId, clientId);
+ List<ModelValidationEntry> resultListForComponent =
+ buildModelValidationEntryList(key, this.modelValidationEntries);
+
+ if(resultListForPage == null || resultListForPage.isEmpty())
+ {
+ return resultListForComponent;
+ }
+ else if(resultListForComponent.isEmpty())
+ {
+ return resultListForPage;
+ }
+
+ return mergeResults(resultListForPage, resultListForComponent);
+ }
+
+ private List<ModelValidationEntry> mergeResults(
+ List<ModelValidationEntry> resultListForPage, List<ModelValidationEntry> resultListForComponent)
+ {
+ List<ModelValidationEntry> mergedResult = new ArrayList<ModelValidationEntry>();
+ mergedResult.addAll(resultListForPage);
+ mergedResult.addAll(resultListForComponent);
+ return mergedResult;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultModelValidationStorageManager.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultModelValidationStorageManager.java
new file mode 100644
index 0000000..1831012
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/DefaultModelValidationStorageManager.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.storage;
+
+import org.apache.myfaces.extensions.validator.core.storage.StorageManager;
+import org.apache.myfaces.extensions.validator.core.storage.AbstractRequestScopeAwareStorageManager;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+/**
+ * default storage-manager for model-validation entries
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultModelValidationStorageManager
+ extends AbstractRequestScopeAwareStorageManager<ModelValidationStorage>
+{
+ public String getStorageManagerKey()
+ {
+ return StorageManager.class.getName() + "_FOR_MODEL_VALIDATION:KEY";
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/ModelValidationEntry.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/ModelValidationEntry.java
new file mode 100644
index 0000000..a78a8f3
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/ModelValidationEntry.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.API;
+import org.apache.myfaces.extensions.validator.beanval.annotation.ModelValidation;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(API)
+public class ModelValidationEntry
+{
+ private UIComponent component;
+ private List<Class> groups = new ArrayList<Class>();
+ private List<Object> validationTargets = new ArrayList<Object>();
+ private boolean displayMessageInline = false;
+ private String customMessage = ModelValidation.DEFAULT;
+
+ //the original source where the extval-bv meta-data has been found
+ private Object metaDataSourceObject;
+ private String viewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();
+
+ public void addGroup(Class group)
+ {
+ if(!this.groups.contains(group))
+ {
+ if(!(this.groups instanceof ArrayList))
+ {
+ List<Class> newGroupList = new ArrayList<Class>();
+
+ for(Class currentClass : this.groups)
+ {
+ newGroupList.add(currentClass);
+ }
+ this.groups = newGroupList;
+ }
+
+ this.groups.add(group);
+ }
+ }
+
+ public void removeGroup(Class group)
+ {
+ this.groups.remove(group);
+ }
+
+ public void addValidationTarget(Object target)
+ {
+ if(!this.validationTargets.contains(target))
+ {
+ if(!(this.validationTargets instanceof ArrayList))
+ {
+ List<Object> validationTargetList = new ArrayList<Object>();
+
+ for(Object currentTarget : this.validationTargets)
+ {
+ validationTargetList.add(currentTarget);
+ }
+ this.validationTargets = validationTargetList;
+ }
+
+ this.validationTargets.add(target);
+ }
+ }
+
+ /*
+ * generated
+ */
+ public UIComponent getComponent()
+ {
+ return component;
+ }
+
+ public void setComponent(UIComponent component)
+ {
+ this.component = component;
+ }
+
+ public Class[] getGroups()
+ {
+ return this.groups.toArray(new Class[this.groups.size()]);
+ }
+
+ public void setGroups(List<Class> groups)
+ {
+ this.groups = groups;
+ }
+
+ public List<Object> getValidationTargets()
+ {
+ return validationTargets;
+ }
+
+ public Object getMetaDataSourceObject()
+ {
+ return metaDataSourceObject;
+ }
+
+ public void setMetaDataSourceObject(Object metaDataSourceObject)
+ {
+ this.metaDataSourceObject = metaDataSourceObject;
+ }
+
+ @SuppressWarnings({"RedundantIfStatement"})
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ ModelValidationEntry that = (ModelValidationEntry) o;
+
+ if (component != null ? !component.equals(that.component) : that.component != null)
+ {
+ return false;
+ }
+ if (!groups.equals(that.groups))
+ {
+ return false;
+ }
+ if (!validationTargets.equals(that.validationTargets))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean isDisplayMessageInline()
+ {
+ return displayMessageInline;
+ }
+
+ public void setDisplayMessageInline(boolean displayMessageInline)
+ {
+ this.displayMessageInline = displayMessageInline;
+ }
+
+ public String getCustomMessage()
+ {
+ return customMessage;
+ }
+
+ public void setCustomMessage(String customMessage)
+ {
+ this.customMessage = customMessage;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = component != null ? component.hashCode() : 0;
+ result = 31 * result + groups.hashCode();
+ result = 31 * result + validationTargets.hashCode();
+ return result;
+ }
+
+ public String getViewId()
+ {
+ return viewId;
+ }
+
+ public void setViewId(String viewId)
+ {
+ this.viewId = viewId;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/ModelValidationStorage.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/ModelValidationStorage.java
new file mode 100644
index 0000000..6dbdf93
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/ModelValidationStorage.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.List;
+
+/**
+ * suggested interface for a model-validation storage
+ * <p/>
+ * it allows to manage model-validation-entries for the current request
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.API)
+public interface ModelValidationStorage
+{
+ void addModelValidationEntry(ModelValidationEntry modelValidationEntry);
+
+ List<ModelValidationEntry> getModelValidationEntriesToValidate();
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/mapper/BeanValidationGroupStorageNameMapper.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/mapper/BeanValidationGroupStorageNameMapper.java
new file mode 100644
index 0000000..4ec2e39
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/mapper/BeanValidationGroupStorageNameMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.beanval.annotation.BeanValidation;
+import org.apache.myfaces.extensions.validator.beanval.storage.DefaultBeanValidationGroupStorage;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(200)
+@UsageInformation(INTERNAL)
+public class BeanValidationGroupStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String key)
+ {
+ return (BeanValidation.class.getName().equals(key)) ?
+ DefaultBeanValidationGroupStorage.class.getName() : null;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/mapper/ModelValidationStorageNameMapper.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/mapper/ModelValidationStorageNameMapper.java
new file mode 100644
index 0000000..ba62050
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/storage/mapper/ModelValidationStorageNameMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.beanval.annotation.ModelValidation;
+import org.apache.myfaces.extensions.validator.beanval.storage.DefaultModelValidationStorage;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(200)
+@UsageInformation(INTERNAL)
+public class ModelValidationStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String key)
+ {
+ return (ModelValidation.class.getName().equals(key)) ?
+ DefaultModelValidationStorage.class.getName() : null;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/BeanValidationUtils.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/BeanValidationUtils.java
new file mode 100644
index 0000000..b76d173
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/BeanValidationUtils.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.beanval.storage.ModelValidationEntry;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.validation.message.FacesMessageHolder;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import javax.validation.ConstraintViolation;
+import javax.validation.ValidatorFactory;
+import javax.validation.Validation;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class BeanValidationUtils
+{
+ private static final Log LOGGER = LogFactory.getLog(BeanValidationUtils.class);
+ private static ExtValBeanValidationMetaDataInternals bvmi = new ExtValBeanValidationMetaDataInternals(LOGGER);
+ private static final String VALIDATOR_FACTORY_KEY = "javax.faces.validator.beanValidator.ValidatorFactory";
+
+ public static void addMetaDataToContext(
+ UIComponent component, PropertyDetails propertyDetails, boolean processModelValidation)
+ {
+ String[] key = propertyDetails.getKey().split("\\.");
+
+ Object firstBean = ExtValUtils.getELHelper().getBean(key[0]);
+
+ List<Class> foundGroupsForPropertyValidation = new ArrayList<Class>();
+ List<Class> restrictedGroupsForPropertyValidation = new ArrayList<Class>();
+ List<ModelValidationEntry> modelValidationEntryList = new ArrayList<ModelValidationEntry>();
+ List<Class> restrictedGroupsForModelValidation = new ArrayList<Class>();
+
+ bvmi.extractExtValBeanValidationMetaData(propertyDetails,
+ processModelValidation,
+ key,
+ firstBean,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation);
+
+ bvmi.processExtValBeanValidationMetaData(component,
+ propertyDetails,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation);
+ }
+
+ public static void processConstraintViolations(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object convertedObject,
+ Set<ConstraintViolation> violations)
+ {
+ List<FacesMessageHolder> facesMessageHolderList = new ArrayList<FacesMessageHolder>();
+
+ FacesMessage facesMessage;
+ for (ConstraintViolation violation : violations)
+ {
+ facesMessage = createFacesMessageForConstraintViolation(uiComponent, convertedObject, violation);
+
+ if (facesMessage == null)
+ {
+ continue;
+ }
+
+ bvmi.processFacesMessage(facesContext, uiComponent, facesMessageHolderList, facesMessage);
+ }
+
+ processViolationMessages(facesMessageHolderList);
+ }
+
+ public static FacesMessage createFacesMessageForConstraintViolation(UIComponent uiComponent,
+ Object convertedObject,
+ ConstraintViolation violation)
+ {
+ String violationMessage = violation.getMessage();
+
+ String labeledMessageSummary = bvmi.createLabeledMessage(violationMessage, false);
+ String labeledMessageDetail = bvmi.createLabeledMessage(violationMessage, true);
+
+ FacesMessage.Severity severity = bvmi.calcSeverity(violation);
+
+ ValidatorException validatorException = bvmi
+ .createValidatorException(labeledMessageSummary, labeledMessageDetail, severity);
+
+ if (!bvmi.executeAfterThrowingInterceptors(uiComponent, convertedObject, validatorException))
+ {
+ return null;
+ }
+
+ if (bvmi.isMessageTextUnchanged(validatorException, labeledMessageSummary, labeledMessageDetail))
+ {
+ return ExtValUtils.createFacesMessage(severity, violationMessage, violationMessage);
+ }
+ else
+ {
+ return ExtValUtils.createFacesMessage(severity,
+ validatorException.getFacesMessage().getSummary(),
+ validatorException.getFacesMessage().getDetail());
+ }
+ }
+
+ public static void processViolationMessages(List<FacesMessageHolder> violationMessageHolderList)
+ {
+ if (violationMessageHolderList == null || violationMessageHolderList.isEmpty())
+ {
+ return;
+ }
+
+ List<FacesMessageHolder> facesMessageListWithLowSeverity =
+ bvmi.getFacesMessageListWithLowSeverity(violationMessageHolderList);
+ List<FacesMessageHolder> facesMessageListWithHighSeverity =
+ bvmi.getFacesMessageListWithHighSeverity(violationMessageHolderList);
+
+ bvmi.addMessages(facesMessageListWithHighSeverity);
+ bvmi.addMessages(facesMessageListWithLowSeverity);
+ }
+
+ public static ValidatorFactory getDefaultValidatorFactory()
+ {
+ Map<String, Object> applicationMap = FacesContext.getCurrentInstance().getExternalContext().getApplicationMap();
+ ValidatorFactory validatorFactory = null;
+
+ if (applicationMap.containsKey(VALIDATOR_FACTORY_KEY))
+ {
+ if (applicationMap.get(VALIDATOR_FACTORY_KEY) instanceof ValidatorFactory)
+ {
+ validatorFactory = (ValidatorFactory) applicationMap.get(VALIDATOR_FACTORY_KEY);
+ }
+ }
+
+ if (validatorFactory == null)
+ {
+ validatorFactory = Validation.buildDefaultValidatorFactory();
+ applicationMap.put(VALIDATOR_FACTORY_KEY, validatorFactory);
+ }
+ return validatorFactory;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/ExtValBeanValidationMetaDataInternals.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/ExtValBeanValidationMetaDataInternals.java
new file mode 100644
index 0000000..1b21894
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/ExtValBeanValidationMetaDataInternals.java
@@ -0,0 +1,668 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.myfaces.extensions.validator.beanval.ExtValBeanValidationContext;
+import org.apache.myfaces.extensions.validator.beanval.payload.ViolationSeverity;
+import org.apache.myfaces.extensions.validator.beanval.annotation.BeanValidation;
+import org.apache.myfaces.extensions.validator.beanval.annotation.ModelValidation;
+import org.apache.myfaces.extensions.validator.beanval.annotation.extractor.DefaultGroupControllerScanningExtractor;
+import org.apache.myfaces.extensions.validator.beanval.storage.ModelValidationEntry;
+import org.apache.myfaces.extensions.validator.core.el.ELHelper;
+import org.apache.myfaces.extensions.validator.core.el.ValueBindingExpression;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.validation.message.FacesMessageHolder;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import javax.validation.ConstraintViolation;
+import javax.validation.Payload;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class ExtValBeanValidationMetaDataInternals
+{
+ private Log logger;
+ private LabeledMessageInternals labeledMessageInternals = new LabeledMessageInternals();
+
+ ExtValBeanValidationMetaDataInternals(Log logger)
+ {
+ this.logger = logger;
+ }
+
+ void extractExtValBeanValidationMetaData(PropertyDetails propertyDetails,
+ boolean processModelValidation,
+ String[] key,
+ Object firstBean,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation)
+ {
+ inspectFirstBean(processModelValidation,
+ firstBean,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation);
+
+ inspectFirstProperty(processModelValidation,
+ key,
+ firstBean,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ key.length == 2);
+
+ inspectBaseOfProperty(propertyDetails,
+ processModelValidation,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation);
+
+ inspectLastProperty(propertyDetails,
+ processModelValidation,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation);
+ }
+
+ void processExtValBeanValidationMetaData(UIComponent component,
+ PropertyDetails propertyDetails,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation)
+ {
+ ExtValBeanValidationContext extValBeanValidationContext = ExtValBeanValidationContext.getCurrentInstance();
+ String currentViewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();
+
+ String clientId = component.getClientId(FacesContext.getCurrentInstance());
+
+ processFoundGroups(extValBeanValidationContext, currentViewId, clientId,
+ foundGroupsForPropertyValidation);
+
+ processRestrictedGroups(extValBeanValidationContext, currentViewId, clientId,
+ restrictedGroupsForPropertyValidation);
+
+ initModelValidation(extValBeanValidationContext, component, propertyDetails,
+ modelValidationEntryList, restrictedGroupsForModelValidation);
+ }
+
+ private void inspectFirstBean(boolean processModelValidation,
+ Object firstBean,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation)
+ {
+ processClass(firstBean,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+ }
+
+ private void inspectFirstProperty(boolean processModelValidation,
+ String[] key,
+ Object firstBean,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation,
+ boolean isLastProperty)
+ {
+ processFieldsAndProperties(key[0] + "." + key[1],
+ firstBean,
+ key[1],
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation,
+ isLastProperty);
+ }
+
+ private void inspectBaseOfProperty(PropertyDetails propertyDetails,
+ boolean processModelValidation,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation)
+ {
+ processClass(propertyDetails.getBaseObject(),
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+ }
+
+ private void inspectLastProperty(PropertyDetails propertyDetails,
+ boolean processModelValidation,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation)
+ {
+ processFieldsAndProperties(
+ propertyDetails.getKey(),
+ propertyDetails.getBaseObject(),
+ propertyDetails.getProperty(),
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation,
+ true);
+ }
+
+ private void processClass(Object objectToInspect,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation,
+ boolean processModelValidation)
+ {
+ Class classToInspect = ProxyUtils.getUnproxiedClass(objectToInspect.getClass());
+
+ while (!Object.class.getName().equals(classToInspect.getName()))
+ {
+ transferGroupValidationInformationToFoundGroups(objectToInspect,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+
+ processInterfaces(objectToInspect.getClass(), objectToInspect,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+
+ classToInspect = classToInspect.getSuperclass();
+ }
+ }
+
+ private void processFieldsAndProperties(String key,
+ Object base,
+ String property,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation,
+ boolean processModelValidation,
+ boolean isLastProperty)
+ {
+ PropertyInformation propertyInformation = new DefaultGroupControllerScanningExtractor()
+ .extract(FacesContext.getCurrentInstance(), new PropertyDetails(key, base, property));
+
+ for (MetaDataEntry metaDataEntry : propertyInformation.getMetaDataEntries())
+ {
+ if (metaDataEntry.getValue() instanceof BeanValidation)
+ {
+ tryToProcessMetaData((BeanValidation) metaDataEntry.getValue(),
+ tryToCreateNewTarget(base, property, isLastProperty),
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+ }
+ else if (metaDataEntry.getValue() instanceof BeanValidation.List)
+ {
+ for (BeanValidation currentBeanValidation : ((BeanValidation.List) metaDataEntry.getValue()).value())
+ {
+ tryToProcessMetaData(currentBeanValidation,
+ tryToCreateNewTarget(base, property, isLastProperty),
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+ }
+ }
+ }
+ }
+
+ private Object tryToCreateNewTarget(Object base, String property, boolean isLastProperty)
+ {
+ if(isLastProperty)
+ {
+ return base;
+ }
+
+ Object result = getValueOfProperty(base, property);
+
+ if (result == null)
+ {
+ return base;
+ }
+
+ return result;
+ }
+
+ private Object getValueOfProperty(Object base, String property)
+ {
+ property = property.substring(0, 1).toUpperCase() + property.substring(1, property.length());
+
+ Class targetClass = ProxyUtils.getUnproxiedClass(base.getClass());
+
+ Method targetMethod = ReflectionUtils.tryToGetMethod(targetClass, "get" + property);
+
+ if (targetMethod == null)
+ {
+ targetMethod = ReflectionUtils.tryToGetMethod(targetClass, "is" + property);
+ }
+
+ if (targetMethod == null)
+ {
+ throw new IllegalStateException(
+ "class " + targetClass + " has no public get/is " + property.toLowerCase());
+ }
+ return ReflectionUtils.tryToInvokeMethod(base, targetMethod);
+ }
+
+ private void processFoundGroups(ExtValBeanValidationContext extValBeanValidationContext,
+ String currentViewId,
+ String clientId,
+ List<Class> foundGroupsForPropertyValidation)
+ {
+ /*
+ * add found groups to context
+ */
+ for (Class currentGroupClass : foundGroupsForPropertyValidation)
+ {
+ extValBeanValidationContext.addGroup(currentGroupClass, currentViewId, clientId);
+ }
+ }
+
+ private void processRestrictedGroups(ExtValBeanValidationContext extValBeanValidationContext,
+ String currentViewId,
+ String clientId,
+ List<Class> restrictedGroupsForPropertyValidation)
+ {
+ /*
+ * add restricted groups
+ */
+ for (Class currentGroupClass : restrictedGroupsForPropertyValidation)
+ {
+ extValBeanValidationContext.restrictGroup(currentGroupClass, currentViewId, clientId);
+ }
+ }
+
+ private void initModelValidation(ExtValBeanValidationContext extValBeanValidationContext,
+ UIComponent component,
+ PropertyDetails propertyDetails,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation)
+ {
+ /*
+ * add model validation entry list
+ */
+ for (ModelValidationEntry modelValidationEntry : modelValidationEntryList)
+ {
+ for (Class restrictedGroup : restrictedGroupsForModelValidation)
+ {
+ modelValidationEntry.removeGroup(restrictedGroup);
+ }
+
+ if (modelValidationEntry.getGroups().length > 0)
+ {
+ if (modelValidationEntry.getValidationTargets().isEmpty())
+ {
+ modelValidationEntry.addValidationTarget(propertyDetails.getBaseObject());
+ }
+ modelValidationEntry.setComponent(component);
+ extValBeanValidationContext.addModelValidationEntry(modelValidationEntry);
+ }
+ }
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "test proxy support")
+ private void transferGroupValidationInformationToFoundGroups(
+ Object objectToInspect,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation,
+ boolean processModelValidation)
+ {
+ if (objectToInspect.getClass().isAnnotationPresent(BeanValidation.class))
+ {
+ tryToProcessMetaData(objectToInspect.getClass().getAnnotation(BeanValidation.class),
+ objectToInspect,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+ }
+ else if (objectToInspect.getClass().isAnnotationPresent(BeanValidation.List.class))
+ {
+ for (BeanValidation currentBeanValidation :
+ (objectToInspect.getClass().getAnnotation(BeanValidation.List.class)).value())
+ {
+ tryToProcessMetaData(currentBeanValidation,
+ objectToInspect,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+ }
+ }
+ }
+
+ private void processInterfaces(Class currentClass,
+ Object metaDataSourceObject,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation,
+ boolean processModelValidation)
+ {
+ for (Class currentInterface : currentClass.getInterfaces())
+ {
+ transferGroupValidationInformationToFoundGroups(metaDataSourceObject,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+
+ processInterfaces(currentInterface, metaDataSourceObject,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+ }
+ }
+
+ private void tryToProcessMetaData(BeanValidation beanValidation,
+ Object metaDataSourceObject,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation,
+ boolean processModelValidation)
+ {
+ for (String currentViewId : beanValidation.viewIds())
+ {
+ if (useMetaDataForViewId(beanValidation, currentViewId))
+ {
+ processMetaData(beanValidation,
+ metaDataSourceObject,
+ foundGroupsForPropertyValidation,
+ restrictedGroupsForPropertyValidation,
+ modelValidationEntryList,
+ restrictedGroupsForModelValidation,
+ processModelValidation);
+ break;
+ }
+ }
+ }
+
+ private boolean useMetaDataForViewId(BeanValidation beanValidation, String currentViewId)
+ {
+ return (currentViewId.equals(FacesContext.getCurrentInstance().getViewRoot().getViewId()) ||
+ currentViewId.equals("*")) && isValidationPermitted(beanValidation);
+ }
+
+ private void processMetaData(BeanValidation beanValidation,
+ Object metaDataSourceObject,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation,
+ boolean processModelValidation)
+ {
+ if (processModelValidation && isModelValidation(beanValidation))
+ {
+ addModelValidationEntry(
+ beanValidation, metaDataSourceObject,
+ modelValidationEntryList, restrictedGroupsForModelValidation);
+ }
+ else if (!isModelValidation(beanValidation))
+ {
+ processGroups(
+ beanValidation, foundGroupsForPropertyValidation, restrictedGroupsForPropertyValidation);
+ }
+ }
+
+ private boolean isValidationPermitted(BeanValidation beanValidation)
+ {
+ ELHelper elHelper = ExtValUtils.getELHelper();
+
+ for (String condition : beanValidation.conditions())
+ {
+ if (elHelper.isELTermWellFormed(condition) &&
+ elHelper.isELTermValid(FacesContext.getCurrentInstance(), condition))
+ {
+ if (Boolean.TRUE.equals(elHelper.getValueOfExpression(
+ FacesContext.getCurrentInstance(), new ValueBindingExpression(condition))))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if (this.logger.isErrorEnabled())
+ {
+ this.logger.error("an invalid condition is used: " + condition);
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isModelValidation(BeanValidation beanValidation)
+ {
+ return beanValidation.modelValidation().isActive();
+ }
+
+ private void addModelValidationEntry(BeanValidation beanValidation,
+ Object metaDataSourceObject,
+ List<ModelValidationEntry> modelValidationEntryList,
+ List<Class> restrictedGroupsForModelValidation)
+ {
+ ModelValidationEntry modelValidationEntry = new ModelValidationEntry();
+
+ modelValidationEntry.setGroups(Arrays.asList(beanValidation.useGroups()));
+ modelValidationEntry.setDisplayMessageInline(beanValidation.modelValidation().displayInline());
+ modelValidationEntry.setCustomMessage(beanValidation.modelValidation().message());
+ modelValidationEntry.setMetaDataSourceObject(metaDataSourceObject);
+
+ Object validationTarget;
+ for (String validationTargetExpression : beanValidation.modelValidation().validationTargets())
+ {
+ if (ModelValidation.DEFAULT.equals(validationTargetExpression))
+ {
+ continue;
+ }
+
+ validationTarget = tryToResolveValidationTargetExpression(validationTargetExpression);
+ if (validationTarget != null)
+ {
+ modelValidationEntry.addValidationTarget(validationTarget);
+ }
+ }
+
+ if (beanValidation.restrictGroups().length > 0)
+ {
+ restrictedGroupsForModelValidation.addAll(Arrays.asList(beanValidation.restrictGroups()));
+ }
+
+ if (modelValidationEntry.getValidationTargets().isEmpty())
+ {
+ modelValidationEntry.addValidationTarget(metaDataSourceObject);
+ }
+
+ modelValidationEntryList.add(modelValidationEntry);
+ }
+
+ private Object tryToResolveValidationTargetExpression(String validationTargetExpression)
+ {
+ ValueBindingExpression valueBindingExpression = new ValueBindingExpression(validationTargetExpression);
+ return ExtValUtils.getELHelper()
+ .getValueOfExpression(FacesContext.getCurrentInstance(), valueBindingExpression);
+ }
+
+ private void processGroups(BeanValidation beanValidation,
+ List<Class> foundGroupsForPropertyValidation,
+ List<Class> restrictedGroupsForPropertyValidation)
+ {
+ foundGroupsForPropertyValidation.addAll(Arrays.asList(beanValidation.useGroups()));
+
+ if (beanValidation.restrictGroups().length > 0)
+ {
+ restrictedGroupsForPropertyValidation.addAll(Arrays.asList(beanValidation.restrictGroups()));
+ }
+ }
+
+ String createLabeledMessage(String violationMessage, boolean isDetailMessage)
+ {
+ return this.labeledMessageInternals.createLabeledMessage(violationMessage, isDetailMessage);
+ }
+
+ FacesMessage.Severity calcSeverity(ConstraintViolation<?> violation)
+ {
+ for (Class<? extends Payload> payload : violation.getConstraintDescriptor().getPayload())
+ {
+ if (ExtValUtils.getValidationParameterClassFor(ViolationSeverity.Warn.class).isAssignableFrom(payload))
+ {
+ return FacesMessage.SEVERITY_WARN;
+ }
+ else if (ExtValUtils
+ .getValidationParameterClassFor(ViolationSeverity.Info.class).isAssignableFrom(payload))
+ {
+ return FacesMessage.SEVERITY_INFO;
+ }
+ else if (ExtValUtils
+ .getValidationParameterClassFor(ViolationSeverity.Fatal.class).isAssignableFrom(payload))
+ {
+ return FacesMessage.SEVERITY_FATAL;
+ }
+ }
+ return FacesMessage.SEVERITY_ERROR;
+ }
+
+ void processFacesMessage(FacesContext facesContext, UIComponent uiComponent,
+ List<FacesMessageHolder> facesMessageHolderList, FacesMessage facesMessage)
+ {
+ FacesMessageHolder facesMessageHolder = new FacesMessageHolder(facesMessage);
+
+ facesMessageHolder.setClientId(uiComponent.getClientId(facesContext));
+
+ facesMessageHolderList.add(facesMessageHolder);
+ }
+
+ boolean executeAfterThrowingInterceptors(UIComponent uiComponent,
+ Object convertedObject,
+ ValidatorException validatorException)
+ {
+ return ExtValUtils.executeAfterThrowingInterceptors(
+ uiComponent,
+ null,
+ convertedObject,
+ validatorException,
+ null);
+ }
+
+ boolean isMessageTextUnchanged(
+ ValidatorException validatorException, String violationSummaryMessage, String violationDetailMessage)
+ {
+ return violationSummaryMessage.equals(validatorException.getFacesMessage().getSummary()) &&
+ violationDetailMessage.equals(validatorException.getFacesMessage().getDetail());
+ }
+
+ ValidatorException createValidatorException(
+ String violationSummaryMessage, String violationDetailMessage, FacesMessage.Severity severity)
+ {
+ return new ValidatorException(
+ ExtValUtils.createFacesMessage(severity, violationSummaryMessage, violationDetailMessage));
+ }
+
+ List<FacesMessageHolder> getFacesMessageListWithLowSeverity(
+ List<FacesMessageHolder> violationMessages)
+ {
+ List<FacesMessageHolder> result = new ArrayList<FacesMessageHolder>();
+
+ for (FacesMessageHolder facesMessageHolder : violationMessages)
+ {
+ if (FacesMessage.SEVERITY_WARN.equals(facesMessageHolder.getFacesMessage().getSeverity()) ||
+ FacesMessage.SEVERITY_INFO.equals(facesMessageHolder.getFacesMessage().getSeverity()))
+ {
+ result.add(facesMessageHolder);
+ }
+ }
+ return result;
+ }
+
+ List<FacesMessageHolder> getFacesMessageListWithHighSeverity(
+ List<FacesMessageHolder> violationMessageHolderList)
+ {
+ List<FacesMessageHolder> result = new ArrayList<FacesMessageHolder>();
+
+ for (FacesMessageHolder facesMessageHolder : violationMessageHolderList)
+ {
+ if (FacesMessage.SEVERITY_ERROR.equals(facesMessageHolder.getFacesMessage().getSeverity()) ||
+ FacesMessage.SEVERITY_FATAL.equals(facesMessageHolder.getFacesMessage().getSeverity()))
+ {
+ result.add(facesMessageHolder);
+ }
+ }
+ return result;
+ }
+
+ void addMessages(List<FacesMessageHolder> facesMessageHolderListWithLowSeverity)
+ {
+ for (FacesMessageHolder facesMessageHolder : facesMessageHolderListWithLowSeverity)
+ {
+ ExtValUtils.tryToAddViolationMessageForComponentId(
+ facesMessageHolder.getClientId(), facesMessageHolder.getFacesMessage());
+ }
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/LabeledMessageInternals.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/LabeledMessageInternals.java
new file mode 100644
index 0000000..f40b783
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/util/LabeledMessageInternals.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.util;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+
+import java.util.MissingResourceException;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class LabeledMessageInternals
+{
+ //there is no concurrency issue here - it always leads to the same result
+ private final String defaultSummaryMessageTemplate = "{1}: {0}";
+ private final String defaultDetailMessageTemplate = "{1}: {0}";
+ private String summaryMessageTemplate = defaultSummaryMessageTemplate;
+ private String detailMessageTemplate = defaultDetailMessageTemplate;
+ private static final String JAVAX_FACES_VALIDATOR_BEANVALIDATOR_MESSAGE =
+ "javax.faces.validator.BeanValidator.MESSAGE";
+ private static final String JAVAX_FACES_VALIDATOR_BEANVALIDATOR_MESSAGE_DETAIL =
+ "javax.faces.validator.BeanValidator.MESSAGE_detail";
+
+ String createLabeledMessage(String violationMessage, boolean isDetailMessage)
+ {
+ if(isDetailMessage)
+ {
+ return tryToResolveDetailMessage(violationMessage);
+ }
+ else
+ {
+ return tryToResolveSummaryMessage(violationMessage);
+ }
+ }
+
+ private String tryToResolveSummaryMessage(String violationMessage)
+ {
+ if(summaryMessageTemplate == null)
+ {
+ return this.defaultSummaryMessageTemplate.replace("{0}", violationMessage);
+ }
+
+ this.summaryMessageTemplate = loadStandardMessageTemplate(false);
+
+ if(summaryMessageTemplate == null)
+ {
+ return createLabeledMessage(violationMessage, false);
+ }
+ return summaryMessageTemplate.replace("{0}", violationMessage);
+ }
+
+ private String tryToResolveDetailMessage(String violationMessage)
+ {
+ if(detailMessageTemplate == null)
+ {
+ return this.defaultDetailMessageTemplate.replace("{0}", violationMessage);
+ }
+
+ this.detailMessageTemplate = loadStandardMessageTemplate(true);
+
+ if(detailMessageTemplate == null)
+ {
+ return createLabeledMessage(violationMessage, true);
+ }
+ return detailMessageTemplate.replace("{0}", violationMessage);
+ }
+
+ private String loadStandardMessageTemplate(boolean isDetailMessage)
+ {
+ try
+ {
+ if(isDetailMessage)
+ {
+ return JsfUtils.getMessageFromApplicationMessageBundle(
+ JAVAX_FACES_VALIDATOR_BEANVALIDATOR_MESSAGE_DETAIL);
+ }
+ else
+ {
+ return JsfUtils.getMessageFromApplicationMessageBundle(
+ JAVAX_FACES_VALIDATOR_BEANVALIDATOR_MESSAGE);
+ }
+ }
+ catch (MissingResourceException e)
+ {
+ return null;
+ }
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationPhaseListener.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationPhaseListener.java
new file mode 100644
index 0000000..0dc2895
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationPhaseListener.java
@@ -0,0 +1,479 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.validation;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.beanval.BeanValidationModuleKey;
+import org.apache.myfaces.extensions.validator.beanval.ExtValBeanValidationContext;
+import org.apache.myfaces.extensions.validator.beanval.annotation.ModelValidation;
+import org.apache.myfaces.extensions.validator.beanval.storage.ModelValidationEntry;
+import org.apache.myfaces.extensions.validator.beanval.util.BeanValidationUtils;
+import org.apache.myfaces.extensions.validator.core.property.DefaultPropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.validation.message.FacesMessageHolder;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.validation.ConstraintViolation;
+import javax.validation.MessageInterpolator;
+import javax.validation.Path;
+import javax.validation.ValidatorFactory;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@ToDo(value = Priority.MEDIUM, description = "refactor implementation details")
+@UsageInformation(UsageCategory.INTERNAL)
+public class ModelValidationPhaseListener implements PhaseListener
+{
+ private static final long serialVersionUID = -3482233893186708878L;
+
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public void afterPhase(PhaseEvent phaseEvent)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("jsr303 start model validation");
+ }
+
+ Map<Object, List<Class>> processedValidationTargets = new HashMap<Object, List<Class>>();
+
+ Map<String, ModelValidationResult> results = new HashMap<String, ModelValidationResult>();
+
+ for (ModelValidationEntry modelValidationEntry : getModelValidationEntriesToValidate())
+ {
+ processModelValidation(modelValidationEntry, processedValidationTargets, results);
+ }
+
+ processModelValidationResults(results);
+
+ executeGlobalAfterValidationInterceptorsFor(results);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("jsr303 validation finished");
+ }
+ }
+
+ private List<ModelValidationEntry> getModelValidationEntriesToValidate()
+ {
+ return ExtValBeanValidationContext.getCurrentInstance().getModelValidationEntriesToValidate();
+ }
+
+ private void processModelValidation(ModelValidationEntry modelValidationEntry,
+ Map<Object, List<Class>> processedValidationTargets,
+ Map<String, ModelValidationResult> results)
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ PropertyInformation propertyInformation;
+ Set<ConstraintViolation<Object>> violations;
+ Class[] groupsToValidate;
+
+ for (Object validationTarget : modelValidationEntry.getValidationTargets())
+ {
+ propertyInformation = createPropertyInformation(modelValidationEntry, validationTarget);
+
+ if (!executeGlobalBeforeValidationInterceptors(
+ facesContext, modelValidationEntry.getComponent(), validationTarget, propertyInformation))
+ {
+ continue;
+ }
+
+ if(modelValidationEntry.isDisplayMessageInline())
+ {
+ groupsToValidate = modelValidationEntry.getGroups();
+ }
+ //if violation should displayed inline validation has to take place with all groups
+ //which means: global messages -> filter groups already used for the validation target
+ else
+ {
+ groupsToValidate = filterGroupsToValidate(
+ modelValidationEntry, validationTarget, processedValidationTargets);
+ }
+
+ if(!shouldContinueValidation(modelValidationEntry, groupsToValidate))
+ {
+ continue;
+ }
+
+ addProcessedTarget(validationTarget, groupsToValidate, processedValidationTargets);
+ violations = validateTarget(validationTarget, groupsToValidate);
+
+ if (violations != null && !violations.isEmpty())
+ {
+ processViolations(facesContext, modelValidationEntry, validationTarget, violations, results);
+ }
+ }
+ }
+
+ private Class[] filterGroupsToValidate(ModelValidationEntry modelValidationEntry,
+ Object validationTarget,
+ Map<Object, List<Class>> processedValidationTargets)
+ {
+ if(!processedValidationTargets.containsKey(validationTarget))
+ {
+ return modelValidationEntry.getGroups();
+ }
+
+ List<Class> result = new ArrayList<Class>();
+ List<Class> validatedGroups = processedValidationTargets.get(validationTarget);
+
+ for(Class group : modelValidationEntry.getGroups())
+ {
+ if(!validatedGroups.contains(group))
+ {
+ result.add(group);
+ }
+ }
+ return result.toArray(new Class[result.size()]);
+ }
+
+ private boolean shouldContinueValidation(ModelValidationEntry modelValidationEntry, Class[] groupsToValidate)
+ {
+ return !(groupsToValidate == null || groupsToValidate.length == 0) ||
+ modelValidationEntry.isDisplayMessageInline();
+ }
+
+ private void addProcessedTarget(Object validationTarget,
+ Class[] groups,
+ Map<Object, List<Class>> processedValidationTargets)
+ {
+ if(!processedValidationTargets.containsKey(validationTarget))
+ {
+ processedValidationTargets.put(validationTarget, new ArrayList<Class>());
+ }
+
+ List<Class> validatedGroups = processedValidationTargets.get(validationTarget);
+
+ for(Class group : groups)
+ {
+ if(!validatedGroups.contains(group))
+ {
+ validatedGroups.add(group);
+ }
+ }
+ }
+
+ private PropertyInformation createPropertyInformation(
+ ModelValidationEntry modelValidationEntry, Object validationTarget)
+ {
+ PropertyInformation propertyInformation;
+ PropertyDetails propertyDetails;
+ propertyInformation = new DefaultPropertyInformation();
+ if (modelValidationEntry.getComponent() != null)
+ {
+ propertyDetails = ExtValUtils.getELHelper()
+ .getPropertyDetailsOfValueBinding(modelValidationEntry.getComponent());
+ }
+ else
+ {
+ propertyDetails = new PropertyDetails(null, validationTarget, null);
+ }
+ propertyInformation.setInformation(PropertyInformationKeys.PROPERTY_DETAILS, propertyDetails);
+ return propertyInformation;
+ }
+
+ private boolean executeGlobalBeforeValidationInterceptors(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object validationTarget,
+ PropertyInformation propertyInformation)
+ {
+ return ExtValUtils.executeGlobalBeforeValidationInterceptors(facesContext, uiComponent, validationTarget,
+ PropertyInformation.class.getName(), propertyInformation, BeanValidationModuleKey.class);
+ }
+
+ private void executeGlobalAfterValidationInterceptors(FacesContext facesContext,
+ UIComponent uiComponent,
+ Object validationTarget,
+ PropertyInformation propertyInformation)
+ {
+ ExtValUtils.executeGlobalAfterValidationInterceptors(facesContext, uiComponent, validationTarget,
+ PropertyInformation.class.getName(), propertyInformation, BeanValidationModuleKey.class);
+ }
+
+ private Set<ConstraintViolation<Object>> validateTarget(Object validationTarget, Class[] groups)
+ {
+ if(groups == null || groups.length == 0)
+ {
+ return null;
+ }
+
+ ValidatorFactory validatorFactory = ExtValBeanValidationContext.getCurrentInstance().getValidatorFactory();
+ return validatorFactory
+ .usingContext()
+ .messageInterpolator(ExtValBeanValidationContext.getCurrentInstance().getMessageInterpolator())
+ .constraintValidatorFactory(validatorFactory.getConstraintValidatorFactory())
+ .traversableResolver(validatorFactory.getTraversableResolver())
+ .getValidator()
+ .validate(validationTarget, groups);
+ }
+
+ private void processViolations(FacesContext facesContext,
+ ModelValidationEntry modelValidationEntry,
+ Object validationTarget,
+ Set<ConstraintViolation<Object>> violations,
+ Map<String, ModelValidationResult> results)
+ {
+ //jsf 2.0 is able to display multiple messages per component - so process all violations
+ //jsf < 2.0 will just use the first one (for inline messages - so it's only a little overhead)
+ Iterator<ConstraintViolation<Object>> violationsIterator = violations.iterator();
+ ConstraintViolation<Object> constraintViolation;
+ ModelValidationResult result;
+ while (violationsIterator.hasNext())
+ {
+ tryToCreateModelValidationResult(facesContext, modelValidationEntry, results);
+
+ result = resolveModelValidationResult(facesContext, modelValidationEntry, results);
+
+ constraintViolation = violationsIterator.next();
+ addViolationMessage(modelValidationEntry, validationTarget, constraintViolation, result);
+ }
+ }
+
+ private void tryToCreateModelValidationResult(FacesContext facesContext,
+ ModelValidationEntry modelValidationEntry,
+ Map<String, ModelValidationResult> results)
+ {
+ ModelValidationResult result;
+ if (!isModelValidationResultAvailableFor(facesContext, modelValidationEntry, results))
+ {
+ result = new ModelValidationResult();
+ results.put(modelValidationEntry.getComponent().getClientId(facesContext), result);
+ }
+ }
+
+ private ModelValidationResult resolveModelValidationResult(FacesContext facesContext,
+ ModelValidationEntry modelValidationEntry,
+ Map<String, ModelValidationResult> results)
+ {
+ return results.get(modelValidationEntry.getComponent().getClientId(facesContext));
+ }
+
+ private boolean isModelValidationResultAvailableFor(FacesContext facesContext,
+ ModelValidationEntry modelValidationEntry,
+ Map<String, ModelValidationResult> results)
+ {
+ return results.containsKey(modelValidationEntry.getComponent().getClientId(facesContext));
+ }
+
+ private void addViolationMessage(ModelValidationEntry modelValidationEntry,
+ Object validationTarget,
+ ConstraintViolation<Object> constraintViolation,
+ ModelValidationResult result)
+ {
+ if (modelValidationEntry.isDisplayMessageInline())
+ {
+ result.addFacesMessageHolder(createFacesMessageHolderForConstraintViolation(
+ constraintViolation, modelValidationEntry, validationTarget, true));
+ }
+ else
+ {
+ result.addFacesMessageHolder(createFacesMessageHolderForConstraintViolation(
+ constraintViolation, modelValidationEntry, validationTarget, false));
+ }
+ }
+
+ private FacesMessageHolder createFacesMessageHolderForConstraintViolation(final ConstraintViolation violation,
+ ModelValidationEntry modelValidationEntry,
+ final Object validationTarget,
+ boolean displayAtComponent)
+ {
+ final String newViolationMessage = tryToChangeViolationMessage(
+ modelValidationEntry, validationTarget, violation);
+
+ ConstraintViolation newConstraintViolation = new ConstraintViolation()
+ {
+ private ConstraintViolation wrapped = violation;
+
+ public String getMessage()
+ {
+ return newViolationMessage;
+ }
+
+ public String getMessageTemplate()
+ {
+ return wrapped.getMessageTemplate();
+ }
+
+ public Object getRootBean()
+ {
+ return wrapped.getRootBean();
+ }
+
+ public Class getRootBeanClass()
+ {
+ return wrapped.getRootBeanClass();
+ }
+
+ public Object getLeafBean()
+ {
+ return wrapped.getLeafBean();
+ }
+
+ public Path getPropertyPath()
+ {
+ return wrapped.getPropertyPath();
+ }
+
+ public Object getInvalidValue()
+ {
+ return wrapped.getInvalidValue();
+ }
+
+ public ConstraintDescriptor getConstraintDescriptor()
+ {
+ return wrapped.getConstraintDescriptor();
+ }
+ };
+
+
+ UIComponent uiComponent = null;
+ String clientId = null;
+
+ if (displayAtComponent)
+ {
+ uiComponent = modelValidationEntry.getComponent();
+ clientId = uiComponent.getClientId(FacesContext.getCurrentInstance());
+ }
+
+ FacesMessageHolder result = new FacesMessageHolder(BeanValidationUtils
+ .createFacesMessageForConstraintViolation(uiComponent, validationTarget, newConstraintViolation));
+ result.setClientId(clientId);
+ return result;
+ }
+
+ private String tryToChangeViolationMessage(ModelValidationEntry modelValidationEntry,
+ Object validationTarget,
+ ConstraintViolation violation)
+ {
+ if (!isDefaultMessage(modelValidationEntry))
+ {
+ return interpolateValidationErrorMessage(
+ modelValidationEntry.getCustomMessage(), validationTarget, violation);
+ }
+ return violation.getMessage();
+ }
+
+ private boolean isDefaultMessage(ModelValidationEntry modelValidationEntry)
+ {
+ return ModelValidation.DEFAULT.equals(modelValidationEntry.getCustomMessage());
+ }
+
+ private String interpolateValidationErrorMessage(String extValInlineMessage,
+ final Object validationTarget, final ConstraintViolation violation)
+ {
+ return ExtValBeanValidationContext.getCurrentInstance().getMessageInterpolator()
+ .interpolate(
+ extValInlineMessage,
+ new MessageInterpolator.Context()
+ {
+ public ConstraintDescriptor<?> getConstraintDescriptor()
+ {
+ return violation.getConstraintDescriptor();
+ }
+
+ public Object getValidatedValue()
+ {
+ return validationTarget;
+ }
+ }
+ );
+ }
+
+ @ToDo(Priority.MEDIUM)
+ private void processModelValidationResults(Map<String, ModelValidationResult> results)
+ {
+ for (ModelValidationResult result : results.values())
+ {
+ BeanValidationUtils.processViolationMessages(result.getFacesMessageHolderList());
+ }
+ }
+
+ private void executeGlobalAfterValidationInterceptorsFor(Map<String, ModelValidationResult> results)
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ UIComponent component;
+ for (ModelValidationResult result : results.values())
+ {
+ for (FacesMessageHolder facesMessageHolder : result.getFacesMessageHolderList())
+ {
+ component = null;
+ if (facesMessageHolder.getClientId() != null && !facesMessageHolder.getClientId().equals("*"))
+ {
+ component = facesContext.getViewRoot().findComponent(facesMessageHolder.getClientId());
+ }
+ executeGlobalAfterValidationInterceptors(facesContext, component, null, null);
+ }
+ }
+ }
+
+ public void beforePhase(PhaseEvent phaseEvent)
+ {
+ //do nothing
+ }
+
+ public PhaseId getPhaseId()
+ {
+ return PhaseId.UPDATE_MODEL_VALUES;
+ }
+
+ /*
+ * generated
+ */
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (!(o instanceof ModelValidationPhaseListener))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationResult.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationResult.java
new file mode 100644
index 0000000..e3c198b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationResult.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.validation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.core.validation.message.FacesMessageHolder;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@ToDo(value = Priority.LOW, description = "refactor")
+@UsageInformation(UsageCategory.INTERNAL)
+class ModelValidationResult
+{
+ private List<FacesMessageHolder> facesMessageHolderList = new ArrayList<FacesMessageHolder>();
+
+ public void addFacesMessageHolder(FacesMessageHolder facesMessageHolder)
+ {
+ this.facesMessageHolderList.add(facesMessageHolder);
+ }
+
+ public List<FacesMessageHolder> getFacesMessageHolderList()
+ {
+ return facesMessageHolderList;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/message/interpolator/DefaultMessageInterpolator.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/message/interpolator/DefaultMessageInterpolator.java
new file mode 100644
index 0000000..aa8392f
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/message/interpolator/DefaultMessageInterpolator.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.validation.message.interpolator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.MessageInterpolator;
+import javax.faces.context.FacesContext;
+import java.util.Locale;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultMessageInterpolator implements MessageInterpolator
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private MessageInterpolator wrapped;
+
+ public DefaultMessageInterpolator(MessageInterpolator wrapped)
+ {
+ this.wrapped = wrapped;
+ }
+
+ public String interpolate(String messageOrKey, Context context)
+ {
+ return interpolate(messageOrKey, context, null);
+ }
+
+ public String interpolate(String messageOrKey, Context context, Locale locale)
+ {
+ return this.wrapped.interpolate(messageOrKey, context, getCurrentLocale());
+ }
+
+ protected Locale getCurrentLocale()
+ {
+ return FacesContext.getCurrentInstance().getViewRoot().getLocale();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/message/interpolator/ExtValMessageInterpolatorAdapter.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/message/interpolator/ExtValMessageInterpolatorAdapter.java
new file mode 100644
index 0000000..46e9f33
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/message/interpolator/ExtValMessageInterpolatorAdapter.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.validation.message.interpolator;
+
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.AbstractValidationErrorMessageResolver;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.MessageInterpolator;
+import java.util.Locale;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ExtValMessageInterpolatorAdapter extends DefaultMessageInterpolator
+{
+ private MessageResolver messageResolver;
+
+ public ExtValMessageInterpolatorAdapter(MessageInterpolator wrapped, MessageResolver messageResolver)
+ {
+ super(wrapped);
+ this.messageResolver = messageResolver;
+ }
+
+ @Override
+ public String interpolate(String messageOrKey, Context context)
+ {
+ return interpolate(messageOrKey, context, getCurrentLocale());
+ }
+
+ @Override
+ public String interpolate(String messageOrKey, Context context, Locale locale)
+ {
+ if(this.messageResolver != null)
+ {
+ if(isBeanValidationMessageKeyFormat(messageOrKey))
+ {
+ String newMessageOrKey = this.messageResolver.getMessage(extractKey(messageOrKey), getCurrentLocale());
+
+ if(isValideMessage(newMessageOrKey))
+ {
+ messageOrKey = newMessageOrKey;
+ }
+ }
+ else
+ {
+ if(this.logger.isTraceEnabled())
+ {
+ this.logger.trace("you tried to use an extval message-resolver for" +
+ "jsr303 validation with an invalid key -> using a default interpolator");
+ }
+ }
+ }
+ return super.interpolate(messageOrKey, context, getCurrentLocale());
+ }
+
+ private boolean isBeanValidationMessageKeyFormat(String messageOrKey)
+ {
+ return messageOrKey.startsWith("{") && messageOrKey.endsWith("}");
+ }
+
+ private String extractKey(String messageOrKey)
+ {
+ return messageOrKey.substring(1, messageOrKey.length() - 1);
+ }
+
+ private boolean isValideMessage(String newMessageOrKey)
+ {
+ return !(newMessageOrKey.startsWith(AbstractValidationErrorMessageResolver.MISSING_RESOURCE_MARKER) &&
+ newMessageOrKey.endsWith(AbstractValidationErrorMessageResolver.MISSING_RESOURCE_MARKER));
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/strategy/BeanValidationVirtualValidationStrategy.java b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/strategy/BeanValidationVirtualValidationStrategy.java
new file mode 100644
index 0000000..1ddeef6
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/strategy/BeanValidationVirtualValidationStrategy.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.validation.strategy;
+
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractVirtualValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.validation.metadata.ConstraintDescriptor;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class BeanValidationVirtualValidationStrategy extends AbstractVirtualValidationStrategy
+{
+ private ConstraintDescriptor constraintDescriptor;
+ private Class elementClass; //property type
+
+ public BeanValidationVirtualValidationStrategy(ConstraintDescriptor constraintDescriptor, Class elementClass)
+ {
+ this.constraintDescriptor = constraintDescriptor;
+ this.elementClass = elementClass;
+ }
+
+ public ConstraintDescriptor getConstraintDescriptor()
+ {
+ return constraintDescriptor;
+ }
+
+ public Class getElementClass()
+ {
+ return elementClass;
+ }
+
+ public String getId()
+ {
+ return this.constraintDescriptor.getAnnotation().annotationType().getName();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/resources/LICENSE.txt b/2_0_3_prepare/validation-modules/bean-validation/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/resources/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/2_0_3_prepare/validation-modules/bean-validation/src/main/resources/NOTICE.txt b/2_0_3_prepare/validation-modules/bean-validation/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/bean-validation/src/main/resources/NOTICE.txt
@@ -0,0 +1,9 @@
+Apache MyFaces Extensions Validator
+Copyright 2007-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+------------------------------------------------------------------------
+See the file LICENSE.txt
+------------------------------------------------------------------------
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/pom.xml b/2_0_3_prepare/validation-modules/pom.xml
new file mode 100644
index 0000000..6204a10
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <packaging>pom</packaging>
+
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>validation-modules-project</artifactId>
+
+ <name>MyFaces Extensions-Validator Validation-Modules</name>
+ <version>2.0.3-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-parent</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/validation-modules</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/1_2_2_rc/validation-modules</developerConnection>
+ <url>http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/1_2_2_rc/validation-modules</url>
+ </scm>
+
+ <modules>
+ <module>property-validation</module>
+ <module>bean-validation</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-core</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/2_0_3_prepare/validation-modules/property-validation/pom.xml b/2_0_3_prepare/validation-modules/property-validation/pom.xml
new file mode 100644
index 0000000..a382b3f
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/pom.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>jar</packaging>
+
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>myfaces-extval-property-validation</artifactId>
+
+ <name>MyFaces Extensions-Validator Property-Validation-Module</name>
+ <version>2.0.3-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>
+ <artifactId>validation-modules-project</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.myfaces.extensions.validator</groupId>
+ <artifactId>myfaces-extval-core</artifactId>
+ <version>2.0.3-SNAPSHOT</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1.1</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ <version>2.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shale</groupId>
+ <artifactId>shale-test</artifactId>
+ <version>1.0.4</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.myfaces</groupId>
+ <artifactId>myfaces-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.myfaces</groupId>
+ <artifactId>myfaces-impl</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>myfaces</groupId>
+ <artifactId>myfaces-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>myfaces</groupId>
+ <artifactId>myfaces-impl</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/config</directory>
+ <includes>
+ <include>**/*xml</include>
+ </includes>
+ <targetPath>/META-INF</targetPath>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ </includes>
+ <targetPath>/META-INF</targetPath>
+ </resource>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*properties</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.4.2</version>
+ <configuration>
+ <excludes>
+ <exclude>**/Abstract*.java</exclude>
+ <exclude>**/TestUtils.java</exclude>
+ <exclude>**/*Bean.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/config/faces-config.xml b/2_0_3_prepare/validation-modules/property-validation/src/main/config/faces-config.xml
new file mode 100644
index 0000000..1c47d9b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/config/faces-config.xml
@@ -0,0 +1,26 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
+ version="2.0">
+ <lifecycle>
+ <phase-listener>org.apache.myfaces.extensions.validator.PropertyValidationModuleStartupListener</phase-listener>
+ </lifecycle>
+</faces-config>
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/HtmlCoreComponentsComponentInitializer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/HtmlCoreComponentsComponentInitializer.java
new file mode 100644
index 0000000..83785d6
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/HtmlCoreComponentsComponentInitializer.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator;
+
+import org.apache.myfaces.extensions.validator.core.initializer.component
+ .AbstractHtmlCoreComponentsComponentInitializer;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@InvocationOrder(200)
+@UsageInformation(UsageCategory.INTERNAL)
+public class HtmlCoreComponentsComponentInitializer extends AbstractHtmlCoreComponentsComponentInitializer
+{
+ protected void configureRequiredAttribute(FacesContext facesContext,
+ UIComponent uiComponent,
+ Map<String, Object> metaData)
+ {
+ if((Boolean.TRUE.equals(metaData.get(CommonMetaDataKeys.WEAK_REQUIRED)) ||
+ Boolean.TRUE.equals(metaData.get(CommonMetaDataKeys.REQUIRED)))
+ &&
+ Boolean.TRUE.equals(isComponentRequired(uiComponent)))
+ {
+ ((EditableValueHolder)uiComponent).setRequired(true);
+ }
+ else if(Boolean.TRUE.equals(metaData.get(CommonMetaDataKeys.SKIP_VALIDATION)) &&
+ !Boolean.TRUE.equals(metaData.get(CommonMetaDataKeys.REQUIRED)))
+ {
+ ((EditableValueHolder)uiComponent).setRequired(false);
+ }
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/JoinValidationMetaDataStorageFilter.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/JoinValidationMetaDataStorageFilter.java
new file mode 100644
index 0000000..aa123cd
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/JoinValidationMetaDataStorageFilter.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.JoinValidation;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.DefaultComponentMetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.property.DefaultPropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.storage.MetaDataStorageFilter;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * EXTVAL-59
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class JoinValidationMetaDataStorageFilter implements MetaDataStorageFilter
+{
+ private static final String STATIC_SEPARATOR = ":";
+
+ public void filter(PropertyInformation propertyInformation)
+ {
+ if (propertyInformation != null)
+ {
+ List<MetaDataEntry> result = new ArrayList<MetaDataEntry>();
+
+ resolveJoinValidationMetaData(propertyInformation, result);
+
+ propertyInformation.resetMetaDataEntries();
+
+ setDefaultPropertyDetails(propertyInformation, result);
+
+ if (containsJoinValidationConstraint(result))
+ {
+ filter(propertyInformation);
+ }
+ }
+ }
+
+ private void resolveJoinValidationMetaData(PropertyInformation propertyInformation, List<MetaDataEntry> result)
+ {
+ for (MetaDataEntry metaDataEntry : propertyInformation.getMetaDataEntries())
+ {
+ result.addAll(tryToTransformEntry(metaDataEntry));
+ }
+ }
+
+ private void setDefaultPropertyDetails(PropertyInformation propertyInformation, List<MetaDataEntry> result)
+ {
+ for (MetaDataEntry metaDataEntry : result)
+ {
+ metaDataEntry.setProperty(PropertyInformationKeys.PROPERTY_DETAILS,
+ propertyInformation.getInformation(PropertyInformationKeys.PROPERTY_DETAILS));
+ propertyInformation.addMetaDataEntry(metaDataEntry);
+ }
+ }
+
+ private boolean containsJoinValidationConstraint(List<MetaDataEntry> result)
+ {
+ for (MetaDataEntry entry : result)
+ {
+ if (entry.getValue() instanceof JoinValidation)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private List<MetaDataEntry> tryToTransformEntry(MetaDataEntry metaDataEntry)
+ {
+ List<MetaDataEntry> result = new ArrayList<MetaDataEntry>();
+
+ if (metaDataEntry.getValue() instanceof JoinValidation)
+ {
+ JoinValidation annotation = metaDataEntry.getValue(JoinValidation.class);
+
+ replaceMetaData(annotation, metaDataEntry, result);
+ }
+ else
+ {
+ result.add(metaDataEntry);
+ }
+
+ return result;
+ }
+
+ private void replaceMetaData(JoinValidation annotation, MetaDataEntry metaDataEntry, List<MetaDataEntry> result)
+ {
+ for (String target : annotation.value())
+ {
+ tryToReplaceMetaDataOfTarget(target, metaDataEntry, result);
+ }
+ }
+
+ private void tryToReplaceMetaDataOfTarget(String target, MetaDataEntry metaDataEntry, List<MetaDataEntry> result)
+ {
+ try
+ {
+ if (isStaticSyntax(target))
+ {
+ addMetaData(result, extractStaticMetaData(target));
+ }
+ else
+ {
+ addMetaData(result, extractDynamicMetaData(metaDataEntry, target));
+ }
+ }
+ catch (Throwable t)
+ {
+ //do nothing a different filter might introduce a new syntax which causes the exception
+ }
+ }
+
+ private void addMetaData(List<MetaDataEntry> result, MetaDataEntry[] metaDataEntries)
+ {
+ Collections.addAll(result, metaDataEntries);
+ }
+
+ private boolean isStaticSyntax(String target)
+ {
+ return target.contains(STATIC_SEPARATOR);
+ }
+
+ private MetaDataEntry[] extractStaticMetaData(String target)
+ {
+ int separatorIndex = target.lastIndexOf(STATIC_SEPARATOR);
+
+ Class targetClass = loadClass(target.substring(0, separatorIndex));
+ String propertyName = target.substring(separatorIndex + 1);
+
+ return new StaticSyntaxMetaDataExtractor().extract(targetClass, propertyName).getMetaDataEntries();
+ }
+
+ private Class loadClass(String className)
+ {
+ try
+ {
+ return ClassUtils.loadClassForName(className);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ private MetaDataEntry[] extractDynamicMetaData(MetaDataEntry metaDataEntry, String target)
+ {
+ PropertyDetails propertyDetails = ExtValUtils.createPropertyDetailsForNewTarget(metaDataEntry, target);
+
+ Class targetClass = ProxyUtils.getUnproxiedClass(propertyDetails.getBaseObject().getClass());
+ return new StaticSyntaxMetaDataExtractor().extract(
+ targetClass, propertyDetails.getProperty()).getMetaDataEntries();
+ }
+
+ private class StaticSyntaxMetaDataExtractor extends DefaultComponentMetaDataExtractor
+ {
+ public PropertyInformation extract(Class targetClass, String targetProperty)
+ {
+ PropertyInformation propertyInformation = new DefaultPropertyInformation();
+
+ addPropertyAccessAnnotations(targetClass, targetProperty, propertyInformation);
+ addFieldAccessAnnotations(targetClass, targetProperty, propertyInformation);
+
+ return propertyInformation;
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return obj != null && getClass().equals(obj.getClass());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationGroupStorageNameMapper.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationGroupStorageNameMapper.java
new file mode 100644
index 0000000..240cde0
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationGroupStorageNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator;
+
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.storage.DefaultGroupStorage;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+/**
+ * name mapper for group implementations via validation parameters
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(200)
+@UsageInformation(INTERNAL)
+public class PropertyValidationGroupStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String source)
+ {
+ return (ValidationParameter.class.getName().equals(source)) ?
+ DefaultGroupStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleKey.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleKey.java
new file mode 100644
index 0000000..4b74843
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleKey.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.ValidationModuleKey;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@ValidationModuleKey
+@UsageInformation(UsageCategory.API)
+public interface PropertyValidationModuleKey
+{
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleStartupListener.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleStartupListener.java
new file mode 100644
index 0000000..d8e0f8d
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleStartupListener.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator;
+
+import org.apache.myfaces.extensions.validator.baseval.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.core.startup.AbstractStartupListener;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.factory.FactoryNames;
+import org.apache.myfaces.extensions.validator.core.factory.AbstractNameMapperAwareFactory;
+import org.apache.myfaces.extensions.validator.core.storage.StorageManagerHolder;
+import org.apache.myfaces.extensions.validator.core.storage.StorageManager;
+import org.apache.myfaces.extensions.validator.core.storage.GroupStorage;
+import org.apache.myfaces.extensions.validator.core.storage.MetaDataStorage;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.interceptor.ValidationInterceptor;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticResourceBundleConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
+import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticInMemoryConfiguration;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.crossval.recorder.CrossValidationUserInputRecorder;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.DefaultCrossValidationStorageManager;
+import org.apache.myfaces.extensions.validator.crossval.storage.DefaultProcessedInformationStorageManager;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.mapper.CrossValidationStorageNameMapper;
+import org.apache.myfaces.extensions.validator.crossval.storage.mapper.ProcessedInformationStorageNameMapper;
+import org.apache.myfaces.extensions.validator.crossval.CrossValidationPhaseListener;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class PropertyValidationModuleStartupListener extends AbstractStartupListener
+{
+ private static final long serialVersionUID = -2474361612857222283L;
+
+ protected void init()
+ {
+ initProcessedInformationRecorders();
+ initStaticStrategyMappings();
+ initDefaultComponentInitializer();
+ addSkipValidationSupport();
+ initStorageManagerAndNameMappers();
+ initSkipValidationEvaluator();
+ initMetaDataStorageFilters();
+ initPhaseListeners();
+ }
+
+ private void initProcessedInformationRecorders()
+ {
+ ExtValContext.getContext().addProcessedInformationRecorder(new CrossValidationUserInputRecorder());
+ }
+
+ private void initStaticStrategyMappings()
+ {
+ String jpaBasedValidation = WebXmlParameter.DEACTIVATE_JPA_BASED_VALIDATION;
+ if (jpaBasedValidation == null
+ || !jpaBasedValidation.equalsIgnoreCase("true"))
+ {
+ StaticConfiguration<String, String> staticConfig = new StaticResourceBundleConfiguration();
+ staticConfig.setSourceOfMapping(
+ ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME +".jpa_strategy_mappings");
+
+ ExtValContext.getContext().addStaticConfiguration(
+ StaticConfigurationNames.META_DATA_TO_VALIDATION_STRATEGY_CONFIG, staticConfig);
+ }
+ }
+
+ private void initDefaultComponentInitializer()
+ {
+ ExtValContext.getContext().addComponentInitializer(new HtmlCoreComponentsComponentInitializer());
+ }
+
+ private void addSkipValidationSupport()
+ {
+ if(logger.isInfoEnabled())
+ {
+ logger.info("adding support for @SkipValidation");
+ }
+
+ ExtValContext.getContext().denyRendererInterceptor(ValidationInterceptor.class);
+ ExtValContext.getContext().registerRendererInterceptor(new PropertyValidationModuleValidationInterceptor());
+
+ StaticInMemoryConfiguration config = new StaticInMemoryConfiguration();
+ //it's just required to set the target
+ config.addMapping(CommonMetaDataKeys.SKIP_VALIDATION, SkipValidationSupport.class.getName());
+
+ ExtValContext.getContext()
+ .addStaticConfiguration(StaticConfigurationNames.SKIP_VALIDATION_SUPPORT_CONFIG, config);
+
+ //config.addMapping(CommonMetaDataKeys.SKIP_VALIDATION, RequiredStrategy.class.getName());
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void initStorageManagerAndNameMappers()
+ {
+ StorageManagerHolder storageManagerHolder =
+ (ExtValContext.getContext()
+ .getFactoryFinder()
+ .getFactory(FactoryNames.STORAGE_MANAGER_FACTORY, StorageManagerHolder.class));
+
+ //processed-information
+ DefaultProcessedInformationStorageManager processedInfoStorageManager =
+ new DefaultProcessedInformationStorageManager();
+ processedInfoStorageManager.register(new ProcessedInformationStorageNameMapper());
+ storageManagerHolder.setStorageManager(ProcessedInformationStorage.class, processedInfoStorageManager, false);
+
+ //cross-validation
+ DefaultCrossValidationStorageManager crossValidationStorageManager =
+ new DefaultCrossValidationStorageManager();
+ crossValidationStorageManager.register(new CrossValidationStorageNameMapper());
+ storageManagerHolder.setStorageManager(CrossValidationStorage.class, crossValidationStorageManager, false);
+
+ //group-validation light
+ StorageManager storageManager = storageManagerHolder.getStorageManager(GroupStorage.class);
+
+ if(storageManager instanceof AbstractNameMapperAwareFactory)
+ {
+ ((AbstractNameMapperAwareFactory<String>)storageManager)
+ .register(new PropertyValidationGroupStorageNameMapper());
+ }
+ }
+
+ private void initSkipValidationEvaluator()
+ {
+ ExtValContext.getContext().setSkipValidationEvaluator(new PropertyValidationSkipValidationEvaluator(), false);
+ }
+
+ private void initMetaDataStorageFilters()
+ {
+ MetaDataStorage metaDataStorage = ExtValUtils.getStorage(
+ MetaDataStorage.class, MetaDataStorage.class.getName());
+
+ metaDataStorage.registerFilter(new JoinValidationMetaDataStorageFilter());
+ //metaDataStorage.registerFilter(new CompositeMetaDataStorageFilter());
+ }
+
+ private void initPhaseListeners()
+ {
+ JsfUtils.registerPhaseListener(new CrossValidationPhaseListener());
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleValidationInterceptor.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleValidationInterceptor.java
new file mode 100644
index 0000000..78c4526
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationModuleValidationInterceptor.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.core.interceptor.ValidationInterceptor;
+
+/**
+ * the skip validation support was refactored to an independent mechanism
+ * see SkipValidationEvaluator
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+@ToDo(value = Priority.MEDIUM, description = "change the add-ons" +
+ "old name: ValidationInterceptorWithSkipValidationSupport")
+public class PropertyValidationModuleValidationInterceptor extends ValidationInterceptor
+{
+ @Override
+ protected Class getModuleKey()
+ {
+ return PropertyValidationModuleKey.class;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationSkipValidationEvaluator.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationSkipValidationEvaluator.java
new file mode 100644
index 0000000..75a6adc
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/PropertyValidationSkipValidationEvaluator.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.SkipValidationEvaluator;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.util.PropertyValidationUtils;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+import java.util.List;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class PropertyValidationSkipValidationEvaluator implements SkipValidationEvaluator
+{
+ public boolean skipValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ ValidationStrategy validationStrategy,
+ MetaDataEntry metaDataEntry)
+ {
+ boolean result = false;
+
+ if(JsfUtils.isRenderResponsePhase())
+ {
+ result = !isClientSideValidationEnabled(metaDataEntry);
+ }
+ return result || PropertyValidationUtils.isValidationSkipped(facesContext, validationStrategy, metaDataEntry);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private boolean isClientSideValidationEnabled(MetaDataEntry entry)
+ {
+ List<String> keysToDisable = entry.getProperty(
+ CommonMetaDataKeys.DISABLE_CLIENT_SIDE_VALIDATION, List.class);
+
+ return keysToDisable == null || !keysToDisable.contains(entry.getKey());
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/WebXmlParameter.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/WebXmlParameter.java
new file mode 100644
index 0000000..b777a4e
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/WebXmlParameter.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval;
+
+import org.apache.myfaces.extensions.validator.util.WebXmlUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * centralized in order that these information arn't spread over the complete code base
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@ToDo(value = Priority.MEDIUM, description = "documentation")
+@UsageInformation(UsageCategory.INTERNAL)
+public interface WebXmlParameter
+{
+ static final String VALIDATION_MESSAGES_JPA = WebXmlUtils
+ .getInitParameter("JPA_VALIDATION_ERROR_MESSAGES");
+ static final String DEACTIVATE_JPA_BASED_VALIDATION = WebXmlUtils
+ .getInitParameter("DEACTIVATE_JPA_BASED_VALIDATION");
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/DoubleRange.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/DoubleRange.java
new file mode 100644
index 0000000..cb4e02f
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/DoubleRange.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface DoubleRange
+{
+ double minimum() default Double.MIN_VALUE;
+
+ double maximum() default Double.MAX_VALUE;
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/JoinValidation.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/JoinValidation.java
new file mode 100644
index 0000000..ac9a899
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/JoinValidation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface JoinValidation
+{
+ String[] value();
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Length.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Length.java
new file mode 100644
index 0000000..2c437d1
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Length.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface Length
+{
+ int minimum() default 0;
+
+ int maximum() default Integer.MAX_VALUE;
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/LongRange.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/LongRange.java
new file mode 100644
index 0000000..f4251ef
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/LongRange.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface LongRange
+{
+ long minimum() default Long.MIN_VALUE;
+
+ long maximum() default Long.MAX_VALUE;
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Pattern.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Pattern.java
new file mode 100644
index 0000000..e775d89
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Pattern.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface Pattern
+{
+ String[] value();
+
+ String validationErrorMsgKey() default "no_match";
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Required.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Required.java
new file mode 100644
index 0000000..11ce128
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Required.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface Required
+{
+ /**
+ * to customize the error message or
+ * to override the default jsf required message with the usage of the message resolver mechanism
+ *
+ * @return an optional error message key
+ */
+ String validationErrorMsgKey() default "field_required";
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/SkipValidation.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/SkipValidation.java
new file mode 100644
index 0000000..02c529b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/SkipValidation.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface SkipValidation
+{
+ String[] value();
+
+ Class<? extends ValidationParameter>[] parameters() default {};
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/SkipValidationSupport.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/SkipValidationSupport.java
new file mode 100644
index 0000000..7107621
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/SkipValidationSupport.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface SkipValidationSupport
+{
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Validator.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Validator.java
new file mode 100644
index 0000000..fb38aca
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Validator.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface Validator
+{
+ Class<? extends javax.faces.validator.Validator>[] value();
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/extractor/DefaultPropertyScanningMetaDataExtractor.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/extractor/DefaultPropertyScanningMetaDataExtractor.java
new file mode 100644
index 0000000..8a0eeba
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/extractor/DefaultPropertyScanningMetaDataExtractor.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.annotation.extractor;
+
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.property.DefaultPropertyInformation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.DefaultComponentMetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.MetaDataExtractor;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.myfaces.extensions.validator.PropertyValidationModuleKey;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Deprecated
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultPropertyScanningMetaDataExtractor extends DefaultComponentMetaDataExtractor
+{
+ private DefaultPropertyScanningMetaDataExtractor()
+ {
+ }
+
+ public static MetaDataExtractor getInstance()
+ {
+ return ExtValUtils.createInterceptedMetaDataExtractorFor(
+ new DefaultPropertyScanningMetaDataExtractor(), PropertyValidationModuleKey.class);
+ }
+
+ @Override
+ @ToDo(Priority.MEDIUM)
+ public PropertyInformation extract(FacesContext facesContext, Object object)
+ {
+ PropertyInformation propertyInformation = new DefaultPropertyInformation();
+
+ if (!(object instanceof PropertyDetails))
+ {
+ throw new IllegalStateException(object.getClass() + " is not a " + PropertyDetails.class.getName());
+ }
+
+ PropertyDetails propertyDetails = (PropertyDetails)object;
+
+ Class entityClass = ProxyUtils.getUnproxiedClass(propertyDetails.getBaseObject().getClass());
+
+ //TODO test with complex components
+ propertyInformation.setInformation(
+ PropertyInformationKeys.PROPERTY_DETAILS, propertyDetails);
+
+ /*
+ * find and add annotations
+ */
+ addPropertyAccessAnnotations(entityClass, propertyDetails.getProperty(), propertyInformation);
+ addFieldAccessAnnotations(entityClass, propertyDetails.getProperty(), propertyInformation);
+
+ return propertyInformation;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages.properties
new file mode 100644
index 0000000..08e8012
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=Invalid format
+no_match_detail=The required formate is: {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_ar.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_ar.properties
new file mode 100644
index 0000000..97ab543
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_ar.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=\u0627\u0644\u0635\u064a\u063a\u0629 \u062e\u0627\u0637\u0626\u0629
+no_match_detail=\u0627\u0644\u0635\u064a\u063a\u0629 \u0627\u0644\u0645\u0637\u0644\u0648\u0628\u0629 \u0647\u0649: {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_ca.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_ca.properties
new file mode 100644
index 0000000..98d6490
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_ca.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=Format inv\u00e0lid
+no_match_detail=El format requerit \u00e9s: {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_de.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_de.properties
new file mode 100644
index 0000000..9ee701b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_de.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=Ungültiges Format
+no_match_detail=Das erforderliche Format ist: {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_en.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_en.properties
new file mode 100644
index 0000000..08e8012
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_en.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=Invalid format
+no_match_detail=The required formate is: {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_es.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_es.properties
new file mode 100644
index 0000000..93bb98c
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_es.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=Formato inv\u00e1lido
+no_match_detail=El formato requerido es: {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_fr.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_fr.properties
new file mode 100644
index 0000000..120a223
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_fr.properties
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=Le format est invalide
+no_match_detail=Le format doit être de la forme: {0}
+
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_it.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_it.properties
new file mode 100644
index 0000000..e18748c
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_it.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=Formato non valido
+no_match_detail=Il formato richiesto è: {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_tr.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_tr.properties
new file mode 100644
index 0000000..a94bc74
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages_tr.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no_match=Ge\u00e7ersiz bi\u00e7im
+no_match_detail=gereken bi\u00e7im: {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/DefaultValidationErrorMessageResolver.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/DefaultValidationErrorMessageResolver.java
new file mode 100644
index 0000000..4aae64b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/DefaultValidationErrorMessageResolver.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.message.resolver;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultValidationErrorMessageResolver
+ extends
+ org.apache.myfaces.extensions.validator.core.validation.message.resolver.DefaultValidationErrorMessageResolver
+{
+ private static String baseName = null;
+
+ @Override
+ protected String getBaseName()
+ {
+ if (baseName == null)
+ {
+ baseName = super.getBaseName();
+ }
+
+ return baseName;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/JpaValidationErrorMessageResolver.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/JpaValidationErrorMessageResolver.java
new file mode 100644
index 0000000..d476ad9
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/JpaValidationErrorMessageResolver.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.message.resolver;
+
+import org.apache.myfaces.extensions.validator.baseval.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.AbstractValidationErrorMessageResolver;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+/*
+ * the jpa support is an exception in view of some mechanisms - so there's no convention for the message bundle.
+ * instead of the convention there is a global property to have an alternative to web.xml configuration
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class JpaValidationErrorMessageResolver extends AbstractValidationErrorMessageResolver
+{
+ public static final String JPA_VALIDATION_ERROR_MESSAGES = "JPA_VALIDATION_ERROR_MESSAGES";
+
+ private static final String CUSTOM_BASE_NAME = WebXmlParameter.VALIDATION_MESSAGES_JPA;
+ private static final String BASE_NAME = JpaValidationErrorMessageResolver.class
+ .getPackage().getName().replace(".message.resolver", ".message.bundle")+ ".jpa_messages";
+
+ protected String getCustomBaseName()
+ {
+ if(CUSTOM_BASE_NAME != null)
+ {
+ return CUSTOM_BASE_NAME;
+ }
+
+ return (String)ExtValContext.getContext().getGlobalProperty(JPA_VALIDATION_ERROR_MESSAGES);
+ }
+
+ protected String getBaseName()
+ {
+ return BASE_NAME;
+ }
+
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/AbstractValidationParameterAwareTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/AbstractValidationParameterAwareTransformer.java
new file mode 100644
index 0000000..495cd44
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/AbstractValidationParameterAwareTransformer.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.MetaDataTransformer;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.application.FacesMessage;
+import java.lang.annotation.Annotation;
+import java.util.List;
+import java.util.Map;
+import java.util.Collections;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.REUSE)
+public abstract class AbstractValidationParameterAwareTransformer implements MetaDataTransformer
+{
+ public Map<String, Object> convertMetaData(MetaDataEntry metaData)
+ {
+ if (isBlockingMetaData(metaData))
+ {
+ return transformMetaData(metaData);
+ }
+ return Collections.emptyMap();
+ }
+
+ protected abstract Map<String, Object> transformMetaData(MetaDataEntry metaData);
+
+ protected boolean isBlockingMetaData(MetaDataEntry metaDataEntry)
+ {
+ FacesMessage testMessage = new FacesMessage();
+ testMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
+
+ FacesMessage.Severity severity = tryToTransformViolationSeverity(metaDataEntry);
+
+ if(severity != null)
+ {
+ testMessage.setSeverity(severity);
+ }
+
+ return ExtValUtils.severityBlocksSubmitForComponentId(null, testMessage);
+ }
+
+ private FacesMessage.Severity tryToTransformViolationSeverity(MetaDataEntry metaDataEntry)
+ {
+ List<FacesMessage.Severity> result = ExtValUtils.getValidationParameterExtractor()
+ .extract(metaDataEntry.getValue(Annotation.class),
+ ExtValUtils.getValidationParameterClassFor(ViolationSeverity.class),
+ FacesMessage.Severity.class);
+
+ if (result != null && !result.isEmpty())
+ {
+ return result.iterator().next();
+ }
+ return null;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/DoubleRangeMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/DoubleRangeMetaDataTransformer.java
new file mode 100644
index 0000000..08e9e4e
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/DoubleRangeMetaDataTransformer.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.DoubleRange;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DoubleRangeMetaDataTransformer extends AbstractValidationParameterAwareTransformer
+{
+ protected Map<String, Object> transformMetaData(MetaDataEntry metaDataEntry)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+ DoubleRange annotation = metaDataEntry.getValue(DoubleRange.class);
+
+ double minimum = annotation.minimum();
+
+ if(minimum != Double.MIN_VALUE)
+ {
+ results.put(CommonMetaDataKeys.RANGE_MIN, minimum);
+ }
+ else
+ {
+ results.put(CommonMetaDataKeys.RANGE_MIN_DEFAULT, minimum);
+ }
+
+ double maximum = annotation.maximum();
+
+ if(maximum != Double.MAX_VALUE)
+ {
+ results.put(CommonMetaDataKeys.RANGE_MAX, maximum);
+ }
+ else
+ {
+ results.put(CommonMetaDataKeys.RANGE_MAX_DEFAULT, maximum);
+ }
+
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/JoinMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/JoinMetaDataTransformer.java
new file mode 100644
index 0000000..df35324
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/JoinMetaDataTransformer.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.JoinValidation;
+import org.apache.myfaces.extensions.validator.baseval.annotation.extractor.DefaultPropertyScanningMetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.MetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.metadata.transformer.MetaDataTransformer;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.DisableClientSideValidation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.PropertyValidationUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Collections;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+@Deprecated
+public class JoinMetaDataTransformer implements MetaDataTransformer
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public Map<String, Object> convertMetaData(MetaDataEntry metaDataEntry)
+ {
+ try
+ {
+ return convert(metaDataEntry);
+ }
+ catch (Throwable t)
+ {
+ if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn("this class is replaced by a meta-data storage filter. " +
+ "if it gets invoked and an exception occurs, a custom syntax is used." +
+ "this class might be used by an old add-on. please check for a newer version.");
+ }
+ return Collections.emptyMap();
+ }
+ }
+
+ private Map<String, Object> convert(MetaDataEntry metaDataEntry)
+ {
+ MetaDataExtractor extractor = DefaultPropertyScanningMetaDataExtractor.getInstance();
+
+ String[] targetExpressions = metaDataEntry.getValue(JoinValidation.class).value();
+
+ ValidationStrategy validationStrategy;
+ MetaDataTransformer metaDataTransformer;
+
+ Map<String, Object> results = new HashMap<String, Object>();
+
+ PropertyDetails propertyDetails;
+ for (String targetExpression : targetExpressions)
+ {
+ propertyDetails = ExtValUtils
+ .createPropertyDetailsForNewTarget(metaDataEntry, targetExpression);
+
+ for (MetaDataEntry entry : extractor.extract(FacesContext.getCurrentInstance(),
+ propertyDetails).getMetaDataEntries())
+ {
+ validationStrategy = ExtValUtils.getValidationStrategyForMetaData(entry.getKey());
+
+ if(validationStrategy == null ||
+ PropertyValidationUtils.isValidationSkipped(FacesContext.getCurrentInstance(),
+ validationStrategy, entry))
+ {
+ continue;
+ }
+
+ metaDataTransformer = ExtValUtils.getMetaDataTransformerForValidationStrategy(validationStrategy);
+
+ if (metaDataTransformer != null)
+ {
+ if(!(entry.getValue() instanceof Annotation &&
+ ExtValUtils.getValidationParameterExtractor()
+ .extract(entry.getValue(Annotation.class),
+ ExtValUtils
+ .getValidationParameterClassFor(DisableClientSideValidation.class))
+ .iterator().hasNext()))
+ {
+ results.putAll(metaDataTransformer.convertMetaData(entry));
+ }
+ }
+ }
+ }
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/JpaMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/JpaMetaDataTransformer.java
new file mode 100644
index 0000000..dce1011
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/JpaMetaDataTransformer.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Id;
+import java.util.HashMap;
+import java.util.Map;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class JpaMetaDataTransformer extends AbstractValidationParameterAwareTransformer
+{
+ @ToDo(value = Priority.MEDIUM, description = "impl. the rest")
+ protected Map<String, Object> transformMetaData(MetaDataEntry metaDataEntry)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+
+ Annotation annotation = metaDataEntry.getValue(Annotation.class);
+
+ if(annotation instanceof Column)
+ {
+ if((!((Column) annotation).nullable()) && ExtValUtils.interpretEmptyStringValuesAsNull())
+ {
+ results.put(CommonMetaDataKeys.REQUIRED, true);
+ }
+
+ results.put(CommonMetaDataKeys.MAX_LENGTH, ((Column) annotation).length());
+ }
+ else if(annotation instanceof Basic)
+ {
+ if(!((Basic) annotation).optional())
+ {
+ results.put(CommonMetaDataKeys.REQUIRED, true);
+ }
+ }
+ else if(annotation instanceof Id)
+ {
+ results.put(CommonMetaDataKeys.REQUIRED, true);
+ }
+ //TODO impl. the rest!!!
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/LengthMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/LengthMetaDataTransformer.java
new file mode 100644
index 0000000..b391f9a
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/LengthMetaDataTransformer.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.Length;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class LengthMetaDataTransformer extends AbstractValidationParameterAwareTransformer
+{
+ protected Map<String, Object> transformMetaData(MetaDataEntry metaDataEntry)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+ Length annotation = metaDataEntry.getValue(Length.class);
+
+ int minimum = annotation.minimum();
+
+ if(minimum != 0)
+ {
+ results.put(CommonMetaDataKeys.MIN_LENGTH, minimum);
+ }
+ else
+ {
+ results.put(CommonMetaDataKeys.MIN_LENGTH_DEFAULT, minimum);
+ }
+
+ int maximum = annotation.maximum();
+ if(maximum != Integer.MAX_VALUE)
+ {
+ results.put(CommonMetaDataKeys.MAX_LENGTH, maximum);
+ }
+ else
+ {
+ results.put(CommonMetaDataKeys.MAX_LENGTH_DEFAULT, maximum);
+ }
+
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/LongRangeMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/LongRangeMetaDataTransformer.java
new file mode 100644
index 0000000..d0a332b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/LongRangeMetaDataTransformer.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.LongRange;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class LongRangeMetaDataTransformer extends AbstractValidationParameterAwareTransformer
+{
+ protected Map<String, Object> transformMetaData(MetaDataEntry metaDataEntry)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+ LongRange annotation = metaDataEntry.getValue(LongRange.class);
+
+ long minimum = annotation.minimum();
+
+ if(minimum != Long.MIN_VALUE)
+ {
+ results.put(CommonMetaDataKeys.RANGE_MIN, minimum);
+ }
+ else
+ {
+ results.put(CommonMetaDataKeys.RANGE_MIN_DEFAULT, minimum);
+ }
+
+ long maximum = annotation.maximum();
+
+ if(maximum != Long.MAX_VALUE)
+ {
+ results.put(CommonMetaDataKeys.RANGE_MAX, maximum);
+ }
+ else
+ {
+ results.put(CommonMetaDataKeys.RANGE_MAX_DEFAULT, maximum);
+ }
+
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/PatternMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/PatternMetaDataTransformer.java
new file mode 100644
index 0000000..410be65
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/PatternMetaDataTransformer.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.baseval.annotation.Pattern;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.context.FacesContext;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Locale;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class PatternMetaDataTransformer extends AbstractValidationParameterAwareTransformer
+{
+ protected Map<String, Object> transformMetaData(MetaDataEntry metaDataEntry)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+ Pattern annotation = metaDataEntry.getValue(Pattern.class);
+
+ results.put(CommonMetaDataKeys.PATTERN, (annotation).value());
+
+ String validationErrorMsgKey = (annotation).validationErrorMsgKey();
+ Locale currentLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
+
+ ValidationStrategy validationStrategy =
+ ExtValUtils.getValidationStrategyForMetaData(annotation.annotationType().getName());
+
+ String validationErrorMsg = ExtValUtils.getMessageResolverForValidationStrategy(validationStrategy)
+ .getMessage(validationErrorMsgKey, currentLocale);
+
+ results.put(CommonMetaDataKeys.PATTERN_VALIDATION_ERROR_MESSAGE, validationErrorMsg);
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/RequiredMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/RequiredMetaDataTransformer.java
new file mode 100644
index 0000000..4bbecc9
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/RequiredMetaDataTransformer.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class RequiredMetaDataTransformer extends AbstractValidationParameterAwareTransformer
+{
+ public Map<String, Object> transformMetaData(MetaDataEntry metaDataEntry)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+ results.put(CommonMetaDataKeys.WEAK_REQUIRED, true);
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/SkipMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/SkipMetaDataTransformer.java
new file mode 100644
index 0000000..7dc64ab
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/SkipMetaDataTransformer.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class SkipMetaDataTransformer extends AbstractValidationParameterAwareTransformer
+{
+ protected Map<String, Object> transformMetaData(MetaDataEntry metaDataEntry)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+ results.put(CommonMetaDataKeys.SKIP_VALIDATION, true);
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/ValidatorMetaDataTransformer.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/ValidatorMetaDataTransformer.java
new file mode 100644
index 0000000..ed05ab0
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/metadata/transformer/ValidatorMetaDataTransformer.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.metadata.transformer;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.Validator;
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ValidatorMetaDataTransformer extends AbstractValidationParameterAwareTransformer
+{
+ protected Map<String, Object> transformMetaData(MetaDataEntry metaDataEntry)
+ {
+ Map<String, Object> results = new HashMap<String, Object>();
+ Validator annotation = metaDataEntry.getValue(Validator.class);
+
+ Class[] validators = annotation.value();
+
+ List<String> value = new ArrayList<String>();
+
+ for(Class currentClass : validators)
+ {
+ if(currentClass.getSimpleName().toLowerCase().contains(CommonMetaDataKeys.EMAIL))
+ {
+ value.add(CommonMetaDataKeys.EMAIL);
+ }
+ value.add(currentClass.getName());
+ }
+
+ results.put(CommonMetaDataKeys.CUSTOM, value);
+
+ return results;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/DoubleRangeStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/DoubleRangeStrategy.java
new file mode 100644
index 0000000..f175933
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/DoubleRangeStrategy.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.DoubleRange;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.DoubleRangeValidator;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@UsageInformation(UsageCategory.INTERNAL)
+public class DoubleRangeStrategy extends AbstractValidationStrategy
+{
+ protected void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+
+ DoubleRange annotation = metaDataEntry.getValue(DoubleRange.class);
+ DoubleRangeValidator doubleRangeValidator = (DoubleRangeValidator)facesContext.getApplication()
+ .createValidator("javax.faces.DoubleRange");
+
+ doubleRangeValidator.setMinimum(annotation.minimum());
+ doubleRangeValidator.setMaximum(annotation.maximum());
+
+ doubleRangeValidator.validate(facesContext, uiComponent, convertedObject);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JoinValidationStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JoinValidationStrategy.java
new file mode 100644
index 0000000..54da1ac
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JoinValidationStrategy.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.JoinValidation;
+import org.apache.myfaces.extensions.validator.baseval.annotation.extractor.DefaultPropertyScanningMetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.metadata.extractor.MetaDataExtractor;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import javax.faces.FacesException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+@Deprecated
+public class JoinValidationStrategy extends AbstractValidationStrategy
+{
+ public void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+ try
+ {
+ validateJoinValidation(facesContext, uiComponent, metaDataEntry, convertedObject);
+ }
+ catch (FacesException t)
+ {
+ throw t;
+ }
+ catch (Throwable t)
+ {
+ if(this.logger.isWarnEnabled())
+ {
+ this.logger.warn("this class is replaced by a meta-data storage filter. " +
+ "if it gets invoked and an exception occurs, a custom syntax is used." +
+ "this class might be used by an old add-on. please check for a newer version.");
+ }
+ }
+ }
+
+ private void validateJoinValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject)
+ {
+ MetaDataExtractor extractor = DefaultPropertyScanningMetaDataExtractor.getInstance();
+
+ String[] targetExpressions = metaDataEntry.getValue(JoinValidation.class).value();
+
+ ValidationStrategy validationStrategy;
+
+ PropertyDetails propertyDetails;
+ for (String targetExpression : targetExpressions)
+ {
+ propertyDetails = ExtValUtils
+ .createPropertyDetailsForNewTarget(metaDataEntry, targetExpression);
+
+ for (MetaDataEntry entry : extractor.extract(facesContext, propertyDetails).getMetaDataEntries())
+ {
+ validationStrategy = ExtValUtils.getValidationStrategyForMetaData(entry.getKey());
+
+ if (validationStrategy != null)
+ {
+ if(ExtValUtils.processMetaDataEntryAfterSkipValidation(ProxyUtils.getUnproxiedClass(
+ validationStrategy.getClass(), ValidationStrategy.class), entry))
+ {
+ continue;
+ }
+
+ validationStrategy.validate(facesContext, uiComponent, entry, convertedObject);
+ }
+ else
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("no validation strategy found for " + entry.getValue());
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JpaValidationStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JpaValidationStrategy.java
new file mode 100644
index 0000000..3e41a93
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JpaValidationStrategy.java
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.core.metadata.CommonMetaDataKeys;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractAnnotationValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.AbstractValidationErrorMessageResolver;
+import org.apache.myfaces.extensions.validator.core.validation.exception.RequiredValidatorException;
+import org.apache.myfaces.extensions.validator.core.validation.NullValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.EmptyValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import javax.faces.application.FacesMessage;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Id;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@NullValueAwareValidationStrategy
+@EmptyValueAwareValidationStrategy
+@UsageInformation(UsageCategory.INTERNAL)
+public class JpaValidationStrategy extends AbstractAnnotationValidationStrategy
+{
+ private boolean useFacesBundle = false;
+ private static final String VALIDATE_LENGTH = "length";
+
+ private String violation;
+ private int maxLength;
+
+ public void processValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+ Annotation annotation = metaDataEntry.getValue(Annotation.class);
+ if (annotation instanceof Column)
+ {
+ validateColumnAnnotation((Column) annotation, convertedObject);
+ }
+ else if (annotation instanceof Basic)
+ {
+ validateBasicAnnotation((Basic) annotation, convertedObject);
+ }
+ else if (annotation instanceof Id)
+ {
+ checkRequiredConvertedObject(convertedObject);
+ }
+ else if (annotation instanceof OneToOne)
+ {
+ validateOneToOneAnnotation((OneToOne) annotation, convertedObject);
+ }
+ else if (annotation instanceof ManyToOne)
+ {
+ validateManyToOneAnnotation((ManyToOne) annotation, convertedObject);
+ }
+ }
+
+ private void validateColumnAnnotation(Column column, Object convertedObject) throws ValidatorException
+ {
+ if (!column.nullable())
+ {
+ checkRequiredConvertedObject(convertedObject);
+ }
+
+ if (convertedObject == null)
+ {
+ return;
+ }
+
+ if (convertedObject instanceof String
+ && column.length() < ((String) convertedObject).length())
+ {
+ this.violation = VALIDATE_LENGTH;
+ this.maxLength = column.length();
+ throw new ValidatorException(getValidationErrorFacesMessage(null));
+ }
+ }
+
+ private void validateBasicAnnotation(Basic basic, Object convertedObject) throws ValidatorException
+ {
+ if (!basic.optional())
+ {
+ checkRequiredConvertedObject(convertedObject);
+ }
+ }
+
+ private void validateOneToOneAnnotation(OneToOne oneToOne, Object convertedObject)
+ {
+ if (!oneToOne.optional())
+ {
+ checkRequiredConvertedObject(convertedObject);
+ }
+ }
+
+ private void validateManyToOneAnnotation(ManyToOne manyToOne, Object convertedObject)
+ {
+ if (!manyToOne.optional())
+ {
+ checkRequiredConvertedObject(convertedObject);
+ }
+ }
+
+ @ToDo(Priority.MEDIUM)
+ private void checkRequiredConvertedObject(Object convertedObject) throws ValidatorException
+ {
+ if (convertedObject == null || ("".equals(convertedObject) && ExtValUtils.interpretEmptyStringValuesAsNull()))
+ {
+ this.violation = CommonMetaDataKeys.REQUIRED;
+ throw new RequiredValidatorException(getValidationErrorFacesMessage(null));
+ }
+ }
+
+ protected String getValidationErrorMsgKey(Annotation annotation)
+ {
+ if (VALIDATE_LENGTH.equals(this.violation))
+ {
+ return "field_too_long";
+ }
+ else
+ {
+ return "field_required";
+ }
+ }
+
+ protected String getErrorMessageDetail(Annotation annotation)
+ {
+ String message = super.getErrorMessageDetail(annotation);
+
+ if (VALIDATE_LENGTH.equals(this.violation))
+ {
+ return message.replace("{0}", "" + this.maxLength);
+ }
+ else
+ {
+ return message;
+ }
+ }
+
+ @Override
+ protected String resolveMessage(String key)
+ {
+ String result = super.resolveMessage(key);
+ String marker = AbstractValidationErrorMessageResolver.MISSING_RESOURCE_MARKER;
+
+ if((marker + key + marker).equals(result))
+ {
+ this.useFacesBundle = true;
+ }
+
+ return result;
+ }
+
+ @Override
+ protected boolean processAfterValidatorException(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException e)
+ {
+ FacesMessage facesMessage = e.getFacesMessage();
+
+ if(this.useFacesBundle)
+ {
+ if(VALIDATE_LENGTH.equals(this.violation))
+ {
+ ExtValUtils.replaceWithDefaultMaximumMessage(facesMessage, this.maxLength);
+ }
+ else
+ {
+ ExtValUtils.replaceWithDefaultRequiredMessage(facesMessage);
+ }
+ }
+
+ return super.processAfterValidatorException(facesContext, uiComponent, metaDataEntry, convertedObject, e);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LengthStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LengthStrategy.java
new file mode 100644
index 0000000..9cd0558
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LengthStrategy.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.Length;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.LengthValidator;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@UsageInformation(UsageCategory.INTERNAL)
+public class LengthStrategy extends AbstractValidationStrategy
+{
+ protected void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+ Length annotation = metaDataEntry.getValue(Length.class);
+ LengthValidator lengthValidator = (LengthValidator)facesContext.getApplication()
+ .createValidator("javax.faces.Length");
+
+ lengthValidator.setMinimum(annotation.minimum());
+ lengthValidator.setMaximum(annotation.maximum());
+
+ lengthValidator.validate(facesContext, uiComponent, convertedObject);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LongRangeStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LongRangeStrategy.java
new file mode 100644
index 0000000..6358202
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LongRangeStrategy.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.LongRange;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.LongRangeValidator;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@UsageInformation(UsageCategory.INTERNAL)
+public class LongRangeStrategy extends AbstractValidationStrategy
+{
+ protected void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+
+ LongRange annotation = metaDataEntry.getValue(LongRange.class);
+ LongRangeValidator longRangeValidator = (LongRangeValidator)facesContext.getApplication()
+ .createValidator("javax.faces.LongRange");
+
+ longRangeValidator.setMinimum(annotation.minimum());
+ longRangeValidator.setMaximum(annotation.maximum());
+
+ longRangeValidator.validate(facesContext, uiComponent, convertedObject);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/PatternStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/PatternStrategy.java
new file mode 100644
index 0000000..6a3f4ef
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/PatternStrategy.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.Pattern;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractAnnotationValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@UsageInformation(UsageCategory.INTERNAL)
+public class PatternStrategy extends AbstractAnnotationValidationStrategy<Pattern>
+{
+ protected void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+ Pattern annotation = metaDataEntry.getValue(Pattern.class);
+
+ for (String expression : annotation.value())
+ {
+ if (!java.util.regex.Pattern.compile(expression).matcher(convertedObject.toString()).matches())
+ {
+ throw new ValidatorException(new FacesMessage(
+ FacesMessage.SEVERITY_ERROR,
+ getErrorMessageSummary(annotation),
+ getErrorMessageDetail(annotation).replace("{0}", expression)));
+ }
+ }
+ }
+
+ protected String getValidationErrorMsgKey(Pattern annotation)
+ {
+ return annotation.validationErrorMsgKey();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RequiredStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RequiredStrategy.java
new file mode 100644
index 0000000..c09e4c7
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RequiredStrategy.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.Required;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractAnnotationValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.AbstractValidationErrorMessageResolver;
+import org.apache.myfaces.extensions.validator.core.validation.exception.RequiredValidatorException;
+import org.apache.myfaces.extensions.validator.core.validation.NullValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.EmptyValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@NullValueAwareValidationStrategy
+@EmptyValueAwareValidationStrategy
+@UsageInformation(UsageCategory.INTERNAL)
+public class RequiredStrategy extends AbstractAnnotationValidationStrategy<Required>
+{
+ private boolean useFacesBundle = false;
+
+ public void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+ if (convertedObject == null || convertedObject.equals("") ||
+ (convertedObject instanceof Collection && ((Collection)convertedObject).isEmpty()) ||
+ (convertedObject instanceof Map && ((Map)convertedObject).isEmpty()))
+ {
+ throw new RequiredValidatorException(
+ getValidationErrorFacesMessage(metaDataEntry.getValue(Required.class)));
+ }
+ }
+
+ protected String getValidationErrorMsgKey(Required annotation)
+ {
+ return annotation.validationErrorMsgKey();
+ }
+
+ @Override
+ protected String resolveMessage(String key)
+ {
+ String result = super.resolveMessage(key);
+ String marker = AbstractValidationErrorMessageResolver.MISSING_RESOURCE_MARKER;
+
+ if((marker + key + marker).equals(result))
+ {
+ this.useFacesBundle = true;
+ }
+
+ return result;
+ }
+
+ @Override
+ protected boolean processAfterValidatorException(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException e)
+ {
+ if(this.useFacesBundle)
+ {
+ ExtValUtils.replaceWithDefaultRequiredMessage(e.getFacesMessage());
+ }
+
+ return super.processAfterValidatorException(facesContext, uiComponent, metaDataEntry, convertedObject, e);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/SkipValidationStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/SkipValidationStrategy.java
new file mode 100644
index 0000000..adf0d8e
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/SkipValidationStrategy.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidation;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.NullValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.EmptyValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.el.ValueBindingExpression;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@NullValueAwareValidationStrategy
+@EmptyValueAwareValidationStrategy
+@UsageInformation(UsageCategory.INTERNAL)
+public class SkipValidationStrategy implements ValidationStrategy
+{
+ public void validate(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+ String[] valueBindingExpressions = metaDataEntry.getValue(SkipValidation.class).value();
+
+ for(String valueBindingExpression : valueBindingExpressions)
+ {
+ if(Boolean.TRUE.equals(ExtValUtils.getELHelper().getValueOfExpression(
+ facesContext, new ValueBindingExpression(valueBindingExpression))))
+ {
+ metaDataEntry.setProperty(PropertyInformationKeys.SKIP_VALIDATION, true);
+ break;
+ }
+ }
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/ValidatorStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/ValidatorStrategy.java
new file mode 100644
index 0000000..bb3cc91
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/ValidatorStrategy.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.baseval.strategy;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.Validator;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@UsageInformation(UsageCategory.INTERNAL)
+public class ValidatorStrategy extends AbstractValidationStrategy
+{
+ protected void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry,
+ Object convertedObject) throws ValidatorException
+ {
+
+ Class<? extends javax.faces.validator.Validator>[] validatorClasses =
+ metaDataEntry.getValue(Validator.class).value();
+
+ javax.faces.validator.Validator validator;
+ for (Class validatorClassName : validatorClasses)
+ {
+ validator = (javax.faces.validator.Validator) ClassUtils
+ .tryToInstantiateClass(validatorClassName);
+
+ if (validator == null)
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace(validatorClassName.getName() + " not found");
+ }
+
+ continue;
+ }
+ validator.validate(facesContext, uiComponent, convertedObject);
+ }
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationPhaseListener.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationPhaseListener.java
new file mode 100644
index 0000000..c66ac60
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationPhaseListener.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval;
+
+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;
+import org.apache.myfaces.extensions.validator.util.JsfUtils;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.crossval.strategy.AbstractCrossValidationStrategy;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.PropertyValidationModuleKey;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.faces.validator.ValidatorException;
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+
+/**
+ * This phase listener processes cross validation as soon as it finds a special request scoped storage.<br/>
+ * So it's possible to add information during the process validation phase. At the end of this phase it gets processed.
+ * After that the storage gets reseted.<p/>
+ * If you provide a custom extension and you add the same storage type within a different phase,
+ * it also gets processed at the end of that phase.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class CrossValidationPhaseListener implements PhaseListener
+{
+ private boolean isInitialized = false;
+ private static final long serialVersionUID = -5333405897635742732L;
+
+ public void afterPhase(PhaseEvent event)
+ {
+ try
+ {
+ CrossValidationStorage crossValidationStorage = CrossValidationUtils.getOrInitCrossValidationStorage();
+ for (CrossValidationStorageEntry entry : crossValidationStorage.getCrossValidationStorageEntries())
+ {
+ try
+ {
+ if(!ExtValUtils.executeGlobalBeforeValidationInterceptors(
+ FacesContext.getCurrentInstance(),
+ entry.getComponent(),
+ entry.getConvertedObject(),
+ CrossValidationStorageEntry.class.getName(),
+ entry,
+ PropertyValidationModuleKey.class))
+ {
+ continue;
+ }
+
+ //call init-method
+ if(entry.getValidationStrategy() instanceof AbstractCrossValidationStrategy)
+ {
+ ReflectionUtils.tryToInvokeMethod(
+ entry.getValidationStrategy(),
+ ReflectionUtils.tryToGetMethod(
+ ProxyUtils.getUnproxiedClass(entry.getValidationStrategy().getClass()),
+ "initCrossValidation",
+ CrossValidationStorageEntry.class),
+ entry);
+ }
+
+ /*
+ * validation
+ */
+ entry.getValidationStrategy().processCrossValidation(entry, crossValidationStorage);
+ }
+ catch (ValidatorException validatorException)
+ {
+ boolean addMessage = true;
+
+ if(entry.getValidationStrategy() instanceof AbstractCrossValidationStrategy)
+ {
+ try
+ {
+ addMessage = (Boolean)ReflectionUtils.tryToInvokeMethod(
+ entry.getValidationStrategy(),
+ ReflectionUtils.tryToGetMethod(
+ ProxyUtils.getUnproxiedClass(entry.getValidationStrategy().getClass()),
+ "processAfterCrossValidatorException",
+ CrossValidationStorageEntry.class,
+ validatorException.getClass()),
+ entry,
+ validatorException);
+ }
+ catch (Throwable e)
+ {
+ throw new FacesException(e);
+ }
+ }
+
+ if(addMessage)
+ {
+ FacesMessage facesMessage = validatorException.getFacesMessage();
+
+ if (facesMessage != null &&
+ facesMessage.getSummary() != null && facesMessage.getDetail() != null)
+ {
+ ExtValUtils.tryToAddViolationMessageForComponentId(entry.getClientId(), facesMessage);
+ }
+
+ ExtValUtils.tryToBlocksNavigationForComponentId(entry.getClientId(), facesMessage);
+ }
+ }
+ finally
+ {
+ ExtValUtils.executeGlobalAfterValidationInterceptors(
+ FacesContext.getCurrentInstance(),
+ entry.getComponent(),
+ entry.getConvertedObject(),
+ CrossValidationStorageEntry.class.getName(),
+ entry,
+ PropertyValidationModuleKey.class);
+ }
+ }
+ }
+ finally
+ {
+ CrossValidationUtils.resetCrossValidationStorage();
+ }
+ }
+
+ public void beforePhase(PhaseEvent event)
+ {
+ if (!isInitialized)
+ {
+ if (WebXmlParameter.DEACTIVATE_CROSSVALIDATION != null
+ && WebXmlParameter.DEACTIVATE_CROSSVALIDATION.equalsIgnoreCase("true"))
+ {
+ JsfUtils.deregisterPhaseListener(this);
+ }
+ else
+ {
+ isInitialized = true;
+ }
+ }
+ }
+
+ public PhaseId getPhaseId()
+ {
+ return PhaseId.ANY_PHASE;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (!(o instanceof CrossValidationPhaseListener))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/WebXmlParameter.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/WebXmlParameter.java
new file mode 100644
index 0000000..1c40279
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/WebXmlParameter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval;
+
+import org.apache.myfaces.extensions.validator.util.WebXmlUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * centralized in order that these information arn't spread over the complete code base
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public interface WebXmlParameter
+{
+ static final String DEACTIVATE_CROSSVALIDATION = WebXmlUtils
+ .getInitParameter("DEACTIVATE_CROSSVALIDATION");
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIs.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIs.java
new file mode 100644
index 0000000..444d2a4
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIs.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+import java.text.DateFormat;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface DateIs
+{
+ String[] valueOf();
+
+ /*
+ * optional section
+ */
+
+ DateIsType type() default DateIsType.same;
+
+ String validationErrorMsgKey() default "";
+
+ String notBeforeErrorMsgKey() default "wrong_date_not_before";
+
+ String notAfterErrorMsgKey() default "wrong_date_not_after";
+
+ String notEqualErrorMsgKey() default "wrong_date_not_equal";
+
+ int errorMessageDateStyle() default DateFormat.MEDIUM;
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIsType.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIsType.java
new file mode 100644
index 0000000..7c5f482
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIsType.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@ToDo(value = Priority.MEDIUM, description = "beforeOrSame, afterOrSame")
+@UsageInformation(UsageCategory.API)
+public enum DateIsType
+{
+ before, after, same
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/Equals.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/Equals.java
new file mode 100644
index 0000000..ffe76b7
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/Equals.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface Equals
+{
+ String[] value();
+
+ String validationErrorMsgKey() default "duplicated_content_required";
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/NotEquals.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/NotEquals.java
new file mode 100644
index 0000000..927bc44
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/NotEquals.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface NotEquals
+{
+ String[] value();
+
+ String validationErrorMsgKey() default "duplicated_content_denied";
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIf.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIf.java
new file mode 100644
index 0000000..845db24
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIf.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ValidationParameter;
+import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import java.lang.annotation.Documented;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+@Documented
+@UsageInformation(UsageCategory.API)
+public @interface RequiredIf
+{
+ String[] valueOf();
+
+ /*
+ * optional section
+ */
+
+ RequiredIfType is() default RequiredIfType.not_empty;
+
+ String validationErrorMsgKey() default "empty_field";
+
+ Class<? extends ValidationParameter>[] parameters() default ViolationSeverity.Error.class;
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIfType.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIfType.java
new file mode 100644
index 0000000..61c58d9
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIfType.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public enum RequiredIfType
+{
+ empty, not_empty
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages.properties
new file mode 100644
index 0000000..ef60759
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages.properties
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+duplicated_content_required=Input is different
+duplicated_content_required_detail=Input is different
+
+duplicated_content_denied=Same input isn't allowed
+duplicated_content_denied_detail=Same input isn't allowed
+
+wrong_date=Wrong date
+wrong_date_detail=Wrong date
+
+wrong_date_not_before=Date has to be after {0}
+wrong_date_not_before_detail=Date has to be after {0}
+
+wrong_date_not_after=Date has to be before {0}
+wrong_date_not_after_detail=Date has to be before {0}
+
+wrong_date_not_equal=Date isn't equal to {0}
+wrong_date_not_equal_detail=Date isn't equal to {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_ar.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_ar.properties
new file mode 100644
index 0000000..9ff93c4
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_ar.properties
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+duplicated_content_required=\u0627\u0644\u0625\u062f\u062e\u0627\u0644 \u0645\u062e\u062a\u0644\u0641
+duplicated_content_required_detail=\u0627\u0644\u0625\u062f\u062e\u0627\u0644 \u0645\u062e\u062a\u0644\u0641
+
+duplicated_content_denied=\u063a\u064a\u0631 \u0645\u0633\u0645\u0648\u062d \u0628\u0625\u062f\u062e\u0627\u0644 \u0646 \u0641\u0633 \u0642\u064a\u0645\u0629 \u0627\u0644\u0625\u062f\u062e\u0627\u0644
+duplicated_content_denied_detail=\u063a\u064a\u0631 \u0645\u0633\u0645\u0648\u062d \u0628\u0625\u062f\u062e\u0627\u0644 \u0646\u0641\u0633 \u0642\u064a\u0645\u0629 \u0627\u0644\u0625\u062f\u062e\u0627\u0644
+
+wrong_date=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u062e\u0627\u0637\u0649\u0621
+wrong_date_detail=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u062e\u0627\u0637\u0649\u0621
+
+wrong_date_not_before=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648 \u0646 \u0628\u0639\u062f {0}
+wrong_date_not_before_detail=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643 \u0648\u0646 \u0628\u0639\u062f {0}
+
+wrong_date_not_after=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648 \u0646 \u0642\u0628\u0644 {0}
+wrong_date_not_after_detail=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643 \u0648\u0646 \u0642\u0628\u0644 {0}
+
+wrong_date_not_equal=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u0644\u0627 \u064a\u0633\u0627\u0648\u0649 {0}
+wrong_date_not_equal_detail=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u0644\u0627 \u064a\u0633\u0627\u0648\u0649 {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_ca.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_ca.properties
new file mode 100644
index 0000000..2854ed2
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_ca.properties
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+duplicated_content_required=el valor \u00e9 diferent
+duplicated_content_required_detail=el valor \u00e9 diferent
+
+duplicated_content_denied=no es permet el mateix valor
+duplicated_content_denied_detail=no es permet el mateix valor
+
+wrong_date=data err\u00f2nia
+wrong_date_detail=data err\u00f2nia
+
+wrong_date_not_before=la data ha de ser posterior a {0}
+wrong_date_not_before_detail=la data ha de ser posterior a {0}
+
+wrong_date_not_after=la data ha de ser anterior a {0}
+wrong_date_not_after_detail=la data ha de ser posterior a {0}
+
+wrong_date_not_equal=la data no \u000e9s igual a {0}
+wrong_date_not_equal_detail=la data no \u000e9s igual a {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_de.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_de.properties
new file mode 100644
index 0000000..9d87234
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_de.properties
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+duplicated_content_required=Eingabe ist unterschiedlich
+duplicated_content_required_detail=Eingabe ist unterschiedlich
+
+duplicated_content_denied=Der gleiche Wert ist nicht erlaubt
+duplicated_content_denied_detail=Der gleiche Wert ist nicht erlaubt
+
+wrong_date=Datum inkorrekt
+wrong_date_detail=Datum inkorrekt
+
+wrong_date_not_before=Das Datum muss nach dem {0} sein
+wrong_date_not_before_detail=Das Datum muss nach dem {0} sein
+
+wrong_date_not_after=Das Datum muss vor dem {0} sein
+wrong_date_not_after_detail=Das Datum muss vor dem {0} sein
+
+wrong_date_not_equal=Das Datum entspricht nicht dem {0}
+wrong_date_not_equal_detail=Das Datum entspricht nicht dem {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_en.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_en.properties
new file mode 100644
index 0000000..ef60759
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_en.properties
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+duplicated_content_required=Input is different
+duplicated_content_required_detail=Input is different
+
+duplicated_content_denied=Same input isn't allowed
+duplicated_content_denied_detail=Same input isn't allowed
+
+wrong_date=Wrong date
+wrong_date_detail=Wrong date
+
+wrong_date_not_before=Date has to be after {0}
+wrong_date_not_before_detail=Date has to be after {0}
+
+wrong_date_not_after=Date has to be before {0}
+wrong_date_not_after_detail=Date has to be before {0}
+
+wrong_date_not_equal=Date isn't equal to {0}
+wrong_date_not_equal_detail=Date isn't equal to {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_es.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_es.properties
new file mode 100644
index 0000000..00a9170
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_es.properties
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+duplicated_content_required=la entrada es diferente
+duplicated_content_required_detail=la entrada es diferente
+
+duplicated_content_denied=no se permiten entradas iguales
+duplicated_content_denied_detail=no se permiten entradas iguales
+
+wrong_date=fecha equivocada
+wrong_date_detail=fecha equivocada
+
+wrong_date_not_before=la fecha tiene que ser luego de {0}
+wrong_date_not_before_detail=la fecha tiene que ser luego de {0}
+
+wrong_date_not_after=la fecha tiene que ser antes de {0}
+wrong_date_not_after_detail=la fecha tiene que ser antes de {0}
+
+wrong_date_not_equal=la fecha no es igual a {0}
+wrong_date_not_equal_detail=la fecha no es igual a {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_fr.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_fr.properties
new file mode 100644
index 0000000..c5f0218
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_fr.properties
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+duplicated_content_required=Les champs sont différents
+duplicated_content_required_detail=Les champs sont différents
+
+duplicated_content_denied=Les champs doivent être différents
+duplicated_content_denied_detail=Les champs doivent être différents
+
+wrong_date=La date est incorrecte
+wrong_date_detail=La date est incorrecte
+
+wrong_date_not_before=La date doit être après {0}
+wrong_date_not_before_detail=La date doit être après {0}
+
+wrong_date_not_after=La date doit être avant {0}
+wrong_date_not_after_detail=La date doit être avant {0}
+
+wrong_date_not_equal=La date n'est pas égale à {0}
+wrong_date_not_equal_detail=La date n'est pas égale à {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_it.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_it.properties
new file mode 100644
index 0000000..b042801
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_it.properties
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+duplicated_content_required=Valori non uguali
+duplicated_content_required_detail=I valori inseriti non coincidono
+
+duplicated_content_denied=Lo stesso valore non è permesso
+duplicated_content_denied_detail=Lo stesso valore non è permesso
+
+wrong_date=Data errata
+wrong_date_detail=Data errata
+
+wrong_date_not_before=La data deve essere dopo di {0}
+wrong_date_not_before_detail=La data deve essere dopo di {0}
+
+wrong_date_not_after=La data deve essere prima di {0}
+wrong_date_not_after_detail=La data deve essere prima di {0}
+
+wrong_date_not_equal=La data non è uguale a {0}
+wrong_date_not_equal_detail=La data non è uguale a {0}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_tr.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_tr.properties
new file mode 100644
index 0000000..aaf6a9d
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages_tr.properties
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+duplicated_content_required=girilen de\u011fer farkl\u0131
+duplicated_content_required_detail=girilen de\u011fer farkl\u0131
+
+duplicated_content_denied=ayn\u0131 de\u011fer girilemez
+duplicated_content_denied_detail=ayn\u0131 de\u011fer girilemez
+
+wrong_date=yanl\u0131\u015f tarih
+wrong_date_detail=yanl\u0131\u015f tarih
+
+wrong_date_not_before=tarih {0} de\u011ferinden sonra olmal\u0131d\u0131r
+wrong_date_not_before_detail=tarih {0} de\u011ferinden sonra olmal\u0131d\u0131r
+
+wrong_date_not_after=tarih {0} de\u011ferinden \u00f6nce olmal\u0131d\u0131r
+wrong_date_not_after_detail=tarih {0} de\u011ferinden \u00f6nce olmal\u0131d\u0131r
+
+wrong_date_not_equal=tarih {0} de\u011ferine e\u015fit de\u011fil
+wrong_date_not_equal_detail=tarih {0} de\u011ferine e\u015fit de\u011fil
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/resolver/DefaultValidationErrorMessageResolver.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/resolver/DefaultValidationErrorMessageResolver.java
new file mode 100644
index 0000000..3d7659e
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/resolver/DefaultValidationErrorMessageResolver.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.message.resolver;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultValidationErrorMessageResolver
+ extends
+ org.apache.myfaces.extensions.validator.core.validation.message.resolver.DefaultValidationErrorMessageResolver
+{
+ private static String baseName = null;
+
+ @Override
+ protected String getBaseName()
+ {
+ if (baseName == null)
+ {
+ baseName = super.getBaseName();
+ }
+
+ return baseName;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/recorder/CrossValidationUserInputRecorder.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/recorder/CrossValidationUserInputRecorder.java
new file mode 100644
index 0000000..dd3b08d
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/recorder/CrossValidationUserInputRecorder.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.recorder;
+
+import org.apache.myfaces.extensions.validator.core.recorder.ProcessedInformationRecorder;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorage;
+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.context.FacesContext;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class CrossValidationUserInputRecorder implements ProcessedInformationRecorder
+{
+ public void recordUserInput(UIComponent uiComponent, Object value)
+ {
+ if (!(uiComponent instanceof EditableValueHolder))
+ {
+ return;
+ }
+
+ //to support local cross-validation (within the same entity)
+ ProcessedInformationStorage processedInformationStorage = CrossValidationUtils
+ .getOrInitProcessedInformationStorage();
+
+ ProcessedInformationStorageEntry entry;
+
+ PropertyDetails propertyDetails =
+ ExtValUtils.getELHelper().getPropertyDetailsOfValueBinding(uiComponent);
+
+ if(propertyDetails == null)
+ {
+ return;
+ }
+
+ entry = new ProcessedInformationStorageEntry();
+ entry.setBean(propertyDetails.getBaseObject());
+ entry.setConvertedValue(value);
+ entry.setComponent(uiComponent);
+ entry.setClientId(uiComponent.getClientId(FacesContext.getCurrentInstance()));
+
+ String key = propertyDetails.getKey();
+
+ //for local cross-validation
+ if (processedInformationStorage.containsEntry(key) &&
+ processedInformationStorage.getEntry(key).getBean() != null &&
+ !processedInformationStorage.getEntry(key).getBean().equals(entry.getBean()))
+ {
+ //for the validation within a complex component e.g. a table
+ //don't override existing expression (style: #{entry.property}) - make a special mapping
+
+ List<ProcessedInformationStorageEntry> furtherEntries =
+ processedInformationStorage.getEntry(key).getFurtherEntries();
+
+ if (furtherEntries == null)
+ {
+ furtherEntries = new ArrayList<ProcessedInformationStorageEntry>();
+
+ processedInformationStorage.getEntry(key).setFurtherEntries(furtherEntries);
+ }
+
+ furtherEntries.add(entry);
+ }
+ else
+ {
+ //for normal validation
+ processedInformationStorage.setEntry(key, entry);
+ }
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/CrossValidationStorage.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/CrossValidationStorage.java
new file mode 100644
index 0000000..c09fad6
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/CrossValidationStorage.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.List;
+
+/**
+ * normally it should be in the storage package - due to backward compatibility it isn't the case
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface CrossValidationStorage
+{
+ void add(CrossValidationStorageEntry entry);
+
+ List<CrossValidationStorageEntry> getCrossValidationStorageEntries();
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/CrossValidationStorageEntry.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/CrossValidationStorageEntry.java
new file mode 100644
index 0000000..c09e1e7
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/CrossValidationStorageEntry.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.crossval.strategy.CrossValidationStrategy;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+
+/**
+ * normally it should be in the storage package - due to backward compatibility it isn't the case
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public class CrossValidationStorageEntry
+{
+ private MetaDataEntry metaDataEntry;
+ //for complex components (e.g. a table) stores the object of entry (#{entry.property})
+ private UIComponent component;
+ private Object convertedObject;
+ private CrossValidationStrategy validationStrategy;
+ //just for input components within complex components e.g. dataTable,...
+ private String clientId;
+
+ public MetaDataEntry getMetaDataEntry()
+ {
+ return metaDataEntry;
+ }
+
+ public void setMetaDataEntry(MetaDataEntry metaDataEntry)
+ {
+ this.metaDataEntry = metaDataEntry;
+ }
+
+ public UIComponent getComponent()
+ {
+ return component;
+ }
+
+ public void setComponent(UIComponent component)
+ {
+ this.component = component;
+ }
+
+ public Object getConvertedObject()
+ {
+ return convertedObject;
+ }
+
+ public void setConvertedObject(Object convertedObject)
+ {
+ this.convertedObject = convertedObject;
+ }
+
+ public CrossValidationStrategy getValidationStrategy()
+ {
+ return validationStrategy;
+ }
+
+ public void setValidationStrategy(CrossValidationStrategy validationStrategy)
+ {
+ this.validationStrategy = validationStrategy;
+ }
+
+ public String getClientId()
+ {
+ return clientId;
+ }
+
+ public void setClientId(String clientId)
+ {
+ this.clientId = clientId;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultCrossValidationStorage.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultCrossValidationStorage.java
new file mode 100644
index 0000000..ae10a3b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultCrossValidationStorage.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultCrossValidationStorage implements CrossValidationStorage
+{
+ private List<CrossValidationStorageEntry> crossValidationStorageEntries =
+ new ArrayList<CrossValidationStorageEntry>();
+
+ public void add(CrossValidationStorageEntry entry)
+ {
+ this.crossValidationStorageEntries.add(entry);
+ }
+
+ public List<CrossValidationStorageEntry> getCrossValidationStorageEntries()
+ {
+ return crossValidationStorageEntries;
+ }
+
+ public void setCrossValidationStorageEntries(List<CrossValidationStorageEntry> crossValidationStorageEntries)
+ {
+ this.crossValidationStorageEntries = crossValidationStorageEntries;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultCrossValidationStorageManager.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultCrossValidationStorageManager.java
new file mode 100644
index 0000000..e041c95d
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultCrossValidationStorageManager.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.core.storage.AbstractRequestScopeAwareStorageManager;
+
+/**
+ * default storage-manager for cross-validation entries
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultCrossValidationStorageManager
+ extends AbstractRequestScopeAwareStorageManager<CrossValidationStorage>
+{
+ public String getStorageManagerKey()
+ {
+ //for better backward compatibility
+ return CrossValidationStorage.class.getName();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultProcessedInformationStorage.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultProcessedInformationStorage.java
new file mode 100644
index 0000000..c28e187
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultProcessedInformationStorage.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class DefaultProcessedInformationStorage implements ProcessedInformationStorage
+{
+ private Map<String, ProcessedInformationStorageEntry> processedInformationMap =
+ new HashMap<String, ProcessedInformationStorageEntry>();
+
+ public void setEntry(String key, ProcessedInformationStorageEntry entry)
+ {
+ this.processedInformationMap.put(key, entry);
+ }
+
+ public boolean containsEntry(String key)
+ {
+ return processedInformationMap.containsKey(key);
+ }
+
+ public ProcessedInformationStorageEntry getEntry(String key)
+ {
+ return processedInformationMap.get(key);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultProcessedInformationStorageManager.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultProcessedInformationStorageManager.java
new file mode 100644
index 0000000..66182c8
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/DefaultProcessedInformationStorageManager.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.core.storage.AbstractRequestScopeAwareStorageManager;
+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;
+
+/**
+ * default storage-manager for processed information entries
+ *
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public class DefaultProcessedInformationStorageManager
+ extends AbstractRequestScopeAwareStorageManager<CrossValidationStorage>
+{
+ public String getStorageManagerKey()
+ {
+ //for better backward compatibility
+ return CrossValidationUtils.class.getName();
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/ProcessedInformationStorage.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/ProcessedInformationStorage.java
new file mode 100644
index 0000000..a0b156e
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/ProcessedInformationStorage.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@UsageInformation(INTERNAL)
+public interface ProcessedInformationStorage
+{
+ void setEntry(String key, ProcessedInformationStorageEntry entry);
+
+ boolean containsEntry(String key);
+
+ ProcessedInformationStorageEntry getEntry(String key);
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/ProcessedInformationStorageEntry.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/ProcessedInformationStorageEntry.java
new file mode 100644
index 0000000..3cf789c
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/ProcessedInformationStorageEntry.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage;
+
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+
+import javax.faces.component.UIComponent;
+import java.util.List;
+
+/**
+ * In order to build up a mapping which is used for cross-validation.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class ProcessedInformationStorageEntry
+{
+ private Object bean;
+ private Object convertedValue;
+ private UIComponent component;
+ //for complex components (e.g. a table there are multiple entries with
+ //the same key (here the el expression #{entry.property})
+ //however, don't override the previous entry - they arn't the same;
+ private List<ProcessedInformationStorageEntry> furtherEntries;
+ //just for input components within complex components e.g. dataTable,...
+ private String clientId;
+
+ /*
+ * generated
+ */
+ public Object getBean()
+ {
+ return bean;
+ }
+
+ public void setBean(Object bean)
+ {
+ this.bean = bean;
+ }
+
+ public Object getConvertedValue()
+ {
+ return convertedValue;
+ }
+
+ public void setConvertedValue(Object convertedValue)
+ {
+ this.convertedValue = convertedValue;
+ }
+
+ public UIComponent getComponent()
+ {
+ return component;
+ }
+
+ public void setComponent(UIComponent component)
+ {
+ this.component = component;
+ }
+
+ public String getClientId()
+ {
+ return clientId;
+ }
+
+ public void setClientId(String clientId)
+ {
+ this.clientId = clientId;
+ }
+
+ public List<ProcessedInformationStorageEntry> getFurtherEntries()
+ {
+ return furtherEntries;
+ }
+
+ public void setFurtherEntries(List<ProcessedInformationStorageEntry> furtherEntries)
+ {
+ this.furtherEntries = furtherEntries;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/mapper/CrossValidationStorageNameMapper.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/mapper/CrossValidationStorageNameMapper.java
new file mode 100644
index 0000000..58ebf3b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/mapper/CrossValidationStorageNameMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.DefaultCrossValidationStorage;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(200)
+@UsageInformation(INTERNAL)
+public class CrossValidationStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String key)
+ {
+ return (CrossValidationStorage.class.getName().equals(key)) ?
+ DefaultCrossValidationStorage.class.getName() : null;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/mapper/ProcessedInformationStorageNameMapper.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/mapper/ProcessedInformationStorageNameMapper.java
new file mode 100644
index 0000000..9875303
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/storage/mapper/ProcessedInformationStorageNameMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.storage.mapper;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;
+import org.apache.myfaces.extensions.validator.core.InvocationOrder;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.DefaultProcessedInformationStorage;
+
+/**
+ * @author Gerhard Petracek
+ * @since x.x.3
+ */
+@InvocationOrder(200)
+@UsageInformation(INTERNAL)
+public class ProcessedInformationStorageNameMapper implements NameMapper<String>
+{
+ public String createName(String key)
+ {
+ return (ProcessedInformationStorage.class.getName().equals(key)) ?
+ DefaultProcessedInformationStorage.class.getName() : null;
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCompareStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCompareStrategy.java
new file mode 100644
index 0000000..530202b
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCompareStrategy.java
@@ -0,0 +1,337 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.lang.annotation.Annotation;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.validator.ValidatorException;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.util.ClassUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.core.ExtValContext;
+import org.apache.myfaces.extensions.validator.core.CustomInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SuppressWarnings({"unchecked"})
+@UsageInformation(UsageCategory.INTERNAL)
+public abstract class AbstractCompareStrategy<A extends Annotation> extends AbstractCrossValidationStrategy
+{
+ protected static List<ReferencingStrategy> referencingStrategies;
+ protected Map<Object, Object> violationResultStorage = new HashMap<Object, Object>();
+
+ public AbstractCompareStrategy()
+ {
+ initReferencingStrategies();
+ }
+
+ protected void initReferencingStrategies()
+ {
+ if (referencingStrategies == null)
+ {
+ referencingStrategies = new ArrayList<ReferencingStrategy>();
+
+ String customReferencingStrategyClassName =
+ ExtValContext.getContext().getInformationProviderBean()
+ .get(CustomInformation.BASE_PACKAGE) + "ReferencingStrategy";
+
+ ReferencingStrategy customReferencingStrategy = (ReferencingStrategy) ClassUtils
+ .tryToInstantiateClassForName(customReferencingStrategyClassName);
+
+ if (customReferencingStrategy != null)
+ {
+ referencingStrategies.add(customReferencingStrategy);
+ }
+
+ referencingStrategies.add(new ELCompareStrategy());
+ //referencingStrategies.add(new AliasCompareStrategy());
+ referencingStrategies.add(new LocalCompareStrategy());
+ referencingStrategies.add(new LocalPropertyChainCompareStrategy());
+ }
+ }
+
+ public void processCrossValidation(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage) throws ValidatorException
+ {
+ //initCrossValidation is done in the CrossValidationPhaseListener
+
+ String[] validationTargets = getValidationTargets((A)
+ crossValidationStorageEntry.getMetaDataEntry().getValue());
+
+ for (String validationTarget : validationTargets)
+ {
+ validationTarget = validationTarget.trim();
+
+ //select validation method
+ tryToValidate(crossValidationStorageEntry, crossValidationStorage, validationTarget);
+ }
+ }
+
+ private boolean tryToValidate(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage,
+ String validationTarget)
+ {
+ for (ReferencingStrategy referencingStrategy : referencingStrategies)
+ {
+ if (referencingStrategy.evaluateReferenceAndValidate(
+ crossValidationStorageEntry, crossValidationStorage, validationTarget, this))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @SuppressWarnings({"ThrowableInstanceNeverThrown"})
+ protected final void processTargetComponentAfterViolation(
+ CrossValidationStorageEntry entryOfSource,
+ CrossValidationStorageEntry entryOfTarget)
+ {
+ if (!handleTargetViolation(entryOfSource, entryOfTarget))
+ {
+ //no target - because there is no target component - value was validated against the model
+ if(entryOfTarget == null)
+ {
+ processTargetComponentAsSourceComponentAfterViolation(entryOfSource);
+ return;
+ }
+
+ return;
+ }
+
+ //get validation error messages for the target component
+ String summary = getErrorMessageSummary((A)entryOfSource.getMetaDataEntry().getValue(), true);
+ String details = getErrorMessageDetail((A)entryOfSource.getMetaDataEntry().getValue(), true);
+
+ //validation target isn't bound to a component withing the current page
+ //(see validateFoundEntry, tryToValidateLocally and tryToValidateBindingOnly)
+ if (entryOfTarget == null)
+ {
+ entryOfTarget = entryOfSource;
+ }
+
+ FacesMessage message;
+ if (entryOfTarget.getMetaDataEntry() != null)
+ {
+ message = getTargetComponentErrorMessage((A)entryOfTarget.getMetaDataEntry().getValue(), summary, details);
+ }
+ else
+ {
+ //TODO document possible side effects
+ //due to a missing target annotation (see: tryToValidateLocally)
+ message = getTargetComponentErrorMessage((A)entryOfSource.getMetaDataEntry().getValue(), summary, details);
+ }
+
+ if ((message.getSummary() != null || message.getDetail() != null) &&
+ entryOfSource.getClientId() != null && !entryOfSource.getClientId().equals(entryOfTarget.getClientId()))
+ {
+ ValidatorException validatorException = new ValidatorException(message);
+
+ boolean isSourceMetaDataUsed = false;
+
+ if(entryOfTarget.getMetaDataEntry() == null)
+ {
+ prepareTargetMetaDataForSeverityAwareInterception(entryOfSource, entryOfTarget);
+ isSourceMetaDataUsed = true;
+ }
+
+ if(ExtValUtils.executeAfterThrowingInterceptors(
+ entryOfTarget.getComponent(), entryOfTarget.getMetaDataEntry(),
+ entryOfTarget.getConvertedObject(), validatorException, this))
+ {
+ ExtValUtils.tryToAddViolationMessageForComponentId(entryOfTarget.getClientId(),
+ ExtValUtils.convertFacesMessage(validatorException.getFacesMessage()));
+ }
+
+ if(isSourceMetaDataUsed)
+ {
+ resetTargetMetaData(entryOfTarget);
+ }
+ }
+ }
+
+ private void prepareTargetMetaDataForSeverityAwareInterception(
+ CrossValidationStorageEntry entryOfSource, CrossValidationStorageEntry entryOfTarget)
+ {
+ entryOfTarget.setMetaDataEntry(entryOfSource.getMetaDataEntry());
+ }
+
+ private void resetTargetMetaData(CrossValidationStorageEntry entryOfTarget)
+ {
+ entryOfTarget.setMetaDataEntry(null);
+ }
+
+ @SuppressWarnings({"ThrowableInstanceNeverThrown"})
+ private void processTargetComponentAsSourceComponentAfterViolation(CrossValidationStorageEntry entryOfSource)
+ {
+ //get validation error messages for the current component
+ String summary = getReverseErrorMessageSummary((A)entryOfSource.getMetaDataEntry().getValue());
+ String details = getReverseErrorMessageDetail((A)entryOfSource.getMetaDataEntry().getValue());
+
+ FacesMessage message = getSourceComponentErrorMessage(
+ (A)entryOfSource.getMetaDataEntry().getValue(), summary, details);
+
+ if (message.getSummary() != null || message.getDetail() != null)
+ {
+ //TODO
+ if(ExtValUtils.executeAfterThrowingInterceptors(entryOfSource.getComponent(),
+ entryOfSource.getMetaDataEntry(),
+ entryOfSource.getConvertedObject(),
+ new ValidatorException(message),
+ this))
+ {
+ ExtValUtils.tryToThrowValidatorExceptionForComponent(entryOfSource.getComponent(), message, null);
+ }
+ }
+ else
+ {
+ //TODO logging
+ }
+ }
+
+ protected final void processSourceComponentAfterViolation(CrossValidationStorageEntry entryOfSource)
+ {
+ if (handleSourceViolation(entryOfSource))
+ {
+ //get validation error messages for the current component
+ String summary = getErrorMessageSummary((A)entryOfSource.getMetaDataEntry().getValue(), false);
+ String details = getErrorMessageDetail((A)entryOfSource.getMetaDataEntry().getValue(), false);
+
+ FacesMessage message = getSourceComponentErrorMessage(
+ (A)entryOfSource.getMetaDataEntry().getValue(), summary, details);
+
+ if (message.getSummary() != null || message.getDetail() != null)
+ {
+ //TODO
+ ExtValUtils.tryToThrowValidatorExceptionForComponent(entryOfSource.getComponent(), message, null);
+ }
+ }
+
+ //just throw a new message - the error message is at the target
+ ExtValUtils.tryToThrowValidatorExceptionForComponent(
+ entryOfSource.getComponent(), new FacesMessage(FacesMessage.SEVERITY_ERROR, null, null), null);
+ }
+
+ protected FacesMessage getSourceComponentErrorMessage(A annotation, String summary, String detail)
+ {
+ return ExtValUtils.createFacesMessage(summary, detail);
+ }
+
+ protected FacesMessage getTargetComponentErrorMessage(A foundAnnotation, String summary, String detail)
+ {
+ return ExtValUtils.createFacesMessage(summary, detail);
+ }
+
+ protected String getErrorMessageSummary(A annotation, boolean isTargetComponent)
+ {
+ return resolveMessage(getValidationErrorMsgKey(annotation, isTargetComponent));
+ }
+
+ protected String getErrorMessageDetail(A annotation, boolean isTargetComponent)
+ {
+ try
+ {
+ String key = getValidationErrorMsgKey(annotation, isTargetComponent);
+ return (key != null) ? resolveMessage(key + DETAIL_MESSAGE_KEY_POSTFIX) : null;
+ }
+ catch (MissingResourceException e)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("couldn't find key " + getValidationErrorMsgKey(annotation, isTargetComponent)
+ + DETAIL_MESSAGE_KEY_POSTFIX, e);
+ }
+ }
+ return null;
+ }
+
+ protected final String getValidationErrorMsgKey(Annotation annotation)
+ {
+ return getValidationErrorMsgKey((A)annotation, false);
+ }
+
+ protected boolean handleTargetViolation(
+ CrossValidationStorageEntry entryOfSource,
+ CrossValidationStorageEntry entryOfTarget)
+ {
+ return entryOfTarget != null && entryOfTarget.getComponent() != null;
+ }
+
+ protected boolean handleSourceViolation(CrossValidationStorageEntry entryOfSource)
+ {
+ return true;
+ }
+
+ protected boolean useTargetComponentToDisplayErrorMsg(CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ return handleTargetViolation(crossValidationStorageEntry, null);
+ }
+
+ /*
+ * no target component (validation against the model) -> get reverse message for source component
+ */
+ protected String getReverseErrorMessageSummary(A annotation)
+ {
+ //if the message is neutral
+ return getErrorMessageSummary(annotation, true);
+ }
+
+ /*
+ * no target component (validation against the model) -> get reverse message for source component
+ */
+ protected String getReverseErrorMessageDetail(A annotation)
+ {
+ //if the message is neutral
+ return getErrorMessageDetail(annotation, true);
+ }
+
+ /*
+ * abstract methods
+ */
+
+ protected abstract String getValidationErrorMsgKey(A annotation, boolean isTargetComponent);
+
+ /*
+ * implements the specific validation logic
+ */
+
+ public abstract boolean isViolation(Object object1, Object object2, A annotation);
+
+ /*
+ * returns the referenced validation targets of the annotation
+ * e.g. @DateIs(type = DateIsType.before, value = "finalExam")
+ * -> method returns an array with one value ("finalExam")
+ */
+ public abstract String[] getValidationTargets(A annotation);
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCrossValidationStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCrossValidationStrategy.java
new file mode 100644
index 0000000..4537612
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCrossValidationStrategy.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractAnnotationValidationStrategy;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public abstract class AbstractCrossValidationStrategy extends
+ AbstractAnnotationValidationStrategy implements CrossValidationStrategy
+{
+ //init cross-validation
+ public void processValidation(FacesContext facesContext,
+ UIComponent uiComponent, MetaDataEntry metaDataEntry, Object convertedObject) throws ValidatorException
+ {
+ CrossValidationStorageEntry entry =
+ getCrossValidationStorageEntry(facesContext, uiComponent, metaDataEntry, convertedObject);
+
+ CrossValidationUtils.getOrInitCrossValidationStorage().add(entry);
+ }
+
+ public CrossValidationStorageEntry getCrossValidationStorageEntry(
+ FacesContext facesContext, UIComponent uiComponent,
+ MetaDataEntry metaDataEntry, Object convertedObject)
+ {
+ CrossValidationStorageEntry entry = new CrossValidationStorageEntry();
+
+ entry.setMetaDataEntry(metaDataEntry);
+ entry.setComponent(uiComponent);
+ entry.setClientId(uiComponent.getClientId(facesContext));
+ entry.setConvertedObject(convertedObject);
+ entry.setValidationStrategy(this);
+
+ return entry;
+ }
+
+ @Override
+ protected final boolean processAfterValidatorException(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject,
+ ValidatorException validatorException)
+ {
+ throw new IllegalStateException("not available for cross validation - use processAfterCrossValidatorException");
+ }
+
+ @Override
+ protected final String getLabel(FacesContext facesContext, UIComponent uiComponent, MetaDataEntry metaDataEntry)
+ {
+ throw new IllegalStateException("not available for cross validation");
+ }
+
+ @Override
+ protected final void initValidation(FacesContext facesContext,
+ UIComponent uiComponent,
+ MetaDataEntry metaDataEntry,
+ Object convertedObject)
+ {
+ //not available for cross validation - use initCrossValidation
+ }
+
+ protected void initCrossValidation(CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ //override if needed
+ }
+
+ //override if needed
+ protected boolean processAfterCrossValidatorException(CrossValidationStorageEntry crossValidationStorageEntry,
+ ValidatorException validatorException)
+ {
+ return ExtValUtils.executeAfterThrowingInterceptors(
+ crossValidationStorageEntry.getComponent(), crossValidationStorageEntry.getMetaDataEntry(),
+ crossValidationStorageEntry.getConvertedObject(), validatorException, this);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationHelper.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationHelper.java
new file mode 100644
index 0000000..07d476e
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationHelper.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class CrossValidationHelper
+{
+ public static void crossValidateCompareStrategy(AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ ProcessedInformationStorageEntry validationTargetEntry,
+ boolean isModelAwareValidation)
+ {
+ if (compareStrategy.isViolation(
+ crossValidationStorageEntry.getConvertedObject(),
+ validationTargetEntry.getConvertedValue(),
+ crossValidationStorageEntry.getMetaDataEntry().getValue(Annotation.class)))
+ {
+ //process after violation
+ //just add messages
+ if(!isModelAwareValidation)
+ {
+ processTargetAfterCrossComponentValidation(
+ compareStrategy, crossValidationStorageEntry, validationTargetEntry);
+ }
+ else
+ {
+ processTargetAfterModelAwareCrossValidation(
+ compareStrategy, crossValidationStorageEntry);
+ }
+
+ //thow exception
+ compareStrategy.processSourceComponentAfterViolation(crossValidationStorageEntry);
+ }
+ }
+
+ private static void processTargetAfterCrossComponentValidation(
+ AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry sourceCrossValidationStorageEntry,
+ ProcessedInformationStorageEntry validationTargetEntry)
+ {
+ CrossValidationStorageEntry targetCrossValidationStorageEntry = new CrossValidationStorageEntry();
+
+ if (compareStrategy.useTargetComponentToDisplayErrorMsg(sourceCrossValidationStorageEntry))
+ {
+ targetCrossValidationStorageEntry.setComponent(validationTargetEntry.getComponent());
+ targetCrossValidationStorageEntry.setClientId(validationTargetEntry.getClientId());
+ }
+ else
+ {
+ targetCrossValidationStorageEntry.setComponent(sourceCrossValidationStorageEntry.getComponent());
+ targetCrossValidationStorageEntry.setClientId(sourceCrossValidationStorageEntry.getClientId());
+ }
+
+ targetCrossValidationStorageEntry.setConvertedObject(validationTargetEntry.getConvertedValue());
+ targetCrossValidationStorageEntry.setValidationStrategy(compareStrategy);
+
+ //add message
+ compareStrategy.processTargetComponentAfterViolation(
+ sourceCrossValidationStorageEntry, targetCrossValidationStorageEntry);
+ }
+
+ private static void processTargetAfterModelAwareCrossValidation(
+ AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ //no target - because there is no target component - value was validated against the model
+ compareStrategy.processTargetComponentAfterViolation(crossValidationStorageEntry, null);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationStrategy.java
new file mode 100644
index 0000000..0c27da5
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationStrategy.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.API)
+public interface CrossValidationStrategy extends ValidationStrategy
+{
+ CrossValidationStorageEntry getCrossValidationStorageEntry(
+ FacesContext facesContext, UIComponent uiComponent,
+ MetaDataEntry metaDataEntry, Object convertedObject);
+
+ void processCrossValidation(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage)
+ throws ValidatorException;
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/DateIsStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/DateIsStrategy.java
new file mode 100644
index 0000000..10afc8f
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/DateIsStrategy.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.annotation.DateIs;
+import org.apache.myfaces.extensions.validator.crossval.annotation.DateIsType;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+import javax.faces.context.FacesContext;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.MissingResourceException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@UsageInformation(UsageCategory.INTERNAL)
+public class DateIsStrategy extends AbstractCompareStrategy<DateIs>
+{
+ protected static final String TOO_EARLY = "early";
+ protected static final String TOO_LATE = "late";
+ protected static final String NOT_EQUAL_DATE_TIME = "not equal";
+ protected static final String RESULT_KEY = "result";
+ protected static final String COMPARED_VALUE_KEY = "target value";
+ protected static final String REVERSE_COMPARED_VALUE_KEY = "reverse target value";
+
+ @Override
+ public boolean useTargetComponentToDisplayErrorMsg(
+ CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ return true;
+ }
+
+ //TODO test & remove
+ @Override
+ protected boolean handleSourceViolation(CrossValidationStorageEntry entryOfSource)
+ {
+ return false;
+ }
+
+ public boolean isViolation(Object object1, Object object2, DateIs annotation)
+ {
+ boolean violationFound;
+
+ if (annotation.type().equals(DateIsType.same))
+ {
+ violationFound = object1 != null && !object1.equals(object2);
+
+ if (violationFound)
+ {
+ this.violationResultStorage.put(RESULT_KEY, NOT_EQUAL_DATE_TIME);
+ }
+ }
+ else if (annotation.type().equals(DateIsType.before))
+ {
+ violationFound = object1 != null && object2 != null &&
+ (!new Date(((Date) object1).getTime()).before((Date) object2) || object1.equals(object2));
+
+ if (violationFound)
+ {
+ this.violationResultStorage.put(RESULT_KEY, TOO_LATE);
+ }
+ }
+ else
+ {
+ violationFound = object1 != null && object2 != null &&
+ (!new Date(((Date) object1).getTime()).after((Date) object2) || object1.equals(object2));
+
+ if (violationFound)
+ {
+ this.violationResultStorage.put(RESULT_KEY, TOO_EARLY);
+ }
+ }
+
+ if (violationFound)
+ {
+ this.violationResultStorage.put(COMPARED_VALUE_KEY, object1);
+ this.violationResultStorage.put(REVERSE_COMPARED_VALUE_KEY, object2);
+ }
+
+ return violationFound;
+ }
+
+ public String[] getValidationTargets(DateIs annotation)
+ {
+ return annotation.valueOf();
+ }
+
+ /*
+ * protected
+ */
+ protected String getValidationErrorMsgKey(DateIs annotation, boolean isTargetComponent)
+ {
+ String result = (String) this.violationResultStorage.get(RESULT_KEY);
+
+ if (!isTargetComponent)
+ {
+ result = reverseResult(result);
+ }
+
+ if (TOO_EARLY.equals(result))
+ {
+ return getNotAfterErrorMsgKey(annotation);
+ }
+ else if (TOO_LATE.equals(result))
+ {
+ return getNotBeforeErrorMsgKey(annotation);
+ }
+ else
+ {
+ return getNotEqualErrorMsgKey(annotation);
+ }
+ }
+
+ private String reverseResult(String result)
+ {
+ if (TOO_EARLY.equals(result))
+ {
+ return TOO_LATE;
+ }
+ else
+ {
+ return TOO_EARLY;
+ }
+ }
+
+ @Override
+ protected String getErrorMessageSummary(DateIs annotation, boolean isTargetComponent)
+ {
+ if (!isTargetComponent)
+ {
+ return super.getErrorMessageSummary(annotation, isTargetComponent);
+ }
+
+ return getErrorMessage(getValidationErrorMsgKey(annotation, isTargetComponent), annotation, isTargetComponent);
+ }
+
+ @Override
+ protected String getErrorMessageDetail(DateIs annotation, boolean isTargetComponent)
+ {
+ if (!isTargetComponent)
+ {
+ return super.getErrorMessageDetail(annotation, isTargetComponent);
+ }
+
+ try
+ {
+ return getErrorMessage(getValidationErrorMsgKey(annotation, isTargetComponent)
+ + DETAIL_MESSAGE_KEY_POSTFIX, annotation, isTargetComponent);
+ }
+ catch (MissingResourceException e)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("couldn't find key " + getValidationErrorMsgKey(annotation, isTargetComponent)
+ + DETAIL_MESSAGE_KEY_POSTFIX, e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected String getReverseErrorMessageSummary(DateIs annotation)
+ {
+ return getErrorMessage(getValidationErrorMsgKey(annotation, false), annotation, false);
+ }
+
+ @Override
+ protected String getReverseErrorMessageDetail(DateIs annotation)
+ {
+ try
+ {
+ return getErrorMessage(getValidationErrorMsgKey(annotation, false)
+ + DETAIL_MESSAGE_KEY_POSTFIX, annotation, false);
+ }
+ catch (MissingResourceException e)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("couldn't find key " + getValidationErrorMsgKey(annotation)
+ + DETAIL_MESSAGE_KEY_POSTFIX, e);
+ }
+ }
+ return null;
+ }
+
+ protected String getErrorMessage(String key, DateIs annotation, boolean isTargetComponent)
+ {
+ String message = resolveMessage(key);
+
+ DateFormat dateFormat = DateFormat.getDateInstance(annotation.errorMessageDateStyle(),
+ FacesContext.getCurrentInstance().getViewRoot().getLocale());
+
+ String result;
+
+ if(isTargetComponent)
+ {
+ result = message.replace("{0}",
+ dateFormat.format((Date) this.violationResultStorage.get(COMPARED_VALUE_KEY)));
+ }
+ else
+ {
+ result = message.replace("{0}",
+ dateFormat.format((Date) this.violationResultStorage.get(REVERSE_COMPARED_VALUE_KEY)));
+ }
+
+ //replace placeholder with the value of the other component
+ return result;
+ }
+
+ /*
+ * private
+ */
+ private String getNotAfterErrorMsgKey(DateIs annotation)
+ {
+ if (annotation.validationErrorMsgKey().equals(""))
+ {
+ return annotation.notAfterErrorMsgKey();
+ }
+ return annotation.validationErrorMsgKey();
+ }
+
+ private String getNotBeforeErrorMsgKey(DateIs annotation)
+ {
+ if (annotation.validationErrorMsgKey().equals(""))
+ {
+ return annotation.notBeforeErrorMsgKey();
+ }
+ return annotation.validationErrorMsgKey();
+ }
+
+ private String getNotEqualErrorMsgKey(DateIs annotation)
+ {
+ if (annotation.validationErrorMsgKey().equals(""))
+ {
+ return annotation.notEqualErrorMsgKey();
+ }
+ return annotation.validationErrorMsgKey();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/ELCompareStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/ELCompareStrategy.java
new file mode 100644
index 0000000..56911d5
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/ELCompareStrategy.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorageEntry;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.el.ValueBindingExpression;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * referencing validation targets - possible formats:
+ * "#{[bean_name].[property_name]}" ... cross-entity validation with value binding
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class ELCompareStrategy implements ReferencingStrategy
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public boolean evaluateReferenceAndValidate(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage,
+ String validationTarget, AbstractCompareStrategy compareStrategy)
+ {
+ if (ExtValUtils.getELHelper().isELTermWellFormed(validationTarget) &&
+ ExtValUtils.getELHelper().isELTermValid(FacesContext.getCurrentInstance(), validationTarget))
+ {
+ tryToValidateValueBinding(
+ crossValidationStorageEntry,
+ new ValueBindingExpression(validationTarget), crossValidationStorage, compareStrategy);
+
+ return true;
+ }
+ return false;
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "test")
+ protected boolean tryToValidateValueBinding(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ ValueBindingExpression validationTarget,
+ CrossValidationStorage crossValidationStorage,
+ AbstractCompareStrategy compareStrategy)
+ {
+ ProcessedInformationStorageEntry validationTargetEntry =
+ resolveTargetForCrossComponentValidation(crossValidationStorageEntry, validationTarget);
+
+ if(validationTargetEntry != null)
+ {
+ processCrossComponentValidation(compareStrategy, crossValidationStorageEntry, validationTargetEntry);
+ }
+ else
+ {
+ processModelAwareCrossValidation(compareStrategy, crossValidationStorageEntry, validationTarget);
+ }
+
+ return true;
+ }
+
+ private ProcessedInformationStorageEntry resolveTargetForCrossComponentValidation(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ ValueBindingExpression validationTarget)
+ {
+ ProcessedInformationStorage processedInformationStorage =
+ CrossValidationUtils.getOrInitProcessedInformationStorage();
+
+ return CrossValidationUtils.resolveValidationTargetEntry(
+ processedInformationStorage,
+ CrossValidationUtils.convertValueBindingExpressionToProcessedInformationKey(validationTarget),
+ crossValidationStorageEntry);
+ }
+
+ private void processCrossComponentValidation(
+ AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ ProcessedInformationStorageEntry validationTargetEntry)
+ {
+ CrossValidationHelper
+ .crossValidateCompareStrategy(
+ compareStrategy, crossValidationStorageEntry, validationTargetEntry, false);
+ }
+
+ private void processModelAwareCrossValidation(
+ AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ ValueBindingExpression validationTarget)
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ Object targetValue = ExtValUtils.getELHelper().getValueOfExpression(facesContext, validationTarget);
+
+ ProcessedInformationStorageEntry targetEntry = new ProcessedInformationStorageEntry();
+ targetEntry.setBean(
+ ExtValUtils.getELHelper().getValueOfExpression(facesContext, validationTarget.getBaseExpression()));
+ targetEntry.setConvertedValue(targetValue);
+
+ CrossValidationHelper
+ .crossValidateCompareStrategy(compareStrategy, crossValidationStorageEntry, targetEntry, true);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/EqualsStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/EqualsStrategy.java
new file mode 100644
index 0000000..4edb3f5
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/EqualsStrategy.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.annotation.Equals;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.NullValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.EmptyValueAwareValidationStrategy;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@NullValueAwareValidationStrategy
+@EmptyValueAwareValidationStrategy
+@UsageInformation(UsageCategory.INTERNAL)
+public class EqualsStrategy extends AbstractCompareStrategy
+{
+ @Override
+ public boolean useTargetComponentToDisplayErrorMsg(CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ return true;
+ }
+
+ protected String getValidationErrorMsgKey(Annotation annotation, boolean isTargetComponent)
+ {
+ return ((Equals) annotation).validationErrorMsgKey();
+ }
+
+ public boolean isViolation(Object object1, Object object2, Annotation annotation)
+ {
+ return object1 != null && !object1.equals(object2);
+ }
+
+ public String[] getValidationTargets(Annotation annotation)
+ {
+ return ((Equals) annotation).value();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/LocalCompareStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/LocalCompareStrategy.java
new file mode 100644
index 0000000..9752f3c
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/LocalCompareStrategy.java
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorageEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.el.ValueBindingExpression;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
+import org.apache.myfaces.extensions.validator.util.ProxyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.Method;
+
+/**
+ * "[property_name]" ... local validation -> cross-component, but no cross-entity validation
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class LocalCompareStrategy implements ReferencingStrategy
+{
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ public boolean evaluateReferenceAndValidate(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage,
+ String validationTarget, AbstractCompareStrategy compareStrategy)
+ {
+ if(validationTarget.contains("."))
+ {
+ //LocalPropertyChainCompareStrategy will continue
+ return false;
+ }
+
+ return tryToValidateLocally(
+ crossValidationStorageEntry,
+ crossValidationStorage,
+ validationTarget,
+ compareStrategy);
+ }
+
+ protected boolean tryToValidateLocally(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage,
+ String targetKey,
+ AbstractCompareStrategy compareStrategy)
+ {
+ ProcessedInformationStorage processedInformationStorage =
+ CrossValidationUtils.getOrInitProcessedInformationStorage();
+
+ boolean isModelAwareValidation =
+ isModelAwareCrossValidation(crossValidationStorageEntry, processedInformationStorage, targetKey);
+
+ String targetProperty = targetKey;
+
+ String sourceKey = resolveSourceKey(crossValidationStorageEntry);
+ targetKey = sourceKey.substring(0, sourceKey.lastIndexOf(".") + 1) + targetKey;
+
+ ProcessedInformationStorageEntry validationTargetEntry = CrossValidationUtils.resolveValidationTargetEntry(
+ processedInformationStorage, targetKey, crossValidationStorageEntry);
+
+ if (validationTargetEntry != null && validationTargetEntry.getComponent() != null && !isModelAwareValidation)
+ {
+ processCrossComponentValidation(compareStrategy, crossValidationStorageEntry, validationTargetEntry);
+ }
+ //no target - because there is no target component - value was validated against the model
+ else if(isModelAwareValidation)
+ {
+ processModelAwareCrossValidation(compareStrategy, crossValidationStorageEntry, targetProperty);
+ }
+ else
+ {
+ unsupportedCase(crossValidationStorageEntry);
+ }
+
+ return true;
+ }
+
+ protected String createTargetKey(CrossValidationStorageEntry crossValidationStorageEntry, String targetKey)
+ {
+ //no real value binding expression
+ //ValueBindingExpression just hepls to replace the property of the key
+ //here only dot-notation is allowed -> no problem
+ ValueBindingExpression baseExpression =
+ new ValueBindingExpression("#{" + crossValidationStorageEntry.getMetaDataEntry()
+ .getProperty(PropertyInformationKeys.PROPERTY_DETAILS,
+ PropertyDetails.class).getKey() + "}");
+
+ String result = ValueBindingExpression.replaceOrAddProperty(baseExpression, targetKey)
+ .getExpressionString();
+ return result.substring(2, result.length() -1);
+ }
+
+ protected Object getValueOfProperty(Object base, String property)
+ {
+ property = property.substring(0,1).toUpperCase() + property.substring(1, property.length());
+ Class targetClass = ProxyUtils.getUnproxiedClass(base.getClass());
+ Method targetMethod = ReflectionUtils.tryToGetMethod(targetClass, "get" + property);
+
+ if(targetMethod == null)
+ {
+ targetMethod = ReflectionUtils.tryToGetMethod(targetClass, "is" + property);
+ }
+
+ if(targetMethod == null)
+ {
+ throw new IllegalStateException(
+ "class " + base.getClass() + " has no public get/is " + property.toLowerCase());
+ }
+ return ReflectionUtils.tryToInvokeMethod(base, targetMethod);
+ }
+
+ private boolean isModelAwareCrossValidation(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ ProcessedInformationStorage keyConvertedValueMapping,
+ String targetKey)
+ {
+ String newKey = createTargetKey(crossValidationStorageEntry, targetKey);
+
+ return !keyConvertedValueMapping.containsEntry(newKey);
+
+ }
+
+ private String resolveSourceKey(CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ PropertyDetails propertyDetails = crossValidationStorageEntry.getMetaDataEntry()
+ .getProperty(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
+
+ String sourceKey = propertyDetails.getKey();
+
+ if(!sourceKey.contains("."))
+ {
+ throw new IllegalStateException("source path: " + sourceKey + " invalid");
+ }
+
+ return sourceKey;
+ }
+
+ private void unsupportedCase(CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ if(logger.isWarnEnabled())
+ {
+ logger.warn("couldn't find converted object for " + crossValidationStorageEntry.getMetaDataEntry()
+ .getProperty(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class).getKey());
+ }
+ }
+
+ private void processCrossComponentValidation(
+ AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ ProcessedInformationStorageEntry validationTargetEntry)
+ {
+ CrossValidationHelper
+ .crossValidateCompareStrategy(
+ compareStrategy, crossValidationStorageEntry, validationTargetEntry, false);
+ }
+
+ private void processModelAwareCrossValidation(
+ AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ String targetProperty)
+ {
+ ProcessedInformationStorageEntry targetEntry = new ProcessedInformationStorageEntry();
+
+ targetEntry.setBean(
+ crossValidationStorageEntry.getMetaDataEntry()
+ .getProperty(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class).getBaseObject());
+ targetEntry
+ .setConvertedValue(getValueOfProperty(targetEntry.getBean(), targetProperty));
+
+ CrossValidationHelper
+ .crossValidateCompareStrategy(compareStrategy, crossValidationStorageEntry, targetEntry, true);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/LocalPropertyChainCompareStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/LocalPropertyChainCompareStrategy.java
new file mode 100644
index 0000000..0eb656c
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/LocalPropertyChainCompareStrategy.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorage;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * "[local_property.property1.property2]"
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+class LocalPropertyChainCompareStrategy extends LocalCompareStrategy
+{
+ @Override
+ public boolean evaluateReferenceAndValidate(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage,
+ String validationTarget, AbstractCompareStrategy compareStrategy)
+ {
+ if(!validationTarget.contains("."))
+ {
+ //not supported - TODO add logging
+ return false;
+ }
+
+ return tryToValidateLocally(
+ crossValidationStorageEntry,
+ crossValidationStorage,
+ validationTarget,
+ compareStrategy);
+ }
+
+ @Override
+ protected boolean tryToValidateLocally(CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage,
+ String targetKey,
+ AbstractCompareStrategy compareStrategy)
+ {
+ ProcessedInformationStorage processedInformationStorage =
+ CrossValidationUtils.getOrInitProcessedInformationStorage();
+
+ String newKey = createTargetKey(crossValidationStorageEntry, targetKey);
+
+ if (processedInformationStorage.containsEntry(newKey))
+ {
+ ProcessedInformationStorageEntry validationTargetEntry = processedInformationStorage.getEntry(newKey);
+
+ processCrossComponentValidation(compareStrategy, crossValidationStorageEntry, validationTargetEntry);
+ }
+ //no target - because there is no target component - value was validated against the model
+ else
+ {
+ processModelAwareCrossValidation(compareStrategy, crossValidationStorageEntry, targetKey);
+ }
+
+ return true;
+ }
+
+ private void processCrossComponentValidation(
+ AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ ProcessedInformationStorageEntry targetInformationEntry)
+ {
+ if (compareStrategy.isViolation(
+ crossValidationStorageEntry.getConvertedObject(),
+ targetInformationEntry.getConvertedValue(),
+ crossValidationStorageEntry.getMetaDataEntry().getValue(Annotation.class)))
+ {
+ CrossValidationStorageEntry tmpCrossValidationStorageEntry = new CrossValidationStorageEntry();
+ tmpCrossValidationStorageEntry.setComponent(crossValidationStorageEntry.getComponent());
+ tmpCrossValidationStorageEntry.setClientId(targetInformationEntry.getClientId());
+ tmpCrossValidationStorageEntry.setConvertedObject(targetInformationEntry.getConvertedValue());
+ tmpCrossValidationStorageEntry.setValidationStrategy(compareStrategy);
+
+ //process after violation
+ //just add messages
+ if(crossValidationStorageEntry.getComponent() != null)
+ {
+ compareStrategy.processTargetComponentAfterViolation(
+ crossValidationStorageEntry, tmpCrossValidationStorageEntry);
+ }
+ else
+ {
+ compareStrategy.processTargetComponentAfterViolation(crossValidationStorageEntry, null);
+ }
+
+ //thow exception
+ compareStrategy.processSourceComponentAfterViolation(crossValidationStorageEntry);
+ }
+ }
+
+ private void processModelAwareCrossValidation(
+ AbstractCompareStrategy compareStrategy,
+ CrossValidationStorageEntry crossValidationStorageEntry, String targetKey)
+ {
+ PropertyDetails propertyDetails = crossValidationStorageEntry.getMetaDataEntry()
+ .getProperty(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
+
+ Object newBase = ReflectionUtils
+ .getBaseOfPropertyChain(propertyDetails.getBaseObject(), targetKey);
+
+ if(targetKey.contains("."))
+ {
+ //find the last property
+ targetKey = targetKey.substring(targetKey.lastIndexOf(".") + 1, targetKey.length());
+ }
+
+ Object targetValue = getValueOfProperty(newBase, targetKey);
+
+ ProcessedInformationStorageEntry targetEntry = new ProcessedInformationStorageEntry();
+ targetEntry.setBean(newBase);
+ targetEntry.setConvertedValue(targetValue);
+
+ CrossValidationHelper
+ .crossValidateCompareStrategy(
+ compareStrategy, crossValidationStorageEntry, targetEntry, true);
+ }
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/NotEqualsStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/NotEqualsStrategy.java
new file mode 100644
index 0000000..f509e84
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/NotEqualsStrategy.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.annotation.NotEquals;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.NullValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.EmptyValueAwareValidationStrategy;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@NullValueAwareValidationStrategy
+@EmptyValueAwareValidationStrategy
+@UsageInformation(UsageCategory.INTERNAL)
+public class NotEqualsStrategy extends EqualsStrategy
+{
+ @Override
+ protected String getValidationErrorMsgKey(Annotation annotation, boolean isTargetComponent)
+ {
+ return ((NotEquals) annotation).validationErrorMsgKey();
+ }
+
+ @Override
+ public boolean isViolation(Object object1, Object object2,
+ Annotation annotation)
+ {
+ return !super.isViolation(object1, object2, annotation);
+ }
+
+ @Override
+ public String[] getValidationTargets(Annotation annotation)
+ {
+ return ((NotEquals) annotation).value();
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/ReferencingStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/ReferencingStrategy.java
new file mode 100644
index 0000000..9dc5011
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/ReferencingStrategy.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+
+/**
+ * Internal interface to allow multiple referencing strategies for cross component validation.
+ *
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+interface ReferencingStrategy
+{
+ boolean evaluateReferenceAndValidate(
+ CrossValidationStorageEntry crossValidationStorageEntry,
+ CrossValidationStorage crossValidationStorage,
+ String validationTarget,
+ AbstractCompareStrategy abstractCompareStrategy);
+}
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/RequiredIfStrategy.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/RequiredIfStrategy.java
new file mode 100644
index 0000000..98750b3
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/RequiredIfStrategy.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.crossval.strategy;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.annotation.RequiredIf;
+import org.apache.myfaces.extensions.validator.crossval.annotation.RequiredIfType;
+import org.apache.myfaces.extensions.validator.baseval.annotation.SkipValidationSupport;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.AbstractValidationErrorMessageResolver;
+import org.apache.myfaces.extensions.validator.core.validation.NullValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.validation.EmptyValueAwareValidationStrategy;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@SkipValidationSupport
+@NullValueAwareValidationStrategy
+@EmptyValueAwareValidationStrategy
+@UsageInformation(UsageCategory.INTERNAL)
+public class RequiredIfStrategy extends AbstractCompareStrategy<RequiredIf>
+{
+ private boolean useFacesBundle = false;
+
+ @Override
+ public boolean useTargetComponentToDisplayErrorMsg(CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ return false;
+ }
+
+ @Override
+ protected String resolveMessage(String key)
+ {
+ String result = super.resolveMessage(key);
+ String marker = AbstractValidationErrorMessageResolver.MISSING_RESOURCE_MARKER;
+
+ if((marker + key + marker).equals(result))
+ {
+ this.useFacesBundle = true;
+ }
+
+ return result;
+ }
+
+ protected String getValidationErrorMsgKey(RequiredIf annotation, boolean isTargetComponent)
+ {
+ return annotation.validationErrorMsgKey();
+ }
+
+ public boolean isViolation(Object source, Object target, RequiredIf annotation)
+ {
+ boolean violationFound = false;
+
+ if (annotation.is().equals(RequiredIfType.empty))
+ {
+ violationFound = (isTargetEmpty(target) || Boolean.FALSE.equals(target)) && isSourceEmpty(source);
+ }
+ else if (annotation.is().equals(RequiredIfType.not_empty))
+ {
+ violationFound = (isTargetNotEmpty(target) && isSourceEmpty(source) && !(target instanceof Boolean)) ||
+ (Boolean.TRUE.equals(target) && isSourceEmpty(source));
+ }
+
+ return violationFound;
+ }
+
+ private boolean isTargetEmpty(Object target)
+ {
+ return target == null || target.equals("");
+ }
+
+ private boolean isSourceEmpty(Object source)
+ {
+ return source == null || source.equals("");
+ }
+
+ private boolean isTargetNotEmpty(Object target)
+ {
+ return target != null && !target.equals("");
+ }
+
+ public String[] getValidationTargets(RequiredIf annotation)
+ {
+ return annotation.valueOf();
+ }
+
+ @Override
+ protected boolean processAfterCrossValidatorException(
+ CrossValidationStorageEntry crossValidationStorageEntry, ValidatorException validatorException)
+ {
+ if(this.useFacesBundle)
+ {
+ ExtValUtils.replaceWithDefaultRequiredMessage(validatorException.getFacesMessage());
+ }
+
+ return super.processAfterCrossValidatorException(crossValidationStorageEntry, validatorException);
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/jpa_strategy_mappings.properties b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/jpa_strategy_mappings.properties
new file mode 100644
index 0000000..c7d9929
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/jpa_strategy_mappings.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+javax.persistence.Column=org.apache.myfaces.extensions.validator.baseval.strategy.JpaValidationStrategy
+javax.persistence.Basic=org.apache.myfaces.extensions.validator.baseval.strategy.JpaValidationStrategy
+javax.persistence.Id=org.apache.myfaces.extensions.validator.baseval.strategy.JpaValidationStrategy
+javax.persistence.OneToOne=org.apache.myfaces.extensions.validator.baseval.strategy.JpaValidationStrategy
+javax.persistence.ManyToOne=org.apache.myfaces.extensions.validator.baseval.strategy.JpaValidationStrategy
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/util/CrossValidationUtils.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/util/CrossValidationUtils.java
new file mode 100644
index 0000000..49f852a
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/util/CrossValidationUtils.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorage;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.storage.CrossValidationStorageEntry;
+import org.apache.myfaces.extensions.validator.crossval.storage.ProcessedInformationStorage;
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.el.ValueBindingExpression;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.1
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class CrossValidationUtils
+{
+ public static CrossValidationStorage getOrInitCrossValidationStorage()
+ {
+ return ExtValUtils.getStorage(CrossValidationStorage.class, CrossValidationStorage.class.getName());
+ }
+
+ public static void resetCrossValidationStorage()
+ {
+ ExtValUtils.resetStorage(CrossValidationStorage.class, CrossValidationStorage.class.getName());
+ }
+
+ public static ProcessedInformationStorage getOrInitProcessedInformationStorage()
+ {
+ return ExtValUtils.getStorage(
+ ProcessedInformationStorage.class, ProcessedInformationStorage.class.getName());
+ }
+
+ public static void resetKeyToConvertedValueMapping()
+ {
+ ExtValUtils.resetStorage(ProcessedInformationStorage.class, ProcessedInformationStorage.class.getName());
+ }
+
+ public static ProcessedInformationStorageEntry resolveValidationTargetEntry(
+ ProcessedInformationStorage processedInformationStorage,
+ String targetKey, CrossValidationStorageEntry crossValidationStorageEntry)
+ {
+ ProcessedInformationStorageEntry processedInformationEntry =
+ processedInformationStorage.getEntry(targetKey);
+
+ //value not submitted at this request - use model value (validation against the model)
+ if(processedInformationEntry == null)
+ {
+ return null;
+ }
+
+ //simple case
+ if (processedInformationEntry.getFurtherEntries() == null)
+ {
+ return processedInformationEntry;
+ }
+
+ PropertyDetails propertyDetails = crossValidationStorageEntry.getMetaDataEntry()
+ .getProperty(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
+
+ Object targetBean = propertyDetails.getBaseObject();
+
+ //process complex component entries (e.g. a table)
+ //supported: cross-component but no cross-entity validation (= locale validation)
+ if (processedInformationEntry.getBean().equals(targetBean))
+ {
+ return processedInformationEntry;
+ }
+
+ for (ProcessedInformationStorageEntry entry : processedInformationEntry.getFurtherEntries())
+ {
+ if (entry.getBean().equals(targetBean))
+ {
+ return entry;
+ }
+ }
+
+ return null;
+ }
+
+ @ToDo(value = Priority.MEDIUM, description = "support for map syntax")
+ public static String convertValueBindingExpressionToProcessedInformationKey(ValueBindingExpression vbe)
+ {
+ return vbe.getExpressionString().replace("#{", "").replace("}", "");
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/util/PropertyValidationUtils.java b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/util/PropertyValidationUtils.java
new file mode 100644
index 0000000..1f73a28
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/java/org/apache/myfaces/extensions/validator/util/PropertyValidationUtils.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.util;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
+import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
+import org.apache.myfaces.extensions.validator.baseval.strategy.SkipValidationStrategy;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.3
+ */
+@UsageInformation(UsageCategory.INTERNAL)
+public class PropertyValidationUtils
+{
+ private static final Log LOGGER = LogFactory.getLog(PropertyValidationUtils.class);
+
+ public static boolean isValidationSkipped(FacesContext facesContext,
+ ValidationStrategy validationStrategy,
+ MetaDataEntry metaDataEntry)
+ {
+ if(ExtValUtils.isSkipableValidationStrategy(
+ ProxyUtils.getUnproxiedClass(validationStrategy.getClass(), ValidationStrategy.class)))
+ {
+ Boolean skipValidation = metaDataEntry.getProperty(
+ PropertyInformationKeys.SKIP_VALIDATION, Boolean.class);
+
+ if(Boolean.TRUE.equals(skipValidation))
+ {
+ if(LOGGER.isTraceEnabled())
+ {
+ LOGGER.trace("validation of " + validationStrategy.getClass().getName() + " canceled");
+ }
+
+ return true;
+ }
+ }
+ else if(validationStrategy instanceof SkipValidationStrategy)
+ {
+ validationStrategy.validate(facesContext, null, metaDataEntry, null);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/resources/LICENSE.txt b/2_0_3_prepare/validation-modules/property-validation/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/resources/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/main/resources/NOTICE.txt b/2_0_3_prepare/validation-modules/property-validation/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/main/resources/NOTICE.txt
@@ -0,0 +1,9 @@
+Apache MyFaces Extensions Validator
+Copyright 2007-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+------------------------------------------------------------------------
+See the file LICENSE.txt
+------------------------------------------------------------------------
\ No newline at end of file
diff --git a/2_0_3_prepare/validation-modules/property-validation/src/site/apt/index.apt b/2_0_3_prepare/validation-modules/property-validation/src/site/apt/index.apt
new file mode 100644
index 0000000..c339255
--- /dev/null
+++ b/2_0_3_prepare/validation-modules/property-validation/src/site/apt/index.apt
@@ -0,0 +1,10 @@
+ ------
+Apache MyFaces Extensions Property Validation Module
+ ------
+
+Apache MyFaces Extensions Property Validation Module Overview
+
+ MyFaces Extensions Validator Property Validation provides annotation based validation for bean properties.
+ It also provides JPA 1.0 based validation Support.
+
+ MyFaces Extensions Validator is compatible with JSF 1.1.x and JSF 1.2.x. Both versions require Java 1.5+
\ No newline at end of file