View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package javax.faces.component;
20  
21  import java.util.Iterator;
22  
23  import javax.el.ValueExpression;
24  import javax.faces.application.FacesMessage;
25  import javax.faces.context.FacesContext;
26  import javax.faces.el.EvaluationException;
27  import javax.faces.el.MethodBinding;
28  import javax.faces.el.ValueBinding;
29  import javax.faces.validator.Validator;
30  import javax.faces.validator.ValidatorException;
31  
32  /**
33   * A collection of static helper methods for locating UIComponents.
34   * 
35   * @author Manfred Geiler (latest modification by $Author: bommel $)
36   * @version $Revision: 1187289 $ $Date: 2011-10-21 05:25:17 -0500 (Fri, 21 Oct 2011) $
37   */
38  class _ComponentUtils
39  {
40      private _ComponentUtils() {}
41  
42      static UIComponent findParentNamingContainer(UIComponent component,
43                                                   boolean returnRootIfNotFound)
44      {
45          UIComponent parent = component.getParent();
46          if (returnRootIfNotFound && parent == null)
47          {
48              return component;
49          }
50          while (parent != null)
51          {
52              if (parent instanceof NamingContainer) return parent;
53              if (returnRootIfNotFound)
54              {
55                  UIComponent nextParent = parent.getParent();
56                  if (nextParent == null)
57                  {
58                      return parent;  //Root
59                  }
60                  parent = nextParent;
61              }
62              else
63              {
64                  parent = parent.getParent();
65              }
66          }
67          return null;
68      }
69  
70      static UIComponent getRootComponent(UIComponent component)
71      {
72          UIComponent parent;
73          for(;;)
74          {
75              parent = component.getParent();
76              if (parent == null) return component;
77              component = parent;
78          }
79      }
80  
81      /**
82       * Find the component with the specified id starting from the specified
83       * component.
84       * <p>
85       * Param id must not contain any NamingContainer.SEPARATOR_CHAR characters
86       * (ie ":"). This method explicitly does <i>not</i> search into any
87       * child naming container components; this is expected to be handled
88       * by the caller of this method.
89       * <p>
90       * For an implementation of findComponent which does descend into
91       * child naming components, see org.apache.myfaces.custom.util.ComponentUtils.
92       * 
93       * @return findBase, a descendant of findBase, or null.
94       */
95      static UIComponent findComponent(UIComponent findBase, String id)
96      {
97          if (!(findBase instanceof NamingContainer) && idsAreEqual(id,findBase))
98          {
99              return findBase;
100         }
101         for (Iterator it = findBase.getFacetsAndChildren(); it.hasNext(); )
102         {
103             UIComponent childOrFacet = (UIComponent)it.next();
104             if (!(childOrFacet instanceof NamingContainer))
105             {
106                 UIComponent find = findComponent(childOrFacet, id);
107                 if (find != null) return find;
108             }
109             else if (idsAreEqual(id,childOrFacet))
110             {
111                 return childOrFacet;
112             }
113         }
114         if (findBase instanceof NamingContainer && idsAreEqual(id,findBase))
115         {
116             return findBase;
117         }
118         return null;
119     }
120 
121     /*
122      * Return true if the specified component matches the provided id.
123      * This needs some quirks to handle components whose id value gets
124      * dynamically "tweaked", eg a UIData component whose id gets
125      * the current row index appended to it.
126      */
127     private static boolean idsAreEqual(String id, UIComponent cmp)
128     {
129         if(id.equals(cmp.getId()))
130             return true;
131 
132         if(cmp instanceof UIData)
133         {
134             UIData uiData = ((UIData) cmp);
135 
136             if(uiData.getRowIndex()==-1)
137             {
138                 return dynamicIdIsEqual(id,cmp.getId());
139             }
140             return id.equals(cmp.getId()+NamingContainer.SEPARATOR_CHAR+uiData.getRowIndex());
141         }
142 
143         return false;
144     }
145 
146     private static boolean dynamicIdIsEqual(String dynamicId, String id)
147     {
148         return dynamicId.matches(id+":[0-9]*");
149     }
150 
151 
152     static void callValidators(FacesContext context, UIInput input, Object convertedValue)
153     {
154         // first invoke the list of validator components
155         Validator[] validators = input.getValidators();
156         for (int i = 0; i < validators.length; i++)
157         {
158             Validator validator = validators[i];
159             try
160             {
161                 validator.validate(context, input, convertedValue);
162             }
163             catch (ValidatorException e)
164             {
165                 input.setValid(false);
166                 
167                 String validatorMessage = input.getValidatorMessage();
168                 if(validatorMessage != null) {
169                     context.addMessage(input.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,validatorMessage,validatorMessage));
170                 } else {
171                     FacesMessage facesMessage = e.getFacesMessage();
172                     if (facesMessage != null)
173                     {
174                         facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
175                         context.addMessage(input.getClientId(context), facesMessage);
176                     }
177                 }
178             }
179         }
180 
181         // now invoke the validator method defined as a method-binding attribute
182         // on the component
183         MethodBinding validatorBinding = input.getValidator();
184         if (validatorBinding != null)
185         {
186             try
187             {
188                 validatorBinding.invoke(context,
189                                         new Object[] {context, input, convertedValue});
190             }
191             catch (EvaluationException e)
192             {
193                 input.setValid(false);
194                 Throwable cause = e.getCause();
195                 if (cause instanceof ValidatorException)
196                 {
197                     String validatorMessage = input.getValidatorMessage();
198                     if(validatorMessage != null) {
199                         context.addMessage(input.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,validatorMessage,validatorMessage));
200                     } 
201                     else {
202                         FacesMessage facesMessage = ((ValidatorException)cause).getFacesMessage();
203                         if (facesMessage != null)
204                         {
205                             facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
206                             context.addMessage(input.getClientId(context), facesMessage);
207                         }
208                     }
209                 }
210                 else
211                 {
212                     throw e;
213                 }
214             }
215         }
216     }
217     
218     static String getStringValue(FacesContext context, ValueBinding vb)
219     {
220         Object value = vb.getValue(context);
221         if(value == null)
222         {
223             return null;
224         }
225         return value.toString();
226     }
227 
228 
229     static <T> T getExpressionValue(UIComponent component, String attribute, T overrideValue, T defaultValue)
230     {
231         if (overrideValue != null)
232         {
233             return overrideValue;
234         }
235         ValueExpression ve = component.getValueExpression(attribute);
236         if (ve != null)
237         {
238             return (T) ve.getValue(component.getFacesContext().getELContext());
239         }
240         return defaultValue;
241     }
242 
243     static String getPathToComponent(UIComponent component) {
244         StringBuffer buf = new StringBuffer();
245 
246         if(component == null)
247         {
248             buf.append("{Component-Path : ");
249             buf.append("[null]}");
250             return buf.toString();
251         }
252 
253         getPathToComponent(component,buf);
254 
255         buf.insert(0,"{Component-Path : ");
256         buf.append("}");
257 
258         return buf.toString();
259     }
260 
261     private static void getPathToComponent(UIComponent component, StringBuffer buf)
262     {
263         if(component == null)
264             return;
265 
266         StringBuffer intBuf = new StringBuffer();
267 
268         intBuf.append("[Class: ");
269         intBuf.append(component.getClass().getName());
270         if(component instanceof UIViewRoot)
271         {
272             intBuf.append(",ViewId: ");
273             intBuf.append(((UIViewRoot) component).getViewId());
274         }
275         else
276         {
277             intBuf.append(",Id: ");
278             intBuf.append(component.getId());
279         }
280         intBuf.append("]");
281 
282         buf.insert(0,intBuf.toString());
283 
284         getPathToComponent(component.getParent(), buf);
285     }
286 }