dev@javaserverfaces.java.net

[280-EZComp] Seeking Retroactive Review

From: Ed Burns <Ed.Burns_at_Sun.COM>
Date: Fri, 26 Sep 2008 12:08:21 -0700

Issue: 280-ComponentResources

To enable <ez:loginPanel action="#{bean.loginAction}" />, where the
action is re-targeted to be an attribute on an inner component inside of
the composite component, at the discretion of the composite component
author, I needed to change the special case clause in
component.getAttributes().get().

Before this change, calling component.getAttributes().get() would cause
any result that is a ValueExpression to have its getValue() called
before return from component.getAttributes.get() if and only if the
component was a composite component. This change reverts this behavior.

Instead, I've added a new method to UIComponent, getAttrs(). getAttrs()
is just like getAttributes() except that its get method *always* will
cause any results that are ValueExpressions to have their getValue()
called before return.


SECTION: Modified Files
----------------------------
M jsf-api/src/javax/faces/component/UIComponent.java

- add getAttrs()

     * <p class="changed_added_2_0">Like {_at_link #getAttributes}, except
     * that the <code>get()</code> implementation must call
     * <code>getValue()</code> on any result whose type is
     * <code>ValueExpression</code> and return the evaluated result.
     * </p>

M jsf-api/src/javax/faces/component/UIComponentBase.java

- remove special case behavior in getAttributes().get().

M jsf-demo/ezcomp00/src/main/webapp/resources/ezcomp/loginPanel.xhtml
M jsf-demo/ezcomp01/src/main/webapp/resources/ezcomp/loginPanel.xhtml
M jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanelTemplate.xhtml
M jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanel.xhtml
M jsf-demo/ezcomp03/src/main/webapp/resources/ezcomp/loginPanelTemplate.xhtml
M jsf-demo/ezcomp03/src/main/webapp/resources/ezcomp/loginPanel.xhtml

- change any expressions that start with "#{compositeComponent.attributes"
  to start with "#{compositeComponent.attrs" instead.

SECTION: Diffs
----------------------------
Index: jsf-api/src/javax/faces/component/UIComponent.java
===================================================================
--- jsf-api/src/javax/faces/component/UIComponent.java (revision 5480)
+++ jsf-api/src/javax/faces/component/UIComponent.java (working copy)
 -45,6 +45,7 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 -54,6 +55,7 @@
 import java.util.Locale;
 import java.util.Map;
 
+import java.util.Map.Entry;
 import java.util.MissingResourceException;
 import java.util.PropertyResourceBundle;
 import java.util.ResourceBundle;
 -247,8 +249,86 @@
      * </p>
      */
     public abstract Map<String, Object> getAttributes();
+
+
+ private transient Map<String, Object> valueExpressionEvaluatingAttrsMap;
+
+ /**
+ * <p class="changed_added_2_0">Like {_at_link #getAttributes}, except that the
+ * <code>get()</code> implementation must call <code>getValue()</code> on
+ * any result whose type is <code>ValueExpression</code> before returning.
+ * </p>
+ *
+ * @since 2.0
+ */
+ public Map<String, Object> getAttrs() {
+
+ if (null == valueExpressionEvaluatingAttrsMap) {
+ valueExpressionEvaluatingAttrsMap = new Map<String, Object>() {
+
+ private Map<String, Object> attrs = UIComponent.this.getAttributes();
 
+ public void clear() {
+ attrs.clear();
+ }
 
+ public boolean containsKey(Object key) {
+ return attrs.containsKey(key);
+ }
+
+ public boolean containsValue(Object value) {
+ return attrs.containsValue(value);
+ }
+
+ public Set<Entry<String, Object>> entrySet() {
+ return attrs.entrySet();
+ }
+
+ public Object get(Object key) {
+ Object result = attrs.get(key);
+ // check if the result is an expression
+ if (result instanceof ValueExpression) {
+ ValueExpression ve = (ValueExpression) result;
+ result = ve.getValue(FacesContext.getCurrentInstance().getELContext());
+ }
+ return result;
+ }
+
+ public boolean isEmpty() {
+ return attrs.isEmpty();
+ }
+
+ public Set<String> keySet() {
+ return attrs.keySet();
+ }
+
+ public Object put(String key, Object value) {
+ return attrs.put(key, value);
+ }
+
+ public void putAll(Map<? extends String, ? extends Object> t) {
+ attrs.putAll(t);
+ }
+
+ public Object remove(Object key) {
+ return attrs.remove(key);
+ }
+
+ public int size() {
+ return attrs.size();
+ }
+
+ public Collection<Object> values() {
+ return attrs.values();
+ }
+
+ };
+ }
+
+ return valueExpressionEvaluatingAttrsMap;
+ }
+
+
     // ---------------------------------------------------------------- Bindings
 
 
Index: jsf-api/src/javax/faces/component/UIComponentBase.java
===================================================================
--- jsf-api/src/javax/faces/component/UIComponentBase.java (revision 5480)
+++ jsf-api/src/javax/faces/component/UIComponentBase.java (working copy)
 -1697,16 +1697,7 @@
                     }
                 } else if (attributes != null) {
                     if (attributes.containsKey(key)) {
- result = (attributes.get(key));
- // If we have a non-null result and
- // this is a composite component
- if (null != result && attributes.containsKey(Resource.COMPONENT_RESOURCE_KEY)) {
- // check if the result is an expression
- if (result instanceof ValueExpression) {
- ValueExpression ve = (ValueExpression) result;
- result = ve.getValue(FacesContext.getCurrentInstance().getELContext());
- }
- }
+ result = attributes.get(key);
                     }
                 }
             }
Index: jsf-demo/ezcomp00/src/main/webapp/resources/ezcomp/loginPanel.xhtml
===================================================================
--- jsf-demo/ezcomp00/src/main/webapp/resources/ezcomp/loginPanel.xhtml (revision 5480)
+++ jsf-demo/ezcomp00/src/main/webapp/resources/ezcomp/loginPanel.xhtml (working copy)
 -108,7 +108,7 @@
 
       <p>
 
- <h:commandButton id="loginEvent" value="Login" action="#{compositeComponent.attributes.model.loginAction}">
+ <h:commandButton id="loginEvent" value="Login" action="#{compositeComponent.attrs.model.loginAction}">
 
         </h:commandButton>
 
Index: jsf-demo/ezcomp01/src/main/webapp/resources/ezcomp/loginPanel.xhtml
===================================================================
--- jsf-demo/ezcomp01/src/main/webapp/resources/ezcomp/loginPanel.xhtml (revision 5480)
+++ jsf-demo/ezcomp01/src/main/webapp/resources/ezcomp/loginPanel.xhtml (working copy)
 -96,7 +96,7 @@
 
       <p>
 
- <h:commandButton id="loginEvent" value="Login" action="#{compositeComponent.attributes.model.loginAction}">
+ <h:commandButton id="loginEvent" value="Login" action="#{compositeComponent.attrs.model.loginAction}">
 
         </h:commandButton>
 
Index: jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanelTemplate.xhtml
===================================================================
--- jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanelTemplate.xhtml (revision 5480)
+++ jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanelTemplate.xhtml (working copy)
 -84,7 +84,7 @@
                                 <tr><td nowrap="nowrap"><div class="logLbl">
                                         &nbsp;<span class="LblLev2Txt">
 <label id="sun_label17" for="Login.username" class="LblLev2Txt_sun4">
-<h:outputText value="#{compositeComponent.attributes.usernameLabel}" />
+<h:outputText value="#{compositeComponent.attrs.usernameLabel}" />
 </label>
                                         </span></div></td>
 
 -97,7 +97,7 @@
                                 <tr><td nowrap="nowrap"><div class="logLblLst">
                                         &nbsp;<span class="LblLev2Txt">
 <label id="sun_label19" for="Login.pin" class="LblLev2Txt_sun4">
-<h:outputText value="#{compositeComponent.attributes.pinLabel}" />
+<h:outputText value="#{compositeComponent.attrs.pinLabel}" />
 </label>
                                         </span></div></td>
                                     <td><div class="logInpLst">
Index: jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanel.xhtml
===================================================================
--- jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanel.xhtml (revision 5480)
+++ jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanel.xhtml (working copy)
 -85,8 +85,8 @@
 
     <ui:define name="loginEvent">
 
- <h:commandButton id="loginEvent" value="#{compositeComponent.attributes.loginLabel}"
- action="#{compositeComponent.attributes.model.loginAction}"
+ <h:commandButton id="loginEvent" value="#{compositeComponent.attrs.loginLabel}"
+ action="#{compositeComponent.attrs.model.loginAction}"
                  onkeypress="javascript: submitenter(event, 'loginButton', Login');"
                  onclick="javascript: submitAndDisable(this, 'Login');"
                  onfocus="javascript: if (this.disabled==0) this.className='Btn1Hov'"
Index: jsf-demo/ezcomp03/src/main/webapp/resources/ezcomp/loginPanelTemplate.xhtml
===================================================================
--- jsf-demo/ezcomp03/src/main/webapp/resources/ezcomp/loginPanelTemplate.xhtml (revision 5480)
+++ jsf-demo/ezcomp03/src/main/webapp/resources/ezcomp/loginPanelTemplate.xhtml (working copy)
 -84,7 +84,7 @@
                                 <tr><td nowrap="nowrap"><div class="logLbl">
                                         &nbsp;<span class="LblLev2Txt">
 <label id="sun_label17" for="Login.username" class="LblLev2Txt_sun4">
-<h:outputText value="#{compositeComponent.attributes.usernameLabel}" />
+<h:outputText value="#{compositeComponent.attrs.usernameLabel}" />
 </label>
                                         </span></div></td>
 
 -97,7 +97,7 @@
                                 <tr><td nowrap="nowrap"><div class="logLblLst">
                                         &nbsp;<span class="LblLev2Txt">
 <label id="sun_label19" for="Login.pin" class="LblLev2Txt_sun4">
-<h:outputText value="#{compositeComponent.attributes.pinLabel}" />
+<h:outputText value="#{compositeComponent.attrs.pinLabel}" />
 </label>
                                         </span></div></td>
                                     <td><div class="logInpLst">
Index: jsf-demo/ezcomp03/src/main/webapp/resources/ezcomp/loginPanel.xhtml
===================================================================
--- jsf-demo/ezcomp03/src/main/webapp/resources/ezcomp/loginPanel.xhtml (revision 5480)
+++ jsf-demo/ezcomp03/src/main/webapp/resources/ezcomp/loginPanel.xhtml (working copy)
 -85,8 +85,8 @@
 
     <ui:define name="loginEvent">
 
- <h:commandButton id="loginEvent" value="#{compositeComponent.attributes.loginLabel}"
- action="#{compositeComponent.attributes.model.loginAction}"
+ <h:commandButton id="loginEvent" value="#{compositeComponent.attrs.loginLabel}"
+ action="#{compositeComponent.attrs.model.loginAction}"
                  onkeypress="javascript: submitenter(event, 'loginButton', Login');"
                  onclick="javascript: submitAndDisable(this, 'Login');"
                  onfocus="javascript: if (this.disabled==0) this.className='Btn1Hov'"

-- 
| ed.burns_at_sun.com  | office: 408 884 9519 OR x31640
| homepage:         | http://ridingthecrest.com/