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: ValueObjectFieldWriter.java,v $
031: * Revision 1.12 2005/10/11 18:54:06 colinmacleod
032: * Fixed some checkstyle and javadoc issues.
033: *
034: * Revision 1.11 2005/10/03 10:17:25 colinmacleod
035: * Fixed some style and javadoc issues.
036: *
037: * Revision 1.10 2005/10/02 14:06:33 colinmacleod
038: * Added/improved log4j logging.
039: *
040: * Revision 1.9 2005/09/29 12:14:44 colinmacleod
041: * Cosmetic (max line length) reformatting.
042: *
043: * Revision 1.8 2005/04/09 18:04:18 colinmacleod
044: * Changed copyright text to GPL v2 explicitly.
045: *
046: * Revision 1.7 2005/01/19 12:50:34 colinmacleod
047: * Added attribute delegate methods.
048: *
049: * Revision 1.6 2005/01/11 10:12:28 colinmacleod
050: * Added workaround for when valuesParam is null.
051: *
052: * Revision 1.5 2005/01/07 08:08:23 colinmacleod
053: * Moved up a version number.
054: * Changed copyright notices to 2005.
055: * Updated the documentation:
056: * - started working on multiproject:site docu.
057: * - changed the logo.
058: * Added checkstyle and fixed LOADS of style issues.
059: * Added separate thirdparty subproject.
060: * Added struts (in web), util and webgui (in webtheme) from ivata op.
061: *
062: * Revision 1.4 2004/12/30 20:20:42 colinmacleod
063: * Set style class if mandatory.
064: *
065: * Revision 1.3 2004/12/29 15:30:10 colinmacleod
066: * Added asserts to check parameters are not null.
067: *
068: * Revision 1.2 2004/12/23 21:28:31 colinmacleod
069: * Modifications to add ivata op compatibility.
070: *
071: * Revision 1.1 2004/11/11 13:41:08 colinmacleod
072: * First version in CVS. Added to display value object contents.
073: *
074: * Revision 1.1.1.1 2004/05/16 20:40:32 colinmacleod
075: * Ready for 0.1 release
076: * -----------------------------------------------------------------------------
077: */
078: package com.ivata.mask.web.field.valueobject;
079:
080: import org.apache.log4j.Logger;
081:
082: import com.ivata.mask.Mask;
083: import com.ivata.mask.field.Field;
084: import com.ivata.mask.util.StringHandling;
085: import com.ivata.mask.valueobject.ValueObject;
086: import com.ivata.mask.web.field.AttributesWriter;
087: import com.ivata.mask.web.field.FieldWriter;
088: import com.ivata.mask.web.format.HTMLFormatter;
089: import org.apache.commons.beanutils.PropertyUtils;
090: import org.apache.struts.taglib.TagUtils;
091: import org.dom4j.Document;
092: import org.dom4j.DocumentFactory;
093: import org.dom4j.Element;
094: import java.lang.reflect.InvocationTargetException;
095: import java.net.MalformedURLException;
096: import java.util.Collection;
097: import java.util.HashMap;
098: import java.util.Iterator;
099: import java.util.List;
100: import java.util.Map;
101: import java.util.Vector;
102: import javax.servlet.jsp.PageContext;
103:
104: /**
105: * <p>
106: * This writer is used to display links to other value objects.
107: * </p>
108: *
109: * @since ivata masks 0.2 (2004-05-14)
110: * @author Colin MacLeod
111: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
112: * @version $Revision: 1.12 $
113: */
114: public class ValueObjectFieldWriter implements FieldWriter {
115: /**
116: * Logger for this class.
117: */
118: private static final Logger logger = Logger
119: .getLogger(ValueObjectFieldWriter.class);
120:
121: /**
122: * <p>
123: * This is the style class used for combo (single choice) lists.
124: * </p>
125: */
126: public static final String CSS_COMBO = "combo";
127: /**
128: * <p>
129: * This is the style class used for multiple choice lists.
130: * </p>
131: */
132: public static final String CSS_LIST = "list";
133: /**
134: * <p>
135: * This is the value which is output as a default. TODO: i18n
136: * </p>
137: */
138: public static final String DEFAULT_DISPLAY_VALUE = "[None]";
139: /**
140: * <p>
141: * This is the value which is output as a default. TODO: i18n
142: * </p>
143: */
144: public static final String DEFAULT_VALUE = "";
145: /**
146: * <p>
147: * This is the value which is output as a new entry. TODO: i18n
148: * </p>
149: */
150: public static final String NEW_DISPLAY_VALUE = "[New]";
151: /**
152: * <p>
153: * Local page of the action to which we'll link, for a read-only field.
154: * </p>
155: */
156: private String actionPage;
157: /**
158: * <copyDoc>Refer to {@link #getAllValueObjects}.</copyDoc>
159: */
160: private Collection allValueObjects;
161: /**
162: * <p>
163: * Stores all of the field's attributes and values, then writes them out
164: * later.
165: * </p>
166: */
167: private AttributesWriter attributesWriter;
168: /**
169: * <p>
170: * Field to be displayed.
171: * </p>
172: */
173: private Field field;
174: /**
175: * <p>
176: * Used to format the returned text.
177: * </p>
178: */
179: private HTMLFormatter formatter;
180: /**
181: * <p>
182: * Stores all of the hidden field's attributes and values, then writes them
183: * out later. This is used for a sublist.
184: * </p>
185: */
186: private AttributesWriter hiddenAttributesWriter;
187:
188: /**
189: * <p>
190: * Construct a field writer.
191: * </p>
192: *
193: * @param fieldParam
194: * defines the field to be displayed.
195: * @param actionPageParam
196: * <copyDoc>Refer to {@link DefaultFieldWriter#getActionPage}.</copyDoc>
197: * @param allValueObjectsParam
198: * <copyDoc>Refer to {@link #getAllValueObjects}.</copyDoc>
199: * @param formatterParam
200: * <copyDoc>Refer to {@link #getFormatter}.</copyDoc>
201: * @param listHeightParam
202: * set as the size attribute in the field.
203: * @param multipleParam
204: * if <code>true</code>, then the user can make more than one
205: * selection.
206: */
207: public ValueObjectFieldWriter(final Field fieldParam,
208: final String actionPageParam,
209: final Collection allValueObjectsParam,
210: final HTMLFormatter formatterParam,
211: final int listHeightParam, final boolean multipleParam) {
212: super ();
213: this .field = fieldParam;
214: this .actionPage = actionPageParam;
215: this .allValueObjects = allValueObjectsParam;
216: this .formatter = formatterParam;
217: boolean multiple = multipleParam;
218: // we don't want to actually submit the values in a sublist
219: String propertyNameSuffix;
220: if (isSublist()) {
221: propertyNameSuffix = "_sublist";
222: // sublists can be multi-choice
223: multiple = false;
224: } else {
225: propertyNameSuffix = "";
226: }
227: attributesWriter = new AttributesWriter(fieldParam,
228: propertyNameSuffix);
229: attributesWriter.setAttribute("size", Integer
230: .toString(listHeightParam));
231: if (fieldParam.isMandatory()) {
232: attributesWriter.appendAttribute("class", "mandatory");
233: }
234: if (multiple) {
235: attributesWriter.setAttribute("multiple", "multiple");
236: // if the field type wasn't set explicitly, set the class here
237: if (StringHandling.isNullOrEmpty(fieldParam.getType())) {
238: attributesWriter.appendAttribute("class", CSS_LIST);
239: }
240: } else {
241: attributesWriter.remove("multiple");
242: // if the field type wasn't set explicitly, set the class here
243: if (StringHandling.isNullOrEmpty(fieldParam.getType())) {
244: attributesWriter.appendAttribute("class", CSS_COMBO);
245: }
246: }
247: }
248:
249: /**
250: * All possible value objects to display in a list - for a choice. The user
251: * will be given the chance to choose from only these values.
252: *
253: * @return Returns the all value objects as a <code>Collection</code> of
254: * <code>ValueObject</code> instances.
255: */
256: protected final Collection getAllValueObjects() {
257: if (logger.isDebugEnabled()) {
258: logger.debug("getAllValueObjects() - start");
259: }
260:
261: if (logger.isDebugEnabled()) {
262: logger.debug("getAllValueObjects() - end - return value = "
263: + allValueObjects);
264: }
265: return allValueObjects;
266: }
267:
268: /**
269: * <p>
270: * Access the attributes writer, which is responsible for converting the
271: * field attributes into text.
272: * </p>
273: *
274: * @return attributes writer.
275: */
276: protected final AttributesWriter getAttributesWriter() {
277: if (logger.isDebugEnabled()) {
278: logger.debug("getAttributesWriter() - start");
279: }
280:
281: if (logger.isDebugEnabled()) {
282: logger
283: .debug("getAttributesWriter() - end - return value = "
284: + attributesWriter);
285: }
286: return attributesWriter;
287: }
288:
289: /**
290: * <p>
291: * Access the field to be displayed.
292: * </p>
293: *
294: * @return field to be displayed.
295: */
296: protected final Field getField() {
297: if (logger.isDebugEnabled()) {
298: logger.debug("getField() - start");
299: }
300:
301: if (logger.isDebugEnabled()) {
302: logger.debug("getField() - end - return value = " + field);
303: }
304: return field;
305: }
306:
307: /**
308: * Used to format the displayed, usually ensuring line breaks are converted
309: * into HTML.
310: *
311: * @return Returns the formatter.
312: */
313: protected final HTMLFormatter getFormatter() {
314: if (logger.isDebugEnabled()) {
315: logger.debug("getFormatter() - start");
316: }
317:
318: if (logger.isDebugEnabled()) {
319: logger.debug("getFormatter() - end - return value = "
320: + formatter);
321: }
322: return formatter;
323: }
324:
325: /**
326: * <p>
327: * Find out whether or not this field represents a sublist.
328: * </p>
329: *
330: * @return <code>true</code> if this is a sublist.
331: */
332: private boolean isSublist() {
333: if (logger.isDebugEnabled()) {
334: logger.debug("isSublist() - start");
335: }
336:
337: boolean returnboolean = "sublist".equals(field.getType());
338: if (logger.isDebugEnabled()) {
339: logger.debug("isSublist() - end - return value = "
340: + returnboolean);
341: }
342: return returnboolean;
343: }
344:
345: /**
346: * {@inheritDoc}
347: *
348: * @param name {@inheritDoc}
349: */
350: public void removeAttribute(final String name) {
351: if (logger.isDebugEnabled()) {
352: logger.debug("removeAttribute(String name = " + name
353: + ") - start");
354: }
355:
356: attributesWriter.remove(name);
357:
358: if (logger.isDebugEnabled()) {
359: logger.debug("removeAttribute(String) - end");
360: }
361: }
362:
363: /**
364: * {@inheritDoc}
365: *
366: * @param name {@inheritDoc}
367: * @param value {@inheritDoc}
368: */
369: public void setAttribute(final String name, final String value) {
370: if (logger.isDebugEnabled()) {
371: logger.debug("setAttribute(String name = " + name
372: + ", String value = " + value + ") - start");
373: }
374:
375: attributesWriter.setAttribute(name, value);
376:
377: if (logger.isDebugEnabled()) {
378: logger.debug("setAttribute(String, String) - end");
379: }
380: }
381:
382: /**
383: * {@inheritDoc}
384: *
385: * @param pageContextParam {@inheritDoc}
386: * @param valueObjectParam {@inheritDoc}
387: * @param displayOnlyParam {@inheritDoc}
388: * @return {@inheritDoc}
389: */
390: public final String write(final PageContext pageContextParam,
391: final ValueObject valueObjectParam,
392: final boolean displayOnlyParam) {
393: if (logger.isDebugEnabled()) {
394: logger.debug("write(PageContext pageContextParam = "
395: + pageContextParam
396: + ", ValueObject valueObjectParam = "
397: + valueObjectParam
398: + ", boolean displayOnlyParam = "
399: + displayOnlyParam + ") - start");
400: }
401:
402: assert (pageContextParam != null);
403: assert (valueObjectParam != null);
404: Collection values;
405: Object object;
406: try {
407: object = PropertyUtils.getProperty(valueObjectParam, field
408: .getPath());
409: // this lets us handle both collections and individual value objects
410: // in the same way
411: if (object != null) {
412: if (object instanceof ValueObject) {
413: values = new Vector();
414: values.add(object);
415: } else {
416: // it must be a collection (will throw class cast exception
417: // if you tried to assign something else)
418: values = (Collection) object;
419: }
420: } else {
421: values = null;
422: }
423: } catch (IllegalAccessException e) {
424: logger.error("write(PageContext, ValueObject, boolean)", e);
425:
426: throw new RuntimeException("ERROR ("
427: + e.getClass().getName()
428: + ") in ValueObjectFieldWriter: " + e.getMessage());
429: } catch (InvocationTargetException e) {
430: logger.error("write(PageContext, ValueObject, boolean)", e);
431:
432: throw new RuntimeException("ERROR ("
433: + e.getClass().getName()
434: + ") in ValueObjectFieldWriter: " + e.getMessage());
435: } catch (NoSuchMethodException e) {
436: logger.error("write(PageContext, ValueObject, boolean)", e);
437:
438: // if there is no matching method, just set all values to null
439: values = null;
440: }
441: if (displayOnlyParam) {
442: String returnString = writeDisplayOnly(pageContextParam,
443: values);
444: if (logger.isDebugEnabled()) {
445: logger.debug("write - end - return value = "
446: + returnString);
447: }
448: return returnString;
449: } else {
450: String returnString = writeChoiceField(pageContextParam,
451: values);
452: if (logger.isDebugEnabled()) {
453: logger.debug("write - end - return value = "
454: + returnString);
455: }
456: return returnString;
457: }
458: }
459:
460: /**
461: * Display a field (which is not read-only).
462: *
463: * @param pageContextParam
464: * <copyDoc>Refer to {@link com.ivata.mask.web.field.FieldWriter#write}.
465: * </copyDoc>
466: * @param valuesParam contains all the possible values as strings.
467: * @return string representing the combo box.
468: */
469: public final String writeChoiceField(
470: final PageContext pageContextParam,
471: final Collection valuesParam) {
472: if (logger.isDebugEnabled()) {
473: logger
474: .debug("writeChoiceField(PageContext pageContextParam = "
475: + pageContextParam
476: + ", Collection valuesParam = "
477: + valuesParam + ") - start");
478: }
479:
480: List values = new Vector();
481: if (valuesParam != null) {
482: values.addAll(valuesParam);
483: }
484: // if there is nothing to display, display, well, nothing...
485: if (allValueObjects.size() == 0) {
486: if (logger.isDebugEnabled()) {
487: logger.debug("writeChoiceField - end - return value = "
488: + DEFAULT_DISPLAY_VALUE);
489: }
490: return DEFAULT_DISPLAY_VALUE;
491: }
492: // if no current values are specified, match the default value
493: if (values == null) {
494: values = new Vector();
495: values.add(DEFAULT_VALUE);
496: }
497: // clear the value attribute if there is no value
498: String stringValue;
499: StringBuffer buffer = new StringBuffer();
500: // if this is a sublist, we actually store the entries to submit in XML
501: // in a hidden field
502: Iterator allValueIterator;
503: if (isSublist()) {
504: writeHiddenContents(buffer, field, values);
505: // sublists call JavaScript to do their funky stuff
506: String onChangeSublist = "onChangeSublist(\""
507: + hiddenAttributesWriter.getAttribute("id")
508: + "\");return true";
509: attributesWriter.setAttribute("onchange", onChangeSublist);
510: // for a sublist, we only show the values in this list - not all
511: // possible values
512: allValueIterator = values.iterator();
513: } else {
514: // for all other choices, we show all possible values so you can
515: // choose one or more
516: allValueIterator = allValueObjects.iterator();
517: }
518: buffer.append("<select");
519: buffer.append(attributesWriter.toString());
520: buffer.append(">");
521: // if this is not a mandatory field, show the default value
522: if (!isSublist() && !field.isMandatory()) {
523: buffer.append("\n<option value='");
524: buffer.append(DEFAULT_VALUE);
525: buffer.append("'>");
526: buffer.append(DEFAULT_DISPLAY_VALUE);
527: buffer.append("</option>");
528: }
529: while (allValueIterator.hasNext()) {
530: ValueObject this Object = (ValueObject) allValueIterator
531: .next();
532: buffer.append("\n<option value='");
533: buffer.append(this Object.getIdString());
534: // check all chosen values against this value
535: Iterator valueIterator = values.iterator();
536: while (valueIterator.hasNext()) {
537: Object value = valueIterator.next();
538: String idString;
539: if (value instanceof String) {
540: idString = (String) value;
541: } else {
542: idString = ((ValueObject) value).getIdString();
543: }
544: // only put out selections if this is not a sublist field
545: if ((idString != null)
546: && idString.equals(this Object.getIdString())
547: && !isSublist()) {
548: buffer.append("' selected='selected");
549: break;
550: }
551: }
552: String displayValue;
553: // sublist displays the field values themselves - this is easier to
554: // replicate in the JavaScript (than the getDisplayValue method)
555: if (isSublist()) {
556: Mask mask = field.getValueObjectMask();
557: Iterator fieldsIterator = mask.getFields().iterator();
558: StringBuffer displayValueBuffer = new StringBuffer();
559: while (fieldsIterator.hasNext()) {
560: if (displayValueBuffer.length() > 0) {
561: displayValueBuffer.append(" ");
562: }
563: Field subField = (Field) fieldsIterator.next();
564: String subDisplayValue;
565: Object subObject;
566: try {
567: subObject = PropertyUtils.getProperty(
568: this Object, subField.getName());
569: } catch (IllegalAccessException e) {
570: logger
571: .error(
572: "writeChoiceField(PageContext, Collection)",
573: e);
574:
575: throw new RuntimeException(e);
576: } catch (InvocationTargetException e) {
577: logger
578: .error(
579: "writeChoiceField(PageContext, Collection)",
580: e);
581:
582: throw new RuntimeException(e);
583: } catch (NoSuchMethodException e) {
584: logger
585: .error(
586: "writeChoiceField(PageContext, Collection)",
587: e);
588:
589: throw new RuntimeException(e);
590: }
591: if (subObject == null) {
592: subDisplayValue = DEFAULT_DISPLAY_VALUE;
593: } else if (subObject instanceof ValueObject) {
594: subDisplayValue = ((ValueObject) subObject)
595: .getDisplayValue();
596: } else {
597: subDisplayValue = subObject.toString();
598: }
599: displayValueBuffer.append(subDisplayValue);
600: }
601: displayValue = displayValueBuffer.toString();
602: } else {
603: displayValue = this Object.getDisplayValue();
604: }
605: buffer.append("'>");
606: buffer.append(formatter.format(displayValue));
607: buffer.append("</option>");
608: }
609: // if this is a sublist append a 'new' option
610: if (isSublist()) {
611: buffer.append("\n<option value='");
612: buffer.append(DEFAULT_VALUE);
613: buffer.append("' selected='selected'>");
614: buffer.append(NEW_DISPLAY_VALUE);
615: buffer.append("</option>");
616: }
617: buffer.append("</select>");
618: stringValue = buffer.toString();
619:
620: if (logger.isDebugEnabled()) {
621: logger.debug("writeChoiceField - end - return value = "
622: + stringValue);
623: }
624: return stringValue;
625: }
626:
627: /**
628: * Display the correct field value from the value object - for a read-only
629: * field.
630: *
631: * @param pageContextParam
632: * <copyDoc>Refer to {@link com.ivata.mask.web.field.FieldWriter#write}.
633: * </copyDoc>
634: * @param valuesParam
635: * <copyDoc>Refer to {@link #writeChoiceField}.</copyDoc>
636: * @return <copyDoc>Refer to {@link #writeChoiceField}.</copyDoc>
637: * @see com.ivata.mask.web.field.FieldWriter#write
638: */
639: public final String writeDisplayOnly(
640: final PageContext pageContextParam,
641: final Collection valuesParam) {
642: if (logger.isDebugEnabled()) {
643: logger
644: .debug("writeDisplayOnly(PageContext pageContextParam = "
645: + pageContextParam
646: + ", Collection valuesParam = "
647: + valuesParam + ") - start");
648: }
649:
650: // if there are no values, display nothing!
651: if (valuesParam == null) {
652: if (logger.isDebugEnabled()) {
653: logger
654: .debug("writeDisplayOnly - end - return value = ");
655: }
656: return "";
657: }
658: Iterator valueIterator = valuesParam.iterator();
659: StringBuffer buffer = new StringBuffer();
660: String type = field.getType();
661: while (valueIterator.hasNext()) {
662: ValueObject valueObject = (ValueObject) valueIterator
663: .next();
664: // clear the value attribute if there is no value
665: String stringValue = valueObject.getDisplayValue();
666: attributesWriter.setAttribute("value", stringValue);
667: // don't link sublists - they are input on the mask for the
668: // containing do directly
669: if (!"sublist".equals(type)) {
670: buffer.append("<a href='");
671: try {
672: Map params = new HashMap();
673: params.put("baseClass", valueObject.getClass()
674: .getName());
675: params.put("idString", valueObject.getIdString());
676: params.put("displayOnly", "true");
677: String uRL = TagUtils.getInstance().computeURL(
678: pageContextParam, null, null, actionPage,
679: null, null, params, null, false);
680: buffer.append(uRL);
681: } catch (MalformedURLException e) {
682: logger
683: .error(
684: "writeDisplayOnly(PageContext, Collection)",
685: e);
686:
687: throw new RuntimeException("ERROR ("
688: + e.getClass().getName()
689: + ") in ValueObjectFieldWriter: "
690: + e.getMessage());
691: }
692: buffer.append("'>");
693: }
694: buffer.append(valueObject.getDisplayValue());
695: if (!"sublist".equals(type)) {
696: buffer.append("</a>");
697: }
698: // if there are more elements after this one, put them on the next
699: // line
700: if (valueIterator.hasNext()) {
701: buffer.append("<br/>\n");
702: }
703: }
704: String returnString = buffer.toString();
705: if (logger.isDebugEnabled()) {
706: logger.debug("writeDisplayOnly - end - return value = "
707: + returnString);
708: }
709: return returnString;
710: }
711:
712: /**
713: * <p>
714: * If this is a sublist, we actually store the entries to submit in XML in a
715: * hidden field. This method generates that hidden field into the string
716: * buffer provided.
717: * </p>
718: *
719: * @param bufferParam
720: * String buffer into which we will write the results.
721: * @param fieldParam
722: * Field to be written out.
723: * @param valuesParam
724: * <copyDoc>Refer to {@link #writeChoiceField}.</copyDoc>
725: */
726: private void writeHiddenContents(final StringBuffer bufferParam,
727: final Field fieldParam, final Collection valuesParam) {
728: if (logger.isDebugEnabled()) {
729: logger
730: .debug("writeHiddenContents(StringBuffer bufferParam = "
731: + bufferParam
732: + ", Field fieldParam = "
733: + fieldParam
734: + ", Collection valuesParam = "
735: + valuesParam + ") - start");
736: }
737:
738: Document document = DocumentFactory.getInstance()
739: .createDocument();
740: Element rootElement = document.addElement("sublist");
741: Mask mask = fieldParam.getValueObjectMask();
742: // go through all the values and output them
743: Iterator valueIterator = valuesParam.iterator();
744: while (valueIterator.hasNext()) {
745: ValueObject valueObject = (ValueObject) valueIterator
746: .next();
747: Element dOElement = rootElement.addElement("valueObject");
748: dOElement.addAttribute("id", valueObject.getIdString());
749: // now output all fields of this value object
750: Iterator fieldIterator = mask.getFields().iterator();
751: while (fieldIterator.hasNext()) {
752: Field subField = (Field) fieldIterator.next();
753: Element fieldElement = dOElement.addElement("field");
754: fieldElement.addAttribute("id", subField.getName());
755: Object value;
756: try {
757: value = PropertyUtils.getProperty(valueObject,
758: subField.getName());
759: } catch (IllegalAccessException e) {
760: logger.error(
761: "writeHiddenContents - error getting property for "
762: + "sub-field " + subField, e);
763: throw new RuntimeException("ERROR ("
764: + e.getClass().getName()
765: + ") in ValueObjectFieldWriter: "
766: + e.getMessage(), e);
767: } catch (InvocationTargetException e) {
768: logger.error(
769: "writeHiddenContents - error getting property for "
770: + "sub-field " + subField, e);
771: throw new RuntimeException("ERROR ("
772: + e.getClass().getName()
773: + ") in ValueObjectFieldWriter: "
774: + e.getMessage(), e);
775: } catch (NoSuchMethodException e) {
776: logger.error(
777: "writeHiddenContents - error getting property for "
778: + "sub-field " + subField, e);
779: throw new RuntimeException("ERROR ("
780: + e.getClass().getName()
781: + ") in ValueObjectFieldWriter: "
782: + e.getMessage(), e);
783: }
784: if (value != null) {
785: // if it is a value object, then set the value to the id
786: if (value instanceof ValueObject) {
787: fieldElement.setText(((ValueObject) value)
788: .getIdString());
789: } else {
790: // otherwise use the string value
791: fieldElement.setText(value.toString());
792: }
793: }
794: }
795: }
796: // finally add empty ones with no id - this ensures we always have the
797: // field names
798: Iterator fieldIterator = mask.getFields().iterator();
799: Element dOElement = rootElement.addElement("valueObject");
800: dOElement.addAttribute("schema", "true");
801: while (fieldIterator.hasNext()) {
802: Field subField = (Field) fieldIterator.next();
803: Element fieldElement = dOElement.addElement("field");
804: fieldElement.addAttribute("id", subField.getName());
805: fieldElement.setText("");
806: }
807: // now output all fields of this value object
808: hiddenAttributesWriter = new AttributesWriter(fieldParam);
809: hiddenAttributesWriter.setAttribute("type", "hidden");
810: hiddenAttributesWriter.setAttribute("value", document.asXML());
811: bufferParam.append("<input");
812: bufferParam.append(hiddenAttributesWriter.toString());
813: bufferParam.append("/>");
814: // id field holds the value of the value object id
815: AttributesWriter idAttributesWriter = new AttributesWriter(
816: fieldParam, "_id");
817: idAttributesWriter.setAttribute("type", "hidden");
818: bufferParam.append("<input");
819: bufferParam.append(idAttributesWriter.toString());
820: bufferParam.append("/>");
821: // index field holds the index of the item within the select
822: AttributesWriter indexAttributesWriter = new AttributesWriter(
823: fieldParam, "_index");
824: indexAttributesWriter.setAttribute("type", "hidden");
825: bufferParam.append("<input");
826: bufferParam.append(indexAttributesWriter.toString());
827: bufferParam.append("/>");
828:
829: if (logger.isDebugEnabled()) {
830: logger.debug("writeHiddenContents - end");
831: }
832: }
833: }
|