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 org.apache.myfaces.custom.equalvalidator;
20  
21  import javax.faces.FacesException;
22  import javax.faces.FactoryFinder;
23  import javax.faces.application.FacesMessage;
24  import javax.faces.component.EditableValueHolder;
25  import javax.faces.component.UIComponent;
26  import javax.faces.context.FacesContext;
27  import javax.faces.convert.Converter;
28  import javax.faces.convert.ConverterException;
29  import javax.faces.el.ValueBinding;
30  import javax.faces.render.RenderKit;
31  import javax.faces.render.RenderKitFactory;
32  import javax.faces.render.Renderer;
33  import javax.faces.validator.ValidatorException;
34  
35  import org.apache.myfaces.validator.ValidatorBase;
36  
37  
38  /**
39   * A custom validator for validations against foreign component values. 
40   * 
41   * Unless otherwise specified, all attributes accept static values or EL expressions.
42   * 
43   * @JSFValidator
44   *   name = "t:validateEqual"
45   *   class = "org.apache.myfaces.custom.equalvalidator.EqualValidator"
46   *   tagClass = "org.apache.myfaces.custom.equalvalidator.ValidateEqualTag"
47   *   serialuidtag = "-3249115551944863108L"
48   * @since 1.1.7
49   * @deprecated use myfaces commons mcv:validateEqual instead
50   * @author mwessendorf (latest modification by $Author: lu4242 $)
51   * @version $Revision: 691856 $ $Date: 2008-09-03 21:40:30 -0500 (Wed, 03 Sep 2008) $
52   */
53  
54  public abstract class AbstractEqualValidator extends ValidatorBase {
55  
56      /**
57       * <p>The standard converter id for this converter.</p>
58       */
59      public static final String     VALIDATOR_ID        = "org.apache.myfaces.validator.Equal";
60  
61      /**
62       * <p>The message identifier of the {@link FacesMessage} to be created if
63       * the equal_for check fails.</p>
64       */
65      public static final String EQUAL_MESSAGE_ID = "org.apache.myfaces.Equal.INVALID";
66  
67      public AbstractEqualValidator(){
68      }
69  
70    // -------------------------------------------------------- ValidatorIF
71      public void validate(
72          FacesContext facesContext,
73          UIComponent uiComponent,
74          Object value)
75          throws ValidatorException {
76  
77          if (facesContext == null) throw new NullPointerException("facesContext");
78          if (uiComponent == null) throw new NullPointerException("uiComponent");
79  
80          if (value == null)
81          {
82              return;
83          }
84  
85          UIComponent foreignComp = uiComponent.getParent().findComponent(getFor());
86          if(foreignComp==null)
87              throw new FacesException("Unable to find component '" + getFor() + "' (calling findComponent on component '" + uiComponent.getId() + "')");
88          if(false == foreignComp instanceof EditableValueHolder)
89              throw new FacesException("Component '" + foreignComp.getId() + "' does not implement EditableValueHolder");
90          EditableValueHolder foreignEditableValueHolder = (EditableValueHolder) foreignComp;
91  
92          if (foreignEditableValueHolder.isRequired() && foreignEditableValueHolder.getValue()== null ) {
93              return;
94          }
95          
96          Object foreignValue;
97          if (foreignEditableValueHolder.isValid())
98          {
99              foreignValue = foreignEditableValueHolder.getValue();
100         }
101         else
102         {
103             try 
104             {
105                 foreignValue = getConvertedValueNonValid(facesContext, foreignComp);
106             }
107             catch(ConverterException e)
108             {
109                 /*
110                  * If the value cannot be converted this should return,
111                  * because does not have sense compare one
112                  * foreign invalid value with other value.
113                  * this force end the validation but do not continue
114                  * with the next phases, because the converter
115                  * of the foreign component fails and show a validation error.
116                  */
117                 return;
118             }
119         }
120 
121         // Don't perform validation if the foreign value is null
122         if (null == foreignValue)
123         {
124             return;
125         }
126         
127 
128         Object[] args = {value.toString(),(foreignValue==null) ? foreignComp.getId():foreignValue.toString()};
129 
130         if(foreignEditableValueHolder.getValue()==null || !foreignValue.toString().equals(value.toString())  )
131         {
132             throw new ValidatorException(getFacesMessage(EQUAL_MESSAGE_ID, args));
133         }
134 
135     }
136     
137     // ---------------- Borrowed to convert foreign submitted values
138 
139     protected Renderer getRenderer(FacesContext context, UIComponent foreignComponent)
140     {
141         if (context == null) throw new NullPointerException("context");
142         String rendererType = foreignComponent.getRendererType();
143         if (rendererType == null) return null;
144         String renderKitId = context.getViewRoot().getRenderKitId();
145         RenderKitFactory rkf = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
146         RenderKit renderKit = rkf.getRenderKit(context, renderKitId);
147         Renderer renderer = renderKit.getRenderer(foreignComponent.getFamily(), rendererType);
148         if (renderer == null)
149         {
150             getFacesContext().getExternalContext().log("No Renderer found for component " + foreignComponent + " (component-family=" + foreignComponent.getFamily() + ", renderer-type=" + rendererType + ")");
151         }
152         return renderer;
153     }
154 
155     protected Converter findUIOutputConverter(FacesContext facesContext, UIComponent component)
156     {
157         Converter converter = ((EditableValueHolder)component).getConverter();
158         if (converter != null) return converter;
159 
160         //Try to find out by value binding
161         ValueBinding vb = component.getValueBinding("value");
162         if (vb == null) return null;
163 
164         Class valueType = vb.getType(facesContext);
165         if (valueType == null) return null;
166 
167         if (String.class.equals(valueType)) return null;    //No converter needed for String type
168         if (Object.class.equals(valueType)) return null;    //There is no converter for Object class
169 
170         try
171         {
172             return facesContext.getApplication().createConverter(valueType);
173         }
174         catch (FacesException e)
175         {
176             getFacesContext().getExternalContext().log("No Converter for type " + valueType.getName() + " found", e);
177             return null;
178         }
179     }
180 
181 
182     // --------------------- borrowed and modified from UIInput ------------
183 
184     protected Object getConvertedValueNonValid(FacesContext facesContext, UIComponent component)
185         throws ConverterException
186     {
187         Object componentValueObject;
188         Object submittedValue = ((EditableValueHolder) component).getSubmittedValue();
189         if (submittedValue == null)
190         {
191             componentValueObject = null;
192         }
193         else
194         {
195             Renderer renderer = getRenderer(facesContext, component);
196             if (renderer != null)
197             {
198                 componentValueObject = renderer.getConvertedValue(facesContext, component, submittedValue);
199             }
200             else if (submittedValue instanceof String)
201             {
202                 Converter converter = findUIOutputConverter(facesContext, component);
203                 if (converter != null)
204                 {
205                     componentValueObject = converter.getAsObject(facesContext, component, (String)submittedValue);
206                 }
207                 else
208                 {
209                     componentValueObject = submittedValue;
210                 }
211             }else{
212                 componentValueObject = submittedValue;
213             }
214         }
215         return componentValueObject;
216     }
217         
218     // -------------------------------------------------------- GETTER & SETTER
219 
220     /**
221      * the id of the foreign component, which is needed for the validation
222      * 
223      * @JSFProperty
224      * @return the foreign component_id, on which a value should be validated
225      */
226     public abstract String getFor();
227 
228     /**
229      * @param string the foreign component_id, on which a value should be validated
230      */
231     public abstract void setFor(String string);
232 }