dev@javaserverfaces.java.net

[REVIEW] Minor improvements to UIData

From: Ryan Lubke <Ryan.Lubke_at_Sun.COM>
Date: Mon, 27 Aug 2007 15:59:13 -0700

Change bundle attached.
Comments welcome.

Thanks,

-rl





SECTION: Modified Files
----------------------------
M src/javax/faces/component/UIData.java
 - add client ID caching scheme for non nested tables.
   In the non-nested case:
      the base client ID will not change, so store this in
      the StringBuilder. When a new per-row ID is needed
      append the row index and call toString() on the builder,
      and then reset the size of the builder to the base client
      ID + the naming container separator
   In the nested case, use the StringBuilder, but reset the
   length to 0 after each computed ID
 - In all cases where we call getChildren() or getFacets() call
   getChildCount() and getFacetCount() and only call the methods
   returning a collection when there are children or facets (reduces
   the chance of creating empty collections)
 - cache the result if isNestedWithinUIData since this is called multiple times



SECTION: Diffs
----------------------------
Index: src/javax/faces/component/UIData.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-api/src/javax/faces/component/UIData.java,v
retrieving revision 1.75.4.1
diff -u -r1.75.4.1 UIData.java
--- src/javax/faces/component/UIData.java 27 Aug 2007 04:57:28 -0000 1.75.4.1
+++ src/javax/faces/component/UIData.java 27 Aug 2007 22:52:13 -0000
@@ -177,6 +177,34 @@
      */
     private String var = null;
 
+
+ /**
+ * <p>Holds the base client ID that will be used to generate per-row
+ * client IDs (this will be null if this UIData is nested within another).</p>
+ */
+ private String baseClientId;
+
+
+ /**
+ * <p> Length of the cached <code>baseClientId</code> plus one for the
+ * NamingContainer.SEPARATOR_CHAR. </p>
+ */
+ private int baseClientIdLength;
+
+
+ /**
+ * <p>StringBuilder used to build per-row client IDs.</p>
+ */
+ private StringBuilder clientIdBuilder;
+
+
+ /**
+ * <p>Flag indicating whether or not this UIData instance is nested
+ * within another UIData instance</p>
+ */
+ private Boolean isNested;
+
+
     // -------------------------------------------------------------- Properties
 
 
@@ -680,11 +708,36 @@
         if (context == null) {
             throw new NullPointerException();
         }
- String baseClientId = super.getClientId(context);
+
+ if (baseClientId == null && clientIdBuilder == null) {
+ if (!isNestedWithinUIData()) {
+ clientIdBuilder = new StringBuilder(super.getClientId(context));
+ baseClientId = clientIdBuilder.toString();
+ baseClientIdLength = (baseClientId.length() + 1);
+ clientIdBuilder.append(NamingContainer.SEPARATOR_CHAR);
+ clientIdBuilder.setLength(baseClientIdLength);
+ } else {
+ clientIdBuilder = new StringBuilder();
+ }
+ }
         if (rowIndex >= 0) {
- return (baseClientId + NamingContainer.SEPARATOR_CHAR + rowIndex);
+ String cid;
+ if (!isNestedWithinUIData()) {
+ cid = clientIdBuilder.append(rowIndex).toString();
+ clientIdBuilder.setLength(baseClientIdLength);
+ } else {
+ cid = clientIdBuilder.append(super.getClientId(context))
+ .append(NamingContainer.SEPARATOR_CHAR).append(rowIndex)
+ .toString();
+ clientIdBuilder.setLength(0);
+ }
+ return (cid);
         } else {
- return (baseClientId);
+ if (!isNestedWithinUIData()) {
+ return (baseClientId);
+ } else {
+ return super.getClientId(context);
+ }
         }
 
     }
@@ -777,7 +830,8 @@
                             this.setRowIndex(newRow);
                             if (this.isRowAvailable()) {
                                 found = super.invokeOnComponent(context,
- clientId, callback);
+ clientId,
+ callback);
                             }
                         }
                     }
@@ -850,7 +904,6 @@
         FacesEvent rowEvent = revent.getFacesEvent();
         rowEvent.getComponent().broadcast(rowEvent);
         setRowIndex(oldRowIndex);
- return;
 
     }
 
@@ -917,8 +970,7 @@
         setDataModel(null); // Re-evaluate even with server-side state saving
         if (null == saved || !keepSaved(context)) {
             //noinspection CollectionWithoutInitialCapacity
- saved =
- new HashMap<String, SavedState>(); // We don't need saved state here
+ saved = new HashMap<String, SavedState>(); // We don't need saved state here
         }
 
         iterate(context, PhaseId.APPLY_REQUEST_VALUES);
@@ -1103,47 +1155,43 @@
 
         // Process each facet of this component exactly once
         setRowIndex(-1);
- Iterator facets = getFacets().keySet().iterator();
- while (facets.hasNext()) {
- UIComponent facet = getFacets().get(facets.next());
- if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
- facet.processDecodes(context);
- } else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
- facet.processValidators(context);
- } else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
- facet.processUpdates(context);
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- // Process each facet of our child UIColumn components exactly once
- setRowIndex(-1);
- Iterator columns = getChildren().iterator();
- while (columns.hasNext()) {
- UIComponent column = (UIComponent) columns.next();
- if (!(column instanceof UIColumn)) {
- continue;
- }
- if (!column.isRendered()) {
- continue;
- }
- Iterator columnFacets = column.getFacets().keySet().iterator();
- while (columnFacets.hasNext()) {
- UIComponent columnFacet =
- column.getFacets().get(columnFacets.next());
+ if (getFacetCount() > 0) {
+ for (UIComponent facet : getFacets().values()) {
                 if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
- columnFacet.processDecodes(context);
+ facet.processDecodes(context);
                 } else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
- columnFacet.processValidators(context);
+ facet.processValidators(context);
                 } else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
- columnFacet.processUpdates(context);
+ facet.processUpdates(context);
                 } else {
                     throw new IllegalArgumentException();
                 }
             }
         }
 
+ // Process each facet of our child UIColumn components exactly once
+ setRowIndex(-1);
+ if (getChildCount() > 0) {
+ for (UIComponent column : getChildren()) {
+ if (!(column instanceof UIColumn) || !column.isRendered()) {
+ continue;
+ }
+ if (column.getFacetCount() > 0) {
+ for (UIComponent columnFacet : column.getFacets().values()) {
+ if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
+ columnFacet.processDecodes(context);
+ } else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
+ columnFacet.processValidators(context);
+ } else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
+ columnFacet.processUpdates(context);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+ }
+ }
+
         // Iterate over our UIColumn children, once per row
         int processed = 0;
         int rowIndex = getFirst() - 1;
@@ -1165,26 +1213,26 @@
             // Perform phase-specific processing as required
             // on the *children* of the UIColumn (facets have
             // been done a single time with rowIndex=-1 already)
- Iterator kids = getChildren().iterator();
- while (kids.hasNext()) {
- UIComponent kid = (UIComponent) kids.next();
- if (!(kid instanceof UIColumn)) {
- continue;
- }
- Iterator grandkids = kid.getChildren().iterator();
- while (grandkids.hasNext()) {
- UIComponent grandkid = (UIComponent) grandkids.next();
- if (!grandkid.isRendered()) {
+ if (getChildCount() > 0) {
+ for (UIComponent kid : getChildren()) {
+ if (!(kid instanceof UIColumn) || !kid.isRendered()) {
                         continue;
                     }
- if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
- grandkid.processDecodes(context);
- } else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
- grandkid.processValidators(context);
- } else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
- grandkid.processUpdates(context);
- } else {
- throw new IllegalArgumentException();
+ if (kid.getChildCount() > 0) {
+ for (UIComponent grandkid : kid.getChildren()) {
+ if (!grandkid.isRendered()) {
+ continue;
+ }
+ if (phaseId == PhaseId.APPLY_REQUEST_VALUES) {
+ grandkid.processDecodes(context);
+ } else if (phaseId == PhaseId.PROCESS_VALIDATIONS) {
+ grandkid.processValidators(context);
+ } else if (phaseId == PhaseId.UPDATE_MODEL_VALUES) {
+ grandkid.processUpdates(context);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
                     }
                 }
             }
@@ -1216,9 +1264,7 @@
      */
     private boolean keepSaved(FacesContext context) {
 
- Iterator clientIds = saved.keySet().iterator();
- while (clientIds.hasNext()) {
- String clientId = (String) clientIds.next();
+ for (String clientId : saved.keySet()) {
             Iterator messages = context.getMessages(clientId);
             while (messages.hasNext()) {
                 FacesMessage message = (FacesMessage) messages.next();
@@ -1232,14 +1278,22 @@
 
     }
 
- private boolean isNestedWithinUIData() {
- UIComponent parent = this;
- while (null != (parent = parent.getParent())) {
- if (parent instanceof UIData) {
- return true;
+ private Boolean isNestedWithinUIData() {
+ if (isNested == null) {
+ UIComponent parent = this;
+ while (null != (parent = parent.getParent())) {
+ if (parent instanceof UIData) {
+ isNested = Boolean.TRUE;
+ break;
+ }
+ }
+ if (isNested == null) {
+ isNested = Boolean.FALSE;
             }
+ return isNested;
+ } else {
+ return isNested;
         }
- return (false);
     }
 
 
@@ -1250,11 +1304,11 @@
     private void restoreDescendantState() {
 
         FacesContext context = getFacesContext();
- Iterator kids = getChildren().iterator();
- while (kids.hasNext()) {
- UIComponent kid = (UIComponent) kids.next();
- if (kid instanceof UIColumn) {
- restoreDescendantState(kid, context);
+ if (getChildCount() > 0) {
+ for (UIComponent kid : getChildren()) {
+ if (kid instanceof UIColumn) {
+ restoreDescendantState(kid, context);
+ }
             }
         }
 
@@ -1292,16 +1346,16 @@
         }
 
         // Restore state for children of this component
- Iterator kids = component.getChildren().iterator();
- while (kids.hasNext()) {
- restoreDescendantState((UIComponent) kids.next(), context);
+ if (component.getChildCount() > 0) {
+ for (UIComponent kid : component.getChildren()) {
+ restoreDescendantState(kid, context);
+ }
         }
+
         // Restore state for facets of this component
- Iterator facetNames = component.getFacets().keySet().iterator();
- while (facetNames.hasNext()) {
- UIComponent c = component.getFacet((String) facetNames.next());
- if (c != null) {
- restoreDescendantState(c, context);
+ if (component.getFacetCount() > 0) {
+ for (UIComponent facet : component.getFacets().values()) {
+ restoreDescendantState(facet, context);
             }
         }
 
@@ -1315,11 +1369,11 @@
     private void saveDescendantState() {
 
         FacesContext context = getFacesContext();
- Iterator kids = getChildren().iterator();
- while (kids.hasNext()) {
- UIComponent kid = (UIComponent) kids.next();
- if (kid instanceof UIColumn) {
- saveDescendantState(kid, context);
+ if (getChildCount() > 0) {
+ for (UIComponent kid : getChildren()) {
+ if (kid instanceof UIColumn) {
+ saveDescendantState(kid, context);
+ }
             }
         }
 
@@ -1352,16 +1406,16 @@
         }
 
         // Save state for children of this component
- Iterator kids = component.getChildren().iterator();
- while (kids.hasNext()) {
- saveDescendantState((UIComponent) kids.next(), context);
+ if (component.getChildCount() > 0) {
+ for (UIComponent uiComponent : component.getChildren()) {
+ saveDescendantState(uiComponent, context);
+ }
         }
+
         // Save state for facets of this component
- Iterator facetNames = component.getFacets().keySet().iterator();
- while (facetNames.hasNext()) {
- UIComponent c = component.getFacet((String) facetNames.next());
- if (c != null) {
- saveDescendantState(c, context);
+ if (component.getFacetCount() > 0) {
+ for (UIComponent facet : component.getFacets().values()) {
+ saveDescendantState(facet, context);
             }
         }