initial import of MyFaces-Extensions-Validator

git-svn-id: https://svn.apache.org/repos/asf/myfaces/extensions/validator/branches/jsf_1.1@676664 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/pom.xml b/core/pom.xml
new file mode 100644
index 0000000..5caf863
--- /dev/null
+++ b/core/pom.xml
@@ -0,0 +1,82 @@
+<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</groupId>

+    <artifactId>myfaces-extval-core</artifactId>

+    <name>MyFaces Extensions-Validator Core</name>

+    <version>${build.version}</version>

+

+    <parent>

+        <groupId>org.apache.myfaces.extensions.validator</groupId>

+        <artifactId>validator-project</artifactId>

+        <version>${build.version}</version>

+    </parent>

+

+    <dependencies>

+        <dependency>

+            <groupId>org.apache.myfaces.core</groupId>

+            <artifactId>myfaces-api</artifactId>

+            <version>${jsf.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        <dependency>

+            <groupId>cglib</groupId>

+            <artifactId>cglib</artifactId>

+            <version>2.1_3</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/core/src/main/config/faces-config.xml b/core/src/main/config/faces-config.xml
new file mode 100644
index 0000000..6a10aff
--- /dev/null
+++ b/core/src/main/config/faces-config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>

+<!DOCTYPE faces-config PUBLIC

+        "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"

+        "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" >

+

+<!--

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT 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>

+    <factory>

+        <application-factory>org.apache.myfaces.extensions.validator.core.ExtValApplicationFactory</application-factory>

+    </factory>

+    <lifecycle>

+        <phase-listener>org.apache.myfaces.extensions.validator.core.ProxyMappingPhaseListener</phase-listener>

+    </lifecycle>

+</faces-config>
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/ExtValInformation.java b/core/src/main/java/org/apache/myfaces/extensions/validator/ExtValInformation.java
new file mode 100644
index 0000000..38a5b23
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/ExtValInformation.java
@@ -0,0 +1,30 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.extensions.validator;

+

+/**

+ * dont't move to an other package!!!

+ *

+ * @author Gerhard Petracek

+ */

+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 = "1.0.1";

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/AbstractStartupConfigListener.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/AbstractStartupConfigListener.java
new file mode 100644
index 0000000..7e21406
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/AbstractStartupConfigListener.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.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import javax.faces.event.PhaseEvent;

+import javax.faces.event.PhaseId;

+import javax.faces.event.PhaseListener;

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * @author Gerhard Petracek

+ */

+public abstract class AbstractStartupConfigListener 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>();

+

+    public void afterPhase(PhaseEvent event) {

+    }

+

+    public void beforePhase(PhaseEvent event) {

+        synchronized (AbstractStartupConfigListener.class) {

+            if (!initializedListeners.contains(getClass())) {

+                try {

+                    init();

+

+                    ExtValUtils.deregisterPhaseListener(this);

+                } catch (Throwable t) {

+                    this.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 abstract void init();

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/ClassMappingFactory.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ClassMappingFactory.java
new file mode 100644
index 0000000..e9e8e91
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ClassMappingFactory.java
@@ -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.

+ */

+package org.apache.myfaces.extensions.validator.core;

+

+/**

+ * @author Gerhard Petracek

+ */

+public interface ClassMappingFactory<P, R> {

+    R create(P source);

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValApplication.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValApplication.java
new file mode 100644
index 0000000..e297b14
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValApplication.java
@@ -0,0 +1,230 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.util.ExtValUtils;

+import org.apache.myfaces.extensions.validator.util.FactoryUtils;

+

+import javax.faces.FacesException;

+import javax.faces.application.Application;

+import javax.faces.application.NavigationHandler;

+import javax.faces.application.StateManager;

+import javax.faces.application.ViewHandler;

+import javax.faces.component.EditableValueHolder;

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.convert.Converter;

+import javax.faces.el.*;

+import javax.faces.event.ActionListener;

+import javax.faces.validator.Validator;

+import java.util.Collection;

+import java.util.Iterator;

+import java.util.Locale;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class ExtValApplication extends Application {

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    private Application wrapped;

+

+    public ExtValApplication() {

+    }

+

+    public ExtValApplication(Application wrapped) {

+        this.wrapped = wrapped;

+    }

+

+    public UIComponent createComponent(ValueBinding componentBinding,

+                                       FacesContext context, String componentType) throws FacesException {

+        UIComponent component = this.wrapped.createComponent(componentBinding, context, componentType);

+        return tryToSetExtValValidatingConverter(component);

+    }

+

+    private UIComponent tryToSetExtValValidatingConverter(UIComponent component) {

+        //if no converter is used add sev-en converter - so it isn't necessary to add sev-en converter manually within the page

+        if (component instanceof EditableValueHolder) {

+            //in order to access the wrapped application and and support other Application wrappers

+            ExtValUtils.setOriginalApplication(wrapped);

+

+            ((EditableValueHolder) component).setConverter(new ExtValConverter());

+        }

+        return component;

+    }

+

+    public Converter createConverter(String converterId) throws FacesException {

+        Converter converter = this.wrapped.createConverter(converterId);

+        return getExtValConverter(converter);

+    }

+

+    public Converter createConverter(Class targetClass) throws FacesException {

+        Converter converter = this.wrapped.createConverter(targetClass);

+

+        return getExtValConverter(converter);

+    }

+

+    private Converter getExtValConverter(Converter converter) {

+        if (converter == null) {

+            return new ExtValConverter();

+        }

+

+        if (!ExtValUtils.useFallbackAdapters()) {

+            return ExtValConverter.newInstance(converter);

+        } else {

+            //fallback adapter solution

+            //if there is a problem with the default approach (the phase-listener) or the alternative (the state-manager)

+            return FactoryUtils.getConverterAdapterFactory().create(converter);

+        }

+    }

+

+    public Iterator getConverterIds() {

+        return this.wrapped.getConverterIds();

+    }

+

+    public Iterator getConverterTypes() {

+        return this.wrapped.getConverterTypes();

+    }

+

+    public void addConverter(String converterId, String converterClass) {

+        this.wrapped.addConverter(converterId, converterClass);

+    }

+

+    public void addConverter(Class targetClass, String converterClass) {

+        this.wrapped.addConverter(targetClass, converterClass);

+    }

+

+    public Iterator getComponentTypes() {

+        return this.wrapped.getComponentTypes();

+    }

+

+    public ActionListener getActionListener() {

+        return this.wrapped.getActionListener();

+    }

+

+    public void setActionListener(ActionListener listener) {

+        this.wrapped.setActionListener(listener);

+    }

+

+    public Locale getDefaultLocale() {

+        return this.wrapped.getDefaultLocale();

+    }

+

+    public void setDefaultLocale(Locale locale) {

+        this.wrapped.setDefaultLocale(locale);

+    }

+

+    public String getDefaultRenderKitId() {

+        return this.wrapped.getDefaultRenderKitId();

+    }

+

+    public void setDefaultRenderKitId(String renderKitId) {

+        this.wrapped.setDefaultRenderKitId(renderKitId);

+    }

+

+    public String getMessageBundle() {

+        return this.wrapped.getMessageBundle();

+    }

+

+    public void setMessageBundle(String bundle) {

+        this.wrapped.setMessageBundle(bundle);

+    }

+

+    public NavigationHandler getNavigationHandler() {

+        return this.wrapped.getNavigationHandler();

+    }

+

+    public void setNavigationHandler(NavigationHandler handler) {

+        this.wrapped.setNavigationHandler(handler);

+    }

+

+    public PropertyResolver getPropertyResolver() {

+        return this.wrapped.getPropertyResolver();

+    }

+

+    public void setPropertyResolver(PropertyResolver resolver) {

+        this.wrapped.setPropertyResolver(resolver);

+    }

+

+    public VariableResolver getVariableResolver() {

+        return this.wrapped.getVariableResolver();

+    }

+

+    public void setVariableResolver(VariableResolver resolver) {

+        this.wrapped.setVariableResolver(resolver);

+    }

+

+    public ViewHandler getViewHandler() {

+        return this.wrapped.getViewHandler();

+    }

+

+    public void setViewHandler(ViewHandler handler) {

+        this.wrapped.setViewHandler(handler);

+    }

+

+    public StateManager getStateManager() {

+        return this.wrapped.getStateManager();

+    }

+

+    public void setStateManager(StateManager manager) {

+        this.wrapped.setStateManager(manager);

+    }

+

+    public void addComponent(String componentType, String componentClass) {

+        this.wrapped.addComponent(componentType, componentClass);

+    }

+

+    public UIComponent createComponent(String componentType) throws FacesException {

+        UIComponent component = this.wrapped.createComponent(componentType);

+

+        return tryToSetExtValValidatingConverter(component);

+    }

+

+    public MethodBinding createMethodBinding(String ref, Class[] params)

+            throws ReferenceSyntaxException {

+        return this.wrapped.createMethodBinding(ref, params);

+    }

+

+    public Iterator getSupportedLocales() {

+        return this.wrapped.getSupportedLocales();

+    }

+

+    public void setSupportedLocales(Collection locales) {

+        this.wrapped.setSupportedLocales(locales);

+    }

+

+    public void addValidator(String validatorId, String validatorClass) {

+        this.wrapped.addValidator(validatorId, validatorClass);

+    }

+

+    public Validator createValidator(String validatorId) throws FacesException {

+        return this.wrapped.createValidator(validatorId);

+    }

+

+    public Iterator getValidatorIds() {

+        return this.wrapped.getValidatorIds();

+    }

+

+    public ValueBinding createValueBinding(String ref)

+            throws ReferenceSyntaxException {

+        return this.wrapped.createValueBinding(ref);

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValApplicationFactory.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValApplicationFactory.java
new file mode 100644
index 0000000..e26e3db
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValApplicationFactory.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;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+

+import javax.faces.application.Application;

+import javax.faces.application.ApplicationFactory;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class ExtValApplicationFactory extends ApplicationFactory {

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    private ApplicationFactory wrapped;

+

+    public ExtValApplicationFactory(ApplicationFactory applicationFactory) {

+        this.wrapped = applicationFactory;

+        setApplication(applicationFactory.getApplication());

+        logger.trace("myfaces-extension-validator application factory instantiated");

+    }

+

+    public Application getApplication() {

+        return this.wrapped.getApplication();

+    }

+

+    public void setApplication(Application application) {

+        if (!(application instanceof ExtValApplication)) {

+            logger.trace("myfaces-extension-validator application created");

+

+            this.wrapped.setApplication(new ExtValApplication(application));

+        } else {

+            this.wrapped.setApplication(application);

+        }

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValConverter.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValConverter.java
new file mode 100644
index 0000000..2a2f10b
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ExtValConverter.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.core;

+

+import net.sf.cglib.proxy.Enhancer;

+import net.sf.cglib.proxy.MethodInterceptor;

+import net.sf.cglib.proxy.MethodProxy;

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.annotation.extractor.AnnotationExtractor;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;

+import org.apache.myfaces.extensions.validator.util.ELUtils;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+import org.apache.myfaces.extensions.validator.util.FactoryUtils;

+

+import javax.faces.component.EditableValueHolder;

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.convert.Converter;

+import java.io.Serializable;

+import java.lang.reflect.Method;

+import java.util.ArrayList;

+import java.util.List;

+import java.util.Map;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class ExtValConverter implements Converter, MethodInterceptor, Serializable {

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public static Converter newInstance(Converter wrappedConverter) {

+        Enhancer enhancer = new Enhancer();

+        enhancer.setSuperclass(wrappedConverter.getClass());

+        enhancer.setInterfaces(new Class[]{Converter.class, Serializable.class});

+        enhancer.setCallback(new ExtValConverter());

+

+        ExtValUtils.increaseProcessedConverterCount();

+

+        return (Converter) enhancer.create();

+    }

+

+    public ExtValConverter() {

+        logger.trace("myfaces-extension-validator converter instantiated");

+    }

+

+    public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {

+

+        Object convertedObject = getConvertedObject(facesContext, uiComponent, s);

+

+        processExtValValidation(facesContext, uiComponent, convertedObject);

+

+        return convertedObject;

+    }

+

+    public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {

+        //indirect approach for complex components

+        Converter converter = ExtValUtils.tryToCreateOriginalConverter(facesContext, uiComponent);

+        return (converter == null) ? (o == null) ? null : o.toString() : converter.getAsString(facesContext, uiComponent, o);

+    }

+

+    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

+        Object convertedObject = proxy.invokeSuper(obj, args);

+

+        if (method.getName().equals("getAsObject")) {

+            processExtValValidation((FacesContext) args[0], (UIComponent) args[1], convertedObject);

+        } else if (method.getName().equals("getAsString")) {

+            storeComponentConverterMappingForProxies((FacesContext) args[0], (UIComponent) args[1], (Converter)obj);

+        }

+        return convertedObject;

+    }

+

+    protected Object getConvertedObject(FacesContext facesContext, UIComponent uiComponent, String s) {

+        //indirect approach for complex components

+        //TODO

+        Converter converter = ExtValUtils.tryToCreateOriginalConverter(facesContext, uiComponent);

+        return (converter != null) ? converter.getAsObject(facesContext, uiComponent, s) : s;

+    }

+

+    /*

+     * private methods

+     */

+    private void createValueBindingConvertedValueMapping(UIComponent uiComponent, Object convertedObject) {

+        //to support local cross-validation (within the same entity)

+        Map<String, ProcessedInformationEntry> valueBindingConvertedValueMapping = ExtValUtils.getOrInitValueBindingConvertedValueMapping();

+

+        String valueBindingExpression;

+        ProcessedInformationEntry entry;

+

+        valueBindingExpression = ELUtils.getReliableValueBindingExpression(uiComponent);

+

+        if (valueBindingExpression == null) {

+            return;

+        }

+

+        entry = new ProcessedInformationEntry();

+        entry.setBean(ELUtils.getBeanObject(valueBindingExpression, uiComponent));

+        entry.setConvertedValue(convertedObject);

+        entry.setComponent(uiComponent);

+

+        //for local cross-validation

+        if (valueBindingConvertedValueMapping.containsKey(valueBindingExpression) && !valueBindingConvertedValueMapping.get(valueBindingExpression).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<ProcessedInformationEntry> furtherEntries = valueBindingConvertedValueMapping.get(valueBindingExpression).getFurtherEntries();

+            if (furtherEntries == null) {

+                furtherEntries = new ArrayList<ProcessedInformationEntry>();

+

+                valueBindingConvertedValueMapping.get(valueBindingExpression).setFurtherEntries(furtherEntries);

+            }

+

+            furtherEntries.add(entry);

+        } else {

+            //for normal validation

+            valueBindingConvertedValueMapping.put(valueBindingExpression, entry);

+        }

+    }

+

+    private void processExtValValidation(FacesContext facesContext, UIComponent uiComponent, Object convertedObject) {

+        if (uiComponent instanceof EditableValueHolder) {

+            ValidationStrategy validationStrategy;

+

+            AnnotationExtractor annotationExtractor = FactoryUtils.getAnnotationExtractorFactory().create();

+            for (AnnotationEntry entry : annotationExtractor.extractAnnotations(facesContext, uiComponent)) {

+                validationStrategy = FactoryUtils.getValidationStrategyFactory().create(entry.getAnnotation());

+

+                if (validationStrategy != null) {

+                    validationStrategy.validate(facesContext, uiComponent, entry, convertedObject);

+                } else {

+                    logger.trace("no validation strategy found for " + entry.getAnnotation().annotationType().getName());

+                }

+            }

+

+            //build mapping value-binding -> processed information entry

+            createValueBindingConvertedValueMapping(uiComponent, convertedObject);

+        }

+    }

+

+

+    private void storeComponentConverterMappingForProxies(FacesContext facesContext, UIComponent uiComponent, Converter converter) {

+        if (ExtValUtils.useProxyMapping()) {

+            ExtValUtils.getOrInitProxyMapping().put(uiComponent.getClientId(facesContext), converter);

+            ExtValUtils.decreaseProcessedConverterCount();

+        }

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/InformationProviderBean.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/InformationProviderBean.java
new file mode 100644
index 0000000..9aef0a7
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/InformationProviderBean.java
@@ -0,0 +1,174 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.core.validation.strategy.ValidationStrategy;

+

+import java.lang.annotation.Annotation;

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * centralized in order that these information arn'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

+ */

+public class InformationProviderBean {

+    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()).replace(".", "_");

+    private String basePackage = WebXmlParameter.CUSTOM_EXTENSION_BASE_PACKAGE;

+

+    public InformationProviderBean() {

+        if (this.basePackage == null) {

+            this.basePackage = ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME + ".custom.";

+        }

+        if (!this.basePackage.endsWith(".")) {

+            this.basePackage = this.basePackage + ".";

+        }

+    }

+

+    public String getBasePackage() {

+        return basePackage;

+    }

+

+    public String getCustomAnnotationExtractorFactory() {

+        return this.basePackage + "AnnotationExtractorFactory";

+    }

+

+    public String getCustomAnnotationExtractor() {

+        return this.basePackage + "AnnotationExtractor";

+    }

+

+    /*

+     * name mapper

+     */

+    public String getCustomValidationStrategyToMsgResolverNameMapper() {

+        return this.basePackage + "ValidationStrategyToMsgResolverNameMapper";

+    }

+

+    public String getCustomAnnotationToValidationStrategyNameMapper() {

+        return this.basePackage + "AnnotationToValidationStrategyNameMapper";

+    }

+

+    @Deprecated

+    public String getCustomAdapterNameMapper() {

+        return this.basePackage + "AdapterNameMapper";

+    }

+

+    /*

+     * factories

+     */

+    public String getCustomMessageResolverFactory() {

+        return this.basePackage + "MessageResolverFactory";

+    }

+

+    public String getCustomValidationStrategyFactory() {

+        return this.basePackage + "ValidationStrategyFactory";

+    }

+

+    @Deprecated

+    public String getCustomConverterAdapterFactory() {

+        return this.basePackage + "ConverterAdapterFactory";

+    }

+

+    //TODO

+    /*

+     * conventions (the rest of the conventions are built with the help of name mappers,...

+     */

+    public String getConventionForMessageBundle() {

+        return this.basePackage + "validation_messages";

+    }

+

+    /*

+     * static strategy mappings (name of property files)

+     */

+    public String getCustomStaticStrategyMappingSource() {

+        return this.basePackage + "strategy_mappings";

+    }

+

+    private List<String> staticStrategyMappings = new ArrayList<String>();

+

+    /*

+     * final methods

+     */

+    //TODO

+    public final String getConventionForModuleMessageBundle(String packageName) {

+        String newPackageName;

+        if (packageName.endsWith(".resolver")) {

+            newPackageName = packageName.replace(".resolver", ".bundle");

+        } else {

+            newPackageName = packageName.replace(".resolver.", ".bundle.");

+        }

+

+        return newPackageName + ".validation_messages";

+    }

+

+    public final List<String> getStaticStrategyMappingSources() {

+        return this.staticStrategyMappings;

+    }

+

+    public final void addStaticStrategyMappingSource(String resourceBundleName) {

+        synchronized (this) {

+            this.staticStrategyMappings.add(resourceBundleName);

+        }

+    }

+

+    public final boolean containsStaticStrategyMappingSource(String resourceBundleName) {

+        return this.staticStrategyMappings.contains(resourceBundleName);

+    }

+

+    /**

+     * use a custom name mapper to implement custom conventions

+     */

+    public final String getConventionNameForMessageResolverPackage(Class<? extends ValidationStrategy> validationStrategyClass, String targetClassName) {

+        String resolverName = validationStrategyClass.getName();

+

+        resolverName = resolverName.replace(".strategy.", ".message.resolver.");

+

+        if (targetClassName == null) {

+            //TODO

+            return null;

+        }

+        return resolverName.substring(0, resolverName.lastIndexOf(".")) + "." + targetClassName;

+    }

+

+    /**

+     * use a custom name mapper to implement custom conventions

+     */

+    public final String getConventionNameForMessageResolverClass(String strategyClassName) {

+        if (strategyClassName.endsWith("ValidationStrategy")) {

+            return strategyClassName.substring(0, strategyClassName.length() - 18) + "ValidationErrorMessageResolver";

+        } else if (strategyClassName.endsWith("Strategy")) {

+            return strategyClassName.substring(0, strategyClassName.length() - 8) + "ValidationErrorMessageResolver";

+        }

+        return strategyClassName;

+    }

+

+    /**

+     * use a custom name mapper to implement custom conventions

+     */

+    public final String getConventionNameForValidationStrategy(Annotation annotation) {

+        return annotation.annotationType().getName().replace(".annotation.", ".strategy.") + "Strategy";

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProcessedInformationEntry.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProcessedInformationEntry.java
new file mode 100644
index 0000000..340e789
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProcessedInformationEntry.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;
+
+import javax.faces.component.UIComponent;
+import java.util.List;
+
+/**
+ * @author Gerhard Petracek
+ */
+public class ProcessedInformationEntry {
+    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<ProcessedInformationEntry> furtherEntries;
+
+    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 List<ProcessedInformationEntry> getFurtherEntries() {
+        return furtherEntries;
+    }
+
+    public void setFurtherEntries(List<ProcessedInformationEntry> furtherEntries) {
+        this.furtherEntries = furtherEntries;
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProxyMappingPhaseListener.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProxyMappingPhaseListener.java
new file mode 100644
index 0000000..dbef049
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/ProxyMappingPhaseListener.java
@@ -0,0 +1,100 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.util.ExtValUtils;

+

+import javax.faces.event.PhaseEvent;

+import javax.faces.event.PhaseId;

+import javax.faces.event.PhaseListener;

+import javax.faces.context.FacesContext;

+import javax.faces.component.UIComponent;

+import javax.faces.component.EditableValueHolder;

+import java.util.List;

+

+/**

+ * due to a restriction at the state saving process

+ * a proxy gets a super-class which might impl. StateHolder

+ * -> saveState: a StateHolder impl. gets handled before Serializable -> callback doesn't get saved

+ * -> restoreState: restoreState of the super-class gets called - no callback -> no interceptor gets executed

+ * if a framework (such as trinidad) provides caching it's no problem

+ * -> use the web.xml context-param to deactivate the mechanism

+ *

+ * @author Gerhard Petracek

+ */

+public class ProxyMappingPhaseListener implements PhaseListener {

+    private boolean isInitialized = false;

+

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public void afterPhase(PhaseEvent event) {

+        if (!isInitialized) {

+            //don't use DEACTIVATE_PROXY_MAPPING here to allow a different concept

+            String initParam = WebXmlParameter.DEACTIVATE_RESTORE_PROXY_PHASE_LISTENER;

+

+            if(initParam != null && initParam.equalsIgnoreCase("true")) {

+                ExtValUtils.deregisterPhaseListener(this);

+            }

+            isInitialized = true;

+        }

+

+        if(!event.getPhaseId().equals(PhaseId.RENDER_RESPONSE)) {

+            return;

+        }

+

+        Integer processedConverterCount = ExtValUtils.getProcessedConverterCount();

+        //don't change the comparison with 0 - in order to reduce the overhead.

+        //if everything works correctly it's not necessary to inspact the full tree

+        //it's just due to a ri bug - normally it's performed during ExtValConverter#intercept#getAsString

+        if(ExtValUtils.useProxyMapping() && (processedConverterCount != null && !processedConverterCount.equals(0))){

+            storeComponentConverterMappingForProxies(event.getFacesContext(), event.getFacesContext().getViewRoot());

+        }

+    }

+

+    public void beforePhase(PhaseEvent event) {

+        if(!event.getPhaseId().equals(PhaseId.APPLY_REQUEST_VALUES)) {

+            return;

+        }

+

+        ExtValUtils.restoreProxies();

+    }

+

+    public PhaseId getPhaseId() {

+        return PhaseId.ANY_PHASE;

+    }

+

+    /**

+     * there is a ri bug (at least with jsp's) -> sometimes getAsString of converters aren't called

+     * -> there is no mapping -> if it's the case and there are unhandled editable value hoder components within the page

+     * -> search all these components and add the equivalent converter to the mapping

+     *

+     * @param facesContext reference to the current faces context

+     * @param uiComponent reference to the current component

+     */

+    private void storeComponentConverterMappingForProxies(FacesContext facesContext, UIComponent uiComponent) {

+        for(UIComponent child : (List<UIComponent>)uiComponent.getChildren()) {

+            if(child instanceof EditableValueHolder) {

+                ExtValUtils.getOrInitProxyMapping().put(child.getClientId(facesContext), ((EditableValueHolder)child).getConverter());

+            }

+            storeComponentConverterMappingForProxies(facesContext, child);

+        }

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/WebXmlParameter.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/WebXmlParameter.java
new file mode 100644
index 0000000..48366c6
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/WebXmlParameter.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.util.WebXmlUtils;

+

+/**

+ * centralized in order that these information arn't spread over the complete code base

+ *

+ * @author Gerhard Petracek

+ */

+public interface WebXmlParameter {

+    /*

+     * custom

+     */

+    static final String CUSTOM_MESSAGE_BUNDLE = WebXmlUtils.getInitParameter("CUSTOM_MESSAGE_BUNDLE");

+    static final String CUSTOM_EXTENSION_BASE_PACKAGE = WebXmlUtils.getInitParameter("CUSTOM_BASE_PACKAGE");

+    static final String CUSTOM_CONVENTION_INFO_PROVIDER_BEAN = WebXmlUtils.getInitParameter("CUSTOM_INFORMATION_PROVIDER_BEAN");

+

+    static final String CUSTOM_STRATEGY_TO_MESSAGE_RESOLVER_NAME_MAPPER = WebXmlUtils.getInitParameter("CUSTOM_STRATEGY_TO_MESSAGE_RESOLVER_NAME_MAPPER");

+    static final String CUSTOM_ANNOTATION_TO_VALIDATION_STRATEGY_NAME_MAPPER = WebXmlUtils.getInitParameter("CUSTOM_ANNOTATION_TO_VALIDATION_STRATEGY_NAME_MAPPER");

+

+    static final String CUSTOM_MESSAGE_RESOLVER_FACTORY = WebXmlUtils.getInitParameter("CUSTOM_MESSAGE_RESOLVER_FACTORY");

+    static final String CUSTOM_VALIDATION_STRATEGY_FACTORY = WebXmlUtils.getInitParameter("CUSTOM_VALIDATION_STRATEGY_FACTORY");

+    static final String CUSTOM_ANNOTATION_EXTRACTOR_FACTORY = WebXmlUtils.getInitParameter("CUSTOM_ANNOTATION_EXTRACTOR_FACTORY");

+

+    static final String CUSTOM_ANNOTATION_EXTRACTOR = WebXmlUtils.getInitParameter("CUSTOM_ANNOTATION_EXTRACTOR");

+

+    //TODO documentation

+    static final String CUSTOM_VALIDATIONSTRATEGY_MAPPING = WebXmlUtils.getInitParameter("CUSTOM_STATIC_VALIDATIONSTRATEGY_MAPPING");

+

+    /*

+     * deactivate

+     */

+    static final String DEACTIVATE_RESTORE_PROXY_PHASE_LISTENER = WebXmlUtils.getInitParameter("DEACTIVATE_RESTORE_PROXY_PHASE_LISTENER");

+    static final String DEACTIVATE_DEFAULT_CONVENTION = WebXmlUtils.getInitParameter("DEACTIVATE_DEFAULT_CONVENTION");

+    static final String DEACTIVATE_PROXY_MAPPING = WebXmlUtils.getInitParameter("DEACTIVATE_PROXY_MAPPING");

+

+    /*

+     * fallback lib - if the usage of cglib is a problem

+     */

+    @Deprecated

+    static final String CUSTOM_CONVERTER_TO_ADAPTER_NAME_MAPPER = WebXmlUtils.getInitParameter("CUSTOM_CONVERTER_TO_ADAPTER_NAME_MAPPER");

+    @Deprecated

+    static final String CUSTOM_CONVERTER_ADAPTER_FACTORY = WebXmlUtils.getInitParameter("CUSTOM_CONVERTER_ADAPTER_FACTORY");

+    @Deprecated

+    static final String USE_ADAPTERS = WebXmlUtils.getInitParameter("USE_ADAPTERS");

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/DefaultConverterAdapterFactory.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/DefaultConverterAdapterFactory.java
new file mode 100644
index 0000000..a089f7b
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/DefaultConverterAdapterFactory.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.adapter;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.core.ClassMappingFactory;

+import org.apache.myfaces.extensions.validator.core.adapter.mapper.CustomConfiguredConverterToAdapterNameMapper;

+import org.apache.myfaces.extensions.validator.core.adapter.mapper.CustomConventionConverterToAdapterNameMapper;

+import org.apache.myfaces.extensions.validator.core.adapter.mapper.DefaultConverterToAdapterNameMapper;

+import org.apache.myfaces.extensions.validator.core.adapter.mapper.SimpleConverterToAdapterNameMapper;

+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;

+import org.apache.myfaces.extensions.validator.util.ClassUtils;

+

+import javax.faces.convert.Converter;

+import java.util.ArrayList;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+/**

+ * just for the fallback solution

+ *

+ * @author Gerhard Petracek

+ */

+@Deprecated

+public class DefaultConverterAdapterFactory implements ClassMappingFactory<Converter, Converter> {

+    private static Map<String, String> converterAdapterMapping = new HashMap<String, String>();

+    private static List<NameMapper<Converter>> nameMapperList = new ArrayList<NameMapper<Converter>>();

+

+    static {

+        nameMapperList.add(new CustomConfiguredConverterToAdapterNameMapper());

+        nameMapperList.add(new CustomConventionConverterToAdapterNameMapper());

+        nameMapperList.add(new DefaultConverterToAdapterNameMapper());

+        nameMapperList.add(new SimpleConverterToAdapterNameMapper());

+    }

+

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public Converter create(Converter converter) {

+        String converterName = converter.getClass().getName();

+

+        if (converterAdapterMapping.containsKey(converterName)) {

+            return (Converter) ClassUtils.tryToInstantiateClassForName(converterAdapterMapping.get(converterName));

+        }

+

+        Converter adapter;

+        String adapterName;

+

+        for (NameMapper<Converter> nameMapper : nameMapperList) {

+            adapterName = nameMapper.createName(converter);

+            adapter = (Converter) ClassUtils.tryToInstantiateClassForName(adapterName);

+

+            if (adapter != null) {

+                addMapping(converterName, adapter.getClass().getName());

+                return adapter;

+            }

+        }

+

+        logger.debug("no adapter found for " + converterName + " -> converter itself is used -> no sev-en support");

+        return converter;

+    }

+

+    private void addMapping(String sourceConverter, String adapter) {

+        synchronized (DefaultConverterAdapterFactory.class) {

+            converterAdapterMapping.put(sourceConverter, adapter);

+        }

+        //TODO logging

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/ExtValFallbackConverter.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/ExtValFallbackConverter.java
new file mode 100644
index 0000000..4bed0ae
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/ExtValFallbackConverter.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.adapter;

+

+import org.apache.myfaces.extensions.validator.core.ExtValConverter;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.convert.Converter;

+

+/**

+ * just for the fallback solution

+ *

+ * @author Gerhard Petracek

+ */

+@Deprecated

+public class ExtValFallbackConverter extends ExtValConverter {

+    private Converter wrapped;

+

+    public ExtValFallbackConverter(Converter converter) {

+        this.wrapped = converter;

+    }

+

+    @Override

+    public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {

+        if (this.wrapped == null) {

+            //indirect approach for complex components

+            Converter converter = ExtValUtils.tryToCreateOriginalConverter(facesContext, uiComponent);

+            if (converter == null) {

+                return (o == null) ? null : o.toString();

+            } else {

+                return converter.getAsString(facesContext, uiComponent, o);

+            }

+        } else {

+            return this.wrapped.getAsString(facesContext, uiComponent, o);

+        }

+    }

+

+    @Override

+    protected Object getConvertedObject(FacesContext facesContext, UIComponent uiComponent, String s) {

+        if (this.wrapped == null) {

+            //indirect approach for complex components

+            //TODO

+            Converter converter = ExtValUtils.tryToCreateOriginalConverter(facesContext, uiComponent);

+

+            return (converter != null) ? converter.getAsObject(facesContext, uiComponent, s) : s;

+        } else {

+            return this.wrapped.getAsObject(facesContext, uiComponent, s);

+        }

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/CustomConfiguredConverterToAdapterNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/CustomConfiguredConverterToAdapterNameMapper.java
new file mode 100644
index 0000000..521af04
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/CustomConfiguredConverterToAdapterNameMapper.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.adapter.mapper;

+

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;

+

+import javax.faces.convert.Converter;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Deprecated

+public class CustomConfiguredConverterToAdapterNameMapper extends AbstractCustomNameMapper<Converter> {

+

+    protected String getCustomNameMapperClassName() {

+        return WebXmlParameter.CUSTOM_CONVERTER_TO_ADAPTER_NAME_MAPPER;

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/CustomConventionConverterToAdapterNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/CustomConventionConverterToAdapterNameMapper.java
new file mode 100644
index 0000000..7ffc153
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/CustomConventionConverterToAdapterNameMapper.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.adapter.mapper;

+

+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import javax.faces.convert.Converter;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Deprecated

+public class CustomConventionConverterToAdapterNameMapper extends AbstractCustomNameMapper<Converter> {

+

+    protected String getCustomNameMapperClassName() {

+        return ExtValUtils.getInformationProviderBean().getCustomAdapterNameMapper();

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/DefaultConverterToAdapterNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/DefaultConverterToAdapterNameMapper.java
new file mode 100644
index 0000000..5e4c7fd
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/DefaultConverterToAdapterNameMapper.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.adapter.mapper;

+

+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;

+

+import javax.faces.convert.Converter;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Deprecated

+public class DefaultConverterToAdapterNameMapper implements NameMapper<Converter> {

+    public String createName(Converter converter) {

+        return converter.getClass().getName() + "Adapter";

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/SimpleConverterToAdapterNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/SimpleConverterToAdapterNameMapper.java
new file mode 100644
index 0000000..4bcc8d5
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/adapter/mapper/SimpleConverterToAdapterNameMapper.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.adapter.mapper;

+

+import org.apache.myfaces.extensions.validator.ExtValInformation;

+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;

+

+import javax.faces.convert.Converter;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Deprecated

+public class SimpleConverterToAdapterNameMapper implements NameMapper<Converter> {

+    public String createName(Converter converter) {

+        return ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME + ".adapter." + converter.getClass().getSimpleName() + "Adapter";

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/AnnotationEntry.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/AnnotationEntry.java
new file mode 100644
index 0000000..8129dc5
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/AnnotationEntry.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.core.annotation;

+

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class AnnotationEntry {

+    private Annotation annotation;

+    private String valueBindingExpression;

+    //e.g. valueBindingName, DefaultValueBindingScanningAnnotationExtractor uses it for the variable-/method-name

+    private String boundTo;

+    private Class entityClass;

+

+    //requested by bernhard huemer

+    public <T> T getAnnotation(Class<T> targetClass) {

+        return (T) annotation;

+    }

+

+    /*

+     * generated

+     */

+    public Annotation getAnnotation() {

+        return annotation;

+    }

+

+    public void setAnnotation(Annotation annotation) {

+        this.annotation = annotation;

+    }

+

+    public String getValueBindingExpression() {

+        return valueBindingExpression;

+    }

+

+    public void setValueBindingExpression(String valueBindingExpression) {

+        this.valueBindingExpression = valueBindingExpression;

+    }

+

+    public String getBoundTo() {

+        return boundTo;

+    }

+

+    public void setBoundTo(String boundTo) {

+        this.boundTo = boundTo;

+    }

+

+    public Class getEntityClass() {

+        return entityClass;

+    }

+

+    public void setEntityClass(Class entityClass) {

+        this.entityClass = entityClass;

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/AnnotationExtractor.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/AnnotationExtractor.java
new file mode 100644
index 0000000..ed12c23
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/AnnotationExtractor.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.annotation.extractor;

+

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+

+import javax.faces.context.FacesContext;

+import java.util.List;

+

+/**

+ * @author Gerhard Petracek

+ */

+public interface AnnotationExtractor {

+    List<AnnotationEntry> extractAnnotations(FacesContext facesContext, Object object);

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/AnnotationExtractorFactory.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/AnnotationExtractorFactory.java
new file mode 100644
index 0000000..15e5946
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/AnnotationExtractorFactory.java
@@ -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.

+ */

+package org.apache.myfaces.extensions.validator.core.annotation.extractor;

+

+/**

+ * @author Gerhard Petracek

+ */

+public interface AnnotationExtractorFactory {

+    AnnotationExtractor create();

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/DefaultAnnotationExtractorFactory.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/DefaultAnnotationExtractorFactory.java
new file mode 100644
index 0000000..c3eec5a
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/DefaultAnnotationExtractorFactory.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.annotation.extractor;

+

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.util.ClassUtils;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DefaultAnnotationExtractorFactory implements AnnotationExtractorFactory {

+

+    private static AnnotationExtractor annotationExtractor = null;

+

+    public AnnotationExtractor create() {

+        if (annotationExtractor == null) {

+            List<String> annotationExtractorClassNames = new ArrayList<String>();

+

+            annotationExtractorClassNames.add(WebXmlParameter.CUSTOM_ANNOTATION_EXTRACTOR);

+            annotationExtractorClassNames.add(ExtValUtils.getInformationProviderBean().getCustomAnnotationExtractor());

+            annotationExtractorClassNames.add(DefaultComponentAnnotationExtractor.class.getName());

+

+            for (String className : annotationExtractorClassNames) {

+                annotationExtractor = (AnnotationExtractor) ClassUtils.tryToInstantiateClassForName(className);

+

+                if (annotationExtractor != null) {

+                    //TODO logging

+                    break;

+                }

+            }

+        }

+

+        return annotationExtractor;

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/DefaultComponentAnnotationExtractor.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/DefaultComponentAnnotationExtractor.java
new file mode 100644
index 0000000..940dc53
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/annotation/extractor/DefaultComponentAnnotationExtractor.java
@@ -0,0 +1,160 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.annotation.extractor;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.util.ELUtils;

+import org.apache.myfaces.extensions.validator.util.FaceletsTaglibExpressionUtils;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import java.lang.annotation.Annotation;

+import java.lang.reflect.Field;

+import java.lang.reflect.Method;

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.List;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DefaultComponentAnnotationExtractor implements AnnotationExtractor {

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public List<AnnotationEntry> extractAnnotations(FacesContext facesContext, Object object) {

+        //should never occur

+        if (!(object instanceof UIComponent)) {

+            //TODO

+            return new ArrayList<AnnotationEntry>();

+        }

+

+        UIComponent uiComponent = (UIComponent) object;

+

+        List<AnnotationEntry> annotationEntries = new ArrayList<AnnotationEntry>();

+

+        String valueBindingExpression = ELUtils.getReliableValueBindingExpression(uiComponent);

+

+        if (valueBindingExpression == null) {

+            return new ArrayList<AnnotationEntry>();

+        }

+

+        /*

+         * get bean class and property name

+         */

+        int beanPropertyBorder = valueBindingExpression.lastIndexOf('.');

+

+        if (beanPropertyBorder < 0) {

+            return new ArrayList<AnnotationEntry>();

+        }

+

+        String beans = valueBindingExpression.substring(valueBindingExpression.indexOf('{') + 1, beanPropertyBorder);

+

+        String property = valueBindingExpression.substring(beanPropertyBorder + 1, valueBindingExpression.indexOf('}'));

+

+        Class entityClass = ELUtils.getTypeOfValueBindingForExpression(facesContext, "#{" + beans + "}");

+

+        //create template entry

+        AnnotationEntry templateEntry = new AnnotationEntry();

+        //TODO test with complex components

+        templateEntry.setValueBindingExpression(valueBindingExpression);

+        templateEntry.setEntityClass(entityClass);

+        //TODO

+        templateEntry.setBoundTo("value");

+

+        /*

+         * find and add annotations

+         */

+        Class currentClass = entityClass;

+

+        while (!Object.class.getName().equals(currentClass.getName())) {

+            addPropertyAccessAnnotations(currentClass, property, annotationEntries, templateEntry);

+            addFieldAccessAnnotations(currentClass, property, annotationEntries, templateEntry);

+

+            currentClass = currentClass.getSuperclass();

+        }

+

+        for (Class currentInterface : entityClass.getInterfaces()) {

+            currentClass = currentInterface;

+

+            while (currentClass != null) {

+                addPropertyAccessAnnotations(currentClass, property, annotationEntries, templateEntry);

+

+                currentClass = currentClass.getSuperclass();

+            }

+        }

+

+        return annotationEntries;

+    }

+

+    protected void addPropertyAccessAnnotations(Class entity, String property, List<AnnotationEntry> annotationEntries, AnnotationEntry templateEntry) {

+        property = property.substring(0, 1).toUpperCase() + property.substring(1);

+

+        Method method;

+

+        try {

+            method = entity.getDeclaredMethod("get" + property);

+        } catch (NoSuchMethodException e) {

+            try {

+                method = entity.getDeclaredMethod("is" + property);

+            } catch (NoSuchMethodException e1) {

+                logger.debug("method not found - class: " + entity.getName() + " - methods: " + "get" + property + " " + "is" + property);

+                return;

+            }

+        }

+

+        addAnnotationToAnnotationEntries(annotationEntries, Arrays.asList(method.getAnnotations()), templateEntry);

+    }

+

+    protected void addFieldAccessAnnotations(Class entity, String property, List<AnnotationEntry> annotationEntries, AnnotationEntry templateEntry) {

+        Field field;

+

+        try {

+            field = entity.getDeclaredField(property);

+        } catch (Exception e) {

+            try {

+                field = entity.getDeclaredField("_" + property);

+            } catch (NoSuchFieldException e1) {

+                logger.debug("field " + property + " or _" + property + " not found");

+                return;

+            }

+        }

+

+        addAnnotationToAnnotationEntries(annotationEntries, Arrays.asList(field.getAnnotations()), templateEntry);

+    }

+

+    protected void addAnnotationToAnnotationEntries(List<AnnotationEntry> annotationEntries, List<Annotation> annotations, AnnotationEntry templateEntry) {

+        for (Annotation annotation : annotations) {

+            annotationEntries.add(createAnnotationEntry(annotation, templateEntry));

+        }

+    }

+

+    protected AnnotationEntry createAnnotationEntry(Annotation foundAnnotation, AnnotationEntry templateEntry) {

+        AnnotationEntry entry = new AnnotationEntry();

+

+        entry.setAnnotation(foundAnnotation);

+

+        entry.setEntityClass(templateEntry.getEntityClass());

+        entry.setValueBindingExpression(templateEntry.getValueBindingExpression());

+        entry.setBoundTo(templateEntry.getBoundTo());

+

+        return entry;

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/AbstractCustomNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/AbstractCustomNameMapper.java
new file mode 100644
index 0000000..1b53c66
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/AbstractCustomNameMapper.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.mapper;

+

+import org.apache.myfaces.extensions.validator.util.ClassUtils;

+

+/**

+ * NameMappers are stateless

+ *

+ * @author Gerhard Petracek

+ */

+public abstract class AbstractCustomNameMapper<T> implements NameMapper<T> {

+    private NameMapper<T> customNameMapper;

+

+    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();

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/NameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/NameMapper.java
new file mode 100644
index 0000000..3a27d7f
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/mapper/NameMapper.java
@@ -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.

+ */

+package org.apache.myfaces.extensions.validator.core.mapper;

+

+/**

+ * @author Gerhard Petracek

+ */

+public interface NameMapper<T> {

+    String createName(T source);

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/AbstractValidationErrorMessageResolver.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/AbstractValidationErrorMessageResolver.java
new file mode 100644
index 0000000..3614dd5
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/AbstractValidationErrorMessageResolver.java
@@ -0,0 +1,112 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import java.util.Locale;

+import java.util.MissingResourceException;

+import java.util.ResourceBundle;

+

+/**

+ * @author Gerhard Petracek

+ */

+public abstract class AbstractValidationErrorMessageResolver implements MessageResolver {

+    private static String deactivateDefaultConvention = WebXmlParameter.DEACTIVATE_DEFAULT_CONVENTION;

+    private static ResourceBundle defaultBundle = null;

+

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public String getMessage(String key, Locale locale) {

+        if (key == null || key.equals("")) {

+            return null;

+        }

+

+        String customMessage = tryToUseMessageBundleConvention(key, locale);

+

+        if (customMessage != null) {

+            return customMessage;

+        }

+

+        /*

+         * no message bundle or message found (with the convention)?

+         */

+        ResourceBundle resourceBundle = null;

+

+        //try to load custom messages

+        try {

+            resourceBundle = ResourceBundle.getBundle(getCustomBaseName(), locale);

+        }

+        catch (Throwable t) {

+            //do nothing - it was just a try

+        }

+

+        if (resourceBundle != null) {

+            try {

+                customMessage = resourceBundle.getString(key);

+            }

+            catch (MissingResourceException e) {

+                logger.trace("no custom message for " + key + " within " + getCustomBaseName());

+            }

+        }

+

+        //use custom name (if possible) otherwise: fallback to default message (if possible)

+        return (customMessage != null) ? customMessage : (getBaseName() != null) ? ResourceBundle.getBundle(getBaseName(), locale).getString(key) : null;

+    }

+

+    private String tryToUseMessageBundleConvention(String key, Locale locale) {

+        String customMessage = null;

+

+        if ((deactivateDefaultConvention == null || !deactivateDefaultConvention.equalsIgnoreCase("true")) &&

+                isDefaultMessageBundleConventionActive()) {

+            if (defaultBundle == null) {

+                try {

+                    defaultBundle = ResourceBundle.getBundle(ExtValUtils.getInformationProviderBean().getConventionForMessageBundle(), locale);

+                } catch (Throwable t) {

+                    //do nothing

+                    deactivateDefaultConvention = "true";

+                }

+            }

+

+            if (defaultBundle != null) {

+                try {

+                    customMessage = defaultBundle.getString(key);

+                }

+                catch (MissingResourceException e) {

+                    //do nothing

+                }

+            }

+        }

+

+        return customMessage;

+    }

+

+    protected boolean isDefaultMessageBundleConventionActive() {

+        return true;

+    }

+

+    protected abstract String getBaseName();

+

+    protected String getCustomBaseName() {

+        return null;

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultMessageResolverFactory.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultMessageResolverFactory.java
new file mode 100644
index 0000000..031645b
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultMessageResolverFactory.java
@@ -0,0 +1,78 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.ClassMappingFactory;

+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;

+import 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.util.ClassUtils;

+

+import java.util.ArrayList;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+/**

+ * @author Gerhard Petracek

+ */

+//TODO add generic java api (de-/register mapping)

+public class DefaultMessageResolverFactory implements ClassMappingFactory<ValidationStrategy, MessageResolver> {

+    private static Map<String, String> strategyMessageResolverMapping = new HashMap<String, String>();

+    private static List<NameMapper<ValidationStrategy>> nameMapperList = new ArrayList<NameMapper<ValidationStrategy>>();

+

+    static {

+        nameMapperList.add(new CustomConfiguredValidationStrategyToMsgResolverNameMapper());

+        nameMapperList.add(new CustomConventionValidationStrategyToMsgResolverNameMapper());

+        nameMapperList.add(new DefaultValidationStrategyToMsgResolverNameMapper());

+        nameMapperList.add(new DefaultModuleValidationStrategyToMsgResolverNameMapper());

+        nameMapperList.add(new SimpleValidationStrategyToMsgResolverNameMapper());

+    }

+

+    public MessageResolver create(ValidationStrategy validationStrategy) {

+        String strategyName = validationStrategy.getClass().getName();

+

+        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);

+            messageResolver = (MessageResolver) ClassUtils.tryToInstantiateClassForName(resolverName);

+

+            if (messageResolver != null) {

+                addMapping(strategyName, resolverName);

+                return messageResolver;

+            }

+        }

+

+        addMapping(strategyName, DefaultValidationErrorMessageResolver.class.getName());

+        return new DefaultValidationErrorMessageResolver();

+    }

+

+    private void addMapping(String strategyName, String messageResolverName) {

+        synchronized (DefaultMessageResolverFactory.class) {

+            strategyMessageResolverMapping.put(strategyName, messageResolverName);

+        }

+        //TODO logging

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultValidationErrorMessageResolver.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultValidationErrorMessageResolver.java
new file mode 100644
index 0000000..4176f41
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/DefaultValidationErrorMessageResolver.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.message.resolver;

+

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+/**

+ * @author Gerhard Petracek

+ */

+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 ExtValUtils.getInformationProviderBean().getConventionForModuleMessageBundle(getClass().getPackage().getName());

+    }

+

+    protected String getCustomBaseName() {

+        return CUSTOM_BUNDLE;

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/MessageResolver.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/MessageResolver.java
new file mode 100644
index 0000000..1750ec0
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/MessageResolver.java
@@ -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.

+ */

+package org.apache.myfaces.extensions.validator.core.validation.message.resolver;

+

+import java.util.Locale;

+

+/**

+ * @author Gerhard Petracek

+ */

+public interface MessageResolver {

+    String getMessage(String key, Locale locale);

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConfiguredValidationStrategyToMsgResolverNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConfiguredValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..b7c6f6a
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConfiguredValidationStrategyToMsgResolverNameMapper.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.validation.message.resolver.mapper;

+

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class CustomConfiguredValidationStrategyToMsgResolverNameMapper extends AbstractCustomNameMapper<ValidationStrategy> {

+

+    protected String getCustomNameMapperClassName() {

+        return WebXmlParameter.CUSTOM_STRATEGY_TO_MESSAGE_RESOLVER_NAME_MAPPER;

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConventionValidationStrategyToMsgResolverNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConventionValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..b806d17
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/CustomConventionValidationStrategyToMsgResolverNameMapper.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.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.util.ExtValUtils;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class CustomConventionValidationStrategyToMsgResolverNameMapper extends AbstractCustomNameMapper<ValidationStrategy> {

+

+    protected String getCustomNameMapperClassName() {

+        return ExtValUtils.getInformationProviderBean().getCustomValidationStrategyToMsgResolverNameMapper();

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultModuleValidationStrategyToMsgResolverNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultModuleValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..5ef4d77
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultModuleValidationStrategyToMsgResolverNameMapper.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.message.resolver.mapper;

+

+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.DefaultValidationErrorMessageResolver;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DefaultModuleValidationStrategyToMsgResolverNameMapper extends DefaultValidationStrategyToMsgResolverNameMapper {

+

+    @Override

+    protected String getClassName(String strategyClassName) {

+        return DefaultValidationErrorMessageResolver.class.getSimpleName();

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultValidationStrategyToMsgResolverNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..54db590
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/DefaultValidationStrategyToMsgResolverNameMapper.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.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.util.ExtValUtils;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DefaultValidationStrategyToMsgResolverNameMapper implements NameMapper<ValidationStrategy> {

+    public String createName(ValidationStrategy validationStrategy) {

+        return ExtValUtils.getInformationProviderBean().getConventionNameForMessageResolverPackage(validationStrategy.getClass(), getClassName(validationStrategy.getClass().getSimpleName()));

+    }

+

+    protected String getClassName(String strategyClassName) {

+        return ExtValUtils.getInformationProviderBean().getConventionNameForMessageResolverClass(strategyClassName);

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/SimpleValidationStrategyToMsgResolverNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/SimpleValidationStrategyToMsgResolverNameMapper.java
new file mode 100644
index 0000000..df6e577
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/message/resolver/mapper/SimpleValidationStrategyToMsgResolverNameMapper.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.validation.message.resolver.mapper;

+

+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class SimpleValidationStrategyToMsgResolverNameMapper implements NameMapper<ValidationStrategy> {

+    public String createName(ValidationStrategy validationStrategy) {

+        String resolverName = validationStrategy.getClass().getName();

+

+        return resolverName.substring(0, resolverName.lastIndexOf(".")) + ".DefaultValidationErrorMessageResolver";

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidationStrategy.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidationStrategy.java
new file mode 100644
index 0000000..227cd6c
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidationStrategy.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.validation.strategy;

+

+import org.apache.myfaces.extensions.validator.util.FactoryUtils;

+

+import javax.faces.application.FacesMessage;

+import javax.faces.context.FacesContext;

+import java.lang.annotation.Annotation;

+import java.util.Locale;

+import java.util.MissingResourceException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public abstract class AbstractValidationStrategy extends AbstractValidatorAdapter {

+    protected static final String DETAIL_MESSAGE_KEY_POSTFIX = "_details";

+

+    protected String resolveMessage(String key) {

+        Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();

+

+        return FactoryUtils.getMessageResolverFactory().create(this).getMessage(key, locale);

+    }

+

+    protected String getErrorMessageSummary(Annotation annotation) {

+        return resolveMessage(getValidationErrorMsgKey(annotation));

+    }

+

+    protected String getErrorMessageDetails(Annotation annotation) {

+        try {

+            String key = getValidationErrorMsgKey(annotation);

+            return (key != null) ? resolveMessage(key + DETAIL_MESSAGE_KEY_POSTFIX) : null;

+        } catch (MissingResourceException e) {

+            logger.warn("couldn't find key " + getValidationErrorMsgKey(annotation) + DETAIL_MESSAGE_KEY_POSTFIX, e);

+        }

+        return null;

+    }

+

+    protected FacesMessage getValidationErrorFacesMassage(Annotation annotation) {

+        return new FacesMessage(FacesMessage.SEVERITY_ERROR, getErrorMessageSummary(annotation), getErrorMessageDetails(annotation));

+    }

+

+    protected abstract String getValidationErrorMsgKey(Annotation annotation);

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidatorAdapter.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidatorAdapter.java
new file mode 100644
index 0000000..76854cc
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/AbstractValidatorAdapter.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.validation.strategy;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.convert.ConverterException;

+import javax.faces.validator.ValidatorException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public abstract class AbstractValidatorAdapter implements ValidationStrategy {

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public void validate(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) {

+        initValidation(facesContext, uiComponent, annotationEntry, convertedObject);

+

+        try {

+            processValidation(facesContext, uiComponent, annotationEntry, convertedObject);

+        }

+        catch (ValidatorException e) {

+            if (processAfterValidatorException(facesContext, uiComponent, annotationEntry, convertedObject, e)) {

+                throw new ConverterException(e.getFacesMessage(), e);

+            }

+        }

+    }

+

+    protected void initValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) {

+        //override if needed

+    }

+

+    //override if needed

+    protected boolean processAfterValidatorException(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject, ValidatorException e) {

+        return true;

+    }

+

+    protected abstract void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException;

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/DefaultValidationStrategyFactory.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/DefaultValidationStrategyFactory.java
new file mode 100644
index 0000000..0d4c2df
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/DefaultValidationStrategyFactory.java
@@ -0,0 +1,137 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.ClassMappingFactory;

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.mapper.CustomConfiguredAnnotationToValidationStrategyNameMapper;

+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.SimpleAnnotationToValidationStrategyNameMapper;

+import org.apache.myfaces.extensions.validator.util.ClassUtils;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import java.lang.annotation.Annotation;

+import java.util.*;

+

+/**

+ * @author Gerhard Petracek

+ */

+//TODO add generic java api (de-/register mapping)

+public class DefaultValidationStrategyFactory implements ClassMappingFactory<Annotation, ValidationStrategy> {

+    private static Map<String, String> annotationStrategyMapping = null;

+    private static List<NameMapper<Annotation>> nameMapperList = new ArrayList<NameMapper<Annotation>>();

+

+    static {

+        nameMapperList.add(new CustomConfiguredAnnotationToValidationStrategyNameMapper());

+        nameMapperList.add(new CustomConventionAnnotationToValidationStrategyNameMapper());

+        nameMapperList.add(new DefaultAnnotationToValidationStrategyNameMapper());

+        nameMapperList.add(new SimpleAnnotationToValidationStrategyNameMapper());

+        //TODO if jsr 303 doesn't change:

+        //nameMapperList.add(new BeanValidationAnnotationStrategyNameMapper());

+    }

+

+    public ValidationStrategy create(Annotation annotation) {

+        if (annotationStrategyMapping == null) {

+            initStaticStrategyMappings();

+        }

+

+        String annotationName = annotation.annotationType().getName();

+

+        if (annotationStrategyMapping.containsKey(annotationName)) {

+            return (ValidationStrategy) ClassUtils.tryToInstantiateClassForName(annotationStrategyMapping.get(annotationName));

+        }

+

+        ValidationStrategy validationStrategy;

+        String strategyName;

+        //null -> use name mappers

+        for (NameMapper<Annotation> nameMapper : nameMapperList) {

+            strategyName = nameMapper.createName(annotation);

+            //build convention (ValidationStrategy)

+            validationStrategy = (ValidationStrategy) ClassUtils.tryToInstantiateClassForName(strategyName);

+

+            if (validationStrategy != null) {

+                addMapping(annotationName, strategyName);

+                return validationStrategy;

+            }

+        }

+

+        return null;

+    }

+

+    private void addMapping(String annotationName, String strategyName) {

+        synchronized (DefaultValidationStrategyFactory.class) {

+            annotationStrategyMapping.put(annotationName, strategyName);

+        }

+        //TODO logging

+    }

+

+    private void initStaticStrategyMappings() {

+        synchronized (DefaultValidationStrategyFactory.class) {

+            annotationStrategyMapping = new HashMap<String, String>();

+

+            //setup internal static mappings

+            for (String internalMappingSource : ExtValUtils.getInformationProviderBean().getStaticStrategyMappingSources()) {

+                setupStrategyMappings(internalMappingSource);

+            }

+

+            //try to setup mapping with base name by convention - overrides default mapping

+            try {

+                //build convention (strategy mapping)

+                setupStrategyMappings(ExtValUtils.getInformationProviderBean().getCustomStaticStrategyMappingSource());

+            }

+            catch (Throwable t) {

+                //do nothing - it was just a try

+            }

+

+            //setup custom mapping - overrides all other mappings

+            String customMappingBaseName = WebXmlParameter.CUSTOM_VALIDATIONSTRATEGY_MAPPING;

+            if (customMappingBaseName != null) {

+                try {

+                    setupStrategyMappings(customMappingBaseName);

+                }

+                catch (MissingResourceException e) {

+                    //TODO logging

+                    e.printStackTrace();

+                }

+            }

+        }

+    }

+

+    private void setupStrategyMappings(String bundle) {

+        ResourceBundle strategyMapping = ResourceBundle.getBundle(bundle);

+

+        if (strategyMapping == null) {

+            return;

+        }

+

+        Enumeration keys = strategyMapping.getKeys();

+

+        String annotationClassName;

+        String validationStrategyClassName;

+

+        while (keys.hasMoreElements()) {

+            annotationClassName = (String) keys.nextElement();

+            validationStrategyClassName = strategyMapping.getString(annotationClassName);

+

+            addMapping(annotationClassName, validationStrategyClassName);

+        }

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/ValidationStrategy.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/ValidationStrategy.java
new file mode 100644
index 0000000..7db2c9b
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/ValidationStrategy.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.strategy;

+

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+

+/**

+ * @author Gerhard Petracek

+ */

+public interface ValidationStrategy {

+    void validate(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject);

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConfiguredAnnotationToValidationStrategyNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConfiguredAnnotationToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..89ad956
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConfiguredAnnotationToValidationStrategyNameMapper.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.strategy.mapper;

+

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;

+

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Deprecated

+public class CustomConfiguredAnnotationToValidationStrategyNameMapper extends AbstractCustomNameMapper<Annotation> {

+

+    protected String getCustomNameMapperClassName() {

+        return WebXmlParameter.CUSTOM_ANNOTATION_TO_VALIDATION_STRATEGY_NAME_MAPPER;

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConventionAnnotationToValidationStrategyNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConventionAnnotationToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..8281da4
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/CustomConventionAnnotationToValidationStrategyNameMapper.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.mapper;

+

+import org.apache.myfaces.extensions.validator.core.mapper.AbstractCustomNameMapper;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import java.lang.annotation.Annotation;

+

+/**

+ * NameMappers are stateless

+ *

+ * @author Gerhard Petracek

+ */

+public class CustomConventionAnnotationToValidationStrategyNameMapper extends AbstractCustomNameMapper<Annotation> {

+

+    protected String getCustomNameMapperClassName() {

+        return ExtValUtils.getInformationProviderBean().getCustomAnnotationToValidationStrategyNameMapper();

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/DefaultAnnotationToValidationStrategyNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/DefaultAnnotationToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..0bbb828
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/DefaultAnnotationToValidationStrategyNameMapper.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.validation.strategy.mapper;

+

+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DefaultAnnotationToValidationStrategyNameMapper implements NameMapper<Annotation> {

+    public String createName(Annotation annotation) {

+        return ExtValUtils.getInformationProviderBean().getConventionNameForValidationStrategy(annotation);

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/SimpleAnnotationToValidationStrategyNameMapper.java b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/SimpleAnnotationToValidationStrategyNameMapper.java
new file mode 100644
index 0000000..5f94084
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/core/validation/strategy/mapper/SimpleAnnotationToValidationStrategyNameMapper.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.strategy.mapper;

+

+import org.apache.myfaces.extensions.validator.core.mapper.NameMapper;

+

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class SimpleAnnotationToValidationStrategyNameMapper implements NameMapper<Annotation> {

+    public String createName(Annotation annotation) {

+        return annotation.annotationType().getName() + "Strategy";

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/util/ClassUtils.java b/core/src/main/java/org/apache/myfaces/extensions/validator/util/ClassUtils.java
new file mode 100644
index 0000000..3a5d613
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/util/ClassUtils.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.util;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class ClassUtils {

+    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 Object tryToInstantiateClass(Class 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();

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/util/ELUtils.java b/core/src/main/java/org/apache/myfaces/extensions/validator/util/ELUtils.java
new file mode 100644
index 0000000..c7921f3
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/util/ELUtils.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.util;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.el.ValueBinding;

+

+/**

+ * in order to centralize the jsf version dependency within the core

+ *

+ * @author Gerhard Petracek

+ */

+public class ELUtils {

+    public static Class getTypeOfValueBindingForExpression(FacesContext facesContext, String valueBindingExpression) {

+        //due to a restriction with the ri

+        Object bean = ELUtils.getValueOfExpression(facesContext, valueBindingExpression);

+        return (bean != null) ? bean.getClass() : null;

+    }

+

+    public static Object getBean(String beanName) {

+        FacesContext facesContext = FacesContext.getCurrentInstance();

+        return facesContext.getApplication().getVariableResolver().resolveVariable(facesContext, beanName);

+    }

+

+    //TODO refactor - problem - static values - jsf 1.2 e.g.: ${value}

+    public static Object getBeanObject(String valueBindingExpression, UIComponent uiComponent) {

+        return getBeanObject(valueBindingExpression);

+    }

+

+    public static Object getBeanObject(String valueBindingExpression) {

+        String newExpression = valueBindingExpression.substring(0, valueBindingExpression.lastIndexOf(".")) + "}";

+

+        return getValueOfExpression(FacesContext.getCurrentInstance(), newExpression);

+    }

+

+    public static Object getValueOfExpression(FacesContext facesContext, String valueBindingExpression) {

+        return (valueBindingExpression != null) ? facesContext.getApplication().createValueBinding(valueBindingExpression).getValue(facesContext) : null;

+    }

+

+    public static boolean isExpressionValid(FacesContext facesContext, String valueBindingExpression) {

+        return facesContext.getApplication().createValueBinding(valueBindingExpression) != null;

+    }

+

+

+    public static String getReliableValueBindingExpression(UIComponent uiComponent) {

+        String valueBindingExpression = getValueBindingExpression(uiComponent);

+

+        String baseExpression = valueBindingExpression;

+        if(baseExpression.contains(".")) {

+            baseExpression = baseExpression.substring(0, valueBindingExpression.lastIndexOf(".")) + "}";

+        }

+

+        if(getTypeOfValueBindingForExpression(FacesContext.getCurrentInstance(), baseExpression) == null) {

+            valueBindingExpression = FaceletsTaglibExpressionUtils.tryToCreateValueBindingForFaceletsBinding(uiComponent);

+        }

+        return valueBindingExpression;

+    }

+

+    public static String getValueBindingExpression(UIComponent uiComponent) {

+        ValueBinding valueExpression = uiComponent.getValueBinding("value");

+

+        return (valueExpression != null) ? valueExpression.getExpressionString() : null;

+    }

+

+    public static Class getTypeOfValueBindingForComponent(FacesContext facesContext, UIComponent uiComponent) {

+        ValueBinding valueBinding = uiComponent.getValueBinding("value");

+

+        return (valueBinding != null) ? valueBinding.getType(facesContext) : null;

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/util/ExtValUtils.java b/core/src/main/java/org/apache/myfaces/extensions/validator/util/ExtValUtils.java
new file mode 100644
index 0000000..306cef0
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/util/ExtValUtils.java
@@ -0,0 +1,298 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.InformationProviderBean;

+import org.apache.myfaces.extensions.validator.core.ProcessedInformationEntry;

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+

+import javax.faces.FactoryFinder;

+import javax.faces.application.Application;

+import javax.faces.component.UIComponent;

+import javax.faces.component.UIViewRoot;

+import javax.faces.component.ValueHolder;

+import javax.faces.context.FacesContext;

+import javax.faces.convert.Converter;

+import javax.faces.event.PhaseListener;

+import javax.faces.lifecycle.Lifecycle;

+import javax.faces.lifecycle.LifecycleFactory;

+import java.util.*;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class ExtValUtils {

+

+    public static String getBasePackage() {

+        return getInformationProviderBean().getBasePackage();

+    }

+

+    public static InformationProviderBean getInformationProviderBean() {

+        Map applicationMap = FacesContext.getCurrentInstance().getExternalContext().getApplicationMap();

+        InformationProviderBean bean = (InformationProviderBean) applicationMap.get(InformationProviderBean.BEAN_NAME);

+

+        if (bean == null) {

+            return initInformationProviderBean(applicationMap);

+        }

+        return bean;

+    }

+

+    private static InformationProviderBean initInformationProviderBean(Map applicationMap) {

+

+        List<String> informationProviderBeanClassNames = new ArrayList<String>();

+

+        informationProviderBeanClassNames.add(WebXmlParameter.CUSTOM_CONVENTION_INFO_PROVIDER_BEAN);

+        informationProviderBeanClassNames.add(ExtValUtils.getCustomInformationProviderBeanClassName());

+        informationProviderBeanClassNames.add(InformationProviderBean.class.getName());

+

+        InformationProviderBean informationProviderBean;

+        for (String className : informationProviderBeanClassNames) {

+            informationProviderBean = (InformationProviderBean) ClassUtils.tryToInstantiateClassForName(className);

+

+            if (informationProviderBean != null) {

+                applicationMap.put(InformationProviderBean.BEAN_NAME, informationProviderBean);

+                return informationProviderBean;

+            }

+        }

+        throw new IllegalStateException(InformationProviderBean.class.getName() + " not found");

+    }

+

+    public static String getCustomInformationProviderBeanClassName() {

+        InformationProviderBean bean = (InformationProviderBean) ELUtils.getBean(InformationProviderBean.CUSTOM_BEAN);

+

+        return (bean != null) ? bean.getClass().getName() : null;

+    }

+

+    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 final String VALUE_BINDING_CONVERTED_VALUE_MAPPING_KEY = ExtValUtils.class.getName();

+

+    public static Map<String, ProcessedInformationEntry> getOrInitValueBindingConvertedValueMapping() {

+        Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();

+

+        if (!requestMap.containsKey(VALUE_BINDING_CONVERTED_VALUE_MAPPING_KEY)) {

+            resetCrossValidationStorage();

+        }

+

+        return (Map<String, ProcessedInformationEntry>) requestMap.get(VALUE_BINDING_CONVERTED_VALUE_MAPPING_KEY);

+    }

+

+    public static void resetCrossValidationStorage() {

+        FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(VALUE_BINDING_CONVERTED_VALUE_MAPPING_KEY, new HashMap<String, ProcessedInformationEntry>());

+    }

+

+    /*

+     * workaround: mapping clientId -> proxy -> after restore view: find component + set converter of the mapping

+     * TODO: find a better solution

+     */

+    public static final String PROXY_MAPPING_KEY = VALUE_BINDING_CONVERTED_VALUE_MAPPING_KEY + ":proxyMapping";

+

+    public static Map<String, Object> getOrInitProxyMapping() {

+        //session scope is just the worst case - cleanup after restore view

+        Map sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();

+

+        if (!sessionMap.containsKey(PROXY_MAPPING_KEY)) {

+            resetProxyMapping();

+        }

+

+        return (Map<String, Object>) sessionMap.get(PROXY_MAPPING_KEY);

+    }

+

+    public static void resetProxyMapping() {

+        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(PROXY_MAPPING_KEY, new HashMap<String, Object>());

+    }

+

+    public static final String PROCESSED_CONVERTER_COUNT_KEY = VALUE_BINDING_CONVERTED_VALUE_MAPPING_KEY + ":processedConverterCount";

+

+    public static Integer getProcessedConverterCount() {

+        Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();

+

+        if (!requestMap.containsKey(PROCESSED_CONVERTER_COUNT_KEY)) {

+            resetProcessedConverterMapping();

+        }

+

+        return (Integer) requestMap.get(PROCESSED_CONVERTER_COUNT_KEY);

+    }

+

+    public static void setProcessedConverterCount(Integer count) {

+        Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();

+

+        if (!requestMap.containsKey(PROCESSED_CONVERTER_COUNT_KEY)) {

+            resetProcessedConverterMapping();

+        }

+

+        requestMap.put(PROCESSED_CONVERTER_COUNT_KEY, count);

+    }

+

+    public static void resetProcessedConverterMapping() {

+        FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(PROCESSED_CONVERTER_COUNT_KEY, 0);

+    }

+

+    public static void increaseProcessedConverterCount() {

+        setProcessedConverterCount(getProcessedConverterCount() + 1);

+    }

+

+    public static void decreaseProcessedConverterCount() {

+        setProcessedConverterCount(getProcessedConverterCount() - 1);

+    }

+

+    public static boolean useProxyMapping() {

+

+        String initParam = WebXmlParameter.DEACTIVATE_PROXY_MAPPING;

+        boolean disableProxyMapping = (initParam != null && initParam.trim().equalsIgnoreCase("true"));

+

+        return !(useFallbackAdapters() || disableProxyMapping);

+    }

+

+    @Deprecated

+    public static boolean useFallbackAdapters() {

+        String initParam = WebXmlParameter.USE_ADAPTERS;

+        return (initParam != null && initParam.trim().equalsIgnoreCase("true"));

+    }

+

+    public static void restoreProxies() {

+        UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();

+

+        if (viewRoot != null && ExtValUtils.useProxyMapping()) {

+            Map componentConverterMapping = ExtValUtils.getOrInitProxyMapping();

+

+            Iterator current = componentConverterMapping.keySet().iterator();

+            String key;

+            Converter converter;

+            Converter converterOfComponent;

+            UIComponent component;

+            while (current.hasNext()) {

+                key = (String) current.next();

+                converter = (Converter) componentConverterMapping.get(key);

+                component = viewRoot.findComponent(key);

+

+                if (component == null) {

+                    component = resolveComponentInComplexComponent(viewRoot, component, key);

+

+                    if (component == null) {

+                        continue;

+                    }

+                }

+

+                if (!(component instanceof ValueHolder)) {

+                    continue;

+                }

+

+                converterOfComponent = ((ValueHolder) component).getConverter();

+

+                //converterOfComponent lost callback during state-saving -> set converter of same type

+                if (converterOfComponent != null && converterOfComponent.getClass().getSuperclass().equals(converter.getClass().getSuperclass())) {

+                    ((ValueHolder) component).setConverter(converter);

+                }

+            }

+        }

+

+        if (ExtValUtils.useProxyMapping()) {

+            ExtValUtils.resetProxyMapping();

+        }

+    }

+

+    //TODO

+    private static UIComponent resolveComponentInComplexComponent(UIComponent viewRoot, UIComponent component, String key) {

+        int index = key.lastIndexOf(":");

+

+        if(index == -1) {

+            return null;

+        }

+        

+        String newKey = key.substring(0, index);

+        if (viewRoot.findComponent(newKey) == null) {

+            int newIndex = newKey.lastIndexOf(":");

+            if (newIndex < 1) {

+                return null;

+            }

+            newKey = newKey.substring(0, newIndex);

+

+            component = viewRoot.findComponent(newKey);

+

+            if (component == null) {

+                return null;

+            } else {

+                return tryToResolveChildComponent(component, key.substring(key.lastIndexOf(":")));

+            }

+        }

+        return null;

+    }

+

+    //TODO

+    private static UIComponent tryToResolveChildComponent(UIComponent component, String endOfKey) {

+        FacesContext facesContext = FacesContext.getCurrentInstance();

+        String clientId = component.getClientId(facesContext);

+

+        if (clientId.substring(clientId.lastIndexOf(":")).endsWith(endOfKey)) {

+            return component;

+        }

+

+        UIComponent foundComponent;

+        for (UIComponent child : (List<UIComponent>) component.getChildren()) {

+            foundComponent = tryToResolveChildComponent(child, endOfKey);

+

+            if (foundComponent != null) {

+                return foundComponent;

+            }

+        }

+

+        return null;

+    }

+

+    public static final String ORIGINAL_APPLICATION_KEY = VALUE_BINDING_CONVERTED_VALUE_MAPPING_KEY + ":wrapped_application";

+

+    //in order to access the wrapped application and support other Application wrappers

+    public static void setOriginalApplication(Application application) {

+        FacesContext facesContext = FacesContext.getCurrentInstance();

+        Map applicationMap = facesContext.getExternalContext().getApplicationMap();

+

+        if (!applicationMap.containsKey(ORIGINAL_APPLICATION_KEY)) {

+            synchronized (ExtValUtils.class) {

+                applicationMap.put(ORIGINAL_APPLICATION_KEY, application);

+            }

+        }

+    }

+

+    public static Application getOriginalApplication() {

+        return (Application) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get(ORIGINAL_APPLICATION_KEY);

+    }

+

+    public static Converter tryToCreateOriginalConverter(FacesContext facesContext, UIComponent uiComponent) {

+        //for backward compatibility: cross-validation workaround with hidden field and static value

+        Class valueBindingType = ELUtils.getTypeOfValueBindingForComponent(facesContext, uiComponent);

+

+        if (valueBindingType == null) {

+            return null;

+        }

+

+        return getOriginalApplication().createConverter(valueBindingType);

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/util/FaceletsTaglibExpressionUtils.java b/core/src/main/java/org/apache/myfaces/extensions/validator/util/FaceletsTaglibExpressionUtils.java
new file mode 100644
index 0000000..8615cfb
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/util/FaceletsTaglibExpressionUtils.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.util;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.el.ValueBinding;

+import java.io.Externalizable;

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class FaceletsTaglibExpressionUtils {

+    public static String tryToCreateValueBindingForFaceletsBinding(UIComponent uiComponent) {

+        String faceletsValueBindingExpression = ELUtils.getValueBindingExpression(uiComponent);

+

+        try {

+            List<String> foundBindings = extractELTerms(uiComponent.getValueBinding("value"));

+

+            return faceletsValueBindingExpression.substring(0, 1) + "{" + createBinding(foundBindings) + "}";

+        } catch (Throwable t) {

+            return faceletsValueBindingExpression;

+        }

+    }

+

+    private static String createBinding(List<String> expressions) {

+        String result = "";

+

+        String prevFaceletsAttributeName = null;

+        String currentBinding;

+        String partOfBinding;

+

+        int indexOfBindingDetails;

+        String[] foundBindingDetails;

+        String[] bindingDetails;

+

+        for (String entry : expressions) {

+            if (entry.startsWith("ValueExpression[")) {

+                continue;

+            }

+            //TODO log entry

+

+            foundBindingDetails = entry.split(" ");

+            indexOfBindingDetails = findIndexOfBindingDetails(foundBindingDetails);

+            if (indexOfBindingDetails == -1) {

+                return null;

+            }

+

+            bindingDetails = foundBindingDetails[indexOfBindingDetails].split("=");

+

+            if (bindingDetails.length < 2) {

+                return null;

+            }

+

+            currentBinding = bindingDetails[1];

+            if (prevFaceletsAttributeName != null) {

+                partOfBinding = currentBinding.substring(currentBinding.indexOf(prevFaceletsAttributeName) + prevFaceletsAttributeName.length(), currentBinding.indexOf("}"));

+                result = result + partOfBinding;

+            } else {

+                result = currentBinding.substring(currentBinding.indexOf("{") + 1, currentBinding.indexOf("}"));

+            }

+

+            prevFaceletsAttributeName = bindingDetails[0];

+        }

+        return result;

+    }

+

+    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()) {

+                elCount += resolveELTerms(entry, visited, foundELTerms, count + 1);

+            }

+            return elCount;

+        }

+

+        if (isELTerm(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 (isELTerm(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 = (Field[]) 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 && isELTerm(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 boolean isELTerm(Object o) {

+        if (o instanceof ValueBinding || o instanceof Externalizable) {

+            return false;

+        }

+

+        String s = o.toString();

+        return ((s.contains("#") || s.contains("$")) && s.contains("{") && s.contains("}"));

+    }

+

+    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;

+    }

+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/util/FactoryUtils.java b/core/src/main/java/org/apache/myfaces/extensions/validator/util/FactoryUtils.java
new file mode 100644
index 0000000..d2cd72a
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/util/FactoryUtils.java
@@ -0,0 +1,132 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.ClassMappingFactory;

+import org.apache.myfaces.extensions.validator.core.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.core.adapter.DefaultConverterAdapterFactory;

+import org.apache.myfaces.extensions.validator.core.annotation.extractor.AnnotationExtractorFactory;

+import org.apache.myfaces.extensions.validator.core.annotation.extractor.DefaultAnnotationExtractorFactory;

+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.DefaultMessageResolverFactory;

+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.DefaultValidationStrategyFactory;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;

+

+import javax.faces.convert.Converter;

+import java.lang.annotation.Annotation;

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * @author Gerhard Petracek

+ */

+//TODO

+public class FactoryUtils {

+    private static AnnotationExtractorFactory annotationExtractorFactory;

+

+    public static AnnotationExtractorFactory getAnnotationExtractorFactory() {

+        if (annotationExtractorFactory == null) {

+            List<String> annotationExtractorFactoryClassNames = new ArrayList<String>();

+

+            annotationExtractorFactoryClassNames.add(WebXmlParameter.CUSTOM_ANNOTATION_EXTRACTOR_FACTORY);

+            annotationExtractorFactoryClassNames.add(ExtValUtils.getInformationProviderBean().getCustomAnnotationExtractorFactory());

+            annotationExtractorFactoryClassNames.add(DefaultAnnotationExtractorFactory.class.getName());

+

+            for (String className : annotationExtractorFactoryClassNames) {

+                annotationExtractorFactory = (AnnotationExtractorFactory) ClassUtils.tryToInstantiateClassForName(className);

+

+                if (annotationExtractorFactory != null) {

+                    //TODO logging

+                    break;

+                }

+            }

+        }

+

+        return annotationExtractorFactory;

+    }

+

+    private static ClassMappingFactory<Annotation, ValidationStrategy> validationStrategyFactory;

+

+    public static ClassMappingFactory<Annotation, ValidationStrategy> getValidationStrategyFactory() {

+        if (validationStrategyFactory == null) {

+            List<String> validationStrategyFactoryClassNames = new ArrayList<String>();

+

+            validationStrategyFactoryClassNames.add(WebXmlParameter.CUSTOM_VALIDATION_STRATEGY_FACTORY);

+            validationStrategyFactoryClassNames.add(ExtValUtils.getInformationProviderBean().getCustomValidationStrategyFactory());

+            validationStrategyFactoryClassNames.add(DefaultValidationStrategyFactory.class.getName());

+

+            for (String className : validationStrategyFactoryClassNames) {

+                validationStrategyFactory = (ClassMappingFactory<Annotation, ValidationStrategy>) ClassUtils.tryToInstantiateClassForName(className);

+

+                if (validationStrategyFactory != null) {

+                    //TODO logging

+                    break;

+                }

+            }

+        }

+

+        return validationStrategyFactory;

+    }

+

+    private static ClassMappingFactory<ValidationStrategy, MessageResolver> messageResolverFactory;

+

+    public static ClassMappingFactory<ValidationStrategy, MessageResolver> getMessageResolverFactory() {

+        if (messageResolverFactory == null) {

+            List<String> messageResolverFactoryClassNames = new ArrayList<String>();

+

+            messageResolverFactoryClassNames.add(WebXmlParameter.CUSTOM_MESSAGE_RESOLVER_FACTORY);

+            messageResolverFactoryClassNames.add(ExtValUtils.getInformationProviderBean().getCustomMessageResolverFactory());

+            messageResolverFactoryClassNames.add(DefaultMessageResolverFactory.class.getName());

+

+            for (String className : messageResolverFactoryClassNames) {

+                messageResolverFactory = (ClassMappingFactory<ValidationStrategy, MessageResolver>) ClassUtils.tryToInstantiateClassForName(className);

+

+                if (messageResolverFactory != null) {

+                    //TODO logging

+                    break;

+                }

+            }

+        }

+

+        return messageResolverFactory;

+    }

+

+    private static ClassMappingFactory<Converter, Converter> converterAdapterFactory;

+

+    @Deprecated

+    public static ClassMappingFactory<Converter, Converter> getConverterAdapterFactory() {

+        if (converterAdapterFactory == null) {

+            List<String> converterAdapterFactoryClassNames = new ArrayList<String>();

+

+            converterAdapterFactoryClassNames.add(WebXmlParameter.CUSTOM_CONVERTER_ADAPTER_FACTORY);

+            converterAdapterFactoryClassNames.add(ExtValUtils.getInformationProviderBean().getCustomConverterAdapterFactory());

+            converterAdapterFactoryClassNames.add(DefaultConverterAdapterFactory.class.getName());

+

+            for (String className : converterAdapterFactoryClassNames) {

+                converterAdapterFactory = (ClassMappingFactory<Converter, Converter>) ClassUtils.tryToInstantiateClassForName(className);

+

+                if (converterAdapterFactory != null) {

+                    //TODO logging

+                    break;

+                }

+            }

+        }

+        return converterAdapterFactory;

+    }

+}

diff --git a/core/src/main/java/org/apache/myfaces/extensions/validator/util/WebXmlUtils.java b/core/src/main/java/org/apache/myfaces/extensions/validator/util/WebXmlUtils.java
new file mode 100644
index 0000000..3bceb72
--- /dev/null
+++ b/core/src/main/java/org/apache/myfaces/extensions/validator/util/WebXmlUtils.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.ExtValInformation;

+

+import javax.faces.context.FacesContext;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class WebXmlUtils {

+

+    public static String getInitParameter(String key) {

+        String value = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(ExtValInformation.WEBXML_PARAM_PREFIX + "." + key);

+        //TODO

+        return (value != null) ? value.replace(" ", "").trim() : null;

+    }

+}

diff --git a/core/src/main/resources/LICENSE.txt b/core/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/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/core/src/main/resources/NOTICE.txt b/core/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/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/examples/feature-set_01/pom.xml b/examples/feature-set_01/pom.xml
new file mode 100644
index 0000000..9183802
--- /dev/null
+++ b/examples/feature-set_01/pom.xml
@@ -0,0 +1,110 @@
+<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>war</packaging>

+

+    <groupId>org.apache.myfaces.extensions.validator.examples</groupId>

+    <artifactId>examples-feature-set_01</artifactId>

+

+    <name>MyFaces Extensions-Validator examples feature-set 01</name>

+    <version>${build.version}</version>

+

+    <parent>

+        <groupId>org.apache.myfaces.extensions.validator.examples</groupId>

+        <artifactId>examples-project</artifactId>

+        <version>${build.version}</version>

+    </parent>

+

+    <dependencies>

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator</groupId>

+            <artifactId>myfaces-extval-core</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>

+            <artifactId>myfaces-extval-cross-validation</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>com.sun.facelets</groupId>

+            <artifactId>jsf-facelets</artifactId>

+            <version>1.1.14</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>org.apache.myfaces.core</groupId>

+            <artifactId>myfaces-api</artifactId>

+            <version>${jsf.version}</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>org.apache.myfaces.core</groupId>

+            <artifactId>myfaces-impl</artifactId>

+            <version>${jsf.version}</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>org.apache.myfaces.trinidad</groupId>

+            <artifactId>trinidad-api</artifactId>

+            <version>${trinidad.version}</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>org.apache.myfaces.trinidad</groupId>

+            <artifactId>trinidad-impl</artifactId>

+            <version>${trinidad.version}</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>javax.el</groupId>

+            <artifactId>el-api</artifactId>

+            <version>1.0</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>el-impl</groupId>

+            <artifactId>el-impl</artifactId>

+            <version>1.0</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>org.apache.myfaces.tomahawk</groupId>

+            <artifactId>tomahawk</artifactId>

+            <version>1.1.6</version>

+            <scope>compile</scope>

+        </dependency>

+    </dependencies>

+

+    <build>

+        <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/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/custom/validation_messages.properties b/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/custom/validation_messages.properties
new file mode 100644
index 0000000..765191a
--- /dev/null
+++ b/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/custom/validation_messages.properties
@@ -0,0 +1,2 @@
+repeated_password_requried=please retype the password

+repeated_password_requried_details=please retype the password
\ No newline at end of file
diff --git a/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/demo/domain/Person.java b/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/demo/domain/Person.java
new file mode 100644
index 0000000..b5f915b
--- /dev/null
+++ b/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/demo/domain/Person.java
@@ -0,0 +1,129 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.extensions.validator.demo.domain;

+

+import org.apache.myfaces.extensions.validator.baseval.annotation.Length;

+import org.apache.myfaces.extensions.validator.baseval.annotation.Regex;

+import org.apache.myfaces.extensions.validator.crossval.annotation.DateIs;

+import org.apache.myfaces.extensions.validator.crossval.annotation.DateIsType;

+import org.apache.myfaces.extensions.validator.crossval.annotation.NotEquals;

+

+import javax.persistence.Column;

+import javax.persistence.Temporal;

+import javax.persistence.TemporalType;

+import java.util.Date;

+

+public class Person {

+    @Length(minimum = 2)

+    @Column(nullable = false, length = 20)

+    @NotEquals("lastName")

+    @Regex("[A-Z][a-z]+")

+    private String firstName;

+

+    @Length(minimum = 2)

+    @Column(nullable = false, length = 20)

+    private String lastName;

+

+    @Column(nullable = false, length = 10)

+    private String password;

+

+    @DateIs(type = DateIsType.before, valueOf = "finalExam")

+    @Column(nullable = false)

+    @Temporal(TemporalType.DATE)

+    private Date birthday;

+

+    @Column(nullable = false)

+    @Temporal(TemporalType.DATE)

+    private Date finalExam;

+

+    @Length(minimum = 2)

+    @Column(nullable = false, length = 10)

+    private String nickName;

+

+    @Length(minimum = 6)

+    @Column(nullable = false, length = 60)

+    private String email;

+

+    @Column(nullable = false)

+    private int numberOfSiblings;

+

+    public String getFirstName() {

+        return firstName;

+    }

+

+    public void setFirstName(String firstName) {

+        this.firstName = firstName;

+    }

+

+    public String getLastName() {

+        return lastName;

+    }

+

+    public void setLastName(String lastName) {

+        this.lastName = lastName;

+    }

+

+    public String getPassword() {

+        return password;

+    }

+

+    public void setPassword(String password) {

+        this.password = password;

+    }

+

+    public Date getBirthday() {

+        return birthday;

+    }

+

+    public void setBirthday(Date birthday) {

+        this.birthday = birthday;

+    }

+

+    public Date getFinalExam() {

+        return finalExam;

+    }

+

+    public void setFinalExam(Date finalExam) {

+        this.finalExam = finalExam;

+    }

+

+    public String getNickName() {

+        return nickName;

+    }

+

+    public void setNickName(String nickName) {

+        this.nickName = nickName;

+    }

+

+    public String getEmail() {

+        return email;

+    }

+

+    public void setEmail(String email) {

+        this.email = email;

+    }

+

+    public int getNumberOfSiblings() {

+        return numberOfSiblings;

+    }

+

+    public void setNumberOfSiblings(int numberOfSiblings) {

+        this.numberOfSiblings = numberOfSiblings;

+    }

+}

diff --git a/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/demo/gui/beans/RegistrationPage.java b/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/demo/gui/beans/RegistrationPage.java
new file mode 100644
index 0000000..5025a65
--- /dev/null
+++ b/examples/feature-set_01/src/main/java/org/apache/myfaces/extensions/validator/demo/gui/beans/RegistrationPage.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.demo.gui.beans;

+

+import org.apache.myfaces.custom.emailvalidator.EmailValidator;

+import org.apache.myfaces.extensions.validator.baseval.annotation.JoinValidation;

+import org.apache.myfaces.extensions.validator.baseval.annotation.LongRange;

+import org.apache.myfaces.extensions.validator.baseval.annotation.Required;

+import org.apache.myfaces.extensions.validator.baseval.annotation.Validator;

+import org.apache.myfaces.extensions.validator.crossval.annotation.Equals;

+import org.apache.myfaces.extensions.validator.crossval.annotation.NotEquals;

+import org.apache.myfaces.extensions.validator.demo.domain.Person;

+

+public class RegistrationPage {

+

+    //the old password of the person isn't used within the page

+    //-> validate with value of the model

+    @Required

+    @Equals("#{person.password}")

+    @NotEquals("password")

+    private String oldPassword;

+

+    @Required

+    @Equals("passwordRepeated")

+    private String password;

+

+    @Required(validationErrorMsgKey = "repeated_password_requried")

+    private String passwordRepeated;

+

+    //use #{registrationPage.person.nickName}, #{person.nickName}

+    //or a global alias in connection with the TargetAlias annotation

+    //use registrationPage to display the second error message at old nickname

+    @NotEquals("#{registrationPage.person.nickName}")

+    @JoinValidation("#{person.nickName}")

+    private String newNickName;

+

+    private Person person;

+

+    public String finish() {

+        this.person.setPassword(this.password);

+        return "home";

+    }

+

+    public String updateNickName() {

+        this.person.setNickName(this.newNickName);

+        return "home";

+    }

+

+    //combine gui related annotations with the annoations of the domain model

+    @JoinValidation("#{person.email}")

+    @Validator(EmailValidator.class)

+    public String getEmail() {

+        return this.person.getEmail();

+    }

+

+    public void setEmail(String email) {

+        this.person.setEmail(email);

+    }

+

+    @JoinValidation("#{person.numberOfSiblings}")

+    @LongRange(maximum = 20)

+    public int getNumberOfSiblings() {

+        return this.person.getNumberOfSiblings();

+    }

+

+    public void setNumberOfSiblings(int numberOfSiblings) {

+        this.person.setNumberOfSiblings(numberOfSiblings);

+    }

+

+    /*

+     * generated

+     */

+    public String getOldPassword() {

+        return oldPassword;

+    }

+

+    public void setOldPassword(String oldPassword) {

+        this.oldPassword = oldPassword;

+    }

+

+    public String getPassword() {

+        return password;

+    }

+

+    public void setPassword(String password) {

+        this.password = password;

+    }

+

+    public String getPasswordRepeated() {

+        return passwordRepeated;

+    }

+

+    public void setPasswordRepeated(String passwordRepeated) {

+        this.passwordRepeated = passwordRepeated;

+    }

+

+    public Person getPerson() {

+        return person;

+    }

+

+    public void setPerson(Person person) {

+        this.person = person;

+    }

+

+    public String getNewNickName() {

+        return newNickName;

+    }

+

+    public void setNewNickName(String newNickName) {

+        this.newNickName = newNickName;

+    }

+}

diff --git a/examples/feature-set_01/src/main/webapp/WEB-INF/LICENSE.txt b/examples/feature-set_01/src/main/webapp/WEB-INF/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/WEB-INF/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/examples/feature-set_01/src/main/webapp/WEB-INF/NOTICE.txt b/examples/feature-set_01/src/main/webapp/WEB-INF/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/WEB-INF/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/examples/feature-set_01/src/main/webapp/WEB-INF/faces-config.xml b/examples/feature-set_01/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..c69df4f
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0"?>
+<!DOCTYPE faces-config PUBLIC
+        "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
+        "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" >
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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>
+    <application>
+        <!-- trinidad -->
+        <default-render-kit-id>
+            org.apache.myfaces.trinidad.core
+        </default-render-kit-id>
+
+    </application>
+
+    <managed-bean>
+        <managed-bean-name>registrationPage</managed-bean-name>
+        <managed-bean-class>org.apache.myfaces.extensions.validator.demo.gui.beans.RegistrationPage</managed-bean-class>
+        <managed-bean-scope>request</managed-bean-scope>
+
+        <managed-property>
+            <property-name>person</property-name>
+            <value>#{person}</value>
+        </managed-property>
+    </managed-bean>
+
+    <managed-bean>
+        <managed-bean-name>person</managed-bean-name>
+        <managed-bean-class>org.apache.myfaces.extensions.validator.demo.domain.Person</managed-bean-class>
+        <managed-bean-scope>session</managed-bean-scope>
+    </managed-bean>
+
+    <navigation-rule>
+        <from-view-id>/pages/home.xhtml</from-view-id>
+        <navigation-case>
+            <from-outcome>addUser</from-outcome>
+            <to-view-id>/pages/registration.xhtml</to-view-id>
+        </navigation-case>
+        <navigation-case>
+            <from-outcome>changeNickName</from-outcome>
+            <to-view-id>/pages/change_nickName.xhtml</to-view-id>
+        </navigation-case>
+        <navigation-case>
+            <from-outcome>changePassword</from-outcome>
+            <to-view-id>/pages/change_password.xhtml</to-view-id>
+        </navigation-case>
+    </navigation-rule>
+    <navigation-rule>
+        <from-view-id>*</from-view-id>
+        <navigation-case>
+            <from-outcome>home</from-outcome>
+            <to-view-id>/pages/home.xhtml</to-view-id>
+        </navigation-case>
+    </navigation-rule>
+</faces-config>
\ No newline at end of file
diff --git a/examples/feature-set_01/src/main/webapp/WEB-INF/web.xml b/examples/feature-set_01/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..62852c8
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+         version="2.4">
+
+    <description>MyProject web.xml</description>
+
+    <context-param>
+        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
+        <param-value>.xhtml</param-value>
+    </context-param>
+
+    <context-param>
+        <param-name>org.apache.myfaces.trinidad.ENABLE_LIGHTWEIGHT_DIALOGS</param-name>
+        <param-value>true</param-value>
+    </context-param>
+
+    <context-param>
+        <param-name>org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION</param-name>
+        <param-value>true</param-value>
+    </context-param>
+
+    <context-param>
+        <param-name>org.apache.myfaces.trinidad.ALTERNATE_VIEW_HANDLER</param-name>
+        <param-value>com.sun.facelets.FaceletViewHandler</param-value>
+    </context-param>
+
+    <context-param>
+        <param-name>org.apache.myfaces.trinidad.USE_APPLICATION_VIEW_CACHE</param-name>
+        <param-value>false</param-value>
+    </context-param>
+
+    <context-param>
+        <param-name>org.apache.myfaces.trinidad.CHANGE_PERSISTENCE</param-name>
+        <param-value>session</param-value>
+    </context-param>
+
+    <context-param>
+        <description>State saving method: "client" or "server" (= default)
+            See JSF Specification 2.5.3
+        </description>
+        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
+        <param-value>client</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default).
+            Defines the amount (default = 20) of the latest views are stored in session.
+        </description>
+        <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>
+        <param-value>20</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default).
+            If true (default) the state will be serialized to a byte stream before it
+            is written to the session.
+            If false the state will not be serialized to a byte stream.
+        </description>
+        <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default) and if
+            org.apache.myfaces.SERIALIZE_STATE_IN_SESSION is true (= default)
+            If true (default) the serialized state will be compressed before it
+            is written to the session. If false the state will not be compressed.
+        </description>
+        <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>This parameter tells MyFaces if javascript code should be allowed in the
+            rendered HTML output.
+            If javascript is allowed, command_link anchors will have javascript code
+            that submits the corresponding form.
+            If javascript is not allowed, the state saving info and nested parameters
+            will be added as url parameters.
+            Default: "true"
+        </description>
+        <param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
+        <param-value>false</param-value>
+    </context-param>
+    <context-param>
+        <description>If true, rendered HTML code will be formatted, so that it is "human readable".
+            i.e. additional line separators and whitespace will be written, that do not
+            influence the HTML code.
+            Default: "true"
+        </description>
+        <param-name>org.apache.myfaces.PRETTY_HTML</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>If true, a javascript function will be rendered that is able to restore the
+            former vertical scroll on every request. Convenient feature if you have pages
+            with long lists and you do not want the browser page to always jump to the top
+            if you trigger a link or button action that stays on the same page.
+            Default: "false"
+        </description>
+        <param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
+        <param-value>true</param-value>
+    </context-param>
+
+    <context-param>
+        <description>Used for encrypting view state. Only relevant for client side
+            state saving. See MyFaces wiki/web site documentation for instructions
+            on how to configure an application for diffenent encryption strengths.
+        </description>
+        <param-name>org.apache.myfaces.SECRET</param-name>
+        <param-value>NzY1NDMyMTA=</param-value>
+    </context-param>
+
+    <context-param>
+        <description>
+            Validate managed beans, navigation rules and ensure that forms are not nested.
+        </description>
+        <param-name>org.apache.myfaces.VALIDATE</param-name>
+        <param-value>true</param-value>
+    </context-param>
+
+    <!-- Listener, to allow Jetty serving MyFaces apps -->
+    <listener>
+        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
+    </listener>
+
+    <!-- Faces Servlet -->
+    <servlet>
+        <servlet-name>Faces Servlet</servlet-name>
+        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <servlet>
+        <servlet-name>resources</servlet-name>
+        <servlet-class>org.apache.myfaces.trinidad.webapp.ResourceServlet</servlet-class>
+    </servlet>
+
+    <filter>
+        <filter-name>trinidad</filter-name>
+        <filter-class>org.apache.myfaces.trinidad.webapp.TrinidadFilter</filter-class>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>trinidad</filter-name>
+        <servlet-name>Faces Servlet</servlet-name>
+    </filter-mapping>
+
+    <!-- Faces Servlet Mappings -->
+    <servlet-mapping>
+        <servlet-name>Faces Servlet</servlet-name>
+        <url-pattern>*.faces</url-pattern>
+    </servlet-mapping>
+
+    <servlet-mapping>
+        <servlet-name>resources</servlet-name>
+        <url-pattern>/adf/*</url-pattern>
+    </servlet-mapping>
+
+    <!-- Welcome files -->
+    <welcome-file-list>
+        <welcome-file>index.html</welcome-file>
+    </welcome-file-list>
+
+</web-app>
diff --git a/examples/feature-set_01/src/main/webapp/index.html b/examples/feature-set_01/src/main/webapp/index.html
new file mode 100644
index 0000000..04324aa
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/index.html
@@ -0,0 +1,6 @@
+<html>

+

+<head>

+    <meta http-equiv="refresh" content="0; URL=pages/home.faces">

+</head>

+</html>
\ No newline at end of file
diff --git a/examples/feature-set_01/src/main/webapp/layout/template.xhtml b/examples/feature-set_01/src/main/webapp/layout/template.xhtml
new file mode 100644
index 0000000..63a41a5
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/layout/template.xhtml
@@ -0,0 +1,35 @@
+<tr:document

+        xmlns:ui="http://java.sun.com/jsf/facelets"

+        xmlns:h="http://java.sun.com/jsf/html"

+        xmlns:f="http://java.sun.com/jsf/core"

+        xmlns:tr="http://myfaces.apache.org/trinidad"

+        xmlns:trh="http://myfaces.apache.org/trinidad/html"

+        xmlns:c="http://java.sun.com/jstl/core">

+    <f:facet name="metaContainer">

+        <title>sev-en feature-set demo 01</title>

+    </f:facet>

+

+    <trh:body>

+

+        <!-- original -->

+        <div id="wrap">

+

+            <tr:form id="form" defaultCommand="defaultButton">

+                <div id="main">

+                    <ui:insert name="content">

+                        <div class="under_construction">

+                            <h2>!site under construction!</h2>

+

+                            <p>The content of this site is not available at the moment.</p>

+                        </div>

+                    </ui:insert>

+                </div>

+

+            </tr:form>

+            <tr:messages globalOnly="true"/>

+

+        </div>

+    </trh:body>

+

+

+</tr:document>
\ No newline at end of file
diff --git a/examples/feature-set_01/src/main/webapp/pages/change_nickName.xhtml b/examples/feature-set_01/src/main/webapp/pages/change_nickName.xhtml
new file mode 100644
index 0000000..89dcd03
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/pages/change_nickName.xhtml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC

+        "-//W3C//DTD XHTML 1.0 Transitional//EN"

+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+

+<html xmlns="http://www.w3.org/1999/xhtml"

+      xmlns:ui="http://java.sun.com/jsf/facelets">

+

+<body>

+

+<ui:composition template="../layout/template.xhtml"

+                xmlns="http://www.w3.org/1999/xhtml"

+                xmlns:ui="http://java.sun.com/jsf/facelets"

+                xmlns:f="http://java.sun.com/jsf/core"

+                xmlns:h="http://java.sun.com/jsf/html"

+                xmlns:tr="http://myfaces.apache.org/trinidad"

+                xmlns:trh="http://myfaces.apache.org/trinidad/html">

+

+    <ui:define name="content">

+

+        <tr:panelFormLayout>

+

+            <ui:remove>

+                just for the demo we are using two input components

+            </ui:remove>

+            <tr:inputText label="old nick name" readOnly="true" value="#{registrationPage.person.nickName}"/>

+

+            <tr:inputText label="nick name" value="#{registrationPage.newNickName}"/>

+

+        </tr:panelFormLayout>

+        <tr:commandButton text="save" action="#{registrationPage.updateNickName}"/>

+

+    </ui:define>

+</ui:composition>

+

+</body>

+</html>

diff --git a/examples/feature-set_01/src/main/webapp/pages/change_password.xhtml b/examples/feature-set_01/src/main/webapp/pages/change_password.xhtml
new file mode 100644
index 0000000..59145f6
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/pages/change_password.xhtml
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC

+        "-//W3C//DTD XHTML 1.0 Transitional//EN"

+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+

+<html xmlns="http://www.w3.org/1999/xhtml"

+      xmlns:ui="http://java.sun.com/jsf/facelets">

+

+<body>

+

+<ui:composition template="../layout/template.xhtml"

+                xmlns="http://www.w3.org/1999/xhtml"

+                xmlns:ui="http://java.sun.com/jsf/facelets"

+                xmlns:f="http://java.sun.com/jsf/core"

+                xmlns:h="http://java.sun.com/jsf/html"

+                xmlns:tr="http://myfaces.apache.org/trinidad"

+                xmlns:trh="http://myfaces.apache.org/trinidad/html">

+

+    <ui:define name="content">

+

+        <tr:panelFormLayout>

+

+            <tr:inputText label="old password" value="#{registrationPage.oldPassword}" secret="true"/>

+

+            <tr:inputText label="new password" value="#{registrationPage.password}" secret="true"/>

+            <tr:inputText label="re-enter password" value="#{registrationPage.passwordRepeated}" secret="true"/>

+

+        </tr:panelFormLayout>

+        <tr:commandButton text="save" action="#{registrationPage.finish}"/>

+

+    </ui:define>

+</ui:composition>

+

+</body>

+</html>

diff --git a/examples/feature-set_01/src/main/webapp/pages/home.xhtml b/examples/feature-set_01/src/main/webapp/pages/home.xhtml
new file mode 100644
index 0000000..8c0b29d
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/pages/home.xhtml
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC

+        "-//W3C//DTD XHTML 1.0 Transitional//EN"

+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+

+<html xmlns="http://www.w3.org/1999/xhtml"

+      xmlns:ui="http://java.sun.com/jsf/facelets">

+

+<body>

+

+<ui:composition template="../layout/template.xhtml"

+                xmlns="http://www.w3.org/1999/xhtml"

+                xmlns:ui="http://java.sun.com/jsf/facelets"

+                xmlns:f="http://java.sun.com/jsf/core"

+                xmlns:h="http://java.sun.com/jsf/html"

+                xmlns:tr="http://myfaces.apache.org/trinidad"

+                xmlns:trh="http://myfaces.apache.org/trinidad/html">

+

+    <ui:define name="content">

+        <tr:commandButton text="add user" action="addUser"/><br/>

+        <tr:commandButton text="change nick name" action="changeNickName"/><br/>

+        <tr:commandButton text="change password" action="changePassword"/>

+    </ui:define>

+</ui:composition>

+

+</body>

+</html>

diff --git a/examples/feature-set_01/src/main/webapp/pages/registration.xhtml b/examples/feature-set_01/src/main/webapp/pages/registration.xhtml
new file mode 100644
index 0000000..8340418
--- /dev/null
+++ b/examples/feature-set_01/src/main/webapp/pages/registration.xhtml
@@ -0,0 +1,46 @@
+<!DOCTYPE html PUBLIC

+        "-//W3C//DTD XHTML 1.0 Transitional//EN"

+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+

+<html xmlns="http://www.w3.org/1999/xhtml"

+      xmlns:ui="http://java.sun.com/jsf/facelets">

+

+<body>

+

+<ui:composition template="../layout/template.xhtml"

+                xmlns="http://www.w3.org/1999/xhtml"

+                xmlns:ui="http://java.sun.com/jsf/facelets"

+                xmlns:f="http://java.sun.com/jsf/core"

+                xmlns:h="http://java.sun.com/jsf/html"

+                xmlns:tr="http://myfaces.apache.org/trinidad"

+                xmlns:trh="http://myfaces.apache.org/trinidad/html">

+

+    <ui:define name="content">

+

+        <tr:panelFormLayout>

+

+            <tr:inputText label="nick name" value="#{registrationPage.person.nickName}"/>

+            <tr:inputText label="e-mail" value="#{registrationPage.email}"/>

+

+            <tr:inputText label="first name" value="#{registrationPage.person.firstName}"/>

+            <tr:inputText label="last name" value="#{registrationPage.person.lastName}"/>

+            <tr:inputDate label="birthday" value="#{registrationPage.person.birthday}">

+                <tr:convertDateTime type="date" dateStyle="short"/>

+            </tr:inputDate>

+            <tr:inputDate label="final exam" value="#{registrationPage.person.finalExam}">

+                <tr:convertDateTime type="date" dateStyle="short"/>

+            </tr:inputDate>

+

+            <tr:inputText label="number of siblings" value="#{registrationPage.numberOfSiblings}"/>

+

+            <tr:inputText label="password" value="#{registrationPage.password}" secret="true"/>

+            <tr:inputText label="re-enter password" value="#{registrationPage.passwordRepeated}" secret="true"/>

+

+        </tr:panelFormLayout>

+        <tr:commandButton text="save" action="#{registrationPage.finish}"/>

+

+    </ui:define>

+</ui:composition>

+

+</body>

+</html>

diff --git a/examples/hello_jpa/pom.xml b/examples/hello_jpa/pom.xml
new file mode 100644
index 0000000..fc83b6f
--- /dev/null
+++ b/examples/hello_jpa/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>

+

+<project xmlns="http://maven.apache.org/POM/4.0.0"

+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

+    <modelVersion>4.0.0</modelVersion>

+    <packaging>war</packaging>

+

+    <groupId>org.apache.myfaces.extensions.validator.examples</groupId>

+    <artifactId>examples-hello_jpa</artifactId>

+

+    <name>MyFaces Extensions-Validator examples hello jpa</name>

+    <version>${build.version}</version>

+

+    <parent>

+        <groupId>org.apache.myfaces.extensions.validator.examples</groupId>

+        <artifactId>examples-project</artifactId>

+        <version>${build.version}</version>

+    </parent>

+

+    <dependencies>

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator</groupId>

+            <artifactId>myfaces-extval-core</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>

+            <artifactId>myfaces-extval-base-validation</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        

+        <dependency>

+            <groupId>org.apache.myfaces.core</groupId>

+            <artifactId>myfaces-api</artifactId>

+            <version>${jsf.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        

+        <dependency>

+            <groupId>org.apache.myfaces.core</groupId>

+            <artifactId>myfaces-impl</artifactId>

+            <version>${jsf.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        

+        <dependency>

+            <groupId>javax.el</groupId>

+            <artifactId>el-api</artifactId>

+            <version>1.0</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>el-impl</groupId>

+            <artifactId>el-impl</artifactId>

+            <version>1.0</version>

+            <scope>compile</scope>

+        </dependency>

+    </dependencies>

+</project>

diff --git a/examples/hello_jpa/src/main/java/org/apache/myfaces/blank/HelloWorldController.java b/examples/hello_jpa/src/main/java/org/apache/myfaces/blank/HelloWorldController.java
new file mode 100644
index 0000000..23a796d
--- /dev/null
+++ b/examples/hello_jpa/src/main/java/org/apache/myfaces/blank/HelloWorldController.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.blank;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.Required;
+import org.apache.myfaces.blank.domain.Person;
+
+/**
+ * A typical simple backing bean, that is backed to <code>helloworld.jsp</code>
+ * 
+ */
+public class HelloWorldController {
+
+    
+    //properties
+    private Person person;
+    
+    /**
+     * default empty constructor
+     */
+    public HelloWorldController(){
+    }
+    
+    //-------------------getter & setter
+
+    public Person getPerson() {
+        return person;
+    }
+
+    public void setPerson(Person person) {
+        this.person = person;
+    }
+
+    /**
+     * Method that is backed to a submit button of a form.
+     */
+    public String send(){
+        //do real logic, return a string which will be used for the navigation system of JSF
+        return "success";
+    }
+}
\ No newline at end of file
diff --git a/examples/hello_jpa/src/main/java/org/apache/myfaces/blank/domain/Person.java b/examples/hello_jpa/src/main/java/org/apache/myfaces/blank/domain/Person.java
new file mode 100644
index 0000000..dd3a646
--- /dev/null
+++ b/examples/hello_jpa/src/main/java/org/apache/myfaces/blank/domain/Person.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.blank.domain;

+

+import javax.persistence.Column;

+

+public class Person {

+    @Column(nullable = false, length = 10)

+    private String name;

+

+    public String getName() {

+        return name;

+    }

+

+    public void setName(String name) {

+        this.name = name;

+    }

+}

diff --git a/examples/hello_jpa/src/main/webapp/WEB-INF/faces-config.xml b/examples/hello_jpa/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..3e82b88
--- /dev/null
+++ b/examples/hello_jpa/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!DOCTYPE faces-config PUBLIC
+        "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
+        "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" >
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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>
+
+	<!-- managed beans of the simple hello world app -->
+	<managed-bean>
+		<managed-bean-name>helloWorld</managed-bean-name>
+		<managed-bean-class>org.apache.myfaces.blank.HelloWorldController</managed-bean-class>
+		<managed-bean-scope>request</managed-bean-scope>
+        <managed-property>
+            <property-name>person</property-name>
+            <value>#{person}</value>
+        </managed-property>
+    </managed-bean>
+
+	<managed-bean>
+		<managed-bean-name>person</managed-bean-name>
+		<managed-bean-class>org.apache.myfaces.blank.domain.Person</managed-bean-class>
+		<managed-bean-scope>session</managed-bean-scope>
+	</managed-bean>
+
+	<!-- navigation rules for helloWorld.jsp -->
+	<navigation-rule>
+		<from-view-id>/helloWorld.jsp</from-view-id>
+		<navigation-case>
+			<from-outcome>success</from-outcome>
+			<to-view-id>/page2.jsp</to-view-id>
+		</navigation-case>
+	</navigation-rule>
+	
+	<!-- navigation rules for page2.jsp -->
+	<navigation-rule>
+		<from-view-id>/page2.jsp</from-view-id>
+		<navigation-case>
+			<from-outcome>back</from-outcome>
+			<to-view-id>/helloWorld.jsp</to-view-id>
+		</navigation-case>
+	</navigation-rule>
+</faces-config>
\ No newline at end of file
diff --git a/examples/hello_jpa/src/main/webapp/WEB-INF/web.xml b/examples/hello_jpa/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..9a4a183
--- /dev/null
+++ b/examples/hello_jpa/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+         version="2.4">
+
+    <description>MyProject web.xml</description>
+
+    <!--optional: context-param>
+        <description>Comma separated list of URIs of (additional) faces config files.
+            (e.g. /WEB-INF/my-config.xml)
+            See JSF 1.0 PRD2, 10.3.2
+            Attention: You do not need to put /WEB-INF/faces-config.xml in here.
+        </description>
+        <param-name>javax.faces.CONFIG_FILES</param-name>
+        <param-value>/WEB-INF/examples-config.xml</param-value>
+    </context-param-->
+    <context-param>
+        <description>State saving method: "client" or "server" (= default)
+            See JSF Specification 2.5.3</description>
+        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
+        <param-value>client</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default).
+            Defines the amount (default = 20) of the latest views are stored in session.</description>
+        <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>
+        <param-value>20</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default).
+            If true (default) the state will be serialized to a byte stream before it
+            is written to the session.
+            If false the state will not be serialized to a byte stream.</description>
+        <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default) and if
+            org.apache.myfaces.SERIALIZE_STATE_IN_SESSION is true (= default)
+            If true (default) the serialized state will be compressed before it
+            is written to the session. If false the state will not be compressed.</description>
+        <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>This parameter tells MyFaces if javascript code should be allowed in the
+            rendered HTML output.
+            If javascript is allowed, command_link anchors will have javascript code
+            that submits the corresponding form.
+            If javascript is not allowed, the state saving info and nested parameters
+            will be added as url parameters.
+            Default: "true"</description>
+        <param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
+        <param-value>false</param-value>
+    </context-param>
+    <context-param>
+        <description>If true, rendered HTML code will be formatted, so that it is "human readable".
+            i.e. additional line separators and whitespace will be written, that do not
+            influence the HTML code.
+            Default: "true"</description>
+        <param-name>org.apache.myfaces.PRETTY_HTML</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>If true, a javascript function will be rendered that is able to restore the
+            former vertical scroll on every request. Convenient feature if you have pages
+            with long lists and you do not want the browser page to always jump to the top
+            if you trigger a link or button action that stays on the same page.
+            Default: "false"</description>
+        <param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
+        <param-value>true</param-value>
+    </context-param>
+
+    <context-param>
+        <description>Used for encrypting view state. Only relevant for client side
+            state saving. See MyFaces wiki/web site documentation for instructions
+            on how to configure an application for diffenent encryption strengths.
+        </description>
+        <param-name>org.apache.myfaces.SECRET</param-name>
+        <param-value>NzY1NDMyMTA=</param-value>
+    </context-param>
+
+    <context-param>
+        <description>
+            Validate managed beans, navigation rules and ensure that forms are not nested.
+        </description>
+        <param-name>org.apache.myfaces.VALIDATE</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    
+    <context-param>
+        <description>
+            Treat readonly same as if disabled attribute was set for select elements.
+        </description>
+        <param-name>org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS</param-name>
+        <param-value>true</param-value>
+    </context-param>    
+    
+    <context-param>
+        <description>
+            Use the defined class as the class which will be called when a resource is added to the
+            ExtensionFilter handling. Using StreamingAddResource here helps with performance. If you want to add
+            custom components and want to use the ExtensionFilter, you need to provide your custom implementation here.
+        </description>
+        <param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name>
+        <param-value>org.apache.myfaces.renderkit.html.util.DefaultAddResource</param-value>
+    </context-param>        
+
+    <context-param>
+        <description>
+            Virtual path in the URL which triggers loading of resources for the MyFaces extended components
+            in the ExtensionFilter.
+        </description>
+        <param-name>org.apache.myfaces.RESOURCE_VIRTUAL_PATH</param-name>
+        <param-value>/faces/myFacesExtensionResource</param-value>
+    </context-param>
+    
+    <context-param>
+        <description>
+            Check if the extensions-filter has been properly configured.
+        </description>
+        <param-name>org.apache.myfaces.CHECK_EXTENSIONS_FILTER</param-name>
+        <param-value>true</param-value>
+    </context-param>    
+
+    <context-param>
+        <description>
+            Define partial state saving as true/false.
+        </description>
+        <param-name>javax.faces.PARTIAL_STATE_SAVING_METHOD</param-name>
+        <param-value>false</param-value>
+    </context-param>    
+
+    <!-- Listener, to allow Jetty serving MyFaces apps -->
+    <listener>
+        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
+    </listener>
+
+    <!-- Faces Servlet -->
+    <servlet>
+        <servlet-name>Faces Servlet</servlet-name>
+        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <!-- Faces Servlet Mapping -->
+    <servlet-mapping>
+        <servlet-name>Faces Servlet</servlet-name>
+        <url-pattern>*.jsf</url-pattern>
+    </servlet-mapping>
+
+    <!-- Welcome files -->
+    <welcome-file-list>
+        <welcome-file>index.jsp</welcome-file>
+        <welcome-file>index.html</welcome-file>
+    </welcome-file-list>
+
+</web-app>
diff --git a/examples/hello_jpa/src/main/webapp/helloWorld.jsp b/examples/hello_jpa/src/main/webapp/helloWorld.jsp
new file mode 100644
index 0000000..c549cbf
--- /dev/null
+++ b/examples/hello_jpa/src/main/webapp/helloWorld.jsp
@@ -0,0 +1,22 @@
+<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
+<html>
+    <head>
+        <title>Hello World</title>
+    </head>
+    <body>
+        <f:view>
+            <h:form id="mainForm">
+              <h:panelGrid columns="3">
+                <h:outputLabel for="name" value="Please enter your name" />
+                <h:inputText id="name" value="#{helloWorld.person.name}"/>
+                <h:message for="name" showSummary="false" showDetail="true"/>
+
+                <h:commandButton value="Press me" action="#{helloWorld.send}"/>
+                <h:panelGroup/>
+                <h:panelGroup/>
+              </h:panelGrid>
+            </h:form>
+        </f:view>
+    </body>
+</html>
diff --git a/examples/hello_jpa/src/main/webapp/index.jsp b/examples/hello_jpa/src/main/webapp/index.jsp
new file mode 100644
index 0000000..a29c228
--- /dev/null
+++ b/examples/hello_jpa/src/main/webapp/index.jsp
@@ -0,0 +1,4 @@
+<%@ page session="false"%>
+<%
+response.sendRedirect("helloWorld.jsf");
+%>
\ No newline at end of file
diff --git a/examples/hello_jpa/src/main/webapp/page2.jsp b/examples/hello_jpa/src/main/webapp/page2.jsp
new file mode 100644
index 0000000..be6c75f
--- /dev/null
+++ b/examples/hello_jpa/src/main/webapp/page2.jsp
@@ -0,0 +1,17 @@
+<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
+<html>
+    <head>
+        <title>Hello World</title>
+    </head>
+    <body>
+        <f:view>
+            <h:form id="mainForm">
+                <h2><h:outputText value="Hello #{helloWorld.person.name}. We hope you enjoy Apache MyFaces"/></h2>
+                <h:commandLink action="back">
+                    <h:outputText value="Home"/>
+                </h:commandLink>
+            </h:form>
+        </f:view>
+    </body>
+</html>
\ No newline at end of file
diff --git a/examples/hello_world/pom.xml b/examples/hello_world/pom.xml
new file mode 100644
index 0000000..300163e
--- /dev/null
+++ b/examples/hello_world/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>

+

+<project xmlns="http://maven.apache.org/POM/4.0.0"

+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

+    <modelVersion>4.0.0</modelVersion>

+    <packaging>war</packaging>

+

+    <groupId>org.apache.myfaces.extensions.validator.examples</groupId>

+    <artifactId>examples-hello_world</artifactId>

+

+    <name>MyFaces Extensions-Validator examples hello world</name>

+    <version>${build.version}</version>

+

+    <parent>

+        <groupId>org.apache.myfaces.extensions.validator.examples</groupId>

+        <artifactId>examples-project</artifactId>

+        <version>${build.version}</version>

+    </parent>

+

+    <dependencies>

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator</groupId>

+            <artifactId>myfaces-extval-core</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>

+            <artifactId>myfaces-extval-base-validation</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        

+        <dependency>

+            <groupId>org.apache.myfaces.core</groupId>

+            <artifactId>myfaces-api</artifactId>

+            <version>${jsf.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        

+        <dependency>

+            <groupId>org.apache.myfaces.core</groupId>

+            <artifactId>myfaces-impl</artifactId>

+            <version>${jsf.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        

+        <dependency>

+            <groupId>javax.el</groupId>

+            <artifactId>el-api</artifactId>

+            <version>1.0</version>

+            <scope>compile</scope>

+        </dependency>

+

+        <dependency>

+            <groupId>el-impl</groupId>

+            <artifactId>el-impl</artifactId>

+            <version>1.0</version>

+            <scope>compile</scope>

+        </dependency>

+    </dependencies>

+

+</project>

diff --git a/examples/hello_world/src/main/java/org/apache/myfaces/blank/HelloWorldController.java b/examples/hello_world/src/main/java/org/apache/myfaces/blank/HelloWorldController.java
new file mode 100644
index 0000000..0d3da63
--- /dev/null
+++ b/examples/hello_world/src/main/java/org/apache/myfaces/blank/HelloWorldController.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.blank;
+
+import org.apache.myfaces.extensions.validator.baseval.annotation.Required;
+
+/**
+ * A typical simple backing bean, that is backed to <code>helloworld.jsp</code>
+ * 
+ */
+public class HelloWorldController {
+
+    
+    //properties
+    @Required
+    private String name;
+    
+    /**
+     * default empty constructor
+     */
+    public HelloWorldController(){
+    }
+    
+    //-------------------getter & setter
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    /**
+     * Method that is backed to a submit button of a form.
+     */
+    public String send(){
+        //do real logic, return a string which will be used for the navigation system of JSF
+        return "success";
+    }
+}
\ No newline at end of file
diff --git a/examples/hello_world/src/main/webapp/WEB-INF/faces-config.xml b/examples/hello_world/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..46644d0
--- /dev/null
+++ b/examples/hello_world/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!DOCTYPE faces-config PUBLIC
+        "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
+        "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" >
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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>
+	
+	<!-- managed beans of the simple hello world app -->
+	<managed-bean>
+		<managed-bean-name>helloWorld</managed-bean-name>
+		<managed-bean-class>org.apache.myfaces.blank.HelloWorldController</managed-bean-class>
+		<managed-bean-scope>request</managed-bean-scope>
+	</managed-bean>
+	
+	<!-- navigation rules for helloWorld.jsp -->
+	<navigation-rule>
+		<from-view-id>/helloWorld.jsp</from-view-id>
+		<navigation-case>
+			<from-outcome>success</from-outcome>
+			<to-view-id>/page2.jsp</to-view-id>
+		</navigation-case>
+	</navigation-rule>
+	
+	<!-- navigation rules for page2.jsp -->
+	<navigation-rule>
+		<from-view-id>/page2.jsp</from-view-id>
+		<navigation-case>
+			<from-outcome>back</from-outcome>
+			<to-view-id>/helloWorld.jsp</to-view-id>
+		</navigation-case>
+	</navigation-rule>
+</faces-config>
\ No newline at end of file
diff --git a/examples/hello_world/src/main/webapp/WEB-INF/web.xml b/examples/hello_world/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..9a4a183
--- /dev/null
+++ b/examples/hello_world/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+         version="2.4">
+
+    <description>MyProject web.xml</description>
+
+    <!--optional: context-param>
+        <description>Comma separated list of URIs of (additional) faces config files.
+            (e.g. /WEB-INF/my-config.xml)
+            See JSF 1.0 PRD2, 10.3.2
+            Attention: You do not need to put /WEB-INF/faces-config.xml in here.
+        </description>
+        <param-name>javax.faces.CONFIG_FILES</param-name>
+        <param-value>/WEB-INF/examples-config.xml</param-value>
+    </context-param-->
+    <context-param>
+        <description>State saving method: "client" or "server" (= default)
+            See JSF Specification 2.5.3</description>
+        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
+        <param-value>client</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default).
+            Defines the amount (default = 20) of the latest views are stored in session.</description>
+        <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>
+        <param-value>20</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default).
+            If true (default) the state will be serialized to a byte stream before it
+            is written to the session.
+            If false the state will not be serialized to a byte stream.</description>
+        <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>Only applicable if state saving method is "server" (= default) and if
+            org.apache.myfaces.SERIALIZE_STATE_IN_SESSION is true (= default)
+            If true (default) the serialized state will be compressed before it
+            is written to the session. If false the state will not be compressed.</description>
+        <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>This parameter tells MyFaces if javascript code should be allowed in the
+            rendered HTML output.
+            If javascript is allowed, command_link anchors will have javascript code
+            that submits the corresponding form.
+            If javascript is not allowed, the state saving info and nested parameters
+            will be added as url parameters.
+            Default: "true"</description>
+        <param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
+        <param-value>false</param-value>
+    </context-param>
+    <context-param>
+        <description>If true, rendered HTML code will be formatted, so that it is "human readable".
+            i.e. additional line separators and whitespace will be written, that do not
+            influence the HTML code.
+            Default: "true"</description>
+        <param-name>org.apache.myfaces.PRETTY_HTML</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    <context-param>
+        <description>If true, a javascript function will be rendered that is able to restore the
+            former vertical scroll on every request. Convenient feature if you have pages
+            with long lists and you do not want the browser page to always jump to the top
+            if you trigger a link or button action that stays on the same page.
+            Default: "false"</description>
+        <param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
+        <param-value>true</param-value>
+    </context-param>
+
+    <context-param>
+        <description>Used for encrypting view state. Only relevant for client side
+            state saving. See MyFaces wiki/web site documentation for instructions
+            on how to configure an application for diffenent encryption strengths.
+        </description>
+        <param-name>org.apache.myfaces.SECRET</param-name>
+        <param-value>NzY1NDMyMTA=</param-value>
+    </context-param>
+
+    <context-param>
+        <description>
+            Validate managed beans, navigation rules and ensure that forms are not nested.
+        </description>
+        <param-name>org.apache.myfaces.VALIDATE</param-name>
+        <param-value>true</param-value>
+    </context-param>
+    
+    <context-param>
+        <description>
+            Treat readonly same as if disabled attribute was set for select elements.
+        </description>
+        <param-name>org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS</param-name>
+        <param-value>true</param-value>
+    </context-param>    
+    
+    <context-param>
+        <description>
+            Use the defined class as the class which will be called when a resource is added to the
+            ExtensionFilter handling. Using StreamingAddResource here helps with performance. If you want to add
+            custom components and want to use the ExtensionFilter, you need to provide your custom implementation here.
+        </description>
+        <param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name>
+        <param-value>org.apache.myfaces.renderkit.html.util.DefaultAddResource</param-value>
+    </context-param>        
+
+    <context-param>
+        <description>
+            Virtual path in the URL which triggers loading of resources for the MyFaces extended components
+            in the ExtensionFilter.
+        </description>
+        <param-name>org.apache.myfaces.RESOURCE_VIRTUAL_PATH</param-name>
+        <param-value>/faces/myFacesExtensionResource</param-value>
+    </context-param>
+    
+    <context-param>
+        <description>
+            Check if the extensions-filter has been properly configured.
+        </description>
+        <param-name>org.apache.myfaces.CHECK_EXTENSIONS_FILTER</param-name>
+        <param-value>true</param-value>
+    </context-param>    
+
+    <context-param>
+        <description>
+            Define partial state saving as true/false.
+        </description>
+        <param-name>javax.faces.PARTIAL_STATE_SAVING_METHOD</param-name>
+        <param-value>false</param-value>
+    </context-param>    
+
+    <!-- Listener, to allow Jetty serving MyFaces apps -->
+    <listener>
+        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
+    </listener>
+
+    <!-- Faces Servlet -->
+    <servlet>
+        <servlet-name>Faces Servlet</servlet-name>
+        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <!-- Faces Servlet Mapping -->
+    <servlet-mapping>
+        <servlet-name>Faces Servlet</servlet-name>
+        <url-pattern>*.jsf</url-pattern>
+    </servlet-mapping>
+
+    <!-- Welcome files -->
+    <welcome-file-list>
+        <welcome-file>index.jsp</welcome-file>
+        <welcome-file>index.html</welcome-file>
+    </welcome-file-list>
+
+</web-app>
diff --git a/examples/hello_world/src/main/webapp/helloWorld.jsp b/examples/hello_world/src/main/webapp/helloWorld.jsp
new file mode 100644
index 0000000..7565a3f
--- /dev/null
+++ b/examples/hello_world/src/main/webapp/helloWorld.jsp
@@ -0,0 +1,22 @@
+<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
+<html>
+    <head>
+        <title>Hello World</title>
+    </head>
+    <body>
+        <f:view>
+            <h:form id="mainForm">
+              <h:panelGrid columns="3">
+                <h:outputLabel for="name" value="Please enter your name" />
+                <h:inputText id="name" value="#{helloWorld.name}"/>
+                <h:message for="name" showSummary="true" showDetail="false"/>
+
+                <h:commandButton value="Press me" action="#{helloWorld.send}"/>
+                <h:panelGroup/>
+                <h:panelGroup/>
+              </h:panelGrid>
+            </h:form>
+        </f:view>
+    </body>
+</html>
diff --git a/examples/hello_world/src/main/webapp/index.jsp b/examples/hello_world/src/main/webapp/index.jsp
new file mode 100644
index 0000000..a29c228
--- /dev/null
+++ b/examples/hello_world/src/main/webapp/index.jsp
@@ -0,0 +1,4 @@
+<%@ page session="false"%>
+<%
+response.sendRedirect("helloWorld.jsf");
+%>
\ No newline at end of file
diff --git a/examples/hello_world/src/main/webapp/page2.jsp b/examples/hello_world/src/main/webapp/page2.jsp
new file mode 100644
index 0000000..6d12c41
--- /dev/null
+++ b/examples/hello_world/src/main/webapp/page2.jsp
@@ -0,0 +1,17 @@
+<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
+<html>
+    <head>
+        <title>Hello World</title>
+    </head>
+    <body>
+        <f:view>
+            <h:form id="mainForm">
+                <h2><h:outputText value="Hello #{helloWorld.name}. We hope you enjoy Apache MyFaces"/></h2>
+                <h:commandLink action="back">
+                    <h:outputText value="Home"/>
+                </h:commandLink>
+            </h:form>
+        </f:view>
+    </body>
+</html>
\ No newline at end of file
diff --git a/examples/pom.xml b/examples/pom.xml
new file mode 100644
index 0000000..bca27e3
--- /dev/null
+++ b/examples/pom.xml
@@ -0,0 +1,30 @@
+<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>${build.version}</version>

+

+    <parent>

+        <groupId>org.apache.myfaces.extensions.validator</groupId>

+        <artifactId>validator-project</artifactId>

+        <version>${build.version}</version>

+    </parent>

+

+    <modules>

+        <module>hello_world</module>

+        <module>hello_jpa</module>

+        <module>feature-set_01</module>

+    </modules>

+

+    <properties>

+        <trinidad.version>1.0.5</trinidad.version>

+    </properties>

+

+</project>

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..61bfe39
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,60 @@
+<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</groupId>

+    <artifactId>validator-project</artifactId>

+

+    <name>MyFaces Extensions-Validator Project</name>

+    <version>${build.version}</version>

+

+    <modules>

+        <module>core</module>

+        <module>validation-modules</module>

+        <module>examples</module>

+    </modules>

+

+    <repositories>

+        <repository>

+            <id>java.net</id>

+            <url>http://download.java.net/maven/1</url>

+            <layout>legacy</layout>

+        </repository>

+        <repository>

+            <id>maven2-repository.dev.java.net</id>

+            <name>Java.net Repository for Maven</name>

+            <url>http://download.java.net/maven/1/</url>

+            <layout>legacy</layout>

+        </repository>

+        <repository>

+            <id>apache.snapshots</id>

+            <name>Apache Snapshot Repository</name>

+            <url>http://people.apache.org/repo/m2-snapshot-repository</url>

+        </repository>

+    </repositories>

+

+    <build>

+        <defaultGoal>install</defaultGoal>

+        <pluginManagement>

+            <plugins>

+                <plugin>

+                    <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>

+        </pluginManagement>

+    </build>

+

+    <properties>

+        <build.version>1.0.1-SNAPSHOT</build.version>

+        <jsf.version>1.1.5</jsf.version>

+    </properties>

+</project>

diff --git a/validation-modules/base-validation/pom.xml b/validation-modules/base-validation/pom.xml
new file mode 100644
index 0000000..fd762ce
--- /dev/null
+++ b/validation-modules/base-validation/pom.xml
@@ -0,0 +1,76 @@
+<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-base-validation</artifactId>

+

+    <name>MyFaces Extensions-Validator Validation-Modules Baseval</name>

+    <version>${build.version}</version>

+

+    <parent>

+        <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>

+        <artifactId>validation-modules-project</artifactId>

+        <version>${build.version}</version>

+    </parent>

+

+    <dependencies>

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator</groupId>

+            <artifactId>myfaces-extval-core</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        <dependency>

+            <groupId>javax.persistence</groupId>

+            <artifactId>persistence-api</artifactId>

+            <version>1.0</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/validation-modules/base-validation/src/main/config/faces-config.xml b/validation-modules/base-validation/src/main/config/faces-config.xml
new file mode 100644
index 0000000..5be3fad
--- /dev/null
+++ b/validation-modules/base-validation/src/main/config/faces-config.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>

+<!DOCTYPE faces-config PUBLIC

+        "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"

+        "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" >

+

+<!--

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT 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>

+    <lifecycle>

+        <phase-listener>org.apache.myfaces.extensions.validator.InitStaticStrategyMappingsPhaseListener</phase-listener>

+    </lifecycle>

+</faces-config>
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/InitStaticStrategyMappingsPhaseListener.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/InitStaticStrategyMappingsPhaseListener.java
new file mode 100644
index 0000000..be00e51
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/InitStaticStrategyMappingsPhaseListener.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;

+

+import org.apache.myfaces.extensions.validator.baseval.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.core.AbstractStartupConfigListener;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class InitStaticStrategyMappingsPhaseListener extends AbstractStartupConfigListener {

+

+    protected void init() {

+        String jpaBasedValidation = WebXmlParameter.DEACTIVATE_JPA_BASED_VALIDATION;

+        if (jpaBasedValidation == null || !jpaBasedValidation.equalsIgnoreCase("true")) {

+            ExtValUtils.getInformationProviderBean().addStaticStrategyMappingSource(ExtValInformation.EXTENSIONS_VALIDATOR_BASE_PACKAGE_NAME + ".jpa_strategy_mappings");

+        }

+    }

+}

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/WebXmlParameter.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/WebXmlParameter.java
new file mode 100644
index 0000000..9c8e780
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/WebXmlParameter.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.baseval;

+

+import org.apache.myfaces.extensions.validator.util.WebXmlUtils;

+

+/**

+ * centralized in order that these information arn't spread over the complete code base

+ *

+ * @author Gerhard Petracek

+ */

+public interface WebXmlParameter {

+    //TODO docu

+    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");

+}

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/DoubleRange.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/DoubleRange.java
new file mode 100644
index 0000000..c494a61
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/DoubleRange.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.baseval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface DoubleRange {

+    double minimum() default 0;

+

+    double maximum() default Double.MAX_VALUE;

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/JoinValidation.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/JoinValidation.java
new file mode 100644
index 0000000..78789fe
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/JoinValidation.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.baseval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface JoinValidation {

+    String[] value();

+}

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Length.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Length.java
new file mode 100644
index 0000000..e962f2a
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Length.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.baseval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface Length {

+    int minimum() default 0;

+

+    int maximum() default Integer.MAX_VALUE;

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/LongRange.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/LongRange.java
new file mode 100644
index 0000000..1ff6e23
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/LongRange.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.baseval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface LongRange {

+    long minimum() default 0;

+

+    long maximum() default Long.MAX_VALUE;

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Regex.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Regex.java
new file mode 100644
index 0000000..93a67ae
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Regex.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.baseval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface Regex {

+    String[] value();

+

+    String validationErrorMsgKey() default "no_match";

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Required.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Required.java
new file mode 100644
index 0000000..1b78911
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Required.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.baseval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface Required {

+    String validationErrorMsgKey() default "field_required";

+}

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Validator.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Validator.java
new file mode 100644
index 0000000..be105a9
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/Validator.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.baseval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface Validator {

+    Class[] value();

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/extractor/DefaultPropertyScanningAnnotationExtractor.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/extractor/DefaultPropertyScanningAnnotationExtractor.java
new file mode 100644
index 0000000..007385d
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/annotation/extractor/DefaultPropertyScanningAnnotationExtractor.java
@@ -0,0 +1,69 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.extensions.validator.baseval.annotation.extractor;

+

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.annotation.extractor.DefaultComponentAnnotationExtractor;

+import org.apache.myfaces.extensions.validator.util.ELUtils;

+

+import javax.faces.context.FacesContext;

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DefaultPropertyScanningAnnotationExtractor extends DefaultComponentAnnotationExtractor {

+

+    @Override

+    public List<AnnotationEntry> extractAnnotations(FacesContext facesContext, Object object) {

+        //should never occur

+        if (!(object instanceof String)) {

+            return new ArrayList<AnnotationEntry>();

+        }

+

+        String valueBindingExpression = ((String) object).trim();

+        int beanPropertyBorder = valueBindingExpression.lastIndexOf(".");

+

+        String property = valueBindingExpression.substring(beanPropertyBorder + 1, valueBindingExpression.lastIndexOf("}"));

+

+        valueBindingExpression = valueBindingExpression.substring(0, beanPropertyBorder) + "}";

+

+        List<AnnotationEntry> annotationEntries = new ArrayList<AnnotationEntry>();

+

+        Class entityClass = ELUtils.getTypeOfValueBindingForExpression(facesContext, valueBindingExpression);

+

+        //create template entry

+        AnnotationEntry templateEntry = new AnnotationEntry();

+        templateEntry.setEntityClass(entityClass);

+        //TODO complex components

+        templateEntry.setValueBindingExpression(valueBindingExpression);

+        templateEntry.setBoundTo("value");

+

+        /*

+         * find and add annotations

+         */

+        if (entityClass != null) {

+            addPropertyAccessAnnotations(entityClass, property, annotationEntries, templateEntry);

+            addFieldAccessAnnotations(entityClass, property, annotationEntries, templateEntry);

+        }

+

+        return annotationEntries;

+    }

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/jpa_messages.properties b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/jpa_messages.properties
new file mode 100644
index 0000000..85454d7
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/jpa_messages.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.

+

+field_required=field is required

+field_required_details=field is required

+

+field_too_long=field too long

+field_too_long_details=field too long (max. length: {0})

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages.properties b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages.properties
new file mode 100644
index 0000000..86ef47b
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/bundle/validation_messages.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.

+

+field_required=field is required

+field_required_details=field is required

+

+no_match=invalid format

+no_match_details=the required formate is: {0}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/DefaultValidationErrorMessageResolver.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/DefaultValidationErrorMessageResolver.java
new file mode 100644
index 0000000..cf84ab4
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/DefaultValidationErrorMessageResolver.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.baseval.message.resolver;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DefaultValidationErrorMessageResolver extends org.apache.myfaces.extensions.validator.core.validation.message.resolver.DefaultValidationErrorMessageResolver {

+    private static String BASE_NAME = null;

+

+    @Override

+    protected String getBaseName() {

+        if (BASE_NAME == null) {

+            BASE_NAME = super.getBaseName();

+        }

+

+        return BASE_NAME;

+    }

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/JpaValidationErrorMessageResolver.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/JpaValidationErrorMessageResolver.java
new file mode 100644
index 0000000..b7840fa
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/message/resolver/JpaValidationErrorMessageResolver.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.message.resolver;

+

+import org.apache.myfaces.extensions.validator.baseval.WebXmlParameter;

+import org.apache.myfaces.extensions.validator.core.validation.message.resolver.AbstractValidationErrorMessageResolver;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class JpaValidationErrorMessageResolver extends AbstractValidationErrorMessageResolver {

+

+    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() {

+        return CUSTOM_BASE_NAME;

+    }

+

+    protected String getBaseName() {

+        return BASE_NAME;

+    }

+

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/DoubleRangeStrategy.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/DoubleRangeStrategy.java
new file mode 100644
index 0000000..256b488
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/DoubleRangeStrategy.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.strategy;

+

+import org.apache.myfaces.extensions.validator.baseval.annotation.DoubleRange;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidatorAdapter;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.DoubleRangeValidator;

+import javax.faces.validator.ValidatorException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DoubleRangeStrategy extends AbstractValidatorAdapter {

+

+    protected void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException {

+

+        DoubleRange annotation = annotationEntry.getAnnotation(DoubleRange.class);

+        DoubleRangeValidator doubleRangeValidator = new DoubleRangeValidator();

+

+        doubleRangeValidator.setMinimum(annotation.minimum());

+        doubleRangeValidator.setMaximum(annotation.maximum());

+

+        doubleRangeValidator.validate(facesContext, uiComponent, convertedObject);

+    }

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JoinValidationStrategy.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JoinValidationStrategy.java
new file mode 100644
index 0000000..f618a36
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JoinValidationStrategy.java
@@ -0,0 +1,56 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.extensions.validator.baseval.strategy;

+

+import org.apache.myfaces.extensions.validator.baseval.annotation.JoinValidation;

+import org.apache.myfaces.extensions.validator.baseval.annotation.extractor.DefaultPropertyScanningAnnotationExtractor;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.annotation.extractor.AnnotationExtractor;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidatorAdapter;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;

+import org.apache.myfaces.extensions.validator.util.FactoryUtils;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.ValidatorException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class JoinValidationStrategy extends AbstractValidatorAdapter {

+    public void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException {

+        AnnotationExtractor extractor = new DefaultPropertyScanningAnnotationExtractor();

+

+        String[] targetExpressions = annotationEntry.getAnnotation(JoinValidation.class).value();

+

+        ValidationStrategy validationStrategy;

+

+        for (String targetExpression : targetExpressions) {

+            for (AnnotationEntry entry : extractor.extractAnnotations(facesContext, targetExpression)) {

+                validationStrategy = FactoryUtils.getValidationStrategyFactory().create(entry.getAnnotation());

+

+                if (validationStrategy != null) {

+                    validationStrategy.validate(facesContext, uiComponent, entry, convertedObject);

+                } else {

+                    logger.trace("no validation strategy found for " + entry.getAnnotation().annotationType().getName());

+                }

+            }

+        }

+    }

+}

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JpaValidationStrategy.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JpaValidationStrategy.java
new file mode 100644
index 0000000..54189d8
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/JpaValidationStrategy.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.strategy;

+

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.ValidatorException;

+import javax.persistence.Basic;

+import javax.persistence.Column;

+import javax.persistence.ManyToOne;

+import javax.persistence.OneToOne;

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class JpaValidationStrategy extends AbstractValidationStrategy {

+

+    private static final String VALIDATE_REQUIRED = "required";

+    private static final String VALIDATE_LENGTH = "length";

+

+    private String violation;

+    private int maxLength;

+

+    public void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException {

+        Annotation annotation = annotationEntry.getAnnotation();

+        if (annotation instanceof Column) {

+            validateColumnAnnotation((Column) annotation, convertedObject);

+        } else if (annotation instanceof Basic) {

+            validateBasicAnnotation((Basic) annotation, 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(getValidationErrorFacesMassage(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()) {

+            //TODO

+            checkRequiredConvertedObject(convertedObject);

+        }

+    }

+

+    private void validateManyToOneAnnotation(ManyToOne manyToOne, Object convertedObject) {

+        if (!manyToOne.optional()) {

+            //TODO

+            checkRequiredConvertedObject(convertedObject);

+        }

+    }

+

+    private void checkRequiredConvertedObject(Object convertedObject) throws ValidatorException {

+        if (convertedObject == null || convertedObject.equals("")) {

+            this.violation = VALIDATE_REQUIRED;

+            throw new ValidatorException(getValidationErrorFacesMassage(null));

+        }

+    }

+

+    protected String getValidationErrorMsgKey(Annotation annotation) {

+        if (VALIDATE_LENGTH.equals(this.violation)) {

+            return "field_too_long";

+        } else {

+            return "field_required";

+        }

+    }

+

+    protected String getErrorMessageDetails(Annotation annotation) {

+        String message = super.getErrorMessageDetails(annotation);

+

+        if (VALIDATE_LENGTH.equals(this.violation)) {

+            return message.replace("{0}", "" + this.maxLength);

+        } else {

+            return message;

+        }

+    }

+}

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LengthStrategy.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LengthStrategy.java
new file mode 100644
index 0000000..8b230ed
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LengthStrategy.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.strategy;

+

+import org.apache.myfaces.extensions.validator.baseval.annotation.Length;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidatorAdapter;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.LengthValidator;

+import javax.faces.validator.ValidatorException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class LengthStrategy extends AbstractValidatorAdapter {

+

+    protected void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException {

+

+        Length annotation = annotationEntry.getAnnotation(Length.class);

+        LengthValidator lengthValidator = new LengthValidator();

+

+        lengthValidator.setMinimum(annotation.minimum());

+        lengthValidator.setMaximum(annotation.maximum());

+

+        lengthValidator.validate(facesContext, uiComponent, convertedObject);

+    }

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LongRangeStrategy.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LongRangeStrategy.java
new file mode 100644
index 0000000..9eaf98b
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/LongRangeStrategy.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.strategy;

+

+import org.apache.myfaces.extensions.validator.baseval.annotation.LongRange;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidatorAdapter;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.LongRangeValidator;

+import javax.faces.validator.ValidatorException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class LongRangeStrategy extends AbstractValidatorAdapter {

+

+    protected void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException {

+

+        LongRange annotation = annotationEntry.getAnnotation(LongRange.class);

+        LongRangeValidator longRangeValidator = new LongRangeValidator();

+

+        longRangeValidator.setMinimum(annotation.minimum());

+        longRangeValidator.setMaximum(annotation.maximum());

+

+        longRangeValidator.validate(facesContext, uiComponent, convertedObject);

+    }

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RegexStrategy.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RegexStrategy.java
new file mode 100644
index 0000000..f287a51
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RegexStrategy.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.strategy;

+

+import org.apache.myfaces.extensions.validator.baseval.annotation.Regex;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;

+

+import javax.faces.application.FacesMessage;

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.ValidatorException;

+import java.lang.annotation.Annotation;

+import java.util.regex.Pattern;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class RegexStrategy extends AbstractValidationStrategy {

+

+    protected void processValidation(FacesContext facesContext,

+                                     UIComponent uiComponent,

+                                     AnnotationEntry annotationEntry,

+                                     Object convertedObject) throws ValidatorException {

+

+        Regex annotation = annotationEntry.getAnnotation(Regex.class);

+

+        for (String expression : annotation.value()) {

+            if (convertedObject == null || !Pattern.compile(expression).matcher(convertedObject.toString()).matches()) {

+                throw new ValidatorException(

+                        new FacesMessage(

+                                FacesMessage.SEVERITY_ERROR,

+                                getErrorMessageSummary(annotation),

+                                getErrorMessageDetails(annotation)

+                                        .replace("{0}", expression)));

+            }

+        }

+    }

+

+    protected String getValidationErrorMsgKey(Annotation annotation) {

+        return ((Regex) annotation).validationErrorMsgKey();

+    }

+}

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RequiredStrategy.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RequiredStrategy.java
new file mode 100644
index 0000000..a5f79e4
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/RequiredStrategy.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.baseval.strategy;

+

+import org.apache.myfaces.extensions.validator.baseval.annotation.Required;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.ValidatorException;

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class RequiredStrategy extends AbstractValidationStrategy {

+

+    public void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException {

+        if (convertedObject == null || convertedObject.equals("")) {

+            throw new ValidatorException(getValidationErrorFacesMassage(annotationEntry.getAnnotation()));

+        }

+    }

+

+    protected String getValidationErrorMsgKey(Annotation annotation) {

+        return ((Required) annotation).validationErrorMsgKey();

+    }

+}

diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/ValidatorStrategy.java b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/ValidatorStrategy.java
new file mode 100644
index 0000000..5ab148f
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/baseval/strategy/ValidatorStrategy.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.baseval.strategy;

+

+import org.apache.myfaces.extensions.validator.baseval.annotation.Validator;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidatorAdapter;

+import org.apache.myfaces.extensions.validator.util.ClassUtils;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.ValidatorException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class ValidatorStrategy extends AbstractValidatorAdapter {

+

+    protected void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException {

+

+        Class[] validatorClasses = annotationEntry.getAnnotation(Validator.class).value();

+

+        javax.faces.validator.Validator validator;

+        for (Class validatorClassName : validatorClasses) {

+            validator = (javax.faces.validator.Validator) ClassUtils.tryToInstantiateClass(validatorClassName);

+

+            if (validator == null) {

+                logger.warn(validatorClassName.getName() + " not found");

+                continue;

+            }

+            validator.validate(facesContext, uiComponent, convertedObject);

+        }

+    }

+}
\ No newline at end of file
diff --git a/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/jpa_strategy_mappings.properties b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/jpa_strategy_mappings.properties
new file mode 100644
index 0000000..d5519ad
--- /dev/null
+++ b/validation-modules/base-validation/src/main/java/org/apache/myfaces/extensions/validator/jpa_strategy_mappings.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one

+# or more contributor license agreements.  See the NOTICE file

+# distributed with this work for additional information

+# regarding copyright ownership.  The ASF licenses this file

+# to you under the Apache License, Version 2.0 (the

+# "License"); you may not use this file except in compliance

+# with the License.  You may obtain a copy of the License at

+#

+#   http://www.apache.org/licenses/LICENSE-2.0

+#

+# Unless required by applicable law or agreed to in writing,

+# software distributed under the License is distributed on an

+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+# KIND, either express or implied.  See the License for the

+# specific language governing permissions and limitations

+# under the License.

+

+javax.persistence.Column=org.apache.myfaces.extensions.validator.baseval.strategy.JpaValidationStrategy

+javax.persistence.Basic=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/validation-modules/base-validation/src/main/resources/LICENSE.txt b/validation-modules/base-validation/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/validation-modules/base-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/validation-modules/base-validation/src/main/resources/NOTICE.txt b/validation-modules/base-validation/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/validation-modules/base-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/validation-modules/cross-validation/pom.xml b/validation-modules/cross-validation/pom.xml
new file mode 100644
index 0000000..93e3bcd
--- /dev/null
+++ b/validation-modules/cross-validation/pom.xml
@@ -0,0 +1,76 @@
+<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-cross-validation</artifactId>

+

+    <name>MyFaces Extensions-Validator Validation-Modules Crossval</name>

+    <version>${build.version}</version>

+

+    <parent>

+        <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>

+        <artifactId>validation-modules-project</artifactId>

+        <version>${build.version}</version>

+    </parent>

+

+    <dependencies>

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator</groupId>

+            <artifactId>myfaces-extval-core</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator.validation-modules</groupId>

+            <artifactId>myfaces-extval-base-validation</artifactId>

+            <version>${build.version}</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/validation-modules/cross-validation/src/main/config/faces-config.xml b/validation-modules/cross-validation/src/main/config/faces-config.xml
new file mode 100644
index 0000000..25bc73b
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/config/faces-config.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>

+<!DOCTYPE faces-config PUBLIC

+        "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"

+        "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" >

+

+<!--

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT 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>

+    <lifecycle>

+        <phase-listener>org.apache.myfaces.extensions.validator.crossval.CrossValidationPhaseListener</phase-listener>

+    </lifecycle>

+</faces-config>
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationPhaseListener.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationPhaseListener.java
new file mode 100644
index 0000000..9c6d09d
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationPhaseListener.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.crossval;

+

+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import javax.faces.application.FacesMessage;

+import javax.faces.component.UIComponent;

+import javax.faces.event.PhaseEvent;

+import javax.faces.event.PhaseId;

+import javax.faces.event.PhaseListener;

+import javax.faces.validator.ValidatorException;

+import java.util.MissingResourceException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class CrossValidationPhaseListener implements PhaseListener {

+    private boolean isInitialized = false;

+

+    public void afterPhase(PhaseEvent event) {

+

+        try {

+            CrossValidationStorage crossValidationStorage = CrossValidationUtils.getOrInitCrossValidationStorage();

+            for (CrossValidationStorageEntry entry : crossValidationStorage.getCrossValidationStorageEntries()) {

+                try {

+                    entry.getValidationStrategy().processCrossValidation(entry, crossValidationStorage);

+                } catch (ValidatorException e) {

+

+                    FacesMessage facesMessage = e.getFacesMessage();

+

+                    if (facesMessage != null && facesMessage.getSummary() != null && facesMessage.getDetail() != null) {

+                        UIComponent component = entry.getComponent();

+                        String clientId = null;

+

+                        //TODO

+                        if (component != null) {

+                            clientId = component.getClientId(event.getFacesContext());

+                        }

+

+                        event.getFacesContext().addMessage(clientId, facesMessage);

+                    }

+

+                    event.getFacesContext().renderResponse();

+                } catch (MissingResourceException e) {

+                    event.getFacesContext().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "custom validation message not found", e.toString()));

+                    event.getFacesContext().renderResponse();

+                    throw e;

+                }

+            }

+        } finally {

+            CrossValidationUtils.resetCrossValidationStorage();

+        }

+    }

+

+    public void beforePhase(PhaseEvent event) {

+        if (!isInitialized) {

+            if (WebXmlParameter.DEACTIVATE_CROSSVALIDATION != null && WebXmlParameter.DEACTIVATE_CROSSVALIDATION.equalsIgnoreCase("true")) {

+                ExtValUtils.deregisterPhaseListener(this);

+            } else {

+                isInitialized = true;

+            }

+        }

+    }

+

+    public PhaseId getPhaseId() {

+        return PhaseId.ANY_PHASE;

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationStorage.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationStorage.java
new file mode 100644
index 0000000..365a9d4
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationStorage.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;

+

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class 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/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationStorageEntry.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationStorageEntry.java
new file mode 100644
index 0000000..141d170
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/CrossValidationStorageEntry.java
@@ -0,0 +1,76 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.crossval.strategy.CrossValidationStrategy;

+

+import javax.faces.component.UIComponent;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class CrossValidationStorageEntry {

+    private AnnotationEntry annotationEntry;

+    //for complex components (e.g. a table) stores the object of entry (#{entry.property})

+    private Object bean;

+    private UIComponent component;

+    private Object convertedObject;

+    private CrossValidationStrategy validationStrategy;

+

+    public AnnotationEntry getAnnotationEntry() {

+        return annotationEntry;

+    }

+

+    public void setAnnotationEntry(AnnotationEntry annotationEntry) {

+        this.annotationEntry = annotationEntry;

+    }

+

+    public Object getBean() {

+        return bean;

+    }

+

+    public void setBean(Object bean) {

+        this.bean = bean;

+    }

+

+    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;

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/WebXmlParameter.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/WebXmlParameter.java
new file mode 100644
index 0000000..4a25b1d
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/WebXmlParameter.java
@@ -0,0 +1,30 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.extensions.validator.crossval;

+

+import org.apache.myfaces.extensions.validator.util.WebXmlUtils;

+

+/**

+ * centralized in order that these information arn't spread over the complete code base

+ *

+ * @author Gerhard Petracek

+ */

+public interface WebXmlParameter {

+    static final String DEACTIVATE_CROSSVALIDATION = WebXmlUtils.getInitParameter("DEACTIVATE_CROSSVALIDATION");

+}
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIs.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIs.java
new file mode 100644
index 0000000..00dac68
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIs.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.crossval.annotation;

+

+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.text.DateFormat;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+//TODO DateIsEntry (value, type)

+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;

+}
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIsType.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIsType.java
new file mode 100644
index 0000000..4640b25
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/DateIsType.java
@@ -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.

+ */

+package org.apache.myfaces.extensions.validator.crossval.annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public enum DateIsType {

+    before, after, same //TODO: beforeOrSame, afterOrSame

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/Equals.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/Equals.java
new file mode 100644
index 0000000..18e94a8
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/Equals.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.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface Equals {

+    String[] value();

+

+    String validationErrorMsgKey() default "duplicated_content_required";

+}
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/NotEquals.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/NotEquals.java
new file mode 100644
index 0000000..97ddae5
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/NotEquals.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.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface NotEquals {

+    String[] value();

+

+    String validationErrorMsgKey() default "duplicated_content_denied";

+}
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIf.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIf.java
new file mode 100644
index 0000000..3f606e8
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIf.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.crossval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+//TODO DateIsEntry (value, type)

+public @interface RequiredIf {

+    String[] valueOf();

+

+    /*

+     * optional section

+     */

+

+    RequiredIfType is() default RequiredIfType.not_empty;

+

+    String validationErrorMsgKey() default "empty_field";

+}
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIfType.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIfType.java
new file mode 100644
index 0000000..d770817
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/RequiredIfType.java
@@ -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.

+ */

+package org.apache.myfaces.extensions.validator.crossval.annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public enum RequiredIfType {

+    empty, not_empty

+}
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/TargetAlias.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/TargetAlias.java
new file mode 100644
index 0000000..8f2cd8b
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/TargetAlias.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.crossval.annotation;

+

+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;

+

+/**

+ * @author Gerhard Petracek

+ */

+@Target({METHOD, FIELD})

+@Retention(RUNTIME)

+public @interface TargetAlias {

+    String value() default "";

+}
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/extractor/DefaultValueBindingScanningAnnotationExtractor.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/extractor/DefaultValueBindingScanningAnnotationExtractor.java
new file mode 100644
index 0000000..2db7ac8
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/annotation/extractor/DefaultValueBindingScanningAnnotationExtractor.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.crossval.annotation.extractor;

+

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.annotation.extractor.DefaultComponentAnnotationExtractor;

+import org.apache.myfaces.extensions.validator.util.ELUtils;

+

+import javax.faces.context.FacesContext;

+import java.lang.reflect.Field;

+import java.lang.reflect.Method;

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.List;

+

+/**

+ * to support the usage of vb-xpressions (to reference the target bean)

+ *

+ * @author Gerhard Petracek

+ */

+public class DefaultValueBindingScanningAnnotationExtractor extends DefaultComponentAnnotationExtractor {

+

+    @Override

+    public List<AnnotationEntry> extractAnnotations(FacesContext facesContext, Object object) {

+        //should never occur

+        if (!(object instanceof String)) {

+            return new ArrayList<AnnotationEntry>();

+        }

+

+        String valueBindingExpression = ((String) object).trim();

+

+        List<AnnotationEntry> annotationEntries = new ArrayList<AnnotationEntry>();

+

+        Class entity = ELUtils.getTypeOfValueBindingForExpression(facesContext, valueBindingExpression);

+

+        if (entity != null) {

+            //find and add annotations

+            addPropertyAccessAnnotations(entity, annotationEntries, valueBindingExpression);

+            addFieldAccessAnnotations(entity, annotationEntries, valueBindingExpression);

+        }

+

+        return annotationEntries;

+    }

+

+    protected void addPropertyAccessAnnotations(Class entity, List<AnnotationEntry> annotationEntries, String valueBindingExpression) {

+        AnnotationEntry templateEntry;

+

+        for (Method method : entity.getDeclaredMethods()) {

+            templateEntry = new AnnotationEntry();

+            templateEntry.setEntityClass(entity.getClass());

+            templateEntry.setValueBindingExpression(valueBindingExpression);

+            templateEntry.setBoundTo("[method]:" + method.getName());

+

+            addAnnotationToAnnotationEntries(annotationEntries, Arrays.asList(method.getAnnotations()), templateEntry);

+        }

+    }

+

+    protected void addFieldAccessAnnotations(Class entity, List<AnnotationEntry> annotationEntries, String valueBindingExpression) {

+        AnnotationEntry templateEntry;

+

+        for (Field field : entity.getDeclaredFields()) {

+            templateEntry = new AnnotationEntry();

+            templateEntry.setEntityClass(entity.getClass());

+            templateEntry.setValueBindingExpression(valueBindingExpression);

+            templateEntry.setBoundTo("[field]:" + field.getName());

+

+            addAnnotationToAnnotationEntries(annotationEntries, Arrays.asList(field.getAnnotations()), templateEntry);

+        }

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages.properties b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages.properties
new file mode 100644
index 0000000..ff3f017
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/bundle/validation_messages.properties
@@ -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.

+

+duplicated_content_required=input is different

+duplicated_content_required_details=input is different

+

+duplicated_content_denied=same input isn't allowed

+duplicated_content_denied_details=same input isn't allowed

+

+wrong_date=wrong date

+wrong_date_details=wrong date

+

+wrong_date_not_before=date has to be after {0}

+wrong_date_not_before_details=date has to be after {0}

+

+wrong_date_not_after=date has to be before {0}

+wrong_date_not_after_details=date has to be before {0}

+

+wrong_date_not_equal=date isn't equal to {0}

+wrong_date_not_equal_details=date isn't equal to {0}

+

+empty_field=field is required

+empty_field_details=field is required
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/resolver/DefaultValidationErrorMessageResolver.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/resolver/DefaultValidationErrorMessageResolver.java
new file mode 100644
index 0000000..6a0a6b5
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/message/resolver/DefaultValidationErrorMessageResolver.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.message.resolver;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DefaultValidationErrorMessageResolver extends org.apache.myfaces.extensions.validator.core.validation.message.resolver.DefaultValidationErrorMessageResolver {

+    private static String BASE_NAME = null;

+

+    @Override

+    protected String getBaseName() {

+        if (BASE_NAME == null) {

+            BASE_NAME = super.getBaseName();

+        }

+

+        return BASE_NAME;

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractAliasCompareStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractAliasCompareStrategy.java
new file mode 100644
index 0000000..303f326
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractAliasCompareStrategy.java
@@ -0,0 +1,241 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, 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.referencing.strategy;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.annotation.extractor.AnnotationExtractor;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorage;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.crossval.annotation.TargetAlias;

+import org.apache.myfaces.extensions.validator.crossval.annotation.extractor.DefaultValueBindingScanningAnnotationExtractor;

+import org.apache.myfaces.extensions.validator.crossval.strategy.AbstractCompareStrategy;

+import org.apache.myfaces.extensions.validator.util.ELUtils;

+

+import javax.faces.context.FacesContext;

+import java.lang.reflect.Field;

+

+/**

+ * referencing validation targets - possible formats:

+ * "#{[bean_name]}:@[alias_name]" ... cross-entity validation with @TargetAlias

+ * or "@[alias_name]" ... global alias -> additional abstraction - doesn't depend on bean names, property names...

+ * component which is annotated with the @TargetAlias has to be within the same page

+ *

+ * @author Gerhard Petracek

+ */

+public class AbstractAliasCompareStrategy implements ReferencingStrategy {

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public boolean evalReferenceAndValidate(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorage crossValidationStorage, String validationTarget, AbstractCompareStrategy compareStrategy) {

+        if (validationTarget.startsWith("@")) {

+            tryToValidateWithAlias(crossValidationStorageEntry, crossValidationStorage, validationTarget.substring(1), compareStrategy);

+            return true;

+        } else if (validationTarget.contains(":@*")) {

+            if (validateBindingFormatWithAlias(validationTarget)) {

+                tryToValidateBindingWithAlias(crossValidationStorageEntry, validationTarget, crossValidationStorage, compareStrategy, false);

+                return true;

+            }

+        } else if (validationTarget.contains(":@")) {

+            if (validateBindingFormatWithAlias(validationTarget)) {

+                tryToValidateBindingWithAlias(crossValidationStorageEntry, validationTarget, crossValidationStorage, compareStrategy, true);

+                return true;

+            }

+        }

+        return false;

+    }

+

+    protected void tryToValidateWithAlias(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorage crossValidationStorage, String validationTarget, AbstractCompareStrategy compareStrategy) {

+        boolean validationExecuted = false;

+

+        boolean useModelValue = true;

+        if (validationTarget.startsWith("*")) {

+            useModelValue = false;

+            validationTarget = validationTarget.substring(1);

+        }

+

+        //search for TargetAlias annotations

+        for (CrossValidationStorageEntry entry : crossValidationStorage.getCrossValidationStorageEntries()) {

+

+            if (entry.getAnnotationEntry().getAnnotation() instanceof TargetAlias) {

+                validationExecuted = validateTargetWithAlias(validationTarget, crossValidationStorageEntry, entry, useModelValue, compareStrategy);

+            }

+

+            if (validationExecuted) {

+                break;

+            }

+        }

+    }

+

+    protected boolean tryToValidateBindingWithAlias(CrossValidationStorageEntry crossValidationStorageEntry, String targetProperty, CrossValidationStorage crossValidationStorage, AbstractCompareStrategy compareStrategy, boolean useModelValue) {

+        String[] crossEntityReferenceWithBinding = extractCrossEntityReferenceWithBinding(targetProperty);

+

+        FacesContext facesContext = FacesContext.getCurrentInstance();

+

+        if (!ELUtils.isExpressionValid(facesContext, crossEntityReferenceWithBinding[0])) {

+            return false;

+        }

+

+        AnnotationExtractor extractor = new DefaultValueBindingScanningAnnotationExtractor();

+

+        String alias;

+        AnnotationEntry foundAnnotationEntry = null;

+

+        int aliasStartIndex;

+

+        if (useModelValue) {

+            aliasStartIndex = crossEntityReferenceWithBinding[1].indexOf('@') + 1;

+        } else {

+            aliasStartIndex = crossEntityReferenceWithBinding[1].indexOf('@') + 2;

+        }

+        String targetAliasName = crossEntityReferenceWithBinding[1].substring(aliasStartIndex);

+        for (AnnotationEntry entry : extractor.extractAnnotations(facesContext, crossEntityReferenceWithBinding[0])) {

+            if (entry.getAnnotation() instanceof TargetAlias) {

+                alias = ((TargetAlias) entry.getAnnotation()).value();

+                if (targetAliasName.equals(alias)) {

+                    foundAnnotationEntry = entry;

+                    break;

+                }

+            }

+        }

+

+        if (foundAnnotationEntry == null) {

+            return false;

+        }

+

+        Object referencedBean = null;

+        Object validationTargetObject = null;

+        if (useModelValue) {

+            referencedBean = ELUtils.getValueOfExpression(facesContext, crossEntityReferenceWithBinding[0]);

+            validationTargetObject = getValidationTargetObject(crossValidationStorageEntry, foundAnnotationEntry, referencedBean, crossValidationStorage);

+        } else {

+            for (CrossValidationStorageEntry entry : crossValidationStorage.getCrossValidationStorageEntries()) {

+                if (foundAnnotationEntry.getAnnotation() instanceof TargetAlias && entry.getAnnotationEntry().getAnnotation() != null && entry.getAnnotationEntry().getAnnotation() instanceof TargetAlias) {

+                    if (((TargetAlias) foundAnnotationEntry.getAnnotation()).value().equals(((TargetAlias) entry.getAnnotationEntry().getAnnotation()).value())) {

+                        validationTargetObject = entry.getConvertedObject();

+                        break;

+                    }

+                }

+            }

+        }

+

+        validateFoundEntry(crossValidationStorageEntry, foundAnnotationEntry, referencedBean, crossValidationStorage, validationTargetObject, compareStrategy);

+

+        return true;

+    }

+

+    protected Object getValidationTargetObject(CrossValidationStorageEntry crossValidationStorageEntry, AnnotationEntry foundAnnotationEntry, Object referencedBean, CrossValidationStorage crossValidationStorage) {

+        if (foundAnnotationEntry == null || foundAnnotationEntry.getBoundTo() == null || foundAnnotationEntry.getBoundTo().indexOf(":") < 0) {

+            //TODO logging

+            return null;

+        }

+

+        Object validationTargetObject = null;

+        String boundTo = foundAnnotationEntry.getBoundTo();

+        String name = boundTo.substring(boundTo.indexOf(":") + 1);

+        if (boundTo.startsWith("[method]")) {

+            String baseValueBindingExpression = foundAnnotationEntry.getValueBindingExpression();

+

+            String targetValueBindingExpression = baseValueBindingExpression.substring(0, baseValueBindingExpression.length() - 1) + "." + name + "}";

+            FacesContext facesContext = FacesContext.getCurrentInstance();

+

+            if (ELUtils.isExpressionValid(facesContext, targetValueBindingExpression)) {

+                validationTargetObject = ELUtils.getValueOfExpression(facesContext, targetValueBindingExpression);

+            }

+        } else if (boundTo.startsWith("[field]")) {

+            try {

+                Field foundField;

+                try {

+                    foundField = referencedBean.getClass().getDeclaredField(name);

+                    foundField.setAccessible(true);

+                    validationTargetObject = foundField.get(referencedBean);

+                } catch (NoSuchFieldException e) {

+                    foundField = referencedBean.getClass().getDeclaredField("_" + name);

+                    foundField.setAccessible(true);

+                    validationTargetObject = foundField.get(referencedBean);

+                }

+            } catch (Exception e) {

+                logger.warn("couldn't access field " + name + " details: boundTo=" + boundTo, e);

+            }

+        }

+

+        return validationTargetObject;

+    }

+

+    protected void validateFoundEntry(CrossValidationStorageEntry crossValidationStorageEntry, AnnotationEntry foundAnnotationEntry, Object referencedBean, CrossValidationStorage crossValidationStorage, Object validationTargetObject, AbstractCompareStrategy compareStrategy) {

+        boolean violationFound = false;

+

+        if (compareStrategy.isViolation(crossValidationStorageEntry.getConvertedObject(), validationTargetObject, crossValidationStorageEntry.getAnnotationEntry().getAnnotation())) {

+            compareStrategy.handleTargetViolation(crossValidationStorageEntry, null);

+

+            violationFound = true;

+        }

+

+        if (violationFound) {

+            compareStrategy.processSourceComponentAfterViolation(crossValidationStorageEntry);

+        }

+    }

+

+    //TODO

+    protected boolean validateTargetWithAlias(String validationTarget, CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorageEntry entry, boolean useModelValue, AbstractCompareStrategy compareStrategy) {

+        boolean validationExecuted = false;

+        boolean violationFound = false;

+

+        if (validationTarget.equals(((TargetAlias) entry.getAnnotationEntry().getAnnotation()).value())) {

+            //get an object to store all results

+

+            Object validationTargetObject;

+

+            if (useModelValue) {

+                validationTargetObject = ELUtils.getValueOfExpression(FacesContext.getCurrentInstance(), entry.getAnnotationEntry().getValueBindingExpression());

+            } else {

+                validationTargetObject = entry.getConvertedObject();

+            }

+            if (compareStrategy.isViolation(crossValidationStorageEntry.getConvertedObject(), validationTargetObject, crossValidationStorageEntry.getAnnotationEntry().getAnnotation())) {

+                violationFound = true;

+

+                compareStrategy.handleTargetViolation(crossValidationStorageEntry, entry);

+            }

+            validationExecuted = true;

+        }

+

+        if (violationFound) {

+            compareStrategy.processSourceComponentAfterViolation(crossValidationStorageEntry);

+        }

+

+        return validationExecuted;

+    }

+

+    protected boolean validateBindingFormatWithAlias(String targetProperty) {

+        int bindingStartIndex = targetProperty.indexOf("#{");

+        int bindingEndIndex = targetProperty.indexOf("}");

+        int separatorIndex = targetProperty.indexOf(":@");

+

+        return (bindingStartIndex > -1 && bindingEndIndex > -1 && separatorIndex > -1 && bindingStartIndex < bindingEndIndex && bindingEndIndex < separatorIndex);

+    }

+

+    protected String[] extractCrossEntityReferenceWithBinding(String targetProperty) {

+        String[] result = new String[2];

+

+        result[0] = targetProperty.substring(0, targetProperty.indexOf(":"));

+        result[1] = targetProperty.substring(targetProperty.indexOf(":") + 1);

+

+        return result;

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractELCompareStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractELCompareStrategy.java
new file mode 100644
index 0000000..4aa8e03
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractELCompareStrategy.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.referencing.strategy;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.core.ProcessedInformationEntry;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorage;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.crossval.strategy.AbstractCompareStrategy;

+import org.apache.myfaces.extensions.validator.util.ELUtils;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import javax.faces.context.FacesContext;

+import java.util.Map;

+

+/**

+ * referencing validation targets - possible formats:

+ * "#{[bean_name].[property_name]}" ... cross-entity validation with value binding

+ *

+ * @author Gerhard Petracek

+ */

+public class AbstractELCompareStrategy implements ReferencingStrategy {

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public boolean evalReferenceAndValidate(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorage crossValidationStorage, String validationTarget, AbstractCompareStrategy compareStrategy) {

+        if (validationTarget.startsWith("#{") && validationTarget.endsWith("}") && validateValueBindingFormat(validationTarget)) {

+            tryToValidateValueBinding(crossValidationStorageEntry, validationTarget, crossValidationStorage, compareStrategy);

+            return true;

+        }

+        return false;

+    }

+

+    protected boolean tryToValidateValueBinding(CrossValidationStorageEntry crossValidationStorageEntry, String validationTarget, CrossValidationStorage crossValidationStorage, AbstractCompareStrategy compareStrategy) {

+        boolean violationFound = false;

+

+        FacesContext facesContext = FacesContext.getCurrentInstance();

+

+        if (!ELUtils.isExpressionValid(facesContext, validationTarget)) {

+            return false;

+        }

+

+        if (compareStrategy.isViolation(crossValidationStorageEntry.getConvertedObject(), ELUtils.getValueOfExpression(facesContext, validationTarget), crossValidationStorageEntry.getAnnotationEntry().getAnnotation())) {

+

+            ProcessedInformationEntry validationTargetEntry;

+            Map<String, ProcessedInformationEntry> valueBindingConvertedValueMapping = ExtValUtils.getOrInitValueBindingConvertedValueMapping();

+

+            validationTargetEntry = valueBindingConvertedValueMapping.get(validationTarget);

+

+            CrossValidationStorageEntry tmpCrossValidationStorageEntry = null;

+

+            if (validationTargetEntry != null) {

+                tmpCrossValidationStorageEntry = new CrossValidationStorageEntry();

+                tmpCrossValidationStorageEntry.setComponent(validationTargetEntry.getComponent());

+                tmpCrossValidationStorageEntry.setConvertedObject(validationTargetEntry.getConvertedValue());

+                tmpCrossValidationStorageEntry.setValidationStrategy(compareStrategy);

+            }

+

+            compareStrategy.handleTargetViolation(crossValidationStorageEntry, tmpCrossValidationStorageEntry);

+

+            violationFound = true;

+        }

+

+        if (violationFound) {

+            compareStrategy.processSourceComponentAfterViolation(crossValidationStorageEntry);

+        }

+

+        return true;

+    }

+

+    protected boolean validateValueBindingFormat(String targetProperty) {

+        int bindingStartIndex = targetProperty.indexOf("#{");

+        int bindingEndIndex = targetProperty.indexOf("}");

+        int separatorIndex = targetProperty.indexOf(".");

+

+        return (bindingStartIndex > -1 && bindingEndIndex > -1 && separatorIndex > -1 && bindingStartIndex < bindingEndIndex && bindingEndIndex > separatorIndex);

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractLocalCompareStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractLocalCompareStrategy.java
new file mode 100644
index 0000000..d96f5dd
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/AbstractLocalCompareStrategy.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.crossval.referencing.strategy;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.myfaces.extensions.validator.core.ProcessedInformationEntry;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorage;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.crossval.strategy.AbstractCompareStrategy;

+import org.apache.myfaces.extensions.validator.util.ELUtils;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import javax.faces.context.FacesContext;

+import java.util.Map;

+

+/**

+ * "[property_name]" ... local validation -> cross-component, but no cross-entity validation

+ *

+ * @author Gerhard Petracek

+ */

+public class AbstractLocalCompareStrategy implements ReferencingStrategy {

+    protected final Log logger = LogFactory.getLog(getClass());

+

+    public boolean evalReferenceAndValidate(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorage crossValidationStorage, String validationTarget, AbstractCompareStrategy compareStrategy) {

+        tryToValidateLocally(crossValidationStorageEntry, validationTarget, compareStrategy);

+

+        //TODO

+        return true;

+    }

+

+    protected void tryToValidateLocally(CrossValidationStorageEntry crossValidationStorageEntry, String validationTarget, AbstractCompareStrategy compareStrategy) {

+        boolean violationFound = false;

+

+        String baseValueBindingExpression = crossValidationStorageEntry.getAnnotationEntry().getValueBindingExpression();

+        baseValueBindingExpression = baseValueBindingExpression.substring(0, baseValueBindingExpression.lastIndexOf("."));

+

+        String targetValueBindingExpression;

+

+        FacesContext facesContext = FacesContext.getCurrentInstance();

+

+        Map<String, ProcessedInformationEntry> valueBindingConvertedValueMapping = ExtValUtils.getOrInitValueBindingConvertedValueMapping();

+        ProcessedInformationEntry validationTargetEntry;

+

+        targetValueBindingExpression = baseValueBindingExpression + "." + validationTarget + "}";

+

+        if (!ELUtils.isExpressionValid(facesContext, targetValueBindingExpression)) {

+            return;

+        }

+

+        if (!valueBindingConvertedValueMapping.containsKey(targetValueBindingExpression)) {

+            return;

+        }

+        validationTargetEntry = compareStrategy.resolveValidationTargetEntry(valueBindingConvertedValueMapping, targetValueBindingExpression, crossValidationStorageEntry.getBean());

+

+        if (validationTargetEntry == null) {

+            logger.warn("couldn't find converted object for " + targetValueBindingExpression);

+            return;

+        }

+

+        if (compareStrategy.isViolation(crossValidationStorageEntry.getConvertedObject(), validationTargetEntry.getConvertedValue(), crossValidationStorageEntry.getAnnotationEntry().getAnnotation())) {

+

+            CrossValidationStorageEntry tmpCrossValidationStorageEntry = new CrossValidationStorageEntry();

+            if (compareStrategy.useTargetComponentToDisplayErrorMsg(crossValidationStorageEntry)) {

+                tmpCrossValidationStorageEntry.setComponent(validationTargetEntry.getComponent());

+            } else {

+                tmpCrossValidationStorageEntry.setComponent(crossValidationStorageEntry.getComponent());

+            }

+            tmpCrossValidationStorageEntry.setConvertedObject(validationTargetEntry.getConvertedValue());

+            tmpCrossValidationStorageEntry.setValidationStrategy(compareStrategy);

+

+            compareStrategy.handleTargetViolation(crossValidationStorageEntry, tmpCrossValidationStorageEntry);

+

+            violationFound = true;

+        }

+

+        if (violationFound) {

+            compareStrategy.processSourceComponentAfterViolation(crossValidationStorageEntry);

+        }

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/ReferencingStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/ReferencingStrategy.java
new file mode 100644
index 0000000..e06b064
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/referencing/strategy/ReferencingStrategy.java
@@ -0,0 +1,30 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.extensions.validator.crossval.referencing.strategy;

+

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorage;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.crossval.strategy.AbstractCompareStrategy;

+

+/**

+ * @author Gerhard Petracek

+ */

+public interface ReferencingStrategy {

+    boolean evalReferenceAndValidate(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorage crossValidationStorage, String validationTarget, AbstractCompareStrategy abstractCompareStrategy);

+}
\ No newline at end of file
diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCompareStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCompareStrategy.java
new file mode 100644
index 0000000..bd28874
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCompareStrategy.java
@@ -0,0 +1,219 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.extensions.validator.crossval.strategy;

+

+import org.apache.myfaces.extensions.validator.core.ProcessedInformationEntry;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorage;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.crossval.referencing.strategy.AbstractAliasCompareStrategy;

+import org.apache.myfaces.extensions.validator.crossval.referencing.strategy.AbstractELCompareStrategy;

+import org.apache.myfaces.extensions.validator.crossval.referencing.strategy.AbstractLocalCompareStrategy;

+import org.apache.myfaces.extensions.validator.crossval.referencing.strategy.ReferencingStrategy;

+import org.apache.myfaces.extensions.validator.util.ClassUtils;

+import org.apache.myfaces.extensions.validator.util.ExtValUtils;

+

+import javax.faces.application.FacesMessage;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.ValidatorException;

+import java.lang.annotation.Annotation;

+import java.util.*;

+

+/**

+ * @author Gerhard Petracek

+ */

+public abstract class AbstractCompareStrategy 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 = ExtValUtils.getBasePackage() + "ReferencingStrategy";

+            ReferencingStrategy customReferencingStrategy = (ReferencingStrategy) ClassUtils.tryToInstantiateClassForName(customReferencingStrategyClassName);

+

+            if (customReferencingStrategy != null) {

+                referencingStrategies.add(customReferencingStrategy);

+            }

+

+            referencingStrategies.add(new AbstractELCompareStrategy());

+            referencingStrategies.add(new AbstractAliasCompareStrategy());

+            referencingStrategies.add(new AbstractLocalCompareStrategy());

+        }

+    }

+

+    public void processCrossValidation(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorage crossValidationStorage) throws ValidatorException {

+

+        String[] validationTargets = getValidationTargets(crossValidationStorageEntry.getAnnotationEntry().getAnnotation());

+

+        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.evalReferenceAndValidate(crossValidationStorageEntry, crossValidationStorage, validationTarget, this)) {

+                return true;

+            }

+        }

+

+        return false;

+    }

+

+    //has to be public for custom referencing strategies!!!

+    public void handleTargetViolation(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorageEntry entry) {

+        FacesContext facesContext = FacesContext.getCurrentInstance();

+

+        //get validation error messages for the target component

+        String summary = getErrorMessageSummary(crossValidationStorageEntry.getAnnotationEntry().getAnnotation(), true);

+        String details = getErrorMessageDetails(crossValidationStorageEntry.getAnnotationEntry().getAnnotation(), true);

+

+        //validation target isn't bound to a component withing the current page (see validateFoundEntry, tryToValidateLocally and tryToValidateBindingOnly)

+        if (entry == null) {

+            entry = crossValidationStorageEntry;

+        }

+

+        FacesMessage message;

+        if (entry.getAnnotationEntry() != null) {

+            message = getTargetComponentErrorMessage(entry.getAnnotationEntry().getAnnotation(), summary, details);

+        } else {

+            //TODO document possible side effects

+            //due to a missing target annotation (see: tryToValidateLocally)

+            message = getTargetComponentErrorMessage(crossValidationStorageEntry.getAnnotationEntry().getAnnotation(), summary, details);

+        }

+

+        if (message.getSummary() != null || message.getDetail() != null) {

+            facesContext.addMessage(entry.getComponent().getClientId(facesContext), message);

+        }

+    }

+

+    //has to be public for custom referencing strategies!!!

+    public void processSourceComponentAfterViolation(CrossValidationStorageEntry crossValidationStorageEntry) {

+

+        //get validation error messages for the current component

+        String summary = getErrorMessageSummary(crossValidationStorageEntry.getAnnotationEntry().getAnnotation(), false);

+        String details = getErrorMessageDetails(crossValidationStorageEntry.getAnnotationEntry().getAnnotation(), false);

+

+        FacesMessage message = getSourceComponentErrorMessage(crossValidationStorageEntry.getAnnotationEntry().getAnnotation(), summary, details);

+

+        if (message.getSummary() != null || message.getDetail() != null) {

+            //TODO

+            throw new ValidatorException(message);

+        } else {

+            throw new ValidatorException(new FacesMessage());

+        }

+    }

+

+    //has to be public for custom referencing strategies!!!

+    public FacesMessage getSourceComponentErrorMessage(Annotation annotation, String summary, String details) {

+        FacesMessage message = new FacesMessage();

+

+        message.setSeverity(FacesMessage.SEVERITY_ERROR);

+        message.setSummary(summary);

+        message.setDetail(details);

+

+        return message;

+    }

+

+    //has to be public for custom referencing strategies!!!

+    public FacesMessage getTargetComponentErrorMessage(Annotation foundAnnotation, String summary, String details) {

+        FacesMessage message = new FacesMessage();

+

+        message.setSeverity(FacesMessage.SEVERITY_ERROR);

+        message.setSummary(summary);

+        message.setDetail(details);

+

+        return message;

+    }

+

+    //has to be public for custom referencing strategies!!!

+    public ProcessedInformationEntry resolveValidationTargetEntry(Map<String, ProcessedInformationEntry> valueBindingConvertedValueMapping, String targetValueBinding, Object bean) {

+        ProcessedInformationEntry processedInformationEntry = valueBindingConvertedValueMapping.get(targetValueBinding);

+

+        //simple case

+        if (processedInformationEntry.getFurtherEntries() == null) {

+            return processedInformationEntry;

+        }

+

+        //process complex component entries (e.g. a table)

+        //supported: cross-component but no cross-entity validation (= locale validation)

+        if (processedInformationEntry.getBean().equals(bean)) {

+            return processedInformationEntry;

+        }

+

+        for (ProcessedInformationEntry entry : processedInformationEntry.getFurtherEntries()) {

+            if (entry.getBean().equals(bean)) {

+                return entry;

+            }

+        }

+

+        return null;

+    }

+

+    protected String getErrorMessageSummary(Annotation annotation, boolean isTargetComponent) {

+        return resolveMessage(getValidationErrorMsgKey(annotation, isTargetComponent));

+    }

+

+    protected String getErrorMessageDetails(Annotation annotation, boolean isTargetComponent) {

+        try {

+            String key = getValidationErrorMsgKey(annotation, isTargetComponent);

+            return (key != null) ? resolveMessage(key + DETAIL_MESSAGE_KEY_POSTFIX) : null;

+        } catch (MissingResourceException e) {

+            logger.warn("couldn't find key " + getValidationErrorMsgKey(annotation, isTargetComponent) + DETAIL_MESSAGE_KEY_POSTFIX, e);

+        }

+        return null;

+    }

+

+    protected String getValidationErrorMsgKey(Annotation annotation) {

+        return getValidationErrorMsgKey(annotation, false);

+    }

+

+    /*

+     * recommended methods to override - have to be public for custom referencing strategies!!!

+     */

+

+    /*

+     * abstract methods

+     */

+

+    protected abstract String getValidationErrorMsgKey(Annotation annotation, boolean isTargetComponent);

+

+    public abstract boolean useTargetComponentToDisplayErrorMsg(CrossValidationStorageEntry crossValidationStorageEntry);

+

+    /*

+     * implements the specific validation logic

+     */

+

+    public abstract boolean isViolation(Object object1, Object object2, Annotation 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(Annotation annotation);

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCrossValidationStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCrossValidationStrategy.java
new file mode 100644
index 0000000..edbc796
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/AbstractCrossValidationStrategy.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.strategy;

+

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractValidationStrategy;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.util.CrossValidationUtils;

+import org.apache.myfaces.extensions.validator.util.ELUtils;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.ValidatorException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public abstract class AbstractCrossValidationStrategy extends AbstractValidationStrategy implements CrossValidationStrategy {

+

+    //init cross-validation

+    public void processValidation(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) throws ValidatorException {

+        CrossValidationStorageEntry entry = getCrossValidationStorageEntry(facesContext, uiComponent, annotationEntry, convertedObject);

+

+        CrossValidationUtils.getOrInitCrossValidationStorage().add(entry);

+    }

+

+    public CrossValidationStorageEntry getCrossValidationStorageEntry(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject) {

+        CrossValidationStorageEntry entry = new CrossValidationStorageEntry();

+

+        entry.setAnnotationEntry(annotationEntry);

+        entry.setBean(ELUtils.getBeanObject(annotationEntry.getValueBindingExpression()));

+        entry.setComponent(uiComponent);

+        entry.setConvertedObject(convertedObject);

+        entry.setValidationStrategy(this);

+

+        return entry;

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationStrategy.java
new file mode 100644
index 0000000..27238f3
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/CrossValidationStrategy.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.crossval.strategy;

+

+import org.apache.myfaces.extensions.validator.core.annotation.AnnotationEntry;

+import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorage;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+

+import javax.faces.component.UIComponent;

+import javax.faces.context.FacesContext;

+import javax.faces.validator.ValidatorException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public interface CrossValidationStrategy extends ValidationStrategy {

+    CrossValidationStorageEntry getCrossValidationStorageEntry(FacesContext facesContext, UIComponent uiComponent, AnnotationEntry annotationEntry, Object convertedObject);

+

+    void processCrossValidation(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorage crossValidationStorage) throws ValidatorException;

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/DateIsStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/DateIsStrategy.java
new file mode 100644
index 0000000..7510e82
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/DateIsStrategy.java
@@ -0,0 +1,155 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.extensions.validator.crossval.strategy;

+

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.crossval.annotation.DateIs;

+import org.apache.myfaces.extensions.validator.crossval.annotation.DateIsType;

+

+import javax.faces.context.FacesContext;

+import java.lang.annotation.Annotation;

+import java.text.DateFormat;

+import java.util.Date;

+import java.util.MissingResourceException;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class DateIsStrategy extends AbstractCompareStrategy {

+    //TODO

+    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";

+

+    public boolean useTargetComponentToDisplayErrorMsg(CrossValidationStorageEntry crossValidationStorageEntry) {

+        return true;

+    }

+

+    //TODO

+    public boolean isViolation(Object object1, Object object2, Annotation annotation) {

+        boolean violationFound;

+

+        if (((DateIs) annotation).type().equals(DateIsType.same)) {

+            violationFound = object1 != null && !object1.equals(object2);

+

+            if (violationFound) {

+                this.violationResultStorage.put(RESULT_KEY, NOT_EQUAL_DATE_TIME);

+            }

+        } else if (((DateIs) 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);

+        }

+

+        return violationFound;

+    }

+

+    public String[] getValidationTargets(Annotation annotation) {

+        return ((DateIs) annotation).valueOf();

+    }

+

+    /*

+     * protected

+     */

+    protected String getValidationErrorMsgKey(Annotation annotation, boolean isTargetComponent) {

+        if (!isTargetComponent) {

+            return null;

+        }

+

+        String result = (String) this.violationResultStorage.get(RESULT_KEY);

+        if (TOO_EARLY.equals(result)) {

+            return getNotAfterErrorMsgKey((DateIs) annotation);

+        } else if (TOO_LATE.equals(result)) {

+            return getNotBeforeErrorMsgKey((DateIs) annotation);

+        } else {

+            return getNotEqualErrorMsgKey((DateIs) annotation);

+        }

+    }

+

+    @Override

+    protected String getErrorMessageSummary(Annotation annotation, boolean isTargetComponent) {

+        if (!isTargetComponent) {

+            return super.getErrorMessageSummary(annotation, isTargetComponent);

+        }

+

+        return getErrorMessage(getValidationErrorMsgKey(annotation, isTargetComponent), annotation, isTargetComponent);

+    }

+

+    @Override

+    protected String getErrorMessageDetails(Annotation annotation, boolean isTargetComponent) {

+        if (!isTargetComponent) {

+            return super.getErrorMessageDetails(annotation, isTargetComponent);

+        }

+

+        try {

+            return getErrorMessage(getValidationErrorMsgKey(annotation, isTargetComponent) + DETAIL_MESSAGE_KEY_POSTFIX, annotation, isTargetComponent);

+        } catch (MissingResourceException e) {

+            logger.warn("couldn't find key " + getValidationErrorMsgKey(annotation, isTargetComponent) + DETAIL_MESSAGE_KEY_POSTFIX, e);

+        }

+        return null;

+    }

+

+    //TODO

+    protected String getErrorMessage(String key, Annotation annotation, boolean isTargetComponent) {

+        String message = resolveMessage(key);

+

+        DateFormat dateFormat = DateFormat.getDateInstance(((DateIs) annotation).errorMessageDateStyle(), FacesContext.getCurrentInstance().getViewRoot().getLocale());

+

+        //replace placeholder with the value of the other component

+        return message.replace("{0}", dateFormat.format((Date) this.violationResultStorage.get(COMPARED_VALUE_KEY)));

+    }

+

+    /*

+     * 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/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/EqualsStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/EqualsStrategy.java
new file mode 100644
index 0000000..4ae5dbf
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/EqualsStrategy.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.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.crossval.annotation.Equals;

+

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+//TODO test custom message bundle

+public class EqualsStrategy extends AbstractCompareStrategy {

+

+    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/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/NotEqualsStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/NotEqualsStrategy.java
new file mode 100644
index 0000000..2eca184
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/NotEqualsStrategy.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.crossval.strategy;

+

+import org.apache.myfaces.extensions.validator.crossval.annotation.NotEquals;

+

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+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/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/RequiredIfStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/RequiredIfStrategy.java
new file mode 100644
index 0000000..7dca429
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/RequiredIfStrategy.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.crossval.strategy;

+

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+import org.apache.myfaces.extensions.validator.crossval.annotation.RequiredIf;

+import org.apache.myfaces.extensions.validator.crossval.annotation.RequiredIfType;

+

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class RequiredIfStrategy extends AbstractCompareStrategy {

+

+    public boolean useTargetComponentToDisplayErrorMsg(CrossValidationStorageEntry crossValidationStorageEntry) {

+        return false;

+    }

+

+    protected String getValidationErrorMsgKey(Annotation annotation, boolean isTargetComponent) {

+        return ((RequiredIf) annotation).validationErrorMsgKey();

+    }

+

+    public boolean isViolation(Object object1, Object object2, Annotation annotation) {

+        boolean violationFound = false;

+

+        if (((RequiredIf) annotation).is().equals(RequiredIfType.empty)) {

+            violationFound = (object2 == null || object2.equals("")) && (object1 == null || object1.equals(""));

+        } else if (((RequiredIf) annotation).is().equals(RequiredIfType.not_empty)) {

+            violationFound = (object2 != null && !object2.equals("")) && (object1 == null || object1.equals(""));

+        }

+

+        return violationFound;

+    }

+

+    public String[] getValidationTargets(Annotation annotation) {

+        return ((RequiredIf) annotation).valueOf();

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/TargetAliasStrategy.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/TargetAliasStrategy.java
new file mode 100644
index 0000000..c75d5e6
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/crossval/strategy/TargetAliasStrategy.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.CrossValidationStorage;

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorageEntry;

+

+import javax.faces.validator.ValidatorException;

+import java.lang.annotation.Annotation;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class TargetAliasStrategy extends AbstractCrossValidationStrategy {

+    public void processCrossValidation(CrossValidationStorageEntry crossValidationStorageEntry, CrossValidationStorage crossValidationStorage) throws ValidatorException {

+        //do nothing - it's just a marker - the inherited functionality is required and enough

+    }

+

+    //TODO

+    protected String getValidationErrorMsgKey(Annotation annotation) {

+        //do nothing - it's just a marker - the inherited functionality is required and enough

+        return null;

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/util/CrossValidationUtils.java b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/util/CrossValidationUtils.java
new file mode 100644
index 0000000..e5737f4
--- /dev/null
+++ b/validation-modules/cross-validation/src/main/java/org/apache/myfaces/extensions/validator/util/CrossValidationUtils.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.util;

+

+import org.apache.myfaces.extensions.validator.crossval.CrossValidationStorage;

+

+import javax.faces.context.FacesContext;

+import java.util.Map;

+

+/**

+ * @author Gerhard Petracek

+ */

+public class CrossValidationUtils {

+    public static final String CROSS_VALIDATION_STORAGE_KEY = CrossValidationStorage.class.getName();

+

+    public static CrossValidationStorage getOrInitCrossValidationStorage() {

+        Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();

+

+        if (!requestMap.containsKey(CROSS_VALIDATION_STORAGE_KEY)) {

+            resetCrossValidationStorage();

+        }

+

+        return (CrossValidationStorage) requestMap.get(CROSS_VALIDATION_STORAGE_KEY);

+    }

+

+    public static void resetCrossValidationStorage() {

+        FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(CROSS_VALIDATION_STORAGE_KEY, new CrossValidationStorage());

+    }

+}

diff --git a/validation-modules/cross-validation/src/main/resources/LICENSE.txt b/validation-modules/cross-validation/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..c6055ec
--- /dev/null
+++ b/validation-modules/cross-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/validation-modules/cross-validation/src/main/resources/NOTICE.txt b/validation-modules/cross-validation/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..4278ef3
--- /dev/null
+++ b/validation-modules/cross-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/validation-modules/pom.xml b/validation-modules/pom.xml
new file mode 100644
index 0000000..26cfd76
--- /dev/null
+++ b/validation-modules/pom.xml
@@ -0,0 +1,34 @@
+<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>${build.version}</version>

+

+    <parent>

+        <groupId>org.apache.myfaces.extensions.validator</groupId>

+        <artifactId>validator-project</artifactId>

+        <version>${build.version}</version>

+    </parent>

+

+    <modules>

+        <module>base-validation</module>

+        <module>cross-validation</module>

+    </modules>

+

+    <dependencies>

+        <dependency>

+            <groupId>org.apache.myfaces.extensions.validator</groupId>

+            <artifactId>myfaces-extval-core</artifactId>

+            <version>${build.version}</version>

+            <scope>compile</scope>

+        </dependency>

+    </dependencies>

+

+</project>