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