001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata masks may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: InputMaskForm.java,v $
031: * Revision 1.16 2005/12/05 10:43:03 colinmacleod
032: * Implemented tab key functionality.
033: *
034: * Revision 1.15 2005/10/14 21:00:36 colinmacleod
035: * reset now calls super-method to clear buttons.
036: *
037: * Revision 1.14 2005/10/14 14:05:49 colinmacleod
038: * Added performReset method to check if apply or ok buttons have been
039: * pressed before the form is reset.
040: *
041: * Revision 1.13 2005/10/11 18:54:06 colinmacleod
042: * Fixed some checkstyle and javadoc issues.
043: *
044: * Revision 1.12 2005/10/09 09:55:17 colinmacleod
045: * Merged changes from ivata masks v0.6.2 into main trunk.
046: *
047: * Revision 1.11 2005/10/03 10:17:25 colinmacleod
048: * Fixed some style and javadoc issues.
049: *
050: * Revision 1.10 2005/10/02 14:06:34 colinmacleod
051: * Added/improved log4j logging.
052: *
053: * Revision 1.9 2005/09/29 12:17:35 colinmacleod
054: * Moved resourceFieldPath from InputMaskForm to MaskForm.
055: *
056: * Revision 1.8 2005/09/14 12:57:08 colinmacleod
057: * Added serialVersionUID.
058: * Added setter for valueObject.
059: *
060: * Revision 1.7.2.1 2005/10/08 10:53:58 colinmacleod
061: * Added validation of mandatory fields.
062: *
063: * Revision 1.7 2005/04/27 17:23:28 colinmacleod
064: * Fixed bugs resulting from ivata masks changes
065: * for ivata groupware v0.11.
066: *
067: * Revision 1.6 2005/04/09 18:04:18 colinmacleod
068: * Changed copyright text to GPL v2 explicitly.
069: *
070: * Revision 1.5 2005/03/10 10:40:21 colinmacleod
071: * Added *button hidden* attributes.
072: *
073: * Revision 1.4 2005/01/19 13:14:02 colinmacleod
074: * Renamed CausedByException to SystemException.
075: *
076: * Revision 1.3 2005/01/07 08:08:24 colinmacleod
077: * Moved up a version number.
078: * Changed copyright notices to 2005.
079: * Updated the documentation:
080: * - started working on multiproject:site docu.
081: * - changed the logo.
082: * Added checkstyle and fixed LOADS of style issues.
083: * Added separate thirdparty subproject.
084: * Added struts (in web), util and webgui (in webtheme) from ivata op.
085: *
086: * Revision 1.2 2004/12/23 21:28:32 colinmacleod
087: * Modifications to add ivata op compatibility.
088: *
089: * Revision 1.1.1.1 2004/05/16 20:40:32 colinmacleod
090: * Ready for 0.1 release
091: * -----------------------------------------------------------------------------
092: */
093: package com.ivata.mask.web.struts;
094:
095: import java.beans.PropertyDescriptor;
096: import java.util.Arrays;
097: import java.util.Collection;
098: import java.util.Iterator;
099: import java.util.List;
100: import java.util.Map;
101: import java.util.Vector;
102:
103: import javax.naming.OperationNotSupportedException;
104: import javax.servlet.http.HttpServletRequest;
105: import javax.servlet.http.HttpSession;
106:
107: import org.apache.commons.beanutils.PropertyUtils;
108: import org.apache.log4j.Logger;
109: import org.apache.struts.action.ActionMapping;
110:
111: import com.ivata.mask.Mask;
112: import com.ivata.mask.field.Field;
113: import com.ivata.mask.field.FieldValueConvertor;
114: import com.ivata.mask.util.StringHandling;
115: import com.ivata.mask.util.VeryLazyList;
116: import com.ivata.mask.validation.ValidationError;
117: import com.ivata.mask.validation.ValidationErrors;
118: import com.ivata.mask.valueobject.ValueObject;
119:
120: /**
121: * This form references a single value object to be displayed.
122: *
123: * @author Colin MacLeod <a
124: * href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
125: * @since ivata masks 0.1 (2004-05-09)
126: * @version $Revision: 1.16 $
127: */
128: public class InputMaskForm extends MaskForm {
129: /**
130: * <strong>Log4J </strong> logger to provide tracing information.
131: */
132: private static final Logger logger = Logger
133: .getLogger(InputMaskForm.class);
134:
135: /**
136: * <p>
137: * Request attribute under which name this form is stored.
138: * </p>
139: */
140: public static final String REQUEST_ATTRIBUTE = "InputMaskForm";
141:
142: /**
143: * Serialization version (for <code>Serializable</code> interface).
144: */
145: private static final long serialVersionUID = 1L;
146:
147: /**
148: * <copyDoc>Refer to {@link #isApplyButtonHidden}.</copyDoc>
149: */
150: private boolean applyButtonHidden = false;
151:
152: /**
153: * <copyDoc>Refer to {@link #isClearButtonHidden}.</copyDoc>
154: */
155: private boolean clearButtonHidden = false;
156:
157: /**
158: * <copyDoc>Refer to {@link #isDeleteButtonHidden}.</copyDoc>
159: */
160: private boolean deleteButtonHidden = false;
161:
162: /**
163: * <copyDoc>Refer to {@link #isDeleteWithoutWarn}.</copyDoc>
164: */
165: private boolean deleteWithoutWarn = false;
166:
167: /**
168: * <copyDoc>Refer to {@link #isDisplayOnly}.</copyDoc>
169: */
170: private boolean displayOnly = false;
171:
172: /**
173: * <copyDoc>Refer to {@link #getInputMaskTabActiveTabKey}.</copyDoc>
174: */
175: private String inputMaskTabActiveTabKey;
176:
177: /**
178: * <copyDoc>Refer to {@link #isRefreshOpener}.</copyDoc>
179: */
180: private boolean refreshOpener = false;
181:
182: /**
183: * These are the names of properties which are not cleared, in the
184: * <code>clear</code> method.
185: */
186: private List savedProperties = new Vector();
187:
188: /**
189: * <copyDoc>Refer to {@link #getTabForward}.</copyDoc>
190: */
191: private String tabForward = "imTabFields";
192:
193: /**
194: * Message resource strings for the tab labels.
195: */
196: private List tabKeys = VeryLazyList.decorate(new Vector(Arrays
197: .asList(new String[] { "tab.general" })), String.class);
198:
199: /**
200: * <copyDoc>Refer to {@link #getValueObject}.</copyDoc>
201: */
202: private ValueObject valueObject;
203:
204: /**
205: * <p>
206: * Create a new mask form for the given value object.
207: * </p>
208: *
209: * @param valueObjectParam
210: * value object to be displayed.
211: * @param maskParam
212: * mask containing all the fields definitions to be displayed.
213: * @param baseClassParam
214: * base class of all value objects to show in the list associated
215: * with this mask.
216: */
217: public InputMaskForm(final ValueObject valueObjectParam,
218: final Mask maskParam, final Class baseClassParam) {
219: super (maskParam, baseClassParam);
220: this .valueObject = valueObjectParam;
221: // total hack and temporary workaround for ivata groupware v0.11.x
222: // will be removed in later releases
223: this .saveProperty("modified");
224: this .saveProperty("modifiedBy");
225: this .saveProperty("created");
226: this .saveProperty("createdBy");
227: }
228:
229: /**
230: * <p>
231: * Clear all bean properties to their default state.The difference between
232: * this and <code>reset</code> is that all properties are changed,
233: * regardless of current request state.
234: * </p>
235: *
236: * @see com.ivata.mask.web.struts.MaskForm#clear()
237: * @throws OperationNotSupportedException if the value object does not
238: * have a default constructor.
239: */
240: protected void clear() throws OperationNotSupportedException {
241: if (logger.isDebugEnabled()) {
242: logger.debug("clear() - start");
243: }
244:
245: Class dOClass = valueObject.getClass();
246: try {
247: valueObject = (ValueObject) dOClass.newInstance();
248: } catch (InstantiationException e) {
249: logger.error("clear()", e);
250:
251: throw new OperationNotSupportedException(
252: "You must override InputMask.clear to create a new "
253: + "value object of class '"
254: + dOClass.getName() + "' ("
255: + e.getClass().getName() + ": "
256: + e.getMessage() + ")");
257: } catch (IllegalAccessException e) {
258: logger.error("clear()", e);
259:
260: throw new OperationNotSupportedException(
261: "You must override InputMask.clear to create a new "
262: + "value object of class '"
263: + dOClass.getName() + "' ("
264: + e.getClass().getName() + ": "
265: + e.getMessage() + ")");
266: }
267:
268: if (logger.isDebugEnabled()) {
269: logger.debug("clear() - end");
270: }
271: }
272:
273: /**
274: * <p>
275: * Indicates which TAB is active. This name is generated by the tab control
276: * and depends on the name of the tab control !!!!!
277: * </p>
278: *
279: * @return Returns the key.
280: */
281: public final String getInputMaskTabActiveTabKey() {
282: if (logger.isDebugEnabled()) {
283: logger.debug("getInputMaskTabActiveTabKey - start");
284: }
285: if (logger.isDebugEnabled()) {
286: logger
287: .debug("getInputMaskTabActiveTabKey - end - return value = "
288: + inputMaskTabActiveTabKey);
289: }
290: return inputMaskTabActiveTabKey;
291: }
292:
293: /**
294: * Get the <em>Struts</em> action forward used to process the tab we
295: * are currently showing.
296: *
297: * @return Returns the action forward name of the tab page.
298: */
299: public final String getTabForward() {
300: if (logger.isDebugEnabled()) {
301: logger.debug("getTabForward - start");
302: }
303: if (logger.isDebugEnabled()) {
304: logger.debug("getTabForward - end - return value = "
305: + tabForward);
306: }
307: return tabForward;
308: }
309:
310: /**
311: * Message resource strings for the tab labels.
312: *
313: * @return Returns the tab keys.
314: */
315: public List getTabKeys() {
316: if (logger.isDebugEnabled()) {
317: logger.debug("getTabKeys() - start");
318: }
319:
320: if (logger.isDebugEnabled()) {
321: logger.debug("getTabKeys() - end - return value = "
322: + tabKeys);
323: }
324: return tabKeys;
325: }
326:
327: /**
328: * Value object whose values are to be displayed in the mask.
329: *
330: * @return Value object to be displayed.
331: */
332: public ValueObject getValueObject() {
333: if (logger.isDebugEnabled()) {
334: logger.debug("getValueObject() - start");
335: }
336:
337: if (logger.isDebugEnabled()) {
338: logger.debug("getValueObject() - end - return value = "
339: + valueObject);
340: }
341: return valueObject;
342: }
343:
344: /**
345: * Should the 'apply' button be shown or hidden?
346: *
347: * @return <code>true</code> if the apply button should <u>NOT</u> be
348: * shown.
349: */
350: public boolean isApplyButtonHidden() {
351: if (logger.isDebugEnabled()) {
352: logger.debug("isApplyButtonHidden() - start");
353: }
354:
355: if (logger.isDebugEnabled()) {
356: logger
357: .debug("isApplyButtonHidden() - end - return value = "
358: + applyButtonHidden);
359: }
360: return applyButtonHidden;
361: }
362:
363: /**
364: * Should the 'new' button be shown or hidden?
365: *
366: * @return <code>true</code> if the new button should <u>NOT</u> be
367: * shown.
368: */
369: public boolean isClearButtonHidden() {
370: if (logger.isDebugEnabled()) {
371: logger.debug("isClearButtonHidden() - start");
372: }
373:
374: if (logger.isDebugEnabled()) {
375: logger
376: .debug("isClearButtonHidden() - end - return value = "
377: + clearButtonHidden);
378: }
379: return clearButtonHidden;
380: }
381:
382: /**
383: * Should the 'delete' button be shown or hidden?
384: *
385: * @return <code>true</code> if the delete button should <u>NOT</u> be
386: * shown.
387: */
388: public boolean isDeleteButtonHidden() {
389: if (logger.isDebugEnabled()) {
390: logger.debug("isDeleteButtonHidden() - start");
391: }
392:
393: if (logger.isDebugEnabled()) {
394: logger
395: .debug("isDeleteButtonHidden() - end - return value = "
396: + deleteButtonHidden);
397: }
398: return deleteButtonHidden;
399: }
400:
401: /**
402: * Sets whether or not the dialog should warn before deleting a value
403: * object.
404: *
405: * @return <code>true</code> if a warning is displayed before deleting.
406: */
407: public boolean isDeleteWithoutWarn() {
408: if (logger.isDebugEnabled()) {
409: logger.debug("isDeleteWithoutWarn() - start");
410: }
411:
412: if (logger.isDebugEnabled()) {
413: logger
414: .debug("isDeleteWithoutWarn() - end - return value = "
415: + deleteWithoutWarn);
416: }
417: return deleteWithoutWarn;
418: }
419:
420: /**
421: * If the mask is marked display only, only the text values of the fields
422: * are show (i.e. display mode), and there are no fields for user input.
423: *
424: * @return <code>true</code> if only text field values should be shown.
425: */
426: public boolean isDisplayOnly() {
427: if (logger.isDebugEnabled()) {
428: logger.debug("isDisplayOnly() - start");
429: }
430:
431: boolean returnboolean = displayOnly
432: || getMask().isDisplayOnly();
433: if (logger.isDebugEnabled()) {
434: logger.debug("isDisplayOnly() - end - return value = "
435: + returnboolean);
436: }
437: return returnboolean;
438: }
439:
440: /**
441: * For pop-up windows, it is often useful to refresh the page which opened
442: * the pop-up, after the pop-up has changed something.
443: *
444: * @return Returns <code>true</code> if the page which opened this one
445: * should be refreshed on delete or confirm.
446: */
447: public boolean isRefreshOpener() {
448: if (logger.isDebugEnabled()) {
449: logger.debug("isRefreshOpener() - start");
450: }
451:
452: if (logger.isDebugEnabled()) {
453: logger.debug("isRefreshOpener() - end - return value = "
454: + refreshOpener);
455: }
456: return refreshOpener;
457: }
458:
459: /**
460: * <p>
461: * Decides whether or not we perform the form reset. Override this method
462: * to determine whether or not we should reset.
463: * </p>
464: * <p>
465: * This default implementation
466: * will reset only if the apply or ok button is pressed.
467: * </p>
468: *
469: * @return <code>true</code> if we should reset the form when
470: * <code>reset</code> is called.
471: */
472: protected boolean performReset() {
473: if (logger.isDebugEnabled()) {
474: logger.debug("performReset() - start");
475: }
476:
477: boolean returnboolean = !StringHandling.isNullOrEmpty(getOk())
478: || !StringHandling.isNullOrEmpty(getApply());
479: if (logger.isDebugEnabled()) {
480: logger.debug("performReset() - end - return value = "
481: + returnboolean);
482: }
483: return returnboolean;
484: }
485:
486: /**
487: * {@inheritDoc}
488: *
489: * @param mapping {@inheritDoc}
490: * @param request {@inheritDoc}
491: * @see DialogForm#reset {@inheritDoc}
492: */
493: public void reset(final ActionMapping mapping,
494: final HttpServletRequest request) {
495: if (logger.isDebugEnabled()) {
496: logger.debug("reset(ActionMapping mapping = " + mapping
497: + ", HttpServletRequest request = " + request
498: + ") - start");
499: }
500: // call the super-method to clear any buttons from previous reuqests
501: super .reset(mapping, request);
502:
503: // now only actually clear the elements of this value object if we have
504: // ok or apply button-type-thing pressed
505: if (!performReset()) {
506: if (logger.isDebugEnabled()) {
507: logger
508: .debug("reset() - performReset false, so leaving reset"
509: + " method - end");
510: }
511: return;
512: }
513:
514: // we can have no idea which value object fields were input, so assume
515: // all of them. if you subclass this class, you can override this
516: // behavior by either implementing your own reset method, or adding
517: // your property to the 'savedProperties'.
518: PropertyDescriptor[] descriptors = PropertyUtils
519: .getPropertyDescriptors(valueObject.getClass());
520: FieldValueConvertor convertor = new FieldValueConvertor();
521: for (int i = 0; i < descriptors.length; i++) {
522: PropertyDescriptor descriptor = descriptors[i];
523: try {
524: String propertyName = descriptor.getName();
525: // if the property is read-only, ignore it
526: if (descriptor.getWriteMethod() == null) {
527: continue;
528: }
529: if (!savedProperties.contains(propertyName)) {
530: Class propertyType = descriptor.getPropertyType();
531: // clear any collection
532: if (Collection.class.isAssignableFrom(propertyType)) {
533: Collection collection = (Collection) PropertyUtils
534: .getProperty(valueObject, descriptor
535: .getName());
536: collection.clear();
537: } else if (Map.class.isAssignableFrom(propertyType)) {
538: Map map = (Map) PropertyUtils.getProperty(
539: valueObject, descriptor.getName());
540: map.clear();
541: } else {
542: Object propertyValue = convertor
543: .convertFromString(propertyType, "");
544: PropertyUtils.setProperty(valueObject,
545: descriptor.getName(), propertyValue);
546: }
547: }
548: } catch (Exception e) {
549: // don't actually fail on exceptions here...
550: logger.error("Exception in InputMaskForm.reset", e);
551: }
552: }
553: super .reset(mapping, request);
554:
555: if (logger.isDebugEnabled()) {
556: logger
557: .debug("reset(ActionMapping, HttpServletRequest) - end");
558: }
559: }
560:
561: /**
562: * Mark a property to be saved. By default, the <code>clear</code> method
563: * (and hence the <code>reset</code> method) will set all property values
564: * to <code>null</code>. By adding your property to the list of those
565: * saved here, it will be ignored in the <code>clear</code> method.
566: *
567: * @param propertyNameParam
568: * name of the property to save.
569: */
570: protected final void saveProperty(final String propertyNameParam) {
571: if (logger.isDebugEnabled()) {
572: logger.debug("saveProperty(String propertyNameParam = "
573: + propertyNameParam + ") - start");
574: }
575:
576: savedProperties.add(propertyNameParam);
577:
578: if (logger.isDebugEnabled()) {
579: logger.debug("saveProperty(String) - end");
580: }
581: }
582:
583: /**
584: * <copyDoc>Refer to {@link #isApplyButtonHidden}.</copyDoc>
585: *
586: * @param applyButtonHiddenParam
587: * <copyDoc>Refer to {@link #isApplyButtonHidden}.</copyDoc>
588: */
589: public final void setApplyButtonHidden(
590: final boolean applyButtonHiddenParam) {
591: if (logger.isDebugEnabled()) {
592: logger
593: .debug("setApplyButtonHidden(boolean applyButtonHiddenParam = "
594: + applyButtonHiddenParam + ") - start");
595: }
596:
597: applyButtonHidden = applyButtonHiddenParam;
598:
599: if (logger.isDebugEnabled()) {
600: logger.debug("setApplyButtonHidden(boolean) - end");
601: }
602: }
603:
604: /**
605: * <copyDoc>Refer to {@link #isClearButtonHidden}.</copyDoc>
606: *
607: * @param clearButtonHiddenParam
608: * <copyDoc>Refer to {@link #isClearButtonHidden}.</copyDoc>
609: */
610: public final void setClearButtonHidden(
611: final boolean clearButtonHiddenParam) {
612: if (logger.isDebugEnabled()) {
613: logger
614: .debug("setClearButtonHidden(boolean clearButtonHiddenParam = "
615: + clearButtonHiddenParam + ") - start");
616: }
617:
618: clearButtonHidden = clearButtonHiddenParam;
619:
620: if (logger.isDebugEnabled()) {
621: logger.debug("setClearButtonHidden(boolean) - end");
622: }
623: }
624:
625: /**
626: * <copyDoc>Refer to {@link #isDeleteButtonHidden}.</copyDoc>
627: *
628: * @param deleteButtonHiddenParam
629: * <copyDoc>Refer to {@link #isDeleteButtonHidden}.</copyDoc>
630: */
631: public final void setDeleteButtonHidden(
632: final boolean deleteButtonHiddenParam) {
633: if (logger.isDebugEnabled()) {
634: logger.debug("setDeleteButtonHidden("
635: + "boolean deleteButtonHiddenParam = "
636: + deleteButtonHiddenParam + ") - start");
637: }
638:
639: deleteButtonHidden = deleteButtonHiddenParam;
640:
641: if (logger.isDebugEnabled()) {
642: logger.debug("setDeleteButtonHidden(boolean) - end");
643: }
644: }
645:
646: /**
647: * <copyDoc>Refer to {@link #isDeleteWithoutWarn}.</copyDoc>
648: *
649: * @param deleteWithoutWarnParam
650: * <copyDoc>Refer to {@link #isDeleteWithoutWarn}.</copyDoc>
651: */
652: public final void setDeleteWithoutWarn(
653: final boolean deleteWithoutWarnParam) {
654: if (logger.isDebugEnabled()) {
655: logger.debug("setDeleteWithoutWarn("
656: + "boolean deleteWithoutWarnParam = "
657: + deleteWithoutWarnParam + ") - start");
658: }
659:
660: deleteWithoutWarn = deleteWithoutWarnParam;
661:
662: if (logger.isDebugEnabled()) {
663: logger.debug("setDeleteWithoutWarn(boolean) - end");
664: }
665: }
666:
667: /**
668: * <copyDoc>Refer to {@link #isDisplayOnly}.</copyDoc>
669: *
670: * @param displayOnlyParam
671: * <copyDoc>Refer to {@link #isDisplayOnly}.</copyDoc>
672: */
673: public final void setDisplayOnly(final boolean displayOnlyParam) {
674: if (logger.isDebugEnabled()) {
675: logger.debug("setDisplayOnly(boolean b = "
676: + displayOnlyParam + ") - start");
677: }
678:
679: displayOnly = displayOnlyParam;
680:
681: if (logger.isDebugEnabled()) {
682: logger.debug("setDisplayOnly(boolean) - end");
683: }
684: }
685:
686: /**
687: * <copyCode>Refer to {@link #getInputMaskTabActiveTabKey}.</copyCode>
688: * @param inputMaskTabActiveTabKeyParam
689: * <copyCode>Refer to {@link #getInputMaskTabActiveTabKey}.</copyCode>
690: */
691: public final void setInputMaskTabActiveTabKey(
692: final String inputMaskTabActiveTabKeyParam) {
693: if (logger.isDebugEnabled()) {
694: logger.debug("setInputMaskTabActiveTabKey(InputMaskForm"
695: + " inputMaskTabActiveTabKeyParam = "
696: + inputMaskTabActiveTabKeyParam + ") - start");
697: }
698:
699: inputMaskTabActiveTabKey = inputMaskTabActiveTabKeyParam;
700:
701: if (logger.isDebugEnabled()) {
702: logger.debug("setInputMaskTabActiveTabKey - end");
703: }
704: }
705:
706: /**
707: * <copyDoc>Refer to {@link #isRefreshOpener}.</copyDoc>
708: *
709: * @param refreshOpenerParam
710: * <copyDoc>Refer to {@link #isRefreshOpener}.</copyDoc>
711: */
712: public final void setRefreshOpener(final boolean refreshOpenerParam) {
713: if (logger.isDebugEnabled()) {
714: logger
715: .debug("setRefreshOpener(boolean refreshOpenerParam = "
716: + refreshOpenerParam + ") - start");
717: }
718:
719: refreshOpener = refreshOpenerParam;
720:
721: if (logger.isDebugEnabled()) {
722: logger.debug("setRefreshOpener(boolean) - end");
723: }
724: }
725:
726: /**
727: * <copyDoc>Refer to {@link #getTabForward}.</copyDoc>
728: * @param tabForwardParam
729: * <copyDoc>Refer to {@link #getTabForward}.</copyDoc>
730: */
731: public final void setTabForward(final String tabForwardParam) {
732: if (logger.isDebugEnabled()) {
733: logger
734: .debug("setTabForward(InputMaskForm tabForwardParam = "
735: + tabForwardParam + ") - start");
736: }
737:
738: tabForward = tabForwardParam;
739:
740: if (logger.isDebugEnabled()) {
741: logger.debug("setTabForward - end");
742: }
743: }
744:
745: /**
746: * <copyDoc>Refer to {@link #getvalueObject}.</copyDoc>
747: *
748: * @param valueObjectParam
749: * <copyDoc>Refer to {@link #getvalueObject}.</copyDoc>
750: */
751: public void setValueObject(final ValueObject valueObjectParam) {
752: if (logger.isDebugEnabled()) {
753: logger
754: .debug("setValueObject(ValueObject valueObjectParam = "
755: + valueObjectParam + ") - start");
756: }
757:
758: valueObject = valueObjectParam;
759:
760: if (logger.isDebugEnabled()) {
761: logger.debug("setValueObject(ValueObject) - end");
762: }
763: }
764:
765: /**
766: * Overridden to check mandatory fields.
767: *
768: * @param requestParam {@inheritDoc}
769: * @param sessionParam {@inheritDoc}
770: * @return errors from the super class, with any mandatory field errors
771: * added.
772: */
773: public ValidationErrors validate(
774: final HttpServletRequest requestParam,
775: final HttpSession sessionParam) {
776: if (logger.isDebugEnabled()) {
777: logger.debug("validate(HttpServletRequest requestParam = "
778: + requestParam + ", HttpSession sessionParam = "
779: + sessionParam + ") - start");
780: }
781:
782: ValidationErrors errors = super .validate(requestParam,
783: sessionParam);
784: Mask mask = getMask();
785: List fields = mask.getFields();
786: Iterator fieldIterator = fields.iterator();
787: while (fieldIterator.hasNext()) {
788: Field field = (Field) fieldIterator.next();
789: if (!field.isMandatory()) {
790: continue;
791: }
792: try {
793: Object value = PropertyUtils.getProperty(valueObject,
794: field.getName());
795: if ((value == null)
796: || "".equals(value)
797: || "0".equals(value.toString())
798: || ((value instanceof Collection) && ((Collection) value)
799: .isEmpty())) {
800: errors.add(new ValidationError(field.getName(),
801: field, "errors.required"));
802: }
803: } catch (Exception e) {
804: logger.error("reset - encountered " + e.getClass()
805: + " getting property vale for " + field, e);
806: throw new RuntimeException(e);
807: }
808: }
809:
810: if (logger.isDebugEnabled()) {
811: logger.debug("validate - end - return value = " + errors);
812: }
813: return errors;
814: }
815: }
|