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: FieldTag.java,v $
031: * Revision 1.14 2005/10/17 18:24:23 colinmacleod
032: * Made all list forms display only for now.
033: *
034: * Revision 1.13 2005/10/11 18:54:06 colinmacleod
035: * Fixed some checkstyle and javadoc issues.
036: *
037: * Revision 1.12 2005/10/09 09:55:17 colinmacleod
038: * Merged changes from ivata masks v0.6.2 into main trunk.
039: *
040: * Revision 1.11 2005/10/03 10:17:25 colinmacleod
041: * Fixed some style and javadoc issues.
042: *
043: * Revision 1.10 2005/10/02 14:06:34 colinmacleod
044: * Added/improved log4j logging.
045: *
046: * Revision 1.9 2005/09/29 12:22:34 colinmacleod
047: * Added session parameter to getFieldWriter.
048: *
049: * Revision 1.8 2005/09/14 13:23:25 colinmacleod
050: * Added serialVersionUID.
051: * Added fieldName, subFieldName to
052: * field tag.
053: *
054: * Revision 1.7.2.1 2005/10/08 10:54:51 colinmacleod
055: * Added temporary workarounds for bugs in ivata groupware v0.11.x
056: *
057: * Revision 1.7 2005/04/09 18:04:19 colinmacleod
058: * Changed copyright text to GPL v2 explicitly.
059: *
060: * Revision 1.6 2005/01/19 13:14:04 colinmacleod
061: * Renamed CausedByException to SystemException.
062: *
063: * Revision 1.5 2005/01/06 23:10:02 colinmacleod
064: * Moved up a version number.
065: * Changed copyright notices to 2005.
066: * Updated the documentation:
067: * - started working on multiproject:site docu.
068: * - changed the logo.
069: * Added checkstyle and fixed LOADS of style issues.
070: * Added separate thirdparty subproject.
071: * Added struts (in web), util and webgui (in webtheme) from ivata op.
072: *
073: * Revision 1.4 2004/12/23 21:28:32 colinmacleod
074: * Modifications to add ivata op compatibility.
075: *
076: * Revision 1.3 2004/11/12 15:10:42 colinmacleod
077: * Moved persistence classes from ivata op as a replacement for
078: * ValueObjectLocator.
079: *
080: * Revision 1.2 2004/11/11 13:48:40 colinmacleod
081: * Added subField.
082: *
083: * Revision 1.1.1.1 2004/05/16 20:40:33 colinmacleod
084: * Ready for 0.1 release
085: * -----------------------------------------------------------------------------
086: */
087: package com.ivata.mask.web.tag;
088:
089: import org.apache.log4j.Logger;
090:
091: import javax.servlet.http.HttpServletRequest;
092: import javax.servlet.jsp.JspException;
093: import javax.servlet.jsp.PageContext;
094: import javax.servlet.jsp.tagext.TagSupport;
095:
096: import org.apache.struts.taglib.TagUtils;
097:
098: import com.ivata.mask.Mask;
099: import com.ivata.mask.field.Field;
100: import com.ivata.mask.util.SystemException;
101: import com.ivata.mask.valueobject.ValueObject;
102: import com.ivata.mask.web.field.FieldWriter;
103: import com.ivata.mask.web.field.FieldWriterFactory;
104: import com.ivata.mask.web.struts.InputMaskForm;
105: import com.ivata.mask.web.struts.ListForm;
106:
107: /**
108: * <p>
109: * Creates an input field, or displays the value for a field.
110: * </p>
111: *
112: * @since ivata masks 0.1 (2004-05-11)
113: * @author Colin MacLeod
114: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
115: * @version $Revision: 1.14 $
116: */
117: public class FieldTag extends TagSupport {
118: /**
119: * Logger for this class.
120: */
121: private static final Logger logger = Logger
122: .getLogger(FieldTag.class);
123:
124: /**
125: * Serialization version (for <code>Serializable</code> interface).
126: */
127: private static final long serialVersionUID = 1L;
128: /**
129: * <p>
130: * Set this to the field writer factory we'll be using to create field
131: * writers.
132: * </p>
133: */
134: private static FieldWriterFactory fieldWriterFactory = null;
135:
136: /**
137: * <p>
138: * Get the field writer factory we'll be using to create field writers.
139: * </p>
140: *
141: * @param pageContext current tag page context, used to lookup the factory
142: * attribute.
143: * @return field writer factory, used to create field writers.
144: * @throws JspException
145: * if the field writer factory has not been set to an
146: * application scope attribute called {@link
147: * FieldWriterFactory#APPLICATION_ATTRIBUTE
148: * FieldWriterFactory.APPLICATION_ATTRIBUTE}.
149: */
150: public static synchronized FieldWriterFactory getFieldWriterFactory(
151: final PageContext pageContext) throws JspException {
152: if (logger.isDebugEnabled()) {
153: logger
154: .debug("getFieldWriterFactory(PageContext pageContext = "
155: + pageContext + ") - start");
156: }
157:
158: if (fieldWriterFactory == null) {
159: fieldWriterFactory = (FieldWriterFactory) TagUtils
160: .getInstance().lookup(pageContext,
161: FieldWriterFactory.APPLICATION_ATTRIBUTE,
162: "application");
163: if (fieldWriterFactory == null) {
164: throw new JspException(
165: "ERROR: you must specify a valid field "
166: + "writer factory in application scope, called '"
167: + FieldWriterFactory.APPLICATION_ATTRIBUTE
168: + "'");
169: }
170: }
171:
172: if (logger.isDebugEnabled()) {
173: logger
174: .debug("getFieldWriterFactory - end - return value = "
175: + fieldWriterFactory);
176: }
177: return fieldWriterFactory;
178: }
179:
180: /**
181: * <p>
182: * If <code>true</code>, the field will not allow user entry.
183: * </p>
184: */
185: private boolean disabled = false;
186: /**
187: * <p>
188: * Field to be displayed.
189: * </p>
190: */
191: private Field field;
192: /**
193: * <p>
194: * Name of the field to be displayed. You may specify this instead of the
195: * field, and the appropriate field will be retrieved from the mask.
196: * </p>
197: */
198: private String fieldName;
199: /**
200: * <p>
201: * If <code>true</code>, overrides the hidden value of the field definition,
202: * to make this a hidden field.
203: * </p>
204: * @see Field#isHidden
205: */
206: private boolean hidden = false;
207: /**
208: * <p>
209: * Sub-field within the field to be displayed.
210: * </p>
211: */
212: private Field subField;
213: /**
214: * <p>
215: * Name of the sub-field, within the field to be displayed. You may specify
216: * this instead of the sub-field, and the appropriate field will be
217: * retrieved from the mask.
218: * </p>
219: */
220: private String subFieldName;
221: /**
222: * <p>
223: * Value object to display/edit.
224: * </p>
225: */
226: private ValueObject valueObject;
227:
228: /**
229: * <p>
230: * Called when the tag is first encountered. Simply diplays the field for
231: * now.
232: * </p>
233: *
234: * @see javax.servlet.jsp.tagext.Tag#doStartTag()
235: */
236: public int doStartTag() throws JspException {
237: if (logger.isDebugEnabled()) {
238: logger.debug("doStartTag() - start");
239: }
240:
241: // you need to specify the field or the field name, one of the two
242: Field actualField, actualSubField;
243: ValueObject actualValueObject;
244: if ((fieldName == null) && (field == null)) {
245: throw new JspException("You must specify either field or "
246: + "fieldName attribute in field tag.");
247: }
248:
249: // make sure we have a field writer factory
250: getFieldWriterFactory(pageContext);
251: HttpServletRequest request = (HttpServletRequest) pageContext
252: .getRequest();
253: Mask mask = null;
254: ListForm listForm = (ListForm) request
255: .getAttribute(ListForm.REQUEST_ATTRIBUTE);
256: boolean displayOnly;
257: if (listForm == null) {
258: InputMaskForm maskForm = (InputMaskForm) request
259: .getAttribute(InputMaskForm.REQUEST_ATTRIBUTE);
260: // TODO: temporary workaround for ivata groupware
261: if (maskForm == null) {
262: maskForm = (InputMaskForm) request.getSession()
263: .getAttribute(InputMaskForm.REQUEST_ATTRIBUTE);
264: }
265: if (maskForm == null) {
266: throw new NullPointerException(
267: "Either ListForm or MaskForm "
268: + "must be specified in request scope.");
269: }
270: mask = maskForm.getMask();
271: displayOnly = maskForm.isDisplayOnly();
272: if (valueObject == null) {
273: actualValueObject = maskForm.getValueObject();
274: } else {
275: actualValueObject = valueObject;
276: }
277: } else {
278: mask = listForm.getMask();
279: // TODO: allow writable lists here
280: // displayOnly = mask.isDisplayOnly();
281: displayOnly = true;
282: actualValueObject = valueObject;
283: if (actualValueObject == null) {
284: throw new JspException(
285: "You must specify the valueObject "
286: + "attribute for a field tag in a list form.");
287: }
288: }
289: FieldWriter fieldWriter;
290: if (fieldName != null) {
291: actualField = mask.getField(fieldName);
292: } else {
293: actualField = field;
294: }
295: if (subFieldName != null) {
296: actualSubField = mask.getField(subFieldName);
297: } else {
298: actualSubField = subField;
299: }
300: try {
301: fieldWriter = fieldWriterFactory.getFieldWriter(request
302: .getSession(), actualValueObject, actualField,
303: actualSubField, hidden);
304: } catch (SystemException e) {
305: logger.error("doStartTag()", e);
306:
307: throw new JspException(e);
308: }
309: if (disabled) {
310: fieldWriter.setAttribute("disabled", "true");
311: } else {
312: fieldWriter.removeAttribute("disabled");
313: }
314: String value = fieldWriter.write(pageContext,
315: actualValueObject, displayOnly);
316: TagUtils.getInstance().write(pageContext, value);
317: int returnint = super .doStartTag();
318: if (logger.isDebugEnabled()) {
319: logger.debug("doStartTag() - end - return value = "
320: + returnint);
321: }
322: return returnint;
323: }
324:
325: /**
326: * <p>
327: * Field to be displayed.
328: * </p>
329: *
330: * @return field to be displayed.
331: */
332: public Field getField() {
333: if (logger.isDebugEnabled()) {
334: logger.debug("getField() - start");
335: }
336:
337: if (logger.isDebugEnabled()) {
338: logger.debug("getField() - end - return value = " + field);
339: }
340: return field;
341: }
342:
343: /**
344: * <p>
345: * Name of the field to be displayed. You may specify this instead of the
346: * field, and the appropriate field will be retrieved from the mask.
347: * </p>
348: *
349: * @return Returns the fieldName.
350: */
351: public String getFieldName() {
352: if (logger.isDebugEnabled()) {
353: logger.debug("getFieldName() - start");
354: }
355:
356: if (logger.isDebugEnabled()) {
357: logger.debug("getFieldName() - end - return value = "
358: + fieldName);
359: }
360: return fieldName;
361: }
362:
363: /**
364: * <p>
365: * Sub-field within the field to be displayed.
366: * </p>
367: *
368: * @return Sub-field within the field to be displayed.
369: */
370: public Field getSubField() {
371: if (logger.isDebugEnabled()) {
372: logger.debug("getSubField() - start");
373: }
374:
375: if (logger.isDebugEnabled()) {
376: logger.debug("getSubField() - end - return value = "
377: + subField);
378: }
379: return subField;
380: }
381:
382: /**
383: * <p>
384: * Name of the sub-field, within the field to be displayed. You may specify
385: * this instead of the sub-field, and the appropriate field will be
386: * retrieved from the mask.
387: * </p>
388: *
389: * @return Returns the subFieldName.
390: */
391: public String getSubFieldName() {
392: if (logger.isDebugEnabled()) {
393: logger.debug("getSubFieldName() - start");
394: }
395:
396: if (logger.isDebugEnabled()) {
397: logger.debug("getSubFieldName() - end - return value = "
398: + subFieldName);
399: }
400: return subFieldName;
401: }
402:
403: /**
404: * <p>
405: * Value object to display/edit.
406: * </p>
407: *
408: * @return value object to display/edit.
409: */
410: public ValueObject getValueObject() {
411: if (logger.isDebugEnabled()) {
412: logger.debug("getValueObject() - start");
413: }
414:
415: if (logger.isDebugEnabled()) {
416: logger.debug("getValueObject() - end - return value = "
417: + valueObject);
418: }
419: return valueObject;
420: }
421:
422: /**
423: * <p>
424: * If <code>true</code>, the field will not allow user entry.
425: * </p>
426: *
427: * @return Returns whether or not the field is disabled.
428: */
429: public boolean isDisabled() {
430: if (logger.isDebugEnabled()) {
431: logger.debug("isDisabled() - start");
432: }
433:
434: if (logger.isDebugEnabled()) {
435: logger.debug("isDisabled() - end - return value = "
436: + disabled);
437: }
438: return disabled;
439: }
440:
441: /**
442: * <p>
443: * If <code>true</code>, overrides the hidden value of the field definition,
444: * to make this a hidden field.
445: * </p>
446: * @return Returns whether or not the field definition is overridden as
447: * hidden.
448: * @see Field#isHidden
449: */
450: public boolean isHidden() {
451: if (logger.isDebugEnabled()) {
452: logger.debug("isHidden() - start");
453: }
454:
455: if (logger.isDebugEnabled()) {
456: logger.debug("isHidden() - end - return value = " + hidden);
457: }
458: return hidden;
459: }
460:
461: /**
462: * <p>
463: * If <code>true</code>, the field will not allow user entry.
464: * </p>
465: *
466: * @param disabledParam Set whether or not the field is disabled.
467: */
468: public void setDisabled(final boolean disabledParam) {
469: if (logger.isDebugEnabled()) {
470: logger.debug("setDisabled(boolean disabledParam = "
471: + disabledParam + ") - start");
472: }
473:
474: this .disabled = disabledParam;
475:
476: if (logger.isDebugEnabled()) {
477: logger.debug("setDisabled(boolean) - end");
478: }
479: }
480:
481: /**
482: * <p>
483: * Stores the identifier of the field within this group to be displayed.
484: * </p>
485: *
486: * @param fieldParam definition of the field which this tag is going to
487: * display/edit.
488: */
489: public final void setField(final Field fieldParam) {
490: if (logger.isDebugEnabled()) {
491: logger.debug("setField(Field fieldParam = " + fieldParam
492: + ") - start");
493: }
494:
495: this .field = fieldParam;
496:
497: if (logger.isDebugEnabled()) {
498: logger.debug("setField(Field) - end");
499: }
500: }
501:
502: /**
503: * <p>
504: * Name of the field to be displayed. You may specify this instead of the
505: * field, and the appropriate field will be retrieved from the mask.
506: * </p>
507: *
508: * @param fieldNameParam <copyDoc>Refer to {@link #getfieldName}.</copyDoc>
509: */
510: public void setFieldName(final String fieldNameParam) {
511: if (logger.isDebugEnabled()) {
512: logger.debug("setFieldName(String fieldNameParam = "
513: + fieldNameParam + ") - start");
514: }
515:
516: fieldName = fieldNameParam;
517:
518: if (logger.isDebugEnabled()) {
519: logger.debug("setFieldName(String) - end");
520: }
521: }
522:
523: /**
524: * <p>
525: * If <code>true</code>, overrides the hidden value of the field definition,
526: * to make this a hidden field.
527: * </p>
528: * @param hiddenParam Set to <code>true</code> to hide the field, overriding
529: * any setting in the field definition.
530: * @see Field#isHidden
531: */
532: public void setHidden(final boolean hiddenParam) {
533: if (logger.isDebugEnabled()) {
534: logger.debug("setHidden(boolean hiddenParam = "
535: + hiddenParam + ") - start");
536: }
537:
538: this .hidden = hiddenParam;
539:
540: if (logger.isDebugEnabled()) {
541: logger.debug("setHidden(boolean) - end");
542: }
543: }
544:
545: /**
546: * <p>
547: * Sub-field within the field to be displayed.
548: * </p>
549: *
550: * @param fieldParam
551: * Sub-field within the field to be displayed.
552: */
553: public void setSubField(final Field fieldParam) {
554: if (logger.isDebugEnabled()) {
555: logger.debug("setSubField(Field fieldParam = " + fieldParam
556: + ") - start");
557: }
558:
559: subField = fieldParam;
560:
561: if (logger.isDebugEnabled()) {
562: logger.debug("setSubField(Field) - end");
563: }
564: }
565:
566: /**
567: * <p>
568: * Name of the sub-field, within the field to be displayed. You may specify
569: * this instead of the sub-field, and the appropriate field will be
570: * retrieved from the mask.
571: * </p>
572: *
573: * @param subFieldNameParam
574: * <copyDoc>Refer to {@link #getSubFieldName}.</copyDoc>
575: */
576: public void setSubFieldName(final String subFieldNameParam) {
577: if (logger.isDebugEnabled()) {
578: logger.debug("setSubFieldName(String subFieldNameParam = "
579: + subFieldNameParam + ") - start");
580: }
581:
582: subFieldName = subFieldNameParam;
583:
584: if (logger.isDebugEnabled()) {
585: logger.debug("setSubFieldName(String) - end");
586: }
587: }
588:
589: /**
590: * <p>
591: * Value object to display/edit.
592: * </p>
593: *
594: * @param object
595: * value object to display/edit.
596: */
597: public void setValueObject(final ValueObject object) {
598: if (logger.isDebugEnabled()) {
599: logger.debug("setValueObject(ValueObject object = "
600: + object + ") - start");
601: }
602:
603: valueObject = object;
604:
605: if (logger.isDebugEnabled()) {
606: logger.debug("setValueObject(ValueObject) - end");
607: }
608: }
609: }
|