You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ar...@apache.org on 2009/11/11 19:06:31 UTC

svn commit: r834992 - in /myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad: component/UIXComponent.java util/ComponentUtils.java

Author: arobinson74
Date: Wed Nov 11 18:06:31 2009
New Revision: 834992

URL: http://svn.apache.org/viewvc?rev=834992&view=rev
Log:
Proposed changes

Modified:
    myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java
    myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ComponentUtils.java

Modified: myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java?rev=834992&r1=834991&r2=834992&view=diff
==============================================================================
--- myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java (original)
+++ myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponent.java Wed Nov 11 18:06:31 2009
@@ -251,7 +251,7 @@
   {
     ComponentProcessingContext processingContext = new ComponentProcessingContext();
     processingContext.__setIsRendering();
-    
+
     return processFlattenedChildren(context,
                                     processingContext,
                                     childProcessor,
@@ -481,6 +481,57 @@
   }
 
   /**
+   * @inheritDoc
+   * <p>In addition to the standard {@link UIComponent#findComponent(String)} functionality,
+   * <c>UIXComponent</c> supports relative ID support in the find component method. This involves
+   * the resolution of Trinidad scoped IDs (IDs that search in parent naming containers using
+   * multiple colons). See the static {@link #findComponent(UIComponent, String)} method for
+   * more information on this syntax.</p>
+   *
+   * @param expr The expression to use to find the component
+   * @return The component if found, otherwise null
+   */
+  @Override
+  public UIComponent findComponent(
+    String expr)
+  {
+    return _findComponentImpl(this, expr);
+  }
+
+  /**
+   * Find a component relative to another.
+   * <p>
+   * The relative ID must account for NamingContainers. If the component is already inside
+   * of a naming container, you can use a single colon to start the search from the root,
+   * or multiple colons to move up through the NamingContainers - "::" will
+   * pop out of the current naming container, ":::" will pop out of two
+   * naming containers, etc.
+   * </p>
+   *
+   * @param from the component to search relative to
+   * @param scopedId the relative id path from the 'from' component to the
+   *                 component to find
+   * @return the component if found, null otherwise
+   * @see org.apache.myfaces.trinidad.render.RenderUtils#getRelativeId
+   * @see javax.faces.component.UIComponent#findComponent
+   */
+  public static UIComponent findComponent(
+    UIComponent from,
+    String      scopedId)
+  {
+    if (from == null)
+      return null;
+
+    if (from instanceof UIXComponent)
+    {
+      // UIXComponent can handle relative IDs in its findComponent method
+      return from.findComponent(scopedId);
+    }
+
+    return _findComponentImpl(from, scopedId);
+  }
+
+  /**
    * Add a component as a partial target to the current request. This code handles the
    * delegation to {@link #setPartialTarget(FacesContext, PartialPageContext)}
    * for UIXComponents or assumes for {@link UIComponent} that components with a renderer
@@ -792,4 +843,59 @@
    * @see UIXComponentBase#getClientId(FacesContext context)
    */
   abstract public String getContainerClientId(FacesContext context, UIComponent child);
+
+  private static UIComponent _findComponentImpl(
+    UIComponent from,
+    String scopedId)
+  {
+    boolean isRelative = scopedId.startsWith("::", 0);
+
+    if (isRelative)
+    {
+      // if the component is not a NamingContainer, then we need to
+      // get the component's naming container and set this as the 'from'.
+      // this way we'll pop out of the component's
+      // naming container if there is are multiple colons.
+      if (!(from instanceof NamingContainer))
+      {
+        from = _getParentNamingContainerOrViewRoot(from);
+
+        if (from instanceof UIXComponent)
+        {
+          // The parent naming container is a UIXComponent, let it process the resolution
+          // of the find in case it has overridden the default behavior
+          return ((UIXComponent)from).findComponent(scopedId);
+        }
+      }
+
+      // Pop out of the current naming container and get the parent naming container
+      from = _getParentNamingContainerOrViewRoot(from);
+
+      // Strip off both colons if there are only 2 at the start, otherwise strip off one
+      scopedId = (scopedId.length() >= 3 && scopedId.charAt(2) == ':')
+        ? scopedId.substring(1) : scopedId.substring(2);
+
+      // Let the naming container resolve the remainder
+      return UIXComponent.findComponent(from, scopedId);
+    }
+
+    return from.findComponent(scopedId);
+  }
+
+  /**
+   * Given a component, get its naming container. If the component
+   * is a naming container, it will get its naming container.
+   * If no parent naming containers exist, it stops at the ViewRoot.
+   */
+  private static UIComponent _getParentNamingContainerOrViewRoot (
+    UIComponent from)
+  {
+    while (from.getParent() != null)
+    {
+      from = from.getParent();
+      if (from instanceof NamingContainer)
+        break;
+    }
+    return from;
+  }
 }

Modified: myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ComponentUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ComponentUtils.java?rev=834992&r1=834991&r2=834992&view=diff
==============================================================================
--- myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ComponentUtils.java (original)
+++ myfaces/trinidad/branches/ar_Issue1633/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ComponentUtils.java Wed Nov 11 18:06:31 2009
@@ -6,9 +6,9 @@
  *  to you 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
@@ -24,11 +24,12 @@
 
 import javax.faces.component.NamingContainer;
 import javax.faces.component.UIComponent;
-
 import javax.faces.component.UIViewRoot;
 
+import org.apache.myfaces.trinidad.component.UIXComponent;
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 
+
 /**
  * Utility functions used by the Apache Trinidad components.
  * <p>
@@ -45,7 +46,7 @@
    * returning a default value if the value is null.
    */
   public static Object resolveObject(
-    Object value, 
+    Object value,
     Object defaultValue
     )
   {
@@ -59,7 +60,7 @@
    * Utility method for component code that transforms Object->boolean.
    */
   public static boolean resolveBoolean(
-    Object  value, 
+    Object  value,
     boolean defaultValue
     )
   {
@@ -204,7 +205,7 @@
              ? (Number) value
              : defaultValue;
   }
-  
+
 
   /**
    * Utility method for component code that transforms Object->String.
@@ -231,7 +232,7 @@
              ? value.toString()
              : defaultValue;
   }
-  
+
   /**
    * Utility method for code that transforms Object->String[]
    */
@@ -240,7 +241,7 @@
   {
     return resolveStringArray(value, null);
   }
-  
+
   /**
    * Utility method for code that transforms Object->String[]
    */
@@ -252,15 +253,15 @@
              ? (String[]) value
              : defaultValue;
   }
-  
+
   /**
    * Utility method for code that transforms Object->Date
    */
-  public static Date resolveDate(Object value)  
+  public static Date resolveDate(Object value)
   {
     return resolveDate(value, null);
   }
-  
+
   /**
    * Utility method for code that transforms Object->Date
    */
@@ -271,15 +272,15 @@
     return (value != null)
              ? (Date) value
              : defaultValue;
-  }  
-  
+  }
+
   public static TimeZone resolveTimeZone(
     Object value
     )
   {
     return resolveTimeZone(value, null);
   }
-  
+
   public static TimeZone resolveTimeZone(
     Object value,
     TimeZone defaultValue
@@ -289,14 +290,14 @@
              ? (TimeZone) value
              : defaultValue;
   }
-  
+
   public static Locale resolveLocale(
     Object value
     )
   {
     return resolveLocale(value, null);
   }
-  
+
   public static Locale resolveLocale(
     Object value,
     Locale defaultValue
@@ -306,7 +307,7 @@
              ? (Locale) value
              : defaultValue;
   }
-  
+
   /**
    * Gets the root cause of an exception.
    * Keeps unwrapping the given throwable until the root cause is found.
@@ -323,98 +324,33 @@
     return t;
   }
 
-
   /**
-   * Find a component relative to another.
-   * <p>
-   * The relative ID must account for NamingContainers. If the component is already inside
-   * of a naming container, you can use a single colon to start the search from the root, 
-   * or multiple colons to move up through the NamingContainers - "::" will 
-   * pop out of the current naming container, ":::" will pop out of two
-   * naming containers, etc.
-   * </p>
-   * 
-   * @param from the component to search relative to
-   * @param scopedId the relative id path from the 'from' component to the
-   *                 component to find
-   * @return the component if found, null otherwise
-   * @see org.apache.myfaces.trinidad.render.RenderUtils#getRelativeId
-   * @see javax.faces.component.UIComponent#findComponent
+   * @deprecated Use {@link UIXComponent#findComponent(UIComponent, String)} instead
    */
+  @Deprecated
   public static UIComponent findRelativeComponent(
     UIComponent from,
     String      scopedId)
   {
-    if (from == null)
-        return null;
-    UIComponent originalFrom = from;
-    String originalRelativeId = scopedId;
-    
-    int idLength = scopedId.length();
-    // Figure out how many colons
-    int colonCount = 0;
-    while (colonCount < idLength)
-    {
-      if (scopedId.charAt(colonCount) != NamingContainer.SEPARATOR_CHAR)
-        break;
-      colonCount++;
-    }
-
-    // colonCount == 0: fully relative
-    // colonCount == 1: absolute (still normal findComponent syntax)
-    // colonCount > 1: for each extra colon after 1, pop out of
-    // the naming container (to the view root, if naming containers run out)
-    if (colonCount > 1)
-    {
-      scopedId = scopedId.substring(colonCount);
-      
-      // if the component is not a NamingContainer, then we need to 
-      // get the component's naming container and set this as the 'from'.
-      // this way we'll pop out of the component's 
-      // naming container if there is are multiple colons.
-      if (!(from instanceof NamingContainer))
-      {
-        from = _getParentNamingContainerOrViewRoot(from);
-      }
-      
-      // pop out of the naming containers if there are multiple colons
-      for (int j = 1; j < colonCount; j++)
-      {
-        from = _getParentNamingContainerOrViewRoot(from);
-      }
-    }
-
-    UIComponent found = from.findComponent(scopedId);
-    if (found != null)
-      return found;
-    else
-    {
-      // try the old way for backward compatability as far as it differed,
-      // which is only if the 'from' was not a NamingContainer.
-      if (!(originalFrom instanceof NamingContainer))
-        return _findRelativeComponentDeprecated(originalFrom, originalRelativeId);
-      else
-        return null;
-    }
-    
+    return UIXComponent.findComponent(from, scopedId);
   }
-  
+
   /**
    * Gets the scoped identifier for the target component. The scoping will be
    * within a subtree rooted by the supplied base component. If the supplied
-   * base component were to be the view root, the returned id will be the 
+   * base component were to be the view root, the returned id will be the
    * absolute id and hence prefixed with NamingContainer.SEPARATOR_CHARACTER.
-   * 
-   * This algorithm reverse matches that of UIComponent.findComponent(). 
-   * In other words, the scoped id returned by this method can be safely used 
+   *
+   * This algorithm reverse matches that of UIComponent.findComponent().
+   * In other words, the scoped id returned by this method can be safely used
    * in calls to findComponent() on the baseComponent, if it were to be
    * enclosing the targetComponent.
-   * 
+   *
    * This method assumes that the supplied baseComponent definitely encloses the
    * targetComponent, return value is not reliable if this is not the case.
-   * 
+   *
    * Examples of id returned: ':foo:bar:baz'/'foo:baz'/'foo'
-   * 
+   *
    * @param targetComponent The component for which the scoped id needs to be
    * determined.
    * @param baseComponent The component relative to which the scoped id for the
@@ -427,24 +363,24 @@
     UIComponent baseComponent)
   {
     String targetComponentId = targetComponent.getId();
-    
-    if (targetComponent == null || 
+
+    if (targetComponent == null ||
         targetComponentId == null ||
         targetComponentId.length() == 0)
       return null;
-    
+
     // Optimize when both arguments are the same
     if (targetComponent.equals(baseComponent))
       return targetComponentId;
 
     StringBuilder builder = new StringBuilder(100);
-    
+
     // Add a leading ':' if the baseComponent is the view root
     if (baseComponent instanceof UIViewRoot)
       builder.append(NamingContainer.SEPARATOR_CHAR);
 
     _buildScopedId(targetComponent, baseComponent, builder);
-    
+
     return builder.toString();
   }
 
@@ -463,7 +399,7 @@
     UIComponent  baseComponent,
     StringBuilder builder)
   {
-    UIComponent namingContainer = 
+    UIComponent namingContainer =
       _getParentNamingContainer(targetComponent, baseComponent);
 
     if (namingContainer != null)
@@ -471,17 +407,17 @@
       _buildScopedId(namingContainer, baseComponent, builder);
       builder.append(NamingContainer.SEPARATOR_CHAR);
     }
-      
+
     builder.append(targetComponent.getId());
   }
 
   /**
    * Returns the naming container of the component. This method makes sure that
-   * we don't go beyond the a supplied base component. 
-   * @param component the UIComponent 
+   * we don't go beyond the a supplied base component.
+   * @param component the UIComponent
    * @param baseComponent The component to limit the search up to.
-   * @return the naming container of the component which has to be in the 
-   * subtree rooted by the baseComponent. Returns null if no such ancestor 
+   * @return the naming container of the component which has to be in the
+   * subtree rooted by the baseComponent. Returns null if no such ancestor
    * naming container component exists.
    */
   private static UIComponent _getParentNamingContainer(
@@ -492,24 +428,24 @@
     //  in _buildScopedId()
     if (component.equals(baseComponent))
       return null;
-    
+
     UIComponent checkedParent = component.getParent();
-    
+
     while(checkedParent != null)
     {
       if (checkedParent instanceof NamingContainer)
         break;
-      
+
       // We hit the base component, abort.
       if (checkedParent == baseComponent)
         return null;
-      
+
       checkedParent = checkedParent.getParent();
     }
-    
+
     return checkedParent;
   }
-  
+
   // given a component, get its naming container. If the component
   // is a naming container, it will get its naming container.
   // if no parent naming containers exist, it stops at the ViewRoot.
@@ -532,12 +468,12 @@
    * new findRelativeComponent method is backward compatibility.
     * <p>
     * The relative ID must account for NamingContainers. If the component is already inside
-    * of a naming container, you can use a single colon to start the search from the root, 
-    * or multiple colons to move up through the NamingContainers - "::" will search from 
-    * the parent naming container, ":::" will search from the grandparent 
+    * of a naming container, you can use a single colon to start the search from the root,
+    * or multiple colons to move up through the NamingContainers - "::" will search from
+    * the parent naming container, ":::" will search from the grandparent
     * naming container, etc.
     * </p>
-    * 
+    *
     * @param from the component to search relative to
     * @param relativeId the relative path to the component to find
     * @return the component if found, null otherwise
@@ -545,7 +481,7 @@
   private static UIComponent _findRelativeComponentDeprecated(
     UIComponent from,
     String      relativeId)
-  {  
+  {
     UIComponent originalFrom = from;
     String originalRelativeId = relativeId;
 
@@ -580,12 +516,12 @@
     UIComponent found = from.findComponent(relativeId);
     if (found != null)
     {
-      _LOG.warning("DEPRECATED_RELATIVE_ID_SYNTAX", 
+      _LOG.warning("DEPRECATED_RELATIVE_ID_SYNTAX",
         new Object[] {originalRelativeId, originalFrom});
     }
     return found;
   }
-  
+
   static private final TrinidadLogger _LOG =
     TrinidadLogger.createTrinidadLogger(ComponentUtils.class);
 }