001: /*
002: * DescribeStep.java
003: *
004: * Version: $Revision: 1.4 $
005: *
006: * Date: $Date: 2006/07/13 23:20:54 $
007: *
008: * Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */
040: package org.dspace.app.xmlui.aspect.submission.submit;
041:
042: import java.io.IOException;
043: import java.sql.SQLException;
044: import java.util.ArrayList;
045: import java.util.Locale;
046:
047: import javax.servlet.ServletException;
048:
049: import org.apache.log4j.Logger;
050:
051: import org.dspace.app.util.DCInput;
052: import org.dspace.app.util.DCInputSet;
053: import org.dspace.app.util.DCInputsReader;
054: import org.dspace.app.xmlui.utils.UIException;
055: import org.dspace.app.xmlui.aspect.submission.AbstractSubmissionStep;
056: import org.dspace.app.xmlui.aspect.submission.FlowUtils;
057: import org.dspace.app.xmlui.wing.Message;
058: import org.dspace.app.xmlui.wing.WingException;
059: import org.dspace.app.xmlui.wing.element.Body;
060: import org.dspace.app.xmlui.wing.element.CheckBox;
061: import org.dspace.app.xmlui.wing.element.Composite;
062: import org.dspace.app.xmlui.wing.element.Division;
063: import org.dspace.app.xmlui.wing.element.Field;
064: import org.dspace.app.xmlui.wing.element.List;
065: import org.dspace.app.xmlui.wing.element.Radio;
066: import org.dspace.app.xmlui.wing.element.Select;
067: import org.dspace.app.xmlui.wing.element.Text;
068: import org.dspace.app.xmlui.wing.element.TextArea;
069: import org.dspace.authorize.AuthorizeException;
070: import org.dspace.content.Collection;
071: import org.dspace.content.DCDate;
072: import org.dspace.content.DCPersonName;
073: import org.dspace.content.DCSeriesNumber;
074: import org.dspace.content.DCValue;
075: import org.dspace.content.Item;
076:
077: import org.xml.sax.SAXException;
078:
079: /**
080: * This is a step of the item submission processes. The describe step queries
081: * the user for various metadata items about the item. For the most part all the
082: * questions queried are completely configurable via the input-sets.xml file.
083: * This system allows for multiple pages to be defined so this step is different
084: * from all other stages in that it may represent multiple stages within the
085: * submission processes.
086: *
087: * @author Scott Phillips
088: * @author Tim Donohue (updated for Configurable Submission)
089: */
090: public class DescribeStep extends AbstractSubmissionStep {
091: private static Logger log = Logger.getLogger(DescribeStep.class);
092:
093: /** Language Strings **/
094: protected static final Message T_head = message("xmlui.Submission.submit.DescribeStep.head");
095: protected static final Message T_unknown_field = message("xmlui.Submission.submit.DescribeStep.unknown_field");
096: protected static final Message T_required_field = message("xmlui.Submission.submit.DescribeStep.required_field");
097: protected static final Message T_last_name_help = message("xmlui.Submission.submit.DescribeStep.last_name_help");
098: protected static final Message T_first_name_help = message("xmlui.Submission.submit.DescribeStep.first_name_help");
099: protected static final Message T_year = message("xmlui.Submission.submit.DescribeStep.year");
100: protected static final Message T_month = message("xmlui.Submission.submit.DescribeStep.month");
101: protected static final Message T_day = message("xmlui.Submission.submit.DescribeStep.day");
102: protected static final Message T_series_name = message("xmlui.Submission.submit.DescribeStep.series_name");
103: protected static final Message T_report_no = message("xmlui.Submission.submit.DescribeStep.report_no");
104:
105: /**
106: * The scope of the input sets, this restricts hidden metadata fields from
107: * view by the end user during submission.
108: */
109: private static String SCOPE = "submit";
110:
111: /**
112: * A shared resource of the inputs reader. The 'inputs' are the
113: * questions we ask the user to describe an item during the
114: * submission process. The reader is a utility class to read
115: * that configuration file.
116: */
117: private static DCInputsReader INPUTS_READER = null;
118:
119: /**
120: * Ensure that the inputs reader has been initialized, this method may be
121: * called multiple times with no ill-effect.
122: */
123: private static void initializeInputsReader()
124: throws ServletException {
125: if (INPUTS_READER == null)
126: INPUTS_READER = new DCInputsReader();
127: }
128:
129: /**
130: * Return the inputs reader. Note, the reader must have been
131: * initialized before the reader can be accessed.
132: *
133: * @return The input reader.
134: */
135: private static DCInputsReader getInputsReader() {
136: return INPUTS_READER;
137: }
138:
139: /**
140: * Establish our required parameters, abstractStep will enforce these.
141: */
142: public DescribeStep() throws ServletException {
143: this .requireSubmission = true;
144: this .requireStep = true;
145:
146: //Ensure that the InputsReader is initialized.
147: initializeInputsReader();
148: }
149:
150: public void addBody(Body body) throws SAXException, WingException,
151: UIException, SQLException, IOException, AuthorizeException {
152: // Obtain the inputs (i.e. metadata fields we are going to display)
153: Item item = submission.getItem();
154: Collection collection = submission.getCollection();
155: String actionURL = contextPath + "/handle/"
156: + collection.getHandle() + "/submit";
157:
158: DCInputSet inputSet = null;
159: DCInput[] inputs = {};
160: try {
161: inputSet = getInputsReader().getInputs(
162: submission.getCollection().getHandle());
163: inputs = inputSet.getPageRows(getPage() - 1, submission
164: .hasMultipleTitles(), submission
165: .isPublishedBefore());
166: } catch (ServletException se) {
167: throw new UIException(se);
168: }
169:
170: Division div = body.addInteractiveDivision("submit-describe",
171: actionURL, Division.METHOD_POST, "primary submission");
172: div.setHead(T_submission_head);
173: addSubmissionProgressList(div);
174:
175: List form = div.addList("submit-describe", List.TYPE_FORM);
176: form.setHead(T_head);
177:
178: // Iterate over all inputs and add it to the form.
179: for (DCInput dcInput : inputs) {
180: // If the input is invisible skip it.
181: if (!dcInput.isVisible(SCOPE))
182: continue;
183:
184: String schema = dcInput.getSchema();
185: String element = dcInput.getElement();
186: String qualifier = dcInput.getQualifier();
187:
188: DCValue[] dcValues = item.getMetadata(schema, element,
189: qualifier, Item.ANY);
190:
191: String fieldName = FlowUtils.getFieldName(dcInput);
192:
193: String inputType = dcInput.getInputType();
194: if (inputType.equals("name")) {
195: renderNameField(form, fieldName, dcInput, dcValues);
196: } else if (inputType.equals("date")) {
197: renderDateField(form, fieldName, dcInput, dcValues);
198: } else if (inputType.equals("series")) {
199: renderSeriesField(form, fieldName, dcInput, dcValues);
200: } else if (inputType.equals("twobox")) {
201: // We don't have a twobox field, instead it's just a
202: // one box field that the theme can render in two columns.
203: renderOneboxField(form, fieldName, dcInput, dcValues);
204: } else if (inputType.equals("qualdrop_value")) {
205: // Determine the real field's values. Since the qualifier is
206: // selected we need to search through all the metadata and see
207: // if any match for another field, if not we assume that this field
208: // should handle it.
209: DCValue[] unfiltered = item.getMetadata(dcInput
210: .getSchema(), dcInput.getElement(), Item.ANY,
211: Item.ANY);
212: ArrayList<DCValue> filtered = new ArrayList<DCValue>();
213: for (DCValue dcValue : unfiltered) {
214: String unfilteredFieldName = dcValue.element + "."
215: + dcValue.qualifier;
216: if (!inputSet.isFieldPresent(unfilteredFieldName)) {
217: filtered.add(dcValue);
218: }
219: }
220:
221: renderQualdropField(form, fieldName, dcInput, filtered
222: .toArray(new DCValue[filtered.size()]));
223: } else if (inputType.equals("textarea")) {
224: renderTextArea(form, fieldName, dcInput, dcValues);
225: } else if (inputType.equals("dropdown")) {
226: renderDropdownField(form, fieldName, dcInput, dcValues);
227: } else if (inputType.equals("list")) {
228: renderSelectFromListField(form, fieldName, dcInput,
229: dcValues);
230: } else if (inputType.equals("onebox")) {
231: renderOneboxField(form, fieldName, dcInput, dcValues);
232: } else {
233: form.addItem(T_unknown_field);
234: }
235: }
236:
237: div.addHidden("submission-continue").setValue(knot.getId());
238:
239: // add standard control/paging buttons
240: addControlButtons(form);
241: }
242:
243: /**
244: * Each submission step must define its own information to be reviewed
245: * during the final Review/Verify Step in the submission process.
246: * <P>
247: * The information to review should be tacked onto the passed in
248: * List object.
249: * <P>
250: * NOTE: To remain consistent across all Steps, you should first
251: * add a sub-List object (with this step's name as the heading),
252: * by using a call to reviewList.addList(). This sublist is
253: * the list you return from this method!
254: *
255: * @param reviewList
256: * The List to which all reviewable information should be added
257: * @return
258: * The new sub-List object created by this step, which contains
259: * all the reviewable information. If this step has nothing to
260: * review, then return null!
261: */
262: public List addReviewSection(List reviewList) throws SAXException,
263: WingException, UIException, SQLException, IOException,
264: AuthorizeException {
265: //Create a new list section for this step (and set its heading)
266: List describeSection = reviewList.addList("submit-review-"
267: + this .stepAndPage, List.TYPE_FORM);
268: describeSection.setHead(T_head);
269:
270: //Review the values assigned to all inputs
271: //on this page of the Describe step.
272: DCInputSet inputSet = null;
273: try {
274: inputSet = getInputsReader().getInputs(
275: submission.getCollection().getHandle());
276: } catch (ServletException se) {
277: throw new UIException(se);
278: }
279:
280: DCInput[] inputs = inputSet.getPageRows(getPage() - 1,
281: submission.hasMultipleTitles(), submission
282: .isPublishedBefore());
283:
284: for (DCInput input : inputs) {
285: if (!input.isVisible(SCOPE))
286: continue;
287:
288: String inputType = input.getInputType();
289: String pairsName = input.getPairsType();
290: DCValue[] values = new DCValue[0];
291:
292: if (inputType.equals("qualdrop_value")) {
293: values = submission.getItem().getMetadata(
294: input.getSchema(), input.getElement(),
295: Item.ANY, Item.ANY);
296: } else {
297: values = submission.getItem().getMetadata(
298: input.getSchema(), input.getElement(),
299: input.getQualifier(), Item.ANY);
300: }
301:
302: if (values.length == 0) {
303: describeSection.addLabel(input.getLabel());
304: describeSection.addItem().addHighlight("italic")
305: .addContent(ReviewStep.T_no_metadata);
306: } else {
307: for (DCValue value : values) {
308: String displayValue = null;
309: if (inputType.equals("date")) {
310: DCDate date = new DCDate(value.value);
311: displayValue = date.toString();
312: } else if (inputType.equals("dropdown")) {
313: displayValue = input.getDisplayString(
314: pairsName, value.value);
315: } else if (inputType.equals("qualdrop_value")) {
316: String qualifier = value.qualifier;
317: String displayQual = input.getDisplayString(
318: pairsName, qualifier);
319: displayValue = displayQual + ":" + value.value;
320: } else {
321: displayValue = value.value;
322: }
323: describeSection.addLabel(input.getLabel());
324: describeSection.addItem(displayValue);
325: } // For each DCValue
326: } // If values exist
327: }// For each input
328:
329: //return this new "describe" section
330: return describeSection;
331: }
332:
333: /**
334: * Render a Name field to the DRI document. The name field consists of two
335: * text fields, one for the last name and the other for a first name (plus
336: * all other names).
337: *
338: * @param form
339: * The form list to add the field too
340: * @param fieldName
341: * The field's name.
342: * @param dcInput
343: * The field's input deffinition
344: * @param dcValues
345: * The field's pre-existing values.
346: */
347: private void renderNameField(List form, String fieldName,
348: DCInput dcInput, DCValue[] dcValues) throws WingException {
349: // The name field is a composite field containing two text fields, one
350: // for first name the other for last name.
351: Composite fullName = form.addItem().addComposite(fieldName,
352: "submit-name");
353: Text lastName = fullName.addText(fieldName + "_last");
354: Text firstName = fullName.addText(fieldName + "_first");
355:
356: // Setup the full name
357: fullName.setLabel(dcInput.getLabel());
358: fullName.setHelp(cleanHints(dcInput.getHints()));
359: if (dcInput.isRequired())
360: fullName.setRequired();
361: if (isFieldInError(fieldName))
362: fullName.addError(T_required_field);
363: if (dcInput.isRepeatable())
364: fullName.enableAddOperation();
365: if (dcInput.isRepeatable() || dcValues.length > 1)
366: fullName.enableDeleteOperation();
367:
368: // Setup the first and last name
369: lastName.setLabel(T_last_name_help);
370: firstName.setLabel(T_first_name_help);
371:
372: // Setup the field's values
373: if (dcInput.isRepeatable() || dcValues.length > 1) {
374: for (DCValue dcValue : dcValues) {
375: DCPersonName dpn = new DCPersonName(dcValue.value);
376:
377: lastName.addInstance().setValue(dpn.getLastName());
378: firstName.addInstance().setValue(dpn.getFirstNames());
379: fullName.addInstance().setValue(dcValue.value);
380: }
381: } else if (dcValues.length == 1) {
382: DCPersonName dpn = new DCPersonName(dcValues[0].value);
383:
384: lastName.setValue(dpn.getLastName());
385: firstName.setValue(dpn.getFirstNames());
386: }
387: }
388:
389: /**
390: * Render a date field to the DRI document. The date field consists of
391: * three component fields, a 4 character text field for the year, a select
392: * box for the month, and a 2 character text field for the day.
393: *
394: * @param form
395: * The form list to add the field too
396: * @param fieldName
397: * The field's name.
398: * @param dcInput
399: * The field's input deffinition
400: * @param dcValues
401: * The field's pre-existing values.
402: */
403: private void renderDateField(List form, String fieldName,
404: DCInput dcInput, DCValue[] dcValues) throws WingException {
405: // The date field consists of three primitive fields: a text field
406: // for the year, followed by a select box of the months, follewed
407: // by a text box for the day.
408: Composite fullDate = form.addItem().addComposite(fieldName,
409: "submit-date");
410: Text year = fullDate.addText(fieldName + "_year");
411: Select month = fullDate.addSelect(fieldName + "_month");
412: Text day = fullDate.addText(fieldName + "_day");
413:
414: // Set up the full field
415: fullDate.setLabel(dcInput.getLabel());
416: fullDate.setHelp(cleanHints(dcInput.getHints()));
417: if (dcInput.isRequired())
418: fullDate.setRequired();
419: if (isFieldInError(fieldName))
420: fullDate.addError(T_required_field);
421: if (dcInput.isRepeatable())
422: fullDate.enableAddOperation();
423: if (dcInput.isRepeatable() || dcValues.length > 1)
424: fullDate.enableDeleteOperation();
425:
426: // Setup the year field
427: year.setLabel(T_year);
428: year.setSize(4, 4);
429:
430: // Setup the month field
431: month.setLabel(T_month);
432: month.addOption(0, "");
433: for (int i = 1; i < 13; i++) {
434: month.addOption(i, org.dspace.content.DCDate.getMonthName(
435: i, Locale.getDefault()));
436: }
437:
438: // Setup the day field
439: day.setLabel(T_day);
440: day.setSize(2, 2);
441:
442: // Setup the field's values
443: if (dcInput.isRepeatable() || dcValues.length > 1) {
444: for (DCValue dcValue : dcValues) {
445: DCDate dcDate = new DCDate(dcValue.value);
446:
447: year.addInstance().setValue(
448: String.valueOf(dcDate.getYear()));
449: month.addInstance()
450: .setOptionSelected(dcDate.getMonth());
451: day.addInstance().setValue(
452: String.valueOf(dcDate.getDay()));
453: fullDate.addInstance().setValue(dcDate.toString());
454: }
455: } else if (dcValues.length == 1) {
456: DCDate dcDate = new DCDate(dcValues[0].value);
457:
458: year.setValue(String.valueOf(dcDate.getYear()));
459: month.setOptionSelected(dcDate.getMonth());
460:
461: // Check if the day field is not specified, if so then just
462: // put a blank value in instead of the wiered looking -1.
463: if (dcDate.getDay() == -1)
464: day.setValue("");
465: else
466: day.setValue(String.valueOf(dcDate.getDay()));
467: }
468: }
469:
470: /**
471: * Render a series field to the DRI document. The series field conist of
472: * two component text fields. When interpreted each of these fields are
473: * combined back together to be a single value joined together by a
474: * semicolen. The primary use case is for the journal or report number
475: * the left hand side is the journal and the right hand side in a
476: * unique number within the journal.
477: *
478: * @param form
479: * The form list to add the field too
480: * @param fieldName
481: * The field's name.
482: * @param dcInput
483: * The field's input deffinition
484: * @param dcValues
485: * The field's pre-existing values.
486: */
487: private void renderSeriesField(List form, String fieldName,
488: DCInput dcInput, DCValue[] dcValues) throws WingException {
489: // The seiries field consists of two parts, a series name (text field)
490: // and report or paper number (also a text field).
491: Composite fullSeries = form.addItem().addComposite(fieldName,
492: "submit-" + dcInput.getInputType());
493: Text series = fullSeries.addText(fieldName + "_series");
494: Text number = fullSeries.addText(fieldName + "_number");
495:
496: // Setup the full field.
497: fullSeries.setLabel(dcInput.getLabel());
498: fullSeries.setHelp(cleanHints(dcInput.getHints()));
499: if (dcInput.isRequired())
500: fullSeries.setRequired();
501: if (isFieldInError(fieldName))
502: fullSeries.addError(T_required_field);
503: if (dcInput.isRepeatable())
504: fullSeries.enableAddOperation();
505: if (dcInput.isRepeatable() || dcValues.length > 1)
506: fullSeries.enableDeleteOperation();
507:
508: series.setLabel(T_series_name);
509: number.setLabel(T_report_no);
510:
511: // Setup the field's values
512: if (dcInput.isRepeatable() || dcValues.length > 1) {
513: for (DCValue dcValue : dcValues) {
514: DCSeriesNumber dcSeriesNumber = new DCSeriesNumber(
515: dcValue.value);
516:
517: series.addInstance().setValue(
518: dcSeriesNumber.getSeries());
519: number.addInstance().setValue(
520: dcSeriesNumber.getNumber());
521: fullSeries.addInstance().setValue(
522: dcSeriesNumber.toString());
523: }
524:
525: } else if (dcValues.length == 1) {
526: DCSeriesNumber dcSeriesNumber = new DCSeriesNumber(
527: dcValues[0].value);
528:
529: series.setValue(dcSeriesNumber.getSeries());
530: number.setValue(dcSeriesNumber.getNumber());
531: }
532: }
533:
534: /**
535: * Render a qualdrop field to the DRI document. Qualdrop fields are complicated,
536: * widget wise they are composed of two fields, a select and text box field.
537: * The select field selects the metedata's qualifier and the text box is the
538: * value. This means that that there is not just one metadata element that is
539: * represented so the confusing part is that the name can change.
540: *
541: * @param form
542: * The form list to add the field too
543: * @param fieldName
544: * The field's name.
545: * @param dcInput
546: * The field's input deffinition
547: * @param dcValues
548: * The field's pre-existing values.
549: */
550: private void renderQualdropField(List form, String fieldName,
551: DCInput dcInput, DCValue[] dcValues) throws WingException {
552: Composite qualdrop = form.addItem().addComposite(fieldName,
553: "submit-qualdrop");
554: Select qual = qualdrop.addSelect(fieldName + "_qualifier");
555: Text value = qualdrop.addText(fieldName + "_value");
556:
557: // Setup the full field.
558: qualdrop.setLabel(dcInput.getLabel());
559: qualdrop.setHelp(cleanHints(dcInput.getHints()));
560: if (dcInput.isRequired())
561: qualdrop.setRequired();
562: if (isFieldInError(fieldName))
563: qualdrop.addError(T_required_field);
564: if (dcInput.isRepeatable())
565: qualdrop.enableAddOperation();
566: // Update delete based upon the filtered values.
567: if (dcInput.isRepeatable() || dcValues.length > 1)
568: qualdrop.enableDeleteOperation();
569:
570: // Setup the possible options
571: @SuppressWarnings("unchecked")
572: // This cast is correct
573: java.util.List<String> pairs = dcInput.getPairs();
574: for (int i = 0; i < pairs.size(); i += 2) {
575: String display = pairs.get(i);
576: String returnValue = pairs.get(i + 1);
577: qual.addOption(returnValue, display);
578: }
579:
580: // Setup the field's values
581: if (dcInput.isRepeatable() || dcValues.length > 1) {
582: for (DCValue dcValue : dcValues) {
583: qual.addInstance().setOptionSelected(dcValue.qualifier);
584: value.addInstance().setValue(dcValue.value);
585: qualdrop.addInstance().setValue(
586: dcValue.qualifier + ":" + dcValue.value);
587: }
588: } else if (dcValues.length == 1) {
589: qual.setOptionSelected(dcValues[0].qualifier);
590: value.setValue(dcValues[0].value);
591: }
592: }
593:
594: /**
595: * Render a Text Area field to the DRI document. The text area is a simple
596: * multi row and column text field.
597: *
598: * @param form
599: * The form list to add the field too
600: * @param fieldName
601: * The field's name.
602: * @param dcInput
603: * The field's input deffinition
604: * @param dcValues
605: * The field's pre-existing values.
606: */
607: private void renderTextArea(List form, String fieldName,
608: DCInput dcInput, DCValue[] dcValues) throws WingException {
609: // Plain old Textarea
610: TextArea textArea = form.addItem().addTextArea(fieldName,
611: "submit-textarea");
612:
613: // Setup the text area
614: textArea.setLabel(dcInput.getLabel());
615: textArea.setHelp(cleanHints(dcInput.getHints()));
616: if (dcInput.isRequired())
617: textArea.setRequired();
618: if (isFieldInError(fieldName))
619: textArea.addError(T_required_field);
620: if (dcInput.isRepeatable())
621: textArea.enableAddOperation();
622: if (dcInput.isRepeatable() || dcValues.length > 1)
623: textArea.enableDeleteOperation();
624:
625: // Setup the field's values
626: if (dcInput.isRepeatable() || dcValues.length > 1) {
627: for (DCValue dcValue : dcValues) {
628: textArea.addInstance().setValue(dcValue.value);
629: }
630: } else if (dcValues.length == 1) {
631: textArea.setValue(dcValues[0].value);
632: }
633: }
634:
635: /**
636: * Render a dropdown field to the DRI document. The dropdown field consists
637: * of an HTML select box.
638: *
639: * @param form
640: * The form list to add the field too
641: * @param fieldName
642: * The field's name.
643: * @param dcInput
644: * The field's input deffinition
645: * @param dcValues
646: * The field's pre-existing values.
647: */
648: private void renderDropdownField(List form, String fieldName,
649: DCInput dcInput, DCValue[] dcValues) throws WingException {
650: // Plain old select list.
651: Select select = form.addItem().addSelect(fieldName,
652: "submit-select");
653:
654: //Setup the select field
655: select.setLabel(dcInput.getLabel());
656: select.setHelp(cleanHints(dcInput.getHints()));
657: if (dcInput.isRequired())
658: select.setRequired();
659: if (isFieldInError(fieldName))
660: select.addError(T_required_field);
661: if (dcInput.isRepeatable() || dcValues.length > 1) {
662: // Use the multiple functionality from the HTML
663: // widget instead of DRI's version.
664: select.setMultiple();
665: select.setSize(6);
666: }
667:
668: // Setup the possible options
669: @SuppressWarnings("unchecked")
670: // This cast is correct
671: java.util.List<String> pairs = dcInput.getPairs();
672: for (int i = 0; i < pairs.size(); i += 2) {
673: String display = pairs.get(i);
674: String value = pairs.get(i + 1);
675: select.addOption(value, display);
676: }
677:
678: // Setup the field's pre-selected values
679: for (DCValue dcValue : dcValues) {
680: select.setOptionSelected(dcValue.value);
681: }
682: }
683:
684: /**
685: * Render a select-from-list field to the DRI document.
686: * This field consists of either a series of checkboxes
687: * (if repeatable) or a series of radio buttons (if not repeatable).
688: * <P>
689: * Note: This is NOT the same as a List element
690: * (org.dspace.app.xmlui.wing.element.List). It's just unfortunately
691: * similarly named.
692: *
693: * @param form
694: * The form list to add the field too
695: * @param fieldName
696: * The field's name.
697: * @param dcInput
698: * The field's input deffinition
699: * @param dcValues
700: * The field's pre-existing values.
701: */
702: private void renderSelectFromListField(List form, String fieldName,
703: DCInput dcInput, DCValue[] dcValues) throws WingException {
704: Field listField = null;
705:
706: //if repeatable, this list of fields should be checkboxes
707: if (dcInput.isRepeatable()) {
708: listField = form.addItem().addCheckBox(fieldName);
709: } else //otherwise this is a list of radio buttons
710: {
711: listField = form.addItem().addRadio(fieldName);
712: }
713:
714: // Setup the field
715: listField.setLabel(dcInput.getLabel());
716: listField.setHelp(cleanHints(dcInput.getHints()));
717: if (dcInput.isRequired())
718: listField.setRequired();
719: if (isFieldInError(fieldName))
720: listField.addError(T_required_field);
721:
722: //Setup each of the possible options
723: java.util.List<String> pairs = dcInput.getPairs();
724: for (int i = 0; i < pairs.size(); i += 2) {
725: String display = pairs.get(i);
726: String value = pairs.get(i + 1);
727:
728: if (listField instanceof CheckBox) {
729: ((CheckBox) listField).addOption(value, display);
730: } else if (listField instanceof Radio) {
731: ((Radio) listField).addOption(value, display);
732: }
733: }
734:
735: // Setup the field's pre-selected values
736: for (DCValue dcValue : dcValues) {
737: if (listField instanceof CheckBox) {
738: ((CheckBox) listField).setOptionSelected(dcValue.value);
739: } else if (listField instanceof Radio) {
740: ((Radio) listField).setOptionSelected(dcValue.value);
741: }
742: }
743: }
744:
745: /**
746: * Render a simple text field to the DRI document
747: *
748: * @param form
749: * The form list to add the field too
750: * @param fieldName
751: * The field's name.
752: * @param dcInput
753: * The field's input deffinition
754: * @param dcValues
755: * The field's pre-existing values.
756: */
757: private void renderOneboxField(List form, String fieldName,
758: DCInput dcInput, DCValue[] dcValues) throws WingException {
759: // Both onebox and twobox consist a free form text field
760: // that the user may enter any value. The difference between
761: // the two is that a onebox should be rendered in one column
762: // as twobox should be listed in a two column format. Since this
763: // decision is not something the Aspect can effect we merely place
764: // as a render hint.
765: Text text = form.addItem().addText(fieldName, "submit-text");
766:
767: // Setup the select field
768: text.setLabel(dcInput.getLabel());
769: text.setHelp(cleanHints(dcInput.getHints()));
770: if (dcInput.isRequired())
771: text.setRequired();
772: if (isFieldInError(fieldName))
773: text.addError(T_required_field);
774: if (dcInput.isRepeatable())
775: text.enableAddOperation();
776: if (dcInput.isRepeatable() || dcValues.length > 1)
777: text.enableDeleteOperation();
778:
779: // Setup the field's values
780: if (dcInput.isRepeatable() || dcValues.length > 1) {
781: for (DCValue dcValue : dcValues) {
782: text.addInstance().setValue(dcValue.value);
783: }
784: } else if (dcValues.length == 1) {
785: text.setValue(dcValues[0].value);
786: }
787: }
788:
789: /**
790: * Check if the given fieldname is listed as being in error.
791: *
792: * @param fieldName
793: * @return
794: */
795: private boolean isFieldInError(String fieldName) {
796: if (this .errorFields.contains(fieldName))
797: return true;
798: else
799: return false;
800: }
801:
802: /**
803: * There is a problem with the way hints are handled. The class that we use to
804: * read the input-forms.xml configuration will append and prepend HTML to hints.
805: * This causes all sorts of confusion when inserting into the DRI page, so this
806: * method will strip that extra HTML and just leave the cleaned comments.
807: *
808: *
809: * However this method will not remove naughty or sexual innuendoes from the
810: * field's hints.
811: *
812: *
813: * @param dirtyHints HTML-ized hints
814: * @return Hints without HTML.
815: */
816: private static final String HINT_HTML_PREFIX = "<tr><td colspan=\"4\" class=\"submitFormHelp\">";
817: private static final String HINT_HTML_POSTFIX = "</td></tr>";
818:
819: private String cleanHints(String dirtyHints) {
820: String clean = (dirtyHints != null ? dirtyHints : "");
821:
822: if (clean.startsWith(HINT_HTML_PREFIX)) {
823: clean = clean.substring(HINT_HTML_PREFIX.length());
824: }
825:
826: if (clean.endsWith(HINT_HTML_POSTFIX)) {
827: clean = clean.substring(0, clean.length()
828: - HINT_HTML_POSTFIX.length());
829: }
830:
831: return clean;
832: }
833: }
|