You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gp...@apache.org on 2009/04/10 05:42:51 UTC

svn commit: r763865 - in /myfaces/extensions/validator/branches/beanval_integration/trunk: examples/hello_world/src/main/java/org/apache/myfaces/blank/ examples/hello_world/src/main/java/org/apache/myfaces/blank/domain/ examples/hello_world/src/main/ja...

Author: gpetracek
Date: Fri Apr 10 03:42:49 2009
New Revision: 763865

URL: http://svn.apache.org/viewvc?rev=763865&view=rev
Log:
jsr 303 model-validation

Added:
    myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/validation/group/Address.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/violation.jsp
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/BeanValidation.java
      - copied, changed from r763761, myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/BeanValidation.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/GroupValidationKeys.java
      - copied, changed from r763245, myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/GroupValidationKeys.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/ModelValidation.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/NoRestrictionGroup.java
      - copied, changed from r763744, myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/None.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationEntry.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationPhaseListener.java
Removed:
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/
Modified:
    myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/HelloWorldController.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/domain/Person.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form1.jsp
    myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form2.jsp
    myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/helloWorld.jsp
    myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/result.jsp
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/config/faces-config.xml
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationInterceptor.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/ExtValBeanValidationContext.java
    myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/extractor/DefaultGroupControllerScanningExtractor.java

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/HelloWorldController.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/HelloWorldController.java?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/HelloWorldController.java (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/HelloWorldController.java Fri Apr 10 03:42:49 2009
@@ -21,7 +21,9 @@
 import org.apache.myfaces.blank.domain.Person;
 import org.apache.myfaces.blank.validation.group.Admin;
 import org.apache.myfaces.blank.validation.group.User;
-import org.apache.myfaces.extensions.validator.beanval.annotation.group.BeanValidation;
+import org.apache.myfaces.blank.validation.group.Address;
+import org.apache.myfaces.extensions.validator.beanval.annotation.BeanValidation;
+import org.apache.myfaces.extensions.validator.beanval.annotation.ModelValidation;
 
 /**
  * A typical simple backing bean, that is backed to <code>helloworld.jsp</code>
@@ -53,7 +55,10 @@
     @BeanValidation.List({
             @BeanValidation(viewIds = "/helloWorld.jsp"),
             @BeanValidation(viewIds = "/form1.jsp", useGroups = User.class),
-            @BeanValidation(viewIds = "/form2.jsp", useGroups = {Admin.class})
+            @BeanValidation(viewIds = "/form2.jsp", useGroups = Admin.class),
+            @BeanValidation(viewIds = "/violation.jsp", useGroups = Admin.class),
+            @BeanValidation(viewIds = "/violation.jsp", useGroups = Address.class,
+                    modelValidation = @ModelValidation(isActive = true))
     })
     public Person getPerson()
     {

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/domain/Person.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/domain/Person.java?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/domain/Person.java (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/domain/Person.java Fri Apr 10 03:42:49 2009
@@ -20,6 +20,7 @@
 
 import org.apache.myfaces.blank.validation.group.Admin;
 import org.apache.myfaces.blank.validation.group.User;
+import org.apache.myfaces.blank.validation.group.Address;
 import org.apache.myfaces.extensions.validator.baseval.annotation.Required;
 
 import javax.validation.constraints.NotNull;
@@ -39,6 +40,13 @@
     })
     private String lastName;
 
+    @NotNull(groups = Address.class, message = "street is required")
+    private String street;
+    @NotNull(groups = Address.class, message = "zip is required")
+    private String zip;
+    @NotNull(groups = Address.class, message = "city is required")
+    private String city;
+
     public String getFirstName()
     {
         return firstName;
@@ -58,4 +66,34 @@
     {
         this.lastName = lastName;
     }
+
+    public String getStreet()
+    {
+        return street;
+    }
+
+    public void setStreet(String street)
+    {
+        this.street = street;
+    }
+
+    public String getZip()
+    {
+        return zip;
+    }
+
+    public void setZip(String zip)
+    {
+        this.zip = zip;
+    }
+
+    public String getCity()
+    {
+        return city;
+    }
+
+    public void setCity(String city)
+    {
+        this.city = city;
+    }
 }

Added: myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/validation/group/Address.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/validation/group/Address.java?rev=763865&view=auto
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/validation/group/Address.java (added)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/java/org/apache/myfaces/blank/validation/group/Address.java Fri Apr 10 03:42:49 2009
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.blank.validation.group;
+
+public interface Address
+{
+}
\ No newline at end of file

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form1.jsp
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form1.jsp?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form1.jsp (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form1.jsp Fri Apr 10 03:42:49 2009
@@ -38,6 +38,7 @@
                 <h:panelGroup/>
               </h:panelGrid>
             </h:form>
+            <h:messages globalOnly="true" showDetail="true" showSummary="false"/>
         </f:view>
     </body>
 </html>

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form2.jsp
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form2.jsp?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form2.jsp (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/form2.jsp Fri Apr 10 03:42:49 2009
@@ -38,6 +38,7 @@
                 <h:panelGroup/>
               </h:panelGrid>
             </h:form>
+            <h:messages globalOnly="true" showDetail="true" showSummary="false"/>
         </f:view>
     </body>
 </html>

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/helloWorld.jsp
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/helloWorld.jsp?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/helloWorld.jsp (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/helloWorld.jsp Fri Apr 10 03:42:49 2009
@@ -38,6 +38,7 @@
                 <h:panelGroup/>
               </h:panelGrid>
             </h:form>
+            <h:messages globalOnly="true" showDetail="true" showSummary="false"/>
         </f:view>
     </body>
 </html>

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/result.jsp
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/result.jsp?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/result.jsp (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/result.jsp Fri Apr 10 03:42:49 2009
@@ -29,6 +29,7 @@
                     <h:outputText value="Home"/>
                 </h:commandLink>
             </h:form>
+            <h:messages globalOnly="true" showDetail="true" showSummary="false"/>
         </f:view>
     </body>
 </html>
\ No newline at end of file

Added: myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/violation.jsp
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/violation.jsp?rev=763865&view=auto
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/violation.jsp (added)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/examples/hello_world/src/main/webapp/violation.jsp Fri Apr 10 03:42:49 2009
@@ -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.
+--%>
+
+<%@ 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="first_name" value="First name:"/>
+                <h:inputText id="first_name" label="First name" value="#{helloWorld['person'].firstName}"/>
+                <h:message for="first_name" showSummary="true" showDetail="false"/>
+
+                <h:outputLabel for="last_name" value="Last name:"/>
+                <h:inputText id="last_name" label="Last name" value="#{helloWorld.person.lastName}"/>
+                <h:message for="last_name" showSummary="true" showDetail="false"/>
+
+                <h:commandButton value="Press me" action="#{helloWorld.send}"/>
+                <h:panelGroup/>
+                <h:panelGroup/>
+              </h:panelGrid>
+            </h:form>
+            <h:messages globalOnly="true" showDetail="true" showSummary="false"/>
+        </f:view>
+    </body>
+</html>

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/config/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/config/faces-config.xml?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/config/faces-config.xml (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/config/faces-config.xml Fri Apr 10 03:42:49 2009
@@ -22,5 +22,6 @@
               version="1.2">
     <lifecycle>
         <phase-listener>org.apache.myfaces.extensions.validator.beanval.startup.BeanValidationStartupListener</phase-listener>
+        <phase-listener>org.apache.myfaces.extensions.validator.beanval.validation.ModelValidationPhaseListener</phase-listener>
     </lifecycle>
 </faces-config>
\ No newline at end of file

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationInterceptor.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationInterceptor.java?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationInterceptor.java (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/BeanValidationInterceptor.java Fri Apr 10 03:42:49 2009
@@ -23,6 +23,8 @@
 import org.apache.myfaces.extensions.validator.core.recorder.ProcessedInformationRecorder;
 import org.apache.myfaces.extensions.validator.core.ExtValContext;
 import org.apache.myfaces.extensions.validator.core.WebXmlParameter;
+import org.apache.myfaces.extensions.validator.core.el.ELHelper;
+import org.apache.myfaces.extensions.validator.core.el.ValueBindingExpression;
 import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
 import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
 import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
@@ -32,11 +34,14 @@
 import org.apache.myfaces.extensions.validator.core.metadata.transformer.MetaDataTransformer;
 import org.apache.myfaces.extensions.validator.core.interceptor.AbstractRendererInterceptor;
 import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
 import org.apache.myfaces.extensions.validator.beanval.property.BeanValidationPropertyInformationKeys;
-import org.apache.myfaces.extensions.validator.beanval.annotation.group.BeanValidation;
-import org.apache.myfaces.extensions.validator.beanval.annotation.group.None;
+import org.apache.myfaces.extensions.validator.beanval.annotation.BeanValidation;
+import org.apache.myfaces.extensions.validator.beanval.annotation.ModelValidation;
 import org.apache.myfaces.extensions.validator.beanval.annotation.extractor.DefaultGroupControllerScanningExtractor;
 import org.apache.myfaces.extensions.validator.beanval.validation.strategy.BeanValidationStrategyAdapter;
+import org.apache.myfaces.extensions.validator.beanval.validation.ModelValidationEntry;
+import org.apache.myfaces.extensions.validator.beanval.annotation.NoRestrictionGroup;
 import org.apache.myfaces.extensions.validator.internal.ToDo;
 import org.apache.myfaces.extensions.validator.internal.Priority;
 
@@ -53,12 +58,14 @@
 import javax.validation.ConstraintDescriptor;
 import javax.validation.ValidatorFactory;
 import javax.validation.ConstraintViolation;
+import javax.validation.groups.Default;
 import java.util.Set;
 import java.util.Map;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.io.IOException;
+import java.lang.reflect.Method;
 
 /**
  * @author Gerhard Petracek
@@ -198,6 +205,7 @@
         }
     }
 
+    @ToDo(value = Priority.HIGH, description = "use ExtValUtils#createFacesMessage")
     protected void processValidation(FacesContext facesContext, UIComponent uiComponent, Object convertedObject)
     {
         if (!(uiComponent instanceof EditableValueHolder))
@@ -221,7 +229,7 @@
         PropertyInformation propertyInformation = metaDataExtractor.extract(facesContext, uiComponent);
 
         //extract group validation annotations
-        addGroupsToContext(propertyInformation, uiComponent.getClientId(facesContext));
+        addMetaDataToContext(propertyInformation, uiComponent);
 
         Class baseBeanClass = (propertyInformation.getInformation(
                 PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class)).getBaseObject().getClass();
@@ -261,6 +269,7 @@
                     validatorException,
                     null);
 
+            //TODO check & remove
             propertyInformation.setInformation(
                     BeanValidationPropertyInformationKeys.CONSTRAINT_VIOLATIONS, violations);
 
@@ -282,7 +291,7 @@
         }
     }
 
-    private void addGroupsToContext(PropertyInformation propertyInformation, String clientId)
+    private void addMetaDataToContext(PropertyInformation propertyInformation, UIComponent component)
     {
         PropertyDetails propertyDetails = propertyInformation
                 .getInformation(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
@@ -291,106 +300,175 @@
 
         Object firstBean = ExtValUtils.getELHelper().getBean(key[0]);
 
-        List<Class> foundGroupsForCurrentView = new ArrayList<Class>();
-        List<Class> restrictedGroupsForCurrentView = new ArrayList<Class>();
+        List<Class> foundGroupsForPropertyValidation = new ArrayList<Class>();
+        List<Class> restrictedGroupsForPropertyValidation = new ArrayList<Class>();
+        List<ModelValidationEntry> modelValidationEntryList = new ArrayList<ModelValidationEntry>();
+        List<Class> restrictedGroupsForModelValidation = new ArrayList<Class>();
 
         //extract bv-controller-annotation of
 
         //first bean
-        processClass(firstBean.getClass(), foundGroupsForCurrentView, restrictedGroupsForCurrentView);
+        processClass(firstBean,
+                foundGroupsForPropertyValidation,
+                restrictedGroupsForPropertyValidation,
+                modelValidationEntryList,
+                restrictedGroupsForModelValidation);
 
         //first property
-        processFieldsAndProperties(key[0] + "." + key[1], firstBean, key[1],
-                foundGroupsForCurrentView, restrictedGroupsForCurrentView);
+        processFieldsAndProperties(key[0] + "." + key[1],
+                firstBean,
+                key[1],
+                foundGroupsForPropertyValidation,
+                restrictedGroupsForPropertyValidation,
+                modelValidationEntryList,
+                restrictedGroupsForModelValidation);
 
         //base object (of target property)
-        processClass(propertyDetails.getBaseObject().getClass(),
-                foundGroupsForCurrentView, restrictedGroupsForCurrentView);
+        processClass(propertyDetails.getBaseObject(),
+                foundGroupsForPropertyValidation,
+                restrictedGroupsForPropertyValidation,
+                modelValidationEntryList,
+                restrictedGroupsForModelValidation);
 
         //last property
         processFieldsAndProperties(
                 propertyDetails.getKey(),
                 propertyDetails.getBaseObject(),
                 propertyDetails.getProperty(),
-                foundGroupsForCurrentView,
-                restrictedGroupsForCurrentView);
+                foundGroupsForPropertyValidation,
+                restrictedGroupsForPropertyValidation,
+                modelValidationEntryList,
+                restrictedGroupsForModelValidation);
 
+        ExtValBeanValidationContext extValBeanValidationContext = ExtValBeanValidationContext.getCurrentInstance();
+        String currentViewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();
+
+        String clientId = component.getClientId(FacesContext.getCurrentInstance());
         /*
          * add found groups to context
          */
-        for (Class currentGroupClass : foundGroupsForCurrentView)
+        for (Class currentGroupClass : foundGroupsForPropertyValidation)
         {
-            ExtValBeanValidationContext.getCurrentInstance().addGroup(
-                    currentGroupClass, FacesContext.getCurrentInstance().getViewRoot().getViewId(), clientId);
+            extValBeanValidationContext.addGroup(currentGroupClass, currentViewId, clientId);
         }
 
         /*
          * add restricted groups
          */
-        for (Class currentGroupClass : restrictedGroupsForCurrentView)
+        for (Class currentGroupClass : restrictedGroupsForPropertyValidation)
+        {
+            extValBeanValidationContext.restrictGroup(currentGroupClass, currentViewId, clientId);
+        }
+
+        /*
+         * add model validation entry list
+         */
+        for(ModelValidationEntry modelValidationEntry : modelValidationEntryList)
         {
-            ExtValBeanValidationContext.getCurrentInstance().restrictGroup(
-                    currentGroupClass, FacesContext.getCurrentInstance().getViewRoot().getViewId(), clientId);
+            if(!"true".equalsIgnoreCase(org.apache.myfaces.extensions.validator.beanval.WebXmlParameter
+                    .DEACTIVATE_IMPLICIT_DEFAULT_GROUP_VALIDATION))
+            {
+                modelValidationEntry.addGroup(Default.class);
+            }
+
+            for(Class restrictedGroup : restrictedGroupsForModelValidation)
+            {
+                modelValidationEntry.removeGroup(restrictedGroup);
+            }
+
+            if(modelValidationEntry.getGroups().length > 0 &&
+                    isModelValidationAllowed(modelValidationEntry.getMetaData()))
+            {
+                addTargetsForModelValidation(modelValidationEntry, propertyDetails.getBaseObject());
+                extValBeanValidationContext.addModelValidationEntry(modelValidationEntry, currentViewId, component);
+            }
         }
     }
 
-    private void processClass(Class classToInspect,
-                              List<Class> foundGroupsForCurrentView,
-                              List<Class> restrictedGroupsForCurrentView)
+    private void processClass(Object objectToInspect,
+                              List<Class> foundGroupsForPropertyValidation,
+                              List<Class> restrictedGroupsForPropertyValidation,
+                              List<ModelValidationEntry> modelValidationEntryList,
+                              List<Class> restrictedGroupsForModelValidation)
     {
+        Class classToInspect = objectToInspect.getClass();
         while (!Object.class.getName().equals(classToInspect.getName()))
         {
-            transferGroupValidationInformationToFoundGroups(classToInspect,
-                    foundGroupsForCurrentView,
-                    restrictedGroupsForCurrentView);
-
-            processInterfaces(classToInspect, foundGroupsForCurrentView, restrictedGroupsForCurrentView);
+            transferGroupValidationInformationToFoundGroups(objectToInspect,
+                    foundGroupsForPropertyValidation,
+                    restrictedGroupsForPropertyValidation,
+                    modelValidationEntryList,
+                    restrictedGroupsForModelValidation);
+
+            processInterfaces(objectToInspect.getClass(), objectToInspect,
+                    foundGroupsForPropertyValidation,
+                    restrictedGroupsForPropertyValidation,
+                    modelValidationEntryList,
+                    restrictedGroupsForModelValidation);
 
             classToInspect = classToInspect.getSuperclass();
         }
     }
 
     private void processInterfaces(Class currentClass,
-                                   List<Class> foundGroupsForCurrentView,
-                                   List<Class> restrictedGroupsForCurrentView)
+                                   Object metaDataSourceObject,
+                                   List<Class> foundGroupsForPropertyValidation,
+                                   List<Class> restrictedGroupsForPropertyValidation,
+                                   List<ModelValidationEntry> modelValidationEntryList,
+                                   List<Class> restrictedGroupsForModelValidation)
     {
         for (Class currentInterface : currentClass.getInterfaces())
         {
-            transferGroupValidationInformationToFoundGroups(currentClass,
-                    foundGroupsForCurrentView,
-                    restrictedGroupsForCurrentView);
-
-            processInterfaces(currentInterface, foundGroupsForCurrentView, restrictedGroupsForCurrentView);
+            transferGroupValidationInformationToFoundGroups(metaDataSourceObject,
+                    foundGroupsForPropertyValidation,
+                    restrictedGroupsForPropertyValidation,
+                    modelValidationEntryList,
+                    restrictedGroupsForModelValidation);
+
+            processInterfaces(currentInterface, metaDataSourceObject,
+                    foundGroupsForPropertyValidation,
+                    restrictedGroupsForPropertyValidation,
+                    modelValidationEntryList,
+                    restrictedGroupsForModelValidation);
         }
     }
 
-    private void transferGroupValidationInformationToFoundGroups(Class classToInspect,
-                                                                 List<Class> foundGroupsForCurrentView,
-                                                                 List<Class> restrictedGroupsForCurrentView)
+    private void transferGroupValidationInformationToFoundGroups(Object objectToInspect,
+                                                                 List<Class> foundGroupsForPropertyValidation,
+                                                                 List<Class> restrictedGroupsForPropertyValidation,
+                                                                 List<ModelValidationEntry> modelValidationEntryList,
+                                                                 List<Class> restrictedGroupsForModelValidation)
     {
-        if (classToInspect.isAnnotationPresent(BeanValidation.class))
+        if (objectToInspect.getClass().isAnnotationPresent(BeanValidation.class))
         {
-            addGroupsForCurrentView(
-                    (BeanValidation) classToInspect.getAnnotation(BeanValidation.class),
-                    foundGroupsForCurrentView,
-                    restrictedGroupsForCurrentView);
+            processMetaData(objectToInspect.getClass().getAnnotation(BeanValidation.class),
+                    objectToInspect,
+                    foundGroupsForPropertyValidation,
+                    restrictedGroupsForPropertyValidation,
+                    modelValidationEntryList,
+                    restrictedGroupsForModelValidation);
         }
-        else if (classToInspect.isAnnotationPresent(BeanValidation.List.class))
+        else if (objectToInspect.getClass().isAnnotationPresent(BeanValidation.List.class))
         {
             for(BeanValidation currentBeanValidation :
-                    ((BeanValidation.List)classToInspect.getAnnotation(BeanValidation.List.class)).value())
+                    (objectToInspect.getClass().getAnnotation(BeanValidation.List.class)).value())
             {
-                addGroupsForCurrentView(currentBeanValidation,
-                        foundGroupsForCurrentView,
-                        restrictedGroupsForCurrentView);
+                processMetaData(currentBeanValidation,
+                        objectToInspect,
+                        foundGroupsForPropertyValidation,
+                        restrictedGroupsForPropertyValidation,
+                        modelValidationEntryList,
+                        restrictedGroupsForModelValidation);
             }
         }
     }
 
     private void processFieldsAndProperties(String key,
                                             Object base,
-                                            String property, List<Class> foundGroupsForCurrentView,
-                                            List<Class> restrictedGroupsForCurrentView)
+                                            String property, List<Class> foundGroupsForPropertyValidation,
+                                            List<Class> restrictedGroupsForPropertyValidation,
+                                            List<ModelValidationEntry> modelValidationEntryList,
+                                            List<Class> restrictedGroupsForModelValidation)
     {
         PropertyInformation propertyInformation = new DefaultGroupControllerScanningExtractor()
                 .extract(FacesContext.getCurrentInstance(), new PropertyDetails(key, base, property));
@@ -399,38 +477,200 @@
         {
             if (metaDataEntry.getValue() instanceof BeanValidation)
             {
-                addGroupsForCurrentView((BeanValidation) metaDataEntry.getValue(),
-                        foundGroupsForCurrentView, restrictedGroupsForCurrentView);
+                processMetaData((BeanValidation) metaDataEntry.getValue(),
+                        base,
+                        foundGroupsForPropertyValidation,
+                        restrictedGroupsForPropertyValidation,
+                        modelValidationEntryList,
+                        restrictedGroupsForModelValidation);
             }
             else if(metaDataEntry.getValue() instanceof BeanValidation.List)
             {
                 for(BeanValidation currentBeanValidation : ((BeanValidation.List)metaDataEntry.getValue()).value())
                 {
-                    addGroupsForCurrentView(currentBeanValidation,
-                            foundGroupsForCurrentView,
-                            restrictedGroupsForCurrentView);
+                    processMetaData(currentBeanValidation,
+                            base,
+                            foundGroupsForPropertyValidation,
+                            restrictedGroupsForPropertyValidation,
+                            modelValidationEntryList,
+                            restrictedGroupsForModelValidation);
                 }
             }
         }
     }
 
-    private void addGroupsForCurrentView(BeanValidation beanValidation,
-                                         List<Class> foundGroupsForCurrentView,
-                                         List<Class> restrictedGroupsForCurrentView)
+    private void processMetaData(BeanValidation beanValidation,
+                                 Object metaDataSourceObject,
+                                 List<Class> foundGroupsForPropertyValidation,
+                                 List<Class> restrictedGroupsForPropertyValidation,
+                                 List<ModelValidationEntry> modelValidationEntryList,
+                                 List<Class> restrictedGroupsForModelValidation)
     {
         for (String currentViewId : beanValidation.viewIds())
         {
             if (currentViewId.equals(FacesContext.getCurrentInstance().getViewRoot().getViewId()) ||
                     currentViewId.equals("*"))
             {
-                foundGroupsForCurrentView.addAll(Arrays.asList(beanValidation.useGroups()));
+                if(isModelValidation(beanValidation))
+                {
+                    addModelValidationEntry(
+                            beanValidation, metaDataSourceObject,
+                            modelValidationEntryList, restrictedGroupsForModelValidation);
+                }
+                else
+                {
+                    processGroups(
+                            beanValidation, foundGroupsForPropertyValidation, restrictedGroupsForPropertyValidation);
+                }
+
+                return;
+            }
+        }
+    }
+
+    private void processGroups(BeanValidation beanValidation,
+                           List<Class> foundGroupsForPropertyValidation,
+                           List<Class> restrictedGroupsForPropertyValidation)
+    {
+        foundGroupsForPropertyValidation.addAll(Arrays.asList(beanValidation.useGroups()));
+
+        if(!(beanValidation.restrictGroups().length == 1 &&
+                beanValidation.restrictGroups()[0].equals(NoRestrictionGroup.class)))
+        {
+            restrictedGroupsForPropertyValidation.addAll(Arrays.asList(beanValidation.restrictGroups()));
+        }
+    }
+
+    private boolean isModelValidation(BeanValidation beanValidation)
+    {
+        return beanValidation.modelValidation().isActive();
+    }
+
+    private void addModelValidationEntry(BeanValidation beanValidation,
+                                         Object metaDataSourceObject,
+                                         List<ModelValidationEntry> modelValidationEntryList,
+                                         List<Class> restrictedGroupsForModelValidation)
+    {
+        ModelValidationEntry modelValidationEntry = new ModelValidationEntry();
+
+        modelValidationEntry.setGroups(Arrays.asList(beanValidation.useGroups()));
+        modelValidationEntry.setMetaData(beanValidation.modelValidation());
+        modelValidationEntry.setMetaDataSourceObject(metaDataSourceObject);
+
+        if(!(beanValidation.restrictGroups().length == 1 &&
+                beanValidation.restrictGroups()[0].equals(NoRestrictionGroup.class)))
+        {
+            restrictedGroupsForModelValidation.addAll(Arrays.asList(beanValidation.restrictGroups()));
+        }
+
+        modelValidationEntryList.add(modelValidationEntry);
+    }
+
+    private void addTargetsForModelValidation(ModelValidationEntry modelValidationEntry, Object defaultTarget)
+    {
+        if(modelValidationEntry.getMetaData().validationTargets().length == 1 &&
+                modelValidationEntry.getMetaData().validationTargets()[0].equals(ModelValidation.DEFAULT_TARGET))
+        {
+            modelValidationEntry.addValidationTarget(defaultTarget);
+        }
+        else
+        {
+            Object target;
+            for(String modelValidationTarget : modelValidationEntry.getMetaData().validationTargets())
+            {
+                target = resolveTarget(modelValidationEntry.getMetaDataSourceObject(), modelValidationTarget);
 
-                if(!(beanValidation.restrictGroups().length == 1 &&
-                        beanValidation.restrictGroups()[0].equals(None.class)))
+                if(target == null && this.logger.isErrorEnabled())
+                {
+                    this.logger.error("target unreachable - source class: " +
+                            modelValidationEntry.getMetaDataSourceObject().getClass().getName() +
+                            " target to resolve: " + modelValidationTarget);
+                }
+
+                modelValidationEntry.addValidationTarget(target);
+            }
+        }
+    }
+
+    private Object resolveTarget(Object metaDataSourceObject, String modelValidationTarget)
+    {
+        ELHelper elHelper = ExtValUtils.getELHelper();
+
+        if(elHelper.isELTermWellFormed(modelValidationTarget))
+        {
+            if(elHelper.isELTermValid(FacesContext.getCurrentInstance(), modelValidationTarget))
+            {
+                return elHelper.getValueOfExpression(
+                        FacesContext.getCurrentInstance(), new ValueBindingExpression(modelValidationTarget));
+            }
+            else
+            {
+                if(this.logger.isErrorEnabled())
+                {
+                    this.logger.error("an invalid binding is used: " + modelValidationTarget);
+                }
+            }
+        }
+
+        String[] properties = modelValidationTarget.split("\\.");
+
+        Object result = metaDataSourceObject;
+        for(String property : properties)
+        {
+            result = getValueOfProperty(result, property);
+
+            if(result == null)
+            {
+                return null;
+            }
+        }
+
+        return result;
+    }
+
+    @ToDo(value = Priority.HIGH, description = "move to util class - the original method is in LocalCompareStrategy")
+    protected Object getValueOfProperty(Object base, String property)
+    {
+        property = property.substring(0,1).toUpperCase() + property.substring(1, property.length());
+        Method targetMethod = ReflectionUtils.tryToGetMethod(base.getClass(), "get" + property);
+
+        if(targetMethod == null)
+        {
+            targetMethod = ReflectionUtils.tryToGetMethod(base.getClass(), "is" + property);
+        }
+
+        if(targetMethod == null)
+        {
+            throw new IllegalStateException(
+                "class " + base.getClass() + " has no public get/is " + property.toLowerCase());
+        }
+        return ReflectionUtils.tryToInvokeMethod(base, targetMethod);
+    }
+
+    private boolean isModelValidationAllowed(ModelValidation modelValidation)
+    {
+        ELHelper elHelper = ExtValUtils.getELHelper();
+
+        for(String condition : modelValidation.conditions())
+        {
+            if(elHelper.isELTermWellFormed(condition) &&
+                    elHelper.isELTermValid(FacesContext.getCurrentInstance(), condition))
+            {
+                if(Boolean.TRUE.equals(
+                        elHelper.getValueOfExpression(
+                                FacesContext.getCurrentInstance(), new ValueBindingExpression(condition))))
+                {
+                    return true;
+                }
+            }
+            else
+            {
+                if(this.logger.isErrorEnabled())
                 {
-                    restrictedGroupsForCurrentView.addAll(Arrays.asList(beanValidation.restrictGroups()));
+                    this.logger.error("an invalid condition is used: " + condition);
                 }
             }
         }
+        return false;
     }
 }

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/ExtValBeanValidationContext.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/ExtValBeanValidationContext.java?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/ExtValBeanValidationContext.java (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/ExtValBeanValidationContext.java Fri Apr 10 03:42:49 2009
@@ -20,6 +20,7 @@
 
 import org.apache.myfaces.extensions.validator.beanval.validation.message.interpolator.DefaultMessageInterpolator;
 import org.apache.myfaces.extensions.validator.beanval.validation.message.interpolator.ExtValMessageInterpolatorAdapter;
+import org.apache.myfaces.extensions.validator.beanval.validation.ModelValidationEntry;
 import org.apache.myfaces.extensions.validator.internal.ToDo;
 import org.apache.myfaces.extensions.validator.internal.Priority;
 import org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver;
@@ -27,6 +28,7 @@
 import org.apache.commons.logging.LogFactory;
 
 import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
 import javax.validation.groups.Default;
 import javax.validation.MessageInterpolator;
 import javax.validation.Validation;
@@ -56,6 +58,10 @@
     @ToDo(value = Priority.HIGH, description = "refactor to a pluggable GroupStorage")
     private Map<String, List<Class>> restrictedGroups = new HashMap<String, List<Class>>();
 
+    @ToDo(value = Priority.HIGH, description = "refactor to a pluggable GroupStorage")
+    private Map<String, List<ModelValidationEntry>> modelValidationEntries =
+            new HashMap<String, List<ModelValidationEntry>>();
+
     private ExtValBeanValidationContext()
     {
     }
@@ -80,7 +86,7 @@
 
     private String getGroupKey(String viewId, String componentId)
     {
-        return componentId == null ? viewId : viewId + ":" + componentId;
+        return componentId == null ? viewId : viewId + "@" + componentId;
     }
 
     public void addGroup(Class groupClass)
@@ -98,6 +104,37 @@
         addGroupToGroupStorage(groupClass, viewId, componentId, this.addedGroups);
     }
 
+    public void addModelValidationEntry(ModelValidationEntry modelValidationEntry)
+    {
+        addModelValidationEntry(modelValidationEntry, FacesContext.getCurrentInstance().getViewRoot().getViewId());
+    }
+
+    public void addModelValidationEntry(ModelValidationEntry modelValidationEntry, String viewId)
+    {
+        addModelValidationEntry(modelValidationEntry, viewId, null);
+    }
+
+    public void addModelValidationEntry(
+            ModelValidationEntry modelValidationEntry, String viewId, UIComponent component)
+    {
+        modelValidationEntry.setComponent(component);
+
+        String componentId = component.getClientId(FacesContext.getCurrentInstance());
+        List<ModelValidationEntry> modelValidationEntryList =
+                this.modelValidationEntries.get(getGroupKey(viewId, componentId));
+
+        if(modelValidationEntryList == null)
+        {
+            modelValidationEntryList = new ArrayList<ModelValidationEntry>();
+            this.modelValidationEntries.put(getGroupKey(viewId, componentId), modelValidationEntryList);
+        }
+
+        if(!modelValidationEntryList.contains(modelValidationEntry))
+        {
+            modelValidationEntryList.add(modelValidationEntry);
+        }
+    }
+
     public void restrictGroup(Class groupClass)
     {
         restrictGroup(groupClass, FacesContext.getCurrentInstance().getViewRoot().getViewId());
@@ -140,6 +177,7 @@
         this.addedGroups.put(getGroupKey(viewId, componentId), new ArrayList<Class>());
     }
 
+    /*
     public Class[] getGroups()
     {
         if(this.addedGroups.size() < 1)
@@ -156,12 +194,19 @@
         }
         return (Class[]) fullGroupList.toArray();
     }
+    */
 
     public Class[] getGroups(String viewId)
     {
         return getGroups(viewId, null);
     }
 
+    public Class[] getAllGroups(String viewId)
+    {
+        return getGroups(viewId, "*");
+    }
+
+    @ToDo(value = Priority.HIGH, description = "change impl. for #getAllGroups - see getModelValidationEntries")
     public Class[] getGroups(String viewId, String componentId)
     {
         if(this.addedGroups.size() < 1)
@@ -175,14 +220,14 @@
 
         //add found groups
         String key = getGroupKey(viewId, null);
-        List<Class> resultListForPage = buildResultFor(key, this.addedGroups);
+        List<Class> resultListForPage = buildGroupList(key, this.addedGroups);
 
         key = getGroupKey(viewId, componentId);
-        List<Class> resultListForComponent = buildResultFor(key, this.addedGroups);
+        List<Class> resultListForComponent = buildGroupList(key, this.addedGroups);
 
         //remove restricted groups
-        Class[] resultsForPage = filterResult(getGroupKey(viewId, null), resultListForPage);
-        Class[] resultsForComponent = filterResult(getGroupKey(viewId, componentId), resultListForComponent);
+        Class[] resultsForPage = filterGroupList(getGroupKey(viewId, null), resultListForPage);
+        Class[] resultsForComponent = filterGroupList(getGroupKey(viewId, componentId), resultListForComponent);
 
         if(resultsForPage.length == 0)
         {
@@ -205,15 +250,86 @@
         return mergeResults(resultsForPage, resultsForComponent);
     }
 
-    private List<Class> buildResultFor(String key, Map<String, List<Class>> groupStorage)
+    public List<ModelValidationEntry> getModelValidationEntries(String viewId)
+    {
+        return getModelValidationEntries(viewId, null);
+    }
+
+    public List<ModelValidationEntry> getAllModelValidationEntries(String viewId)
+    {
+        return getModelValidationEntries(viewId, "*");
+    }
+
+    public List<ModelValidationEntry> getModelValidationEntries(String viewId, String componentId)
+    {
+        if(this.modelValidationEntries.size() < 1)
+        {
+            return new ArrayList<ModelValidationEntry>();
+        }
+
+        //add found groups
+        String key;
+        List<ModelValidationEntry> resultListForPage = null;
+
+        if(!"*".equals(componentId))
+        {
+            key = getGroupKey(viewId, null);
+            resultListForPage =
+                    buildModelValidationEntryList(key, this.modelValidationEntries);
+        }
+
+        key = getGroupKey(viewId, componentId);
+        List<ModelValidationEntry> resultListForComponent =
+                buildModelValidationEntryList(key, this.modelValidationEntries);
+
+        if(resultListForPage == null || resultListForPage.isEmpty())
+        {
+            return resultListForComponent;
+        }
+        else if(resultListForComponent.isEmpty())
+        {
+            return resultListForPage;
+        }
+
+        //merge results
+        List<ModelValidationEntry> mergedResult = new ArrayList<ModelValidationEntry>();
+        mergedResult.addAll(resultListForPage);
+        mergedResult.addAll(resultListForComponent);
+        return mergedResult;
+    }
+
+    private List<Class> buildGroupList(String key, Map<String, List<Class>> groupStorage)
     {
         List<Class> list = groupStorage.get(key);
         return (list != null) ? list : new ArrayList<Class>();
     }
 
-    private Class[] filterResult(String key, List<Class> addedGroups)
+    private List<ModelValidationEntry> buildModelValidationEntryList(
+            String key, Map<String, List<ModelValidationEntry>> groupStorage)
+    {
+        List<ModelValidationEntry> list;
+
+        if(key != null && key.endsWith("*"))
+        {
+            list = new ArrayList<ModelValidationEntry>();
+            for(Map.Entry<String,List<ModelValidationEntry>> entry : groupStorage.entrySet())
+            {
+                if(entry.getKey().substring(0, entry.getKey().indexOf("@"))
+                        .equals(key.substring(0, key.indexOf("@"))))
+                {
+                    list.addAll(entry.getValue());
+                }
+            }
+            return list;
+        }
+
+        list = groupStorage.get(key);
+        return (list != null) ? list : new ArrayList<ModelValidationEntry>();
+    }
+
+    private Class[] filterGroupList(String key, List<Class> addedGroups)
     {
-        List<Class> restrictedGroups = buildResultFor(key, this.restrictedGroups);
+        List<Class> restrictedGroups = buildGroupList(key, this.restrictedGroups);
         List<Class> results = new ArrayList<Class>();
 
         for(Class currentGroup : addedGroups)

Copied: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/BeanValidation.java (from r763761, myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/BeanValidation.java)
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/BeanValidation.java?p2=myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/BeanValidation.java&p1=myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/BeanValidation.java&r1=763761&r2=763865&rev=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/BeanValidation.java (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/BeanValidation.java Fri Apr 10 03:42:49 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.myfaces.extensions.validator.beanval.annotation.group;
+package org.apache.myfaces.extensions.validator.beanval.annotation;
 
 import org.apache.myfaces.extensions.validator.internal.UsageInformation;
 import org.apache.myfaces.extensions.validator.internal.UsageCategory;
@@ -41,12 +41,12 @@
 {
     String[] viewIds() default "*";
 
-    boolean useModelValidation() default false;
-
     Class[] useGroups() default Default.class;
 
-    Class[] restrictGroups() default None.class;
+    Class[] restrictGroups() default NoRestrictionGroup.class;
 
+    ModelValidation modelValidation() default @ModelValidation;
+    
     @Retention(RUNTIME) static @interface List
     {
         BeanValidation[] value();

Copied: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/GroupValidationKeys.java (from r763245, myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/GroupValidationKeys.java)
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/GroupValidationKeys.java?p2=myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/GroupValidationKeys.java&p1=myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/GroupValidationKeys.java&r1=763245&r2=763865&rev=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/GroupValidationKeys.java (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/GroupValidationKeys.java Fri Apr 10 03:42:49 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.myfaces.extensions.validator.beanval.annotation.group;
+package org.apache.myfaces.extensions.validator.beanval.annotation;
 
 import org.apache.myfaces.extensions.validator.internal.UsageInformation;
 import org.apache.myfaces.extensions.validator.internal.UsageCategory;

Added: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/ModelValidation.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/ModelValidation.java?rev=763865&view=auto
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/ModelValidation.java (added)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/ModelValidation.java Fri Apr 10 03:42:49 2009
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.annotation;
+
+import org.apache.myfaces.extensions.validator.internal.UsageInformation;
+import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.FIELD;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.3
+ */
+
+@Target({METHOD, FIELD, TYPE})
+@Retention(RUNTIME)
+@UsageInformation(UsageCategory.API)
+public @interface ModelValidation
+{
+    public static final String DEFAULT_TARGET = "base";
+
+    boolean isActive() default false;
+
+    boolean displayInline() default false;
+
+    @ToDo(value = Priority.HIGH, description = "support property chain syntax")
+    String[] conditions() default "#{true}";
+
+    String[] validationTargets() default DEFAULT_TARGET;
+}
\ No newline at end of file

Copied: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/NoRestrictionGroup.java (from r763744, myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/None.java)
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/NoRestrictionGroup.java?p2=myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/NoRestrictionGroup.java&p1=myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/None.java&r1=763744&r2=763865&rev=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/group/None.java (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/NoRestrictionGroup.java Fri Apr 10 03:42:49 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.myfaces.extensions.validator.beanval.annotation.group;
+package org.apache.myfaces.extensions.validator.beanval.annotation;
 
 import org.apache.myfaces.extensions.validator.internal.UsageInformation;
 import org.apache.myfaces.extensions.validator.internal.UsageCategory;
@@ -29,6 +29,6 @@
  */
 
 @UsageInformation(UsageCategory.INTERNAL)
-public interface None
+public interface NoRestrictionGroup
 {
 }
\ No newline at end of file

Modified: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/extractor/DefaultGroupControllerScanningExtractor.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/extractor/DefaultGroupControllerScanningExtractor.java?rev=763865&r1=763864&r2=763865&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/extractor/DefaultGroupControllerScanningExtractor.java (original)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/annotation/extractor/DefaultGroupControllerScanningExtractor.java Fri Apr 10 03:42:49 2009
@@ -22,7 +22,7 @@
 import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
 import org.apache.myfaces.extensions.validator.core.property.DefaultPropertyInformation;
 import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
-import org.apache.myfaces.extensions.validator.beanval.annotation.group.GroupValidationKeys;
+import org.apache.myfaces.extensions.validator.beanval.annotation.GroupValidationKeys;
 
 import javax.faces.context.FacesContext;
 

Added: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationEntry.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationEntry.java?rev=763865&view=auto
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationEntry.java (added)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationEntry.java Fri Apr 10 03:42:49 2009
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.validation;
+
+import org.apache.myfaces.extensions.validator.beanval.annotation.ModelValidation;
+
+import javax.faces.component.UIComponent;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.3
+ */
+public class ModelValidationEntry
+{
+    private UIComponent component;
+    private ModelValidation metaData;
+    private List<Class> groups = new ArrayList<Class>();
+    private List<Object> validationTargets = new ArrayList<Object>();
+    private Object metaDataSourceObject;
+
+    public void addGroup(Class group)
+    {
+        if(!this.groups.contains(group))
+        {
+            if(!(this.groups instanceof ArrayList))
+            {
+                List<Class> newGroupList = new ArrayList<Class>();
+
+                for(Class currentClass : this.groups)
+                {
+                    newGroupList.add(currentClass);
+                }
+                this.groups = newGroupList;
+            }
+
+            this.groups.add(group);
+        }
+    }
+
+    public void removeGroup(Class group)
+    {
+        this.groups.remove(group);
+    }
+
+    public void addValidationTarget(Object target)
+    {
+        if(!this.validationTargets.contains(target))
+        {
+            if(!(this.validationTargets instanceof ArrayList))
+            {
+                List<Object> validationTargetList = new ArrayList<Object>();
+
+                for(Object currentTarget : this.validationTargets)
+                {
+                    validationTargetList.add(currentTarget);
+                }
+                this.validationTargets = validationTargetList;
+            }
+
+            this.validationTargets.add(target);
+        }
+    }
+
+    /*
+     * generated
+     */
+    public UIComponent getComponent()
+    {
+        return component;
+    }
+
+    public void setComponent(UIComponent component)
+    {
+        this.component = component;
+    }
+
+    public ModelValidation getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(ModelValidation metaData)
+    {
+        this.metaData = metaData;
+    }
+
+    public Class[] getGroups()
+    {
+        return this.groups.toArray(new Class[this.groups.size()]);
+    }
+
+    public void setGroups(List<Class> groups)
+    {
+        this.groups = groups;
+    }
+
+    public List<Object> getValidationTargets()
+    {
+        return validationTargets;
+    }
+
+    public void setValidationTargets(List<Object> validationTargets)
+    {
+        this.validationTargets = new ArrayList<Object>();
+    }
+
+    public Object getMetaDataSourceObject()
+    {
+        return metaDataSourceObject;
+    }
+
+    public void setMetaDataSourceObject(Object metaDataSourceObject)
+    {
+        this.metaDataSourceObject = metaDataSourceObject;
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass())
+        {
+            return false;
+        }
+
+        ModelValidationEntry that = (ModelValidationEntry) o;
+
+        if (component != null ? !component.equals(that.component) : that.component != null)
+        {
+            return false;
+        }
+        if (!groups.equals(that.groups))
+        {
+            return false;
+        }
+        if (!validationTargets.equals(that.validationTargets))
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = component != null ? component.hashCode() : 0;
+        result = 31 * result + groups.hashCode();
+        result = 31 * result + validationTargets.hashCode();
+        return result;
+    }
+}

Added: myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationPhaseListener.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationPhaseListener.java?rev=763865&view=auto
==============================================================================
--- myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationPhaseListener.java (added)
+++ myfaces/extensions/validator/branches/beanval_integration/trunk/validation-modules/bean-validation/src/main/java/org/apache/myfaces/extensions/validator/beanval/validation/ModelValidationPhaseListener.java Fri Apr 10 03:42:49 2009
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.extensions.validator.beanval.validation;
+
+import org.apache.myfaces.extensions.validator.beanval.ExtValBeanValidationContext;
+import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.event.PhaseListener;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.validation.ConstraintViolation;
+import javax.validation.ValidatorFactory;
+import javax.validation.Validation;
+import java.util.List;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.3
+ */
+public class ModelValidationPhaseListener implements PhaseListener
+{
+    private static final long serialVersionUID = -3482233893186708878L;
+
+    protected final Log logger = LogFactory.getLog(getClass());
+    private ValidatorFactory validationFactory = Validation.buildDefaultValidatorFactory();
+
+    public void afterPhase(PhaseEvent phaseEvent)
+    {
+        if (logger.isTraceEnabled())
+        {
+            logger.trace("jsr303 start model validation");
+        }
+
+        List<ModelValidationEntry> modelValidationEntries = ExtValBeanValidationContext.getCurrentInstance()
+                .getAllModelValidationEntries(FacesContext.getCurrentInstance().getViewRoot().getViewId());
+
+        List processedValidationTargets = new ArrayList();
+
+        for(ModelValidationEntry modelValidationEntry : modelValidationEntries)
+        {
+            processModelValidation(modelValidationEntry, processedValidationTargets);
+        }
+
+        FacesContext.getCurrentInstance().renderResponse();
+        
+        if (logger.isTraceEnabled())
+        {
+            logger.trace("jsr303 validation finished");
+        }
+    }
+
+    private void processModelValidation(ModelValidationEntry modelValidationEntry, List processedValidationTargets)
+    {
+        for(Object validationTarget : modelValidationEntry.getValidationTargets())
+        {
+            if(processedValidationTargets.contains(validationTarget) &&
+                    !modelValidationEntry.getMetaData().displayInline())
+            {
+                continue;
+            }
+
+            if(!processedValidationTargets.contains(validationTarget))
+            {
+                processedValidationTargets.add(validationTarget);
+            }
+
+            Set<ConstraintViolation<Object>> violations = this.validationFactory.usingContext()
+                    .messageInterpolator(ExtValBeanValidationContext.getCurrentInstance().getMessageInterpolator())
+                    .getValidator()
+                    .validate(validationTarget, modelValidationEntry.getGroups());
+
+            if (violations != null && violations.size() > 0)
+            {
+                //jsf 2.0 is able to display multiple messages per component - so process all violations
+                //jsf < 2.0 will just use the first one (it's only a little overhead)
+                Iterator violationsIterator = violations.iterator();
+                ConstraintViolation constraintViolation;
+                while(violationsIterator.hasNext())
+                {
+                    constraintViolation = (ConstraintViolation)violationsIterator.next();
+                    if(modelValidationEntry.getMetaData().displayInline())
+                    {
+                        processConstraintViolation(constraintViolation, modelValidationEntry, validationTarget, true);
+                    }
+                    else
+                    {
+                        processConstraintViolation(constraintViolation, modelValidationEntry, validationTarget, false);
+                    }
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings({"ThrowableInstanceNeverThrown"})
+    @ToDo(value = Priority.HIGH, description = "use ExtValUtils#createFacesMessage" +
+            "check ExtValUtils#executeAfterThrowingInterceptors")
+    private void processConstraintViolation(ConstraintViolation violation,
+                                                  ModelValidationEntry modelValidationEntry,
+                                                  Object validationTarget,
+                                                  boolean displayAtComponent)
+    {
+        String violationMessage = violation.getMessage();
+
+        ValidatorException validatorException = new ValidatorException(
+                new FacesMessage(FacesMessage.SEVERITY_ERROR, violationMessage, violationMessage));
+
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        UIComponent uiComponent = null;
+        String clientId = null;
+
+        if(displayAtComponent)
+        {
+            uiComponent = modelValidationEntry.getComponent();
+            clientId = modelValidationEntry.getComponent().getClientId(facesContext);
+        }
+
+        ExtValUtils.executeAfterThrowingInterceptors(
+                uiComponent,
+                null,
+                validationTarget,
+                validatorException,
+                null);
+
+        if (violationMessage.equals(validatorException.getFacesMessage().getSummary()) ||
+                violationMessage.equals(validatorException.getFacesMessage().getDetail()))
+        {
+            facesContext.addMessage(clientId,
+                    new FacesMessage(FacesMessage.SEVERITY_ERROR, violationMessage, violationMessage));
+        }
+        else
+        {
+            facesContext.addMessage(clientId, validatorException.getFacesMessage());
+        }
+    }
+
+    public void beforePhase(PhaseEvent phaseEvent)
+    {
+        //do nothing
+    }
+
+    public PhaseId getPhaseId()
+    {
+        return PhaseId.UPDATE_MODEL_VALUES;
+    }
+}
\ No newline at end of file