View Javadoc

1   /*
2    * JaspertReports JSF Plugin Copyright (C) 2011 A. Alonso Dominguez
3    *
4    * This library is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU Lesser General Public License as published by
6    * the Free Software Foundation; either version 2.1 of the License, or (at
7    * your option) any later version. This library is distributed in the hope
8    * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9    * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   *
11   * See the GNU Lesser General Public License for more details. You should have
12   * received a copy of the GNU Lesser General Public License along with this
13   * library; if not, write to the Free Software Foundation, Inc., 59 Temple
14   * Place, Suite 330, Boston, MA 02111-1307 USA A.
15   *
16   * Alonso Dominguez
17   * alonsoft@users.sf.net
18   */
19  package net.sf.jasperreports.jsf.component;
20  
21  import javax.el.ELException;
22  import javax.el.ValueExpression;
23  import javax.faces.FacesException;
24  import javax.faces.application.FacesMessage;
25  import javax.faces.component.UIComponentBase;
26  import javax.faces.context.FacesContext;
27  import javax.faces.validator.Validator;
28  import javax.faces.validator.ValidatorException;
29  
30  import net.sf.jasperreports.jsf.Constants;
31  import net.sf.jasperreports.jsf.context.JRFacesContext;
32  import net.sf.jasperreports.jsf.convert.SourceConverter;
33  import net.sf.jasperreports.jsf.engine.Source;
34  import net.sf.jasperreports.jsf.validation.MissingAttributeException;
35  import net.sf.jasperreports.jsf.validation.SourceValidatorBase;
36  
37  import static net.sf.jasperreports.jsf.util.MessagesFactory.*;
38  
39  /**
40   * Faces component (non-rendered) used to feed the report
41   * with external data.
42   *
43   * @author A. Alonso Dominguez
44   */
45  public class UISource extends UIComponentBase {
46  
47      /** Specific family name used with report sources. */
48      public static final String COMPONENT_FAMILY =
49              Constants.PACKAGE_PREFIX + ".Source";
50  
51      /** Specific component type name. */
52      public static final String COMPONENT_TYPE =
53              Constants.PACKAGE_PREFIX + ".Source";
54  
55      // Fields
56  
57      /** The query used to filter the results. */
58      private String query = null;
59  
60      /** The type of this source instance. */
61      private String type = null;
62      /** Flag to identify if type attribute has been locally set. */
63      private boolean typeSet = false;
64  
65      /** Flag to determine if this source instance is valid. */
66      private boolean valid = true;
67  
68      /** The source value. */
69      private Object value;
70      /** Flag to identify if value attribute has been locally set. */
71      private boolean valueSet = false;
72  
73      /** The source converter instance. */
74      private SourceConverter converter;
75  
76      /** The source validator instance. */
77      private Validator validator;
78  
79      /** The interpretted source value. */
80      private Source submittedSource;
81  
82      /**
83       * Instantiates a new data source.
84       */
85      public UISource() {
86          super();
87          setRendererType(null);
88      }
89  
90      // Properties
91  
92      /**
93       * Gets the query.
94       *
95       * @return the query
96       */
97      public final String getQuery() {
98          if (query != null) {
99              return query;
100         }
101         final ValueExpression ve = getValueExpression("query");
102         if (ve != null) {
103             try {
104                 return (String) ve.getValue(
105                         getFacesContext().getELContext());
106             } catch (final ELException e) {
107                 throw new FacesException(e);
108             }
109         } else {
110             return query;
111         }
112     }
113 
114     /**
115      * Sets the query.
116      *
117      * @param query the new query
118      */
119     public final void setQuery(final String query) {
120         this.query = query;
121     }
122 
123     /**
124      * Gets the type.
125      *
126      * @return the type
127      */
128     public final String getType() {
129         if (typeSet) {
130             return type;
131         }
132         final ValueExpression ve = getValueExpression("type");
133         if (ve != null) {
134             try {
135                 return (String) ve.getValue(
136                         getFacesContext().getELContext());
137             } catch (final ELException e) {
138                 throw new FacesException(e);
139             }
140         } else {
141             return type;
142         }
143     }
144 
145     /**
146      * Sets the type.
147      *
148      * @param type the new type
149      */
150     public final void setType(final String type) {
151         this.type = type;
152         typeSet = true;
153     }
154 
155     /**
156      * Checks if this source configuration is valid.
157      *
158      * @return if this source instance is valid.
159      */
160     public final boolean isValid() {
161         return valid;
162     }
163 
164     /**
165      * Establishes a new value for the <tt>valid</tt> state.
166      *
167      * @param valid new valid value.
168      */
169     protected final void setValid(final boolean valid) {
170         this.valid = valid;
171     }
172 
173     /**
174      * Gets the value.
175      *
176      * @return the value
177      */
178     public final Object getValue() {
179         if (valueSet) {
180             return value;
181         }
182         final ValueExpression ve = getValueExpression("value");
183         if (ve != null) {
184             try {
185                 return ve.getValue(
186                         getFacesContext().getELContext());
187             } catch (final ELException e) {
188                 throw new FacesException(e);
189             }
190         } else {
191             return value;
192         }
193     }
194 
195     /**
196      * Sets the value.
197      *
198      * @param value the new value
199      */
200     public final void setValue(final Object value) {
201         this.value = value;
202         valueSet = true;
203     }
204 
205     /**
206      * Obtains the <tt>SourceConverter</tt> instance.
207      *
208      * @return current <tt>SourceConverter</tt> instance.
209      */
210     public final SourceConverter getConverter() {
211         if (converter != null) {
212             return converter;
213         }
214         ValueExpression ve = getValueExpression("converter");
215         if (ve != null) {
216             try {
217                 return (SourceConverter) ve.getValue(
218                         getFacesContext().getELContext());
219             } catch (ELException e) {
220                 throw new FacesException(e);
221             }
222         } else {
223             return converter;
224         }
225     }
226 
227     /**
228      * Establishes a new <tt>SourceConverter</tt> instance.
229      *
230      * @param converter the new <tt>SourceConverter</tt> instance.
231      */
232     public final void setConverter(final SourceConverter converter) {
233         this.converter = converter;
234     }
235 
236     public Validator getValidator() {
237         if (validator != null) {
238             return validator;
239         }
240         ValueExpression ve = getValueExpression("validator");
241         if (ve != null) {
242             try {
243                 return (Validator) ve.getValue(
244                         getFacesContext().getELContext());
245             } catch (ELException e) {
246                 throw new FacesException(e);
247             }
248         } else {
249             return validator;
250         }
251     }
252 
253     public void setValidator(Validator validator) {
254         this.validator = validator;
255     }
256 
257     public Source getSubmittedSource() {
258         return submittedSource;
259     }
260 
261     public void setSubmittedSource(Source submittedSource) {
262         this.submittedSource = submittedSource;
263     }
264 
265     // UIComponent
266 
267     /*
268      * (non-Javadoc)
269      *
270      * @see javax.faces.component.UIComponent#getFamily()
271      */
272     @Override
273     public String getFamily() {
274         return COMPONENT_FAMILY;
275     }
276 
277     public void resetValue() {
278         setValue(null);
279         setValid(true);
280         setSubmittedSource(null);
281         valueSet = false;
282     }
283 
284     /*
285      * (non-Javadoc)
286      *
287      * @see
288      * javax.faces.component.UIComponentBase#restoreState(javax.faces.context
289      * .FacesContext, java.lang.Object)
290      */
291     @Override
292     public void restoreState(final FacesContext context, final Object state) {
293         final Object[] values = (Object[]) state;
294         super.restoreState(context, values[0]);
295         query = (String) values[1];
296         type = (String) values[2];
297         typeSet = ((Boolean) values[3]).booleanValue();
298         converter = (SourceConverter) values[4];
299         validator = (Validator) values[5];
300         valid = ((Boolean) values[6]).booleanValue();
301     }
302 
303     /*
304      * (non-Javadoc)
305      *
306      * @see javax.faces.component.UIComponentBase#saveState(javax.faces.context.
307      * FacesContext)
308      */
309     @Override
310     public Object saveState(final FacesContext context) {
311         final Object[] values = new Object[7];
312         values[0] = super.saveState(context);
313         values[1] = query;
314         values[2] = type;
315         values[3] = Boolean.valueOf(typeSet);
316         values[4] = converter;
317         values[5] = validator;
318         values[6] = valid;
319         return values;
320     }
321 
322     @Override
323     public void processDecodes(FacesContext context) {
324         if (context == null) {
325             throw new IllegalArgumentException();
326         }
327 
328         setValid(false);
329         setSubmittedSource(null);
330         
331         super.processDecodes(context);
332 
333         try {
334             executeValidate(context);
335             decodeValue(context);
336         } catch (RuntimeException e) {
337             context.renderResponse();
338             throw e;
339         }
340     }
341 
342     @Override
343     public void processUpdates(FacesContext context) {
344         if (context == null) {
345             throw new IllegalArgumentException();
346         }
347         
348         super.processUpdates(context);
349 
350         try {
351             updateModel(context);
352         } catch(RuntimeException e) {
353             context.renderResponse();
354             throw e;
355         }
356 
357         if (!isValid()) {
358             context.renderResponse();
359         }
360     }
361 
362     @Override
363     public void processValidators(FacesContext context) {
364         if (context == null) {
365             throw new IllegalArgumentException();
366         }
367 
368         super.processValidators(context);
369         executeValidate(context);
370     }
371 
372     public void decodeValue(FacesContext context) {
373         if (context == null) {
374             throw new IllegalArgumentException();
375         }
376 
377         SourceConverter aConverter = getConverter();
378         if (aConverter == null) {
379             aConverter = getJRFacesContext()
380                     .createSourceConverter(context, this);
381         }
382 
383         Source source = aConverter.convertFromValue(
384                 context, this, getValue());
385         setSubmittedSource(source);
386     }
387 
388     public void updateModel(FacesContext context) {
389         if (context == null) {
390             throw new IllegalArgumentException();
391         }
392 
393         if (!isValid()) {
394             return;
395         }
396 
397         ValueExpression ve = getValueExpression("value");
398         if (valueSet && (ve != null) && (getSubmittedSource() != null)) {
399             try {
400                 ve.setValue(getFacesContext().getELContext(),
401                         getSubmittedSource());
402             } catch (ELException e) {
403                 throw new FacesException(e);
404             }
405         } else {
406             // Send report source as a request attribute
407             String clientId = getClientId(context);
408             context.getExternalContext().getRequestMap()
409                     .put(clientId, submittedSource);
410         }
411     }
412 
413     public void validate(FacesContext context) throws ValidatorException {
414         if (context == null) {
415             throw new IllegalArgumentException();
416         }
417 
418         String aType = getType();
419         if (aType == null) {
420             FacesMessage message = createMessage(context,
421                     FacesMessage.SEVERITY_FATAL, "MISSING_ATTRIBUTE", "type");
422             throw new MissingAttributeException(message);
423         }
424 
425         Object aValue = getValue();
426         if (aValue == null) {
427             FacesMessage message = createMessage(context,
428                     FacesMessage.SEVERITY_FATAL, "MISSING_ATTRIBUTE", "value");
429             throw new MissingAttributeException(message);
430         }
431 
432         Validator aValidator = getValidator();
433         if (aValidator == null) {
434             aValidator = getFacesContext().getApplication()
435                     .createValidator(SourceValidatorBase.VALIDATOR_TYPE);
436         }
437 
438         if (aValidator != null) {
439             aValidator.validate(context, this, getValue());
440         }
441     }
442 
443     protected void executeValidate(FacesContext context)
444             throws ValidatorException {
445 //        Object providedValue = getValue();
446         if (!isValid()) {
447             try {
448                 validate(context);
449                 setValid(true);
450             } catch(ValidatorException e) {
451                 setValid(false);
452                 context.renderResponse();
453                 throw e;
454             }
455         }
456     }
457 
458     /**
459      * Obtains the current <tt>JRFacesContext</tt> instance.
460      *
461      * @return current <tt>JRFacesContext</tt> instance.
462      */
463     protected final JRFacesContext getJRFacesContext() {
464         return JRFacesContext.getInstance(getFacesContext());
465     }
466 
467 }