dev@glassfish.java.net

Seeking Review: [1156-defaultAttributeValues]

From: Ed Burns <Ed.Burns_at_Sun.COM>
Date: Mon, 15 Jun 2009 15:47:12 -0400

https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1156


Issue: 1156

SECTION: Changes

M jsf-ri/src/com/sun/faces/el/CompositeComponentAttributesELResolver.java

- Affect the change to enable composite component attribute resolution
  within the ExpressionEvalMap inner class.

- If there is no attribute, look at the metadata for a default value.

M jsf-ri/systest/src/com/sun/faces/composite/JavaTopLevelComponentTestCase.java

- Exercise new testcase.

A jsf-ri/systest/web/composite/defaultAttributeValuesUsingPage.xhtml

- look ma, no attribute values.

SECTION: Diffs

Index: jsf-ri/src/com/sun/faces/el/CompositeComponentAttributesELResolver.java
===================================================================
--- jsf-ri/src/com/sun/faces/el/CompositeComponentAttributesELResolver.java (revision 7418)
+++ jsf-ri/src/com/sun/faces/el/CompositeComponentAttributesELResolver.java (working copy)
@@ -42,7 +42,6 @@
 import java.util.Set;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Collections;
 
 import javax.el.ELResolver;
 import javax.el.ELContext;
@@ -53,6 +52,9 @@
 import javax.faces.el.CompositeComponentExpressionHolder;
 
 import com.sun.faces.util.Util;
+import java.beans.BeanDescriptor;
+import java.beans.BeanInfo;
+import java.beans.PropertyDescriptor;
 
 /**
  * <p>
@@ -242,13 +244,13 @@
         if (topMap == null) {
             topMap = new HashMap<UIComponent,Map<String,Object>>();
             ctxAttributes.put(EVAL_MAP_KEY, topMap);
- evalMap = new ExpressionEvalMap(ctx, c.getAttributes());
+ evalMap = new ExpressionEvalMap(ctx, c);
             topMap.put(c, evalMap);
         }
         if (evalMap == null) {
             evalMap = topMap.get(c);
             if (evalMap == null) {
- evalMap = new ExpressionEvalMap(ctx, c.getAttributes());
+ evalMap = new ExpressionEvalMap(ctx, c);
                 topMap.put(c, evalMap);
             }
         }
@@ -268,15 +270,22 @@
     implements Map<String,Object>, CompositeComponentExpressionHolder {
 
         private Map<String,Object> attributesMap;
+ private PropertyDescriptor[] declaredAttributes;
+ private Map<Object, Object> declaredDefaultValues;
         private FacesContext ctx;
 
 
         // -------------------------------------------------------- Constructors
 
 
- ExpressionEvalMap(FacesContext ctx, Map<String,Object> attributesMap) {
+ ExpressionEvalMap(FacesContext ctx, UIComponent c) {
 
- this.attributesMap = attributesMap;
+ this.attributesMap = c.getAttributes();
+ BeanInfo metadata = (BeanInfo) this.attributesMap.get(UIComponent.BEANINFO_KEY);
+ if (null != metadata) {
+ this.declaredAttributes = metadata.getPropertyDescriptors();
+ this.declaredDefaultValues = new HashMap<Object, Object>(5);
+ }
             this.ctx = ctx;
 
         }
@@ -314,15 +323,47 @@
 
         public Object get(Object key) {
             Object v = attributesMap.get(key);
+ if (v == null) {
+ v = getDeclaredDefaultValue(key);
+ }
             if (v != null && v instanceof ValueExpression) {
                 return (((ValueExpression) v).getValue(ctx.getELContext()));
             }
             if (v != null && v instanceof MethodExpression) {
                 return v;
             }
- return null;
+ return v;
         }
 
+ private Object getDeclaredDefaultValue(Object key) {
+ Object result = null;
+
+ // If it's not in the cache...
+ if (!declaredDefaultValues.containsKey(key)) {
+ // iterate through the property descriptors...
+ boolean found = true;
+ for (PropertyDescriptor cur : declaredAttributes) {
+ // and if you find a match...
+ if (cur.getName().equals(key)) {
+ found = true;
+ // put it in the cache, returning the value.
+ declaredDefaultValues.put(key, result = cur.getValue("default"));
+ break;
+ }
+ }
+ // Otherwise, if no attribute was declared
+ if (!found) {
+ // put null into the cache for future lookups.
+ declaredDefaultValues.put(key, null);
+ }
+ } else {
+ // It's in the cache, just return the value.
+ result = declaredDefaultValues.get(key);
+ }
+
+ return result;
+ }
+
         public Object put(String key, Object value) {
             Object v = attributesMap.get(key);
             if (v != null && v instanceof ValueExpression) {
Index: jsf-ri/systest/src/com/sun/faces/composite/JavaTopLevelComponentTestCase.java
===================================================================
--- jsf-ri/systest/src/com/sun/faces/composite/JavaTopLevelComponentTestCase.java (revision 7419)
+++ jsf-ri/systest/src/com/sun/faces/composite/JavaTopLevelComponentTestCase.java (working copy)
@@ -101,5 +101,12 @@
 
     }
 
+ public void testDefaultAttribute() throws Exception {
 
+ HtmlPage page = getPage("/faces/composite/defaultAttributeValuesUsingPage.xhtml");
+ String text = page.asXml();
+ assertTrue(-1 != text.indexOf("User ID:"));
+ assertTrue(-1 != text.indexOf("value=\"Login"));
+ }
+
 }
Index: jsf-ri/systest/web/composite/defaultAttributeValuesUsingPage.xhtml
===================================================================
--- jsf-ri/systest/web/composite/defaultAttributeValuesUsingPage.xhtml (revision 0)
+++ jsf-ri/systest/web/composite/defaultAttributeValuesUsingPage.xhtml (revision 0)
@@ -0,0 +1,28 @@
+<!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:my="http://java.sun.com/jsf/composite/composite">
+<h:head>
+ <title>A Simple JavaServer Faces 2.0 View</title>
+<style type="text/css">
+.grayBox { padding: 8px; margin: 10px 0; border: 1px solid #CCC; background-color: #f9f9f9; }
+</style>
+
+</h:head>
+<h:body>
+ <h:form prependId="false">
+
+ <p>This test shows that composite:attribute default works for both
+ simple attrbutes and method-expression attributes</p>
+
+ <p>Composite Component usage:</p>
+
+<div id="cc" class="grayBox" style="border: 1px solid #090;">
+<p><my:javaTopLevelComponent id="loginPanel1"
+ item="Many Jars"/></p>
+</div>
+
+ </h:form>
+</h:body>
+</html>

--