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 2009/08/20 06:06:44 UTC

svn commit: r806040 - in /myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite: AttributeHandler.java CompositeComponentResourceTagHandler.java

Author: lu4242
Date: Thu Aug 20 04:06:43 2009
New Revision: 806040

URL: http://svn.apache.org/viewvc?rev=806040&view=rev
Log:
MYFACES-2312 Implement <composite:attribute> tag handler

Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttributeHandler.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttributeHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttributeHandler.java?rev=806040&r1=806039&r2=806040&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttributeHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttributeHandler.java Thu Aug 20 04:06:43 2009
@@ -51,12 +51,24 @@
     @JSFFaceletAttribute
     private final TagAttribute _targets;
     
+    /**
+     * If this property is set and the attribute does not have any
+     * value (null), the value set on this property is returned as default
+     * instead null.
+     */
     @JSFFaceletAttribute
     private final TagAttribute _default;
     
     @JSFFaceletAttribute
     private final TagAttribute _displayName;
 
+    /**
+     * Indicate if the attribute is required or not
+     * <p>
+     * Myfaces specific feature: this attribute is checked only if project stage is
+     * not ProjectStage.Production when a composite component is created.
+     * </p>
+     */
     @JSFFaceletAttribute
     private final TagAttribute _required;
 
@@ -75,9 +87,20 @@
     @JSFFaceletAttribute
     private final TagAttribute _type;
     
+    /**
+     * Check if the PropertyDescriptor instance created by this handler
+     * can be cacheable or not. 
+     */
     private boolean _cacheable;
     
-    private volatile PropertyDescriptor _propertyDescriptor; 
+    /**
+     * Cached instance used by this component. Note here we have a 
+     * "racy single-check". If this field is used, it is supposed 
+     * the object cached by this handler is immutable, and this is
+     * granted if all properties not saved as ValueExpression are
+     * "literal". 
+     */
+    private PropertyDescriptor _propertyDescriptor; 
     
     public AttributeHandler(TagConfig config)
     {
@@ -94,15 +117,26 @@
         _type = getAttribute("type");
         
         // We can reuse the same PropertyDescriptor only if the properties
-        // that requires to be evaluated when apply occur are literal or null.
-        // otherwise we need to create it.        
+        // that requires to be evaluated when apply (build view time)
+        // occur are literal or null. Otherwise we need to create it.
         if ( (_name == null             || _name.isLiteral()             ) &&
              (_displayName == null      || _displayName.isLiteral()      ) &&
              (_preferred == null        || _preferred.isLiteral()        ) &&
              (_expert == null           || _expert.isLiteral()           ) &&
              (_shortDescription == null || _shortDescription.isLiteral() ) )
         {
+            // Unfortunately its not possible to create the required 
+            // PropertyDescriptor instance here, because there is no way 
+            // to get a FaceletContext to create ValueExpressions. It is
+            // possible to create it if we not have set all this properties:
+            // targets, default, required, methodSignature and type. This prevents
+            // the racy single-check.
             _cacheable = true;
+            if ( _targets == null && _default == null && _required == null &&
+                 _methodSignature == null && _type == null)
+            {
+                _propertyDescriptor = _createPropertyDescriptor();
+            }
         }
         else
         {
@@ -146,6 +180,47 @@
         nextHandler.apply(ctx, parent);
     }
     
+    /**
+     * This method could be called only if it is not necessary to set the following properties:
+     * targets, default, required, methodSignature and type
+     * 
+     * @return
+     */
+    private PropertyDescriptor _createPropertyDescriptor()
+    {
+        try
+        {
+            CompositeComponentPropertyDescriptor attribute = 
+                new CompositeComponentPropertyDescriptor(_name.getValue());
+            
+            if (_displayName != null)
+            {
+                attribute.setDisplayName(_displayName.getValue());
+            }
+            if (_preferred != null)
+            {
+                attribute.setPreferred(Boolean.valueOf(_preferred.getValue()));
+            }
+            if (_expert != null)
+            {
+                attribute.setExpert(Boolean.valueOf(_expert.getValue()));
+            }
+            if (_shortDescription != null)
+            {
+                attribute.setShortDescription(_shortDescription.getValue());
+            }            
+            return attribute;
+        }
+        catch (IntrospectionException e)
+        {
+            if (log.isErrorEnabled())
+            {
+                log.error("Cannot create PropertyDescriptor for attribute ",e);
+            }
+            throw new TagException(tag,e);
+        }
+    }
+    
     private PropertyDescriptor _createPropertyDescriptor(FaceletContext ctx, UIComponent parent)
         throws TagException, IOException
     {
@@ -166,7 +241,7 @@
             }
             if (_displayName != null)
             {
-                attribute.setDisplayName(_displayName.getValue());
+                attribute.setDisplayName(_displayName.getValue(ctx));
             }
             if (_required != null)
             {

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java?rev=806040&r1=806039&r2=806040&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java Thu Aug 20 04:06:43 2009
@@ -18,9 +18,13 @@
  */
 package org.apache.myfaces.view.facelets.tag.composite;
 
+import java.beans.BeanInfo;
+import java.beans.PropertyDescriptor;
 import java.io.IOException;
 
+import javax.el.ValueExpression;
 import javax.el.VariableMapper;
+import javax.faces.application.ProjectStage;
 import javax.faces.application.Resource;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIPanel;
@@ -30,6 +34,7 @@
 import javax.faces.view.facelets.ComponentHandler;
 import javax.faces.view.facelets.FaceletContext;
 import javax.faces.view.facelets.MetaRuleset;
+import javax.faces.view.facelets.TagException;
 
 import org.apache.myfaces.view.facelets.AbstractFaceletContext;
 import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
@@ -48,7 +53,7 @@
     implements ComponentBuilderHandler
 {
     private final Resource _resource;
-
+    
     public CompositeComponentResourceTagHandler(ComponentConfig config, Resource resource)
     {
         super(config);
@@ -58,8 +63,30 @@
     @Override
     public UIComponent createComponent(FaceletContext ctx)
     {
-        FacesContext faceContext = ctx.getFacesContext();
-        return faceContext.getApplication().createComponent(faceContext, _resource);
+        FacesContext facesContext = ctx.getFacesContext();
+        UIComponent component = facesContext.getApplication().createComponent(facesContext, _resource);
+        
+        // Check required attributes if the app is not on production stage. 
+        // Unfortunately, we can't check it on constructor because we need to call
+        // ViewDeclarationLanguage.getComponentMetadata() and on that point it is possible to not
+        // have a viewId.
+        if (!facesContext.isProjectStage(ProjectStage.Production))
+        {
+            BeanInfo beanInfo = (BeanInfo) component.getAttributes().get(UIComponent.BEANINFO_KEY);
+            for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors())
+            {
+                ValueExpression ve = (ValueExpression) propertyDescriptor.getValue("required");
+                if (ve != null)
+                {
+                    Boolean required = Boolean.valueOf((String)ve.getValue(facesContext.getELContext()));
+                    if (required != null && required.booleanValue())
+                    {
+                        throw new TagException(this.tag, "Attribute '" + propertyDescriptor.getName() + "' is required");
+                    }
+                }
+            }
+        }
+        return component;
     }
 
     @Override
@@ -80,7 +107,7 @@
         //vdl.retargetAttachedObjects(facesContext, c, handlers)
         
         // TODO: Uncomment this code and test it.
-        //vdl.retargetMethodExpressions(facesContext, c);
+        vdl.retargetMethodExpressions(facesContext, c);
         
         if (ctx.getFacesContext().getAttributes().containsKey(
                 FaceletViewDeclarationLanguage.MARK_INITIAL_STATE_KEY))