You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/10/31 17:38:28 UTC

svn commit: r1195559 - in /myfaces/core/branches/2.0.x/impl/src: main/java/org/apache/myfaces/view/facelets/ main/java/org/apache/myfaces/view/facelets/impl/ main/java/org/apache/myfaces/view/facelets/tag/jsf/ test/java/org/apache/myfaces/view/facelets...

Author: lu4242
Date: Mon Oct 31 16:38:27 2011
New Revision: 1195559

URL: http://svn.apache.org/viewvc?rev=1195559&view=rev
Log:
MYFACES-3259 Custom Validator tag attributes are not configured when used with default tag handler in wrapping mode

Added:
    myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/core/testValidateBeanDisableDoubleNesting.xhtml   (with props)
Modified:
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ValidatorTagHandlerDelegate.java
    myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/core/ValidateBeanTestCase.java

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java?rev=1195559&r1=1195558&r2=1195559&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java Mon Oct 31 16:38:27 2011
@@ -20,11 +20,13 @@ package org.apache.myfaces.view.facelets
 
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import javax.faces.component.UIComponent;
 import javax.faces.component.UniqueIdVendor;
 import javax.faces.context.FacesContext;
 import javax.faces.view.AttachedObjectHandler;
+import javax.faces.view.EditableValueHolderAttachedObjectHandler;
 import javax.faces.view.facelets.FaceletContext;
 
 /**
@@ -134,12 +136,14 @@ abstract public class FaceletComposition
      * @return
      * @since 2.0.1
      */
+    @Deprecated
     public abstract String getFirstValidationGroupFromStack();
     
     /**
      * Removes top of stack.
      * @since 2.0.1
      */
+    @Deprecated
     public abstract void popValidationGroupsToStack();
     
     /**
@@ -147,6 +151,7 @@ abstract public class FaceletComposition
      * @param validationGroups
      * @since 2.0.1
      */
+    @Deprecated
     public abstract void pushValidationGroupsToStack(String validationGroups);
     
     /**
@@ -154,12 +159,14 @@ abstract public class FaceletComposition
      * @return
      * @since 2.0.1
      */
+    @Deprecated
     public abstract Iterator<String> getExcludedValidatorIds();
     
     /**
      * Removes top of stack.
      * @since 2.0.1
      */
+    @Deprecated
     public abstract void popExcludedValidatorIdToStack();
     
     /**
@@ -167,6 +174,7 @@ abstract public class FaceletComposition
      * @param validatorId
      * @since 2.0.1
      */
+    @Deprecated
     public abstract void pushExcludedValidatorIdToStack(String validatorId);
     
     /**
@@ -174,6 +182,7 @@ abstract public class FaceletComposition
      * @return
      * @since 2.0.1
      */
+    @Deprecated
     public abstract Iterator<String> getEnclosingValidatorIds();
     
     /**
@@ -187,9 +196,35 @@ abstract public class FaceletComposition
      * @param validatorId
      * @since 2.0.1
      */
+    @Deprecated
     public abstract void pushEnclosingValidatorIdToStack(String validatorId);
     
     /**
+     * Pushes validatorId to the stack of all enclosing validatorIds.
+     * 
+     * @param validatorId
+     * @param attachedObjectHandler
+     * @since 2.0.8
+     */
+    public abstract void pushEnclosingValidatorIdToStack(String validatorId, EditableValueHolderAttachedObjectHandler attachedObjectHandler);
+
+    /**
+     * Gets all validationIds with its associated EditableValueHolderAttachedObjectHandler from the stack.
+     * 
+     * @return
+     * @since 2.0.8
+     */
+    public abstract Iterator<Map.Entry<String, EditableValueHolderAttachedObjectHandler>> getEnclosingValidatorIdsAndHandlers();
+    
+    /**
+     * 
+     * @param id
+     * @return
+     * @since 2.0.8
+     */
+    public abstract boolean containsEnclosingValidatorId(String id);
+    
+    /**
      * Check if this build is being refreshed, adding transient components
      * and adding/removing components under c:if or c:forEach or not.
      * 

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java?rev=1195559&r1=1195558&r2=1195559&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java Mon Oct 31 16:38:27 2011
@@ -18,6 +18,19 @@
  */
 package org.apache.myfaces.view.facelets.impl;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UniqueIdVendor;
+import javax.faces.context.FacesContext;
+import javax.faces.view.AttachedObjectHandler;
+import javax.faces.view.EditableValueHolderAttachedObjectHandler;
+
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 import org.apache.myfaces.shared.util.WebConfigParamUtils;
 import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
@@ -26,17 +39,6 @@ import org.apache.myfaces.view.facelets.
 import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 
-import javax.faces.component.UIComponent;
-import javax.faces.component.UniqueIdVendor;
-import javax.faces.context.FacesContext;
-import javax.faces.view.AttachedObjectHandler;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
 /**
  * @since 2.0.1
  * @author Leonardo Uribe (latest modification by $Author$)
@@ -82,7 +84,7 @@ public class FaceletCompositionContextIm
     
     private LinkedList<String> _excludedValidatorIdsStack;
     
-    private LinkedList<String> _enclosingValidatorIdsStack;
+    private LinkedList<Map.Entry<String, EditableValueHolderAttachedObjectHandler>> _enclosingValidatorIdsStack;
     
     private Boolean _isRefreshingTransientBuild;
     
@@ -303,7 +305,7 @@ public class FaceletCompositionContextIm
     {
         if (_enclosingValidatorIdsStack != null && !_enclosingValidatorIdsStack.isEmpty())
         {
-            return _enclosingValidatorIdsStack.iterator(); 
+            return new KeyEntryIterator<String, EditableValueHolderAttachedObjectHandler>(_enclosingValidatorIdsStack.iterator()); 
         }
         return null;
     }
@@ -329,12 +331,42 @@ public class FaceletCompositionContextIm
     @Override
     public void pushEnclosingValidatorIdToStack(String validatorId)
     {
+        pushEnclosingValidatorIdToStack(validatorId, null);
+    }
+    
+    @Override
+    public void pushEnclosingValidatorIdToStack(String validatorId, EditableValueHolderAttachedObjectHandler attachedObjectHandler)
+    {
         if (_enclosingValidatorIdsStack == null)
         {
-            _enclosingValidatorIdsStack = new LinkedList<String>();
+            _enclosingValidatorIdsStack = new LinkedList<Map.Entry<String, EditableValueHolderAttachedObjectHandler>>();
         }
 
-        _enclosingValidatorIdsStack.addFirst(validatorId);
+        _enclosingValidatorIdsStack.addFirst(new SimpleEntry<String, EditableValueHolderAttachedObjectHandler>(validatorId, attachedObjectHandler));
+    }
+
+    public Iterator<Map.Entry<String, EditableValueHolderAttachedObjectHandler>> getEnclosingValidatorIdsAndHandlers()
+    {
+        if (_enclosingValidatorIdsStack != null && !_enclosingValidatorIdsStack.isEmpty())
+        {
+            return _enclosingValidatorIdsStack.iterator(); 
+        }
+        return null;
+    }
+    
+    public boolean containsEnclosingValidatorId(String id)
+    {
+        if (_enclosingValidatorIdsStack != null && !_enclosingValidatorIdsStack.isEmpty())
+        {
+            for (Map.Entry<String, EditableValueHolderAttachedObjectHandler> entry : _enclosingValidatorIdsStack)
+            {
+                if (entry.getKey().equals(id))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     @Override
@@ -695,4 +727,105 @@ public class FaceletCompositionContextIm
         _sectionUniqueIdCounter.endUniqueIdSection();
         _sectionUniqueComponentIdCounter.endUniqueIdSection();
     }
+    
+    private static class KeyEntryIterator<K, V> implements Iterator<K>
+    {
+        private Iterator<Map.Entry<K, V>> _delegateIterator;
+        
+        public KeyEntryIterator(Iterator<Map.Entry<K, V>> delegate)
+        {
+            _delegateIterator = delegate;
+        }
+        
+        public boolean hasNext()
+        {
+            if (_delegateIterator != null)
+            {
+                return _delegateIterator.hasNext();
+            }
+            return false;
+        }
+
+        public K next()
+        {
+            if (_delegateIterator != null)
+            {
+                return _delegateIterator.next().getKey();
+            }
+            return null;
+        }
+
+        public void remove()
+        {
+            if (_delegateIterator != null)
+            {
+                _delegateIterator.remove();
+            }
+        }
+        
+    }
+    
+    private static class SimpleEntry<K, V> implements Map.Entry<K, V>
+    {
+        private final K _key;
+        private final V _value;
+
+        public SimpleEntry(K key, V value)
+        {
+            _key = key;
+            _value = value;
+        }
+        
+        public K getKey()
+        {
+            return _key;
+        }
+
+        public V getValue()
+        {
+            return _value;
+        }
+
+        @Override
+        public int hashCode()
+        {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((_key == null) ? 0 : _key.hashCode());
+            result = prime * result + ((_value == null) ? 0 : _value.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            SimpleEntry other = (SimpleEntry) obj;
+            if (_key == null)
+            {
+                if (other._key != null)
+                    return false;
+            }
+            else if (!_key.equals(other._key))
+                return false;
+            if (_value == null)
+            {
+                if (other._value != null)
+                    return false;
+            }
+            else if (!_value.equals(other._value))
+                return false;
+            return true;
+        }
+
+        public V setValue(V value)
+        {
+            throw new UnsupportedOperationException();
+        }
+    }
 }

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java?rev=1195559&r1=1195558&r2=1195559&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentTagHandlerDelegate.java Mon Oct 31 16:38:27 2011
@@ -19,6 +19,7 @@
 package org.apache.myfaces.view.facelets.tag.jsf;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -38,6 +39,7 @@ import javax.faces.component.behavior.Cl
 import javax.faces.context.FacesContext;
 import javax.faces.validator.BeanValidator;
 import javax.faces.validator.Validator;
+import javax.faces.view.EditableValueHolderAttachedObjectHandler;
 import javax.faces.view.facelets.ComponentConfig;
 import javax.faces.view.facelets.ComponentHandler;
 import javax.faces.view.facelets.FaceletContext;
@@ -46,6 +48,7 @@ import javax.faces.view.facelets.TagAttr
 import javax.faces.view.facelets.TagException;
 import javax.faces.view.facelets.TagHandler;
 import javax.faces.view.facelets.TagHandlerDelegate;
+import javax.faces.view.facelets.ValidatorHandler;
 
 import org.apache.myfaces.util.ExternalSpecifications;
 import org.apache.myfaces.view.facelets.AbstractFaceletContext;
@@ -420,7 +423,7 @@ public class ComponentTagHandlerDelegate
             {
                 // add default validators here, because this feature 
                 // is only available in facelets (see MYFACES-2362 for details)
-                addDefaultValidators(mctx, facesContext, (EditableValueHolder) c);
+                addEnclosingAndDefaultValidators(ctx, mctx, facesContext, (EditableValueHolder) c);
             }
         }
         
@@ -606,34 +609,34 @@ public class ComponentTagHandlerDelegate
      * @param mctx the AbstractFaceletContext
      * @param component The EditableValueHolder to which the validators should be added
      */
-    private void addDefaultValidators(FaceletCompositionContext mctx, FacesContext context, 
+    private void addEnclosingAndDefaultValidators(FaceletContext ctx, FaceletCompositionContext mctx, FacesContext context, 
                                       EditableValueHolder component)
     {
-        // add all defaultValidators
-        Map<String, String> defaultValidators = context.getApplication().getDefaultValidatorInfo();
-        if (defaultValidators != null && defaultValidators.size() != 0)
+        // add all enclosing validators, because they have precedence over default validators.
+        Iterator<Map.Entry<String, EditableValueHolderAttachedObjectHandler>> enclosingValidatorIds = mctx.getEnclosingValidatorIdsAndHandlers();
+        if (enclosingValidatorIds != null)
         {
-            for (Map.Entry<String, String> entry : defaultValidators.entrySet())
+            while (enclosingValidatorIds.hasNext())
             {
-                addDefaultValidator( mctx, context, component, entry.getKey(), entry.getValue());
+                Map.Entry<String, EditableValueHolderAttachedObjectHandler> entry = enclosingValidatorIds.next();
+                addEnclosingValidator(ctx, mctx, context, component, entry.getKey(), entry.getValue());
             }
         }
-        // add all enclosing validators
-        Iterator<String> enclosingValidatorIds = mctx.getEnclosingValidatorIds();
-        if (enclosingValidatorIds != null)
+        // add all defaultValidators
+        Map<String, String> defaultValidators = context.getApplication().getDefaultValidatorInfo();
+        if (defaultValidators != null && defaultValidators.size() != 0)
         {
-            while (enclosingValidatorIds.hasNext())
+            for (Map.Entry<String, String> entry : defaultValidators.entrySet())
             {
-                String validatorId = enclosingValidatorIds.next();
-                if (!defaultValidators.containsKey(validatorId))
+                if (!mctx.containsEnclosingValidatorId(entry.getKey()))
                 {
-                    addDefaultValidator(mctx, context, component, validatorId, null);
+                    addDefaultValidator(ctx, mctx, context, component, entry.getKey(), entry.getValue());
                 }
             }
         }
     }
-    
-    private void addDefaultValidator(FaceletCompositionContext mctx, FacesContext context, 
+
+    private void addDefaultValidator(FaceletContext ctx, FaceletCompositionContext mctx, FacesContext context, 
             EditableValueHolder component, String validatorId, String validatorClassName)
     {
         Validator enclosingValidator = null;
@@ -662,7 +665,7 @@ public class ComponentTagHandlerDelegate
         
         if (validator == null)
         {
-            if (shouldAddDefaultValidator(mctx, context, component, validatorId))
+            if (shouldAddDefaultValidator(ctx, mctx, context, component, validatorId))
             {
                 if (enclosingValidator != null)
                 {
@@ -696,24 +699,24 @@ public class ComponentTagHandlerDelegate
             {
                 // no validationGroups available
                 // --> get the validationGroups from the stack
-                String stackGroup = mctx.getFirstValidationGroupFromStack();
-                if (stackGroup != null)
-                {
-                    validationGroups = stackGroup;
-                }
-                else
-                {
+                //String stackGroup = mctx.getFirstValidationGroupFromStack();
+                //if (stackGroup != null)
+                //{
+                //    validationGroups = stackGroup;
+                //}
+                //else
+                //{
                     // no validationGroups on the stack
                     // --> set the default validationGroup
                     validationGroups = javax.validation.groups.Default.class.getName();
-                }
+                //}
                 beanValidator.setValidationGroups(validationGroups);
             }
         }
     }
 
     /**
-     * Determine if the default Validator with the given validatorId should be added.
+     * Determine if the validator with the given validatorId should be added.
      *
      * @param validatorId The validatorId.
      * @param facesContext The FacesContext.
@@ -722,7 +725,7 @@ public class ComponentTagHandlerDelegate
      * @return true if the Validator should be added, false otherwise.
      */
     @SuppressWarnings("unchecked")
-    private boolean shouldAddDefaultValidator(FaceletCompositionContext mctx,
+    private boolean shouldAddDefaultValidator(FaceletContext ctx, FaceletCompositionContext mctx,
                                               FacesContext facesContext,
                                               EditableValueHolder component, 
                                               String validatorId)
@@ -743,6 +746,7 @@ public class ComponentTagHandlerDelegate
         }
         
         // check if the validatorId is on the exclusion list on the stack
+        /*
         Iterator<String> it = mctx.getExcludedValidatorIds();
         if (it != null)
         {            
@@ -754,6 +758,22 @@ public class ComponentTagHandlerDelegate
                     return false;
                 }
             }
+        }*/
+        Iterator<Map.Entry<String, EditableValueHolderAttachedObjectHandler>> enclosingValidatorIds = mctx.getEnclosingValidatorIdsAndHandlers();
+        if (enclosingValidatorIds != null)
+        {
+            while (enclosingValidatorIds.hasNext())
+            {
+                Map.Entry<String, EditableValueHolderAttachedObjectHandler> entry = enclosingValidatorIds.next();
+                boolean validatorIdAvailable = entry.getKey() != null && !"".equals(entry.getKey());
+                if (validatorIdAvailable && entry.getKey().equals(validatorId))
+                {
+                    if (((ValidatorHandler)((FacesWrapper<ValidatorHandler>)entry.getValue()).getWrapped()).isDisabled(ctx))
+                    {
+                        return false;
+                    }
+                }
+            }
         }
         
         // Some extra rules are required for Bean Validation.
@@ -774,4 +794,106 @@ public class ComponentTagHandlerDelegate
         // By default, all default validators should be added
         return true;
     }
+
+    private void addEnclosingValidator(FaceletContext ctx, FaceletCompositionContext mctx, FacesContext context, 
+            EditableValueHolder component, String validatorId, EditableValueHolderAttachedObjectHandler attachedObjectHandler)
+    {
+        if (shouldAddEnclosingValidator(mctx, context, component, validatorId))
+        {
+            if (attachedObjectHandler != null)
+            {
+                attachedObjectHandler.applyAttachedObject(context, (UIComponent) component);
+            }
+            else
+            {
+                Validator validator = null;
+                // create it
+                validator = context.getApplication().createValidator(validatorId);
+
+                // special things to configure for a BeanValidator
+                if (validator instanceof BeanValidator)
+                {
+                    BeanValidator beanValidator = (BeanValidator) validator;
+                    
+                    // check the validationGroups
+                    String validationGroups =  beanValidator.getValidationGroups();
+                    if (validationGroups == null 
+                            || validationGroups.matches(BeanValidator.EMPTY_VALIDATION_GROUPS_PATTERN))
+                    {
+                        // no validationGroups available
+                        // --> get the validationGroups from the stack
+                        //String stackGroup = mctx.getFirstValidationGroupFromStack();
+                        //if (stackGroup != null)
+                        //{
+                        //    validationGroups = stackGroup;
+                        //}
+                        //else
+                        //{
+                            // no validationGroups on the stack
+                            // --> set the default validationGroup
+                            validationGroups = javax.validation.groups.Default.class.getName();
+                        //}
+                        beanValidator.setValidationGroups(validationGroups);
+                    }
+                }
+                
+                // add the validator to the component
+                component.addValidator(validator);
+            }
+        }
+    }
+
+    /**
+     * Determine if the validator with the given validatorId should be added.
+     * 
+     * The difference here with shouldAddEnclosingValidator is the inner one has
+     * precedence over the outer one, so a disable="true" over the same outer 
+     * validator, the inner one should ignore this condition. 
+     * 
+     * @param mctx
+     * @param facesContext
+     * @param component
+     * @param validatorId
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    private boolean shouldAddEnclosingValidator(FaceletCompositionContext mctx,
+            FacesContext facesContext,
+            EditableValueHolder component, 
+            String validatorId)
+    {
+        // check if the validatorId is on the exclusion list on the component
+        List<String> exclusionList = (List<String>) ((UIComponent) component)
+                .getAttributes()
+                .get(ValidatorTagHandlerDelegate.VALIDATOR_ID_EXCLUSION_LIST_KEY);
+        if (exclusionList != null)
+        {
+            for (String excludedId : exclusionList)
+            {
+                if (excludedId.equals(validatorId))
+                {
+                    return false;
+                }
+            }
+        }
+
+        // Some extra rules are required for Bean Validation.
+        if (validatorId.equals(BeanValidator.VALIDATOR_ID))
+        {
+            if (!ExternalSpecifications.isBeanValidationAvailable())
+            {
+                // the BeanValidator was added as a default-validator, but
+                // bean validation is not available on the classpath.
+                // --> log a warning about this scenario.
+                log.log(Level.WARNING,
+                        "Bean validation is not available on the "
+                                + "classpath, thus the BeanValidator will not be added for "
+                                + "the component " + component);
+                return false;
+            }
+        }
+
+        // By default, all default validators should be added
+        return true;
+    }
 }

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ValidatorTagHandlerDelegate.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ValidatorTagHandlerDelegate.java?rev=1195559&r1=1195558&r2=1195559&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ValidatorTagHandlerDelegate.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ValidatorTagHandlerDelegate.java Mon Oct 31 16:38:27 2011
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import javax.el.ValueExpression;
+import javax.faces.FacesWrapper;
 import javax.faces.component.EditableValueHolder;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
@@ -53,7 +54,7 @@ import org.apache.myfaces.view.facelets.
  *
  * @since 2.0
  */
-public class ValidatorTagHandlerDelegate extends TagHandlerDelegate implements EditableValueHolderAttachedObjectHandler
+public class ValidatorTagHandlerDelegate extends TagHandlerDelegate implements EditableValueHolderAttachedObjectHandler, FacesWrapper<ValidatorHandler>
 {
     
     /**
@@ -108,7 +109,7 @@ public class ValidatorTagHandlerDelegate
             // So I use the same way as f:ajax for this problem. -=Jakob Korherr=-
             
             String validatorId = _delegate.getValidatorConfig().getValidatorId();
-            
+            /*
             boolean disabled = _delegate.isDisabled(ctx);
             if (disabled)
             {
@@ -131,37 +132,37 @@ public class ValidatorTagHandlerDelegate
                 }
             }
             else
-            {
+            {*/
                 // the validator is enabled 
                 // --> add the validation groups and the validatorId to the stack
-                String groups = getValidationGroups(ctx);
+                //String groups = getValidationGroups(ctx);
                 // spec: don't save the validation groups string if it is null or empty string
-                boolean groupsAvailable = groups != null 
-                        && !groups.matches(BeanValidator.EMPTY_VALIDATION_GROUPS_PATTERN);
-                try
-                {
-                    if (groupsAvailable)
-                    {
-                        mctx.pushValidationGroupsToStack(groups);
-                    }
+                //boolean groupsAvailable = groups != null 
+                        //&& !groups.matches(BeanValidator.EMPTY_VALIDATION_GROUPS_PATTERN);
+                //try
+                //{
+                    //if (groupsAvailable)
+                    //{
+                    //    mctx.pushValidationGroupsToStack(groups);
+                    //}
                     try
                     {
-                        mctx.pushEnclosingValidatorIdToStack(validatorId);
+                        mctx.pushEnclosingValidatorIdToStack(validatorId, this);
                         _delegate.getValidatorConfig().getNextHandler().apply(ctx, parent);
                     }
                     finally
                     {
                         mctx.popEnclosingValidatorIdToStack();
                     }
-                }
-                finally
-                {
-                    if (groupsAvailable)
-                    {
-                        mctx.popValidationGroupsToStack();
-                    }
-                }
-            }
+                //}
+                //finally
+                //{
+                    //if (groupsAvailable)
+                    //{
+                        //mctx.popValidationGroupsToStack();
+                    //}
+                //}
+            /*}*/
         }
         else
         {
@@ -306,4 +307,9 @@ public class ValidatorTagHandlerDelegate
         }
     }
 
+    public ValidatorHandler getWrapped()
+    {
+        return _delegate;
+    }
+
 }

Modified: myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/core/ValidateBeanTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/core/ValidateBeanTestCase.java?rev=1195559&r1=1195558&r2=1195559&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/core/ValidateBeanTestCase.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/core/ValidateBeanTestCase.java Mon Oct 31 16:38:27 2011
@@ -80,11 +80,15 @@ public class ValidateBeanTestCase extend
     @SuppressWarnings("unchecked")
     private <T> T _getValidator(UIInput input, Class<T> validatorClass)
     {
-        for (Validator validator : input.getValidators())
+        Validator[] validators = input.getValidators();
+        if (validators != null)
         {
-            if (validatorClass.isAssignableFrom(validator.getClass()))
+            for (Validator validator : validators)
             {
-                return (T) validator;
+                if (validatorClass.isAssignableFrom(validator.getClass()))
+                {
+                    return (T) validator;
+                }
             }
         }
         
@@ -515,5 +519,43 @@ public class ValidateBeanTestCase extend
         // because bean validation is not available
         Assert.assertFalse(_hasValidator(input, BeanValidator.class));
     }
-    
+
+    /**
+     * 
+     * @throws IOException
+     */
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testValidateBeanValidationDisabledDoubleNesting() throws IOException
+    {
+        final String validationGroupsOuter = "org.apache.myfaces.beanvalidation.OuterGroup";
+        final String validationGroupsInner = "org.apache.myfaces.beanvalidation.InnerGroup";
+        
+        // add the BeanValidator as default-validator
+        application.addDefaultValidatorId(BeanValidator.VALIDATOR_ID);
+        
+        // put the validationGroups on the request scope
+        externalContext.getRequestMap().put("validationGroupsOuter", validationGroupsOuter);
+        externalContext.getRequestMap().put("validationGroupsInner", validationGroupsInner);
+        
+        // build testValidateBeanDoubleNesting.xhtml
+        UIViewRoot root = facesContext.getViewRoot();
+        vdl.buildView(facesContext, root, "testValidateBeanDisableDoubleNesting.xhtml");
+        
+        // get the component instances
+        UIInput nestedinput = (UIInput) root.findComponent("form:nestedinput");
+        UIInput doublenestedinput = (UIInput) root.findComponent("form:doublenestedinput");
+        UIInput nonnestedinput = (UIInput) root.findComponent("form:nonnestedinput");
+        UIInput nesteouterdisabledinput = (UIInput) root.findComponent("form:nesteouterdisabledinput");
+        
+        // the nested component must get the outer wrapping validationGroups,
+        // the double-nested component must get the inner wrapping validationGroups
+        // and the non-nested component must get the Default validationGroups.
+        Assert.assertEquals(validationGroupsOuter, _getValidationGroups(nestedinput));
+        Assert.assertFalse(_hasValidator(doublenestedinput, BeanValidator.class));
+        Assert.assertEquals(validationGroupsInner, _getValidationGroups(nesteouterdisabledinput));
+        Assert.assertEquals(javax.validation.groups.Default.class.getName(),
+                _getValidationGroups(nonnestedinput));
+    }
+
 }

Added: myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/core/testValidateBeanDisableDoubleNesting.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/core/testValidateBeanDisableDoubleNesting.xhtml?rev=1195559&view=auto
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/core/testValidateBeanDisableDoubleNesting.xhtml (added)
+++ myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/core/testValidateBeanDisableDoubleNesting.xhtml Mon Oct 31 16:38:27 2011
@@ -0,0 +1,40 @@
+<!--
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!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:h="http://java.sun.com/jsf/html"
+	xmlns:f="http://java.sun.com/jsf/core"
+	xmlns:ui="http://java.sun.com/jsf/facelets">
+<head>
+</head>
+<body>
+    <h:form id="form">
+        <f:validateBean validationGroups="#{validationGroupsOuter}">
+            <h:inputText id="nestedinput" value="#{myBean.input}" />
+            <f:validateBean validationGroups="#{validationGroupsInner}">
+                <h:inputText id="doublenestedinput" value="#{myBean.input2}">
+                    <f:validateBean disabled="true"/>
+                </h:inputText>
+            </f:validateBean>
+            <f:validateBean disabled="true">
+                <h:inputText id="nesteouterdisabledinput" value="#{myBean.input4}">
+                    <f:validateBean validationGroups="#{validationGroupsInner}"/>
+                </h:inputText>
+            </f:validateBean>
+        </f:validateBean>
+        
+        <h:inputText id="nonnestedinput" value="#{myBean.input3}" />
+    </h:form>
+</body>
+</html>

Propchange: myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/core/testValidateBeanDisableDoubleNesting.xhtml
------------------------------------------------------------------------------
    svn:eol-style = native