/*
* DescribeStep.java
*
* Version: $Revision: 4919 $
*
* Date: $Date: 2010-05-12 11:45:38 +0000 (Wed, 12 May 2010) $
*
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
* Institute of Technology. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Hewlett-Packard Company nor the name of the
* Massachusetts Institute of Technology nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.xmlui.aspect.submission.submit;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Locale;
import javax.servlet.ServletException;
import org.apache.log4j.Logger;
import org.dspace.app.util.DCInput;
import org.dspace.app.util.DCInputSet;
import org.dspace.app.util.DCInputsReader;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.aspect.submission.AbstractSubmissionStep;
import org.dspace.app.xmlui.aspect.submission.FlowUtils;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body;
import org.dspace.app.xmlui.wing.element.CheckBox;
import org.dspace.app.xmlui.wing.element.Composite;
import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.Field;
import org.dspace.app.xmlui.wing.element.Instance;
import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Params;
import org.dspace.app.xmlui.wing.element.Radio;
import org.dspace.app.xmlui.wing.element.Select;
import org.dspace.app.xmlui.wing.element.Text;
import org.dspace.app.xmlui.wing.element.TextArea;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.DCDate;
import org.dspace.content.DCPersonName;
import org.dspace.content.DCSeriesNumber;
import org.dspace.content.DCValue;
import org.dspace.content.Item;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.Choice;
import org.dspace.content.authority.Choices;
import org.xml.sax.SAXException;
/**
* This is a step of the item submission processes. The describe step queries
* the user for various metadata items about the item. For the most part all the
* questions queried are completely configurable via the input-sets.xml file.
* This system allows for multiple pages to be defined so this step is different
* from all other stages in that it may represent multiple stages within the
* submission processes.
*
* @author Scott Phillips
* @author Tim Donohue (updated for Configurable Submission)
*/
public class DescribeStep extends AbstractSubmissionStep
{
private static Logger log = Logger.getLogger(DescribeStep.class);
/** Language Strings **/
protected static final Message T_head =
message("xmlui.Submission.submit.DescribeStep.head");
protected static final Message T_unknown_field=
message("xmlui.Submission.submit.DescribeStep.unknown_field");
protected static final Message T_required_field=
message("xmlui.Submission.submit.DescribeStep.required_field");
protected static final Message T_last_name_help=
message("xmlui.Submission.submit.DescribeStep.last_name_help");
protected static final Message T_first_name_help=
message("xmlui.Submission.submit.DescribeStep.first_name_help");
protected static final Message T_year=
message("xmlui.Submission.submit.DescribeStep.year");
protected static final Message T_month=
message("xmlui.Submission.submit.DescribeStep.month");
protected static final Message T_day=
message("xmlui.Submission.submit.DescribeStep.day");
protected static final Message T_series_name=
message("xmlui.Submission.submit.DescribeStep.series_name");
protected static final Message T_report_no=
message("xmlui.Submission.submit.DescribeStep.report_no");
/**
* A shared resource of the inputs reader. The 'inputs' are the
* questions we ask the user to describe an item during the
* submission process. The reader is a utility class to read
* that configuration file.
*/
private static DCInputsReader INPUTS_READER = null;
/**
* Ensure that the inputs reader has been initialized, this method may be
* called multiple times with no ill-effect.
*/
private static void initializeInputsReader() throws DCInputsReaderException
{
if (INPUTS_READER == null)
INPUTS_READER = new DCInputsReader();
}
/**
* Return the inputs reader. Note, the reader must have been
* initialized before the reader can be accessed.
*
* @return The input reader.
*/
private static DCInputsReader getInputsReader()
{
return INPUTS_READER;
}
/**
* Establish our required parameters, abstractStep will enforce these.
*/
public DescribeStep() throws ServletException
{
this.requireSubmission = true;
this.requireStep = true;
//Ensure that the InputsReader is initialized.
try
{
initializeInputsReader();
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
}
public void addPageMeta(PageMeta pageMeta) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException
{
int collectionID = submission.getCollection().getID();
pageMeta.addMetadata("choice", "collection").addContent(String.valueOf(collectionID));
String jumpTo = submissionInfo.getJumpToField();
if (jumpTo != null)
pageMeta.addMetadata("page","jumpTo").addContent(jumpTo);
}
public void addBody(Body body) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException
{
// Obtain the inputs (i.e. metadata fields we are going to display)
Item item = submission.getItem();
Collection collection = submission.getCollection();
String actionURL = contextPath + "/handle/"+collection.getHandle() + "/submit/" + knot.getId() + ".continue";
DCInputSet inputSet = null;
DCInput[] inputs = {};
try
{
inputSet = getInputsReader().getInputs(submission.getCollection().getHandle());
inputs = inputSet.getPageRows(getPage()-1, submission.hasMultipleTitles(), submission.isPublishedBefore());
}
catch (DCInputsReaderException se)
{
throw new UIException(se);
}
Division div = body.addInteractiveDivision("submit-describe",actionURL,Division.METHOD_POST,"primary submission");
div.setHead(T_submission_head);
addSubmissionProgressList(div);
List form = div.addList("submit-describe",List.TYPE_FORM);
form.setHead(T_head);
// Iterate over all inputs and add it to the form.
for(DCInput dcInput : inputs)
{
String scope = submissionInfo.isInWorkflow() ? DCInput.WORKFLOW_SCOPE : DCInput.SUBMISSION_SCOPE;
boolean readonly = dcInput.isReadOnly(scope);
// If the input is invisible in this scope, then skip it.
if (!dcInput.isVisible(scope) && !readonly)
continue;
String schema = dcInput.getSchema();
String element = dcInput.getElement();
String qualifier = dcInput.getQualifier();
DCValue[] dcValues = item.getMetadata(schema, element, qualifier, Item.ANY);
String fieldName = FlowUtils.getFieldName(dcInput);
String inputType = dcInput.getInputType();
// if this field is configured as choice control and its
// presentation format is SELECT, render it as select field:
String fieldKey = MetadataAuthorityManager.makeFieldKey(schema, element, qualifier);
ChoiceAuthorityManager cmgr = ChoiceAuthorityManager.getManager();
if (cmgr.isChoicesConfigured(fieldKey) &&
Params.PRESENTATION_SELECT.equals(cmgr.getPresentation(fieldKey)))
{
renderChoiceSelectField(form, fieldName, collection, dcInput, dcValues, readonly);
}
else if (inputType.equals("name"))
{
renderNameField(form, fieldName, dcInput, dcValues, readonly);
}
else if (inputType.equals("date"))
{
renderDateField(form, fieldName, dcInput, dcValues, readonly);
}
else if (inputType.equals("series"))
{
renderSeriesField(form, fieldName, dcInput, dcValues, readonly);
}
else if (inputType.equals("twobox"))
{
// We don't have a twobox field, instead it's just a
// one box field that the theme can render in two columns.
renderOneboxField(form, fieldName, dcInput, dcValues, readonly);
}
else if (inputType.equals("qualdrop_value"))
{
// Determine the real field's values. Since the qualifier is
// selected we need to search through all the metadata and see
// if any match for another field, if not we assume that this field
// should handle it.
DCValue[] unfiltered = item.getMetadata(dcInput.getSchema(), dcInput.getElement(), Item.ANY, Item.ANY);
ArrayList<DCValue> filtered = new ArrayList<DCValue>();
for (DCValue dcValue : unfiltered)
{
String unfilteredFieldName = dcValue.element + "." + dcValue.qualifier;
if ( ! inputSet.isFieldPresent(unfilteredFieldName) )
{
filtered.add( dcValue );
}
}
renderQualdropField(form, fieldName, dcInput, filtered.toArray(new DCValue[filtered.size()]), readonly);
}
else if (inputType.equals("textarea"))
{
renderTextArea(form, fieldName, dcInput, dcValues, readonly);
}
else if (inputType.equals("dropdown"))
{
renderDropdownField(form, fieldName, dcInput, dcValues, readonly);
}
else if (inputType.equals("list"))
{
renderSelectFromListField(form, fieldName, dcInput, dcValues, readonly);
}
else if (inputType.equals("onebox"))
{
renderOneboxField(form, fieldName, dcInput, dcValues, readonly);
}
else
{
form.addItem(T_unknown_field);
}
}
// add standard control/paging buttons
addControlButtons(form);
}
/**
* Each submission step must define its own information to be reviewed
* during the final Review/Verify Step in the submission process.
* <P>
* The information to review should be tacked onto the passed in
* List object.
* <P>
* NOTE: To remain consistent across all Steps, you should first
* add a sub-List object (with this step's name as the heading),
* by using a call to reviewList.addList(). This sublist is
* the list you return from this method!
*
* @param reviewList
* The List to which all reviewable information should be added
* @return
* The new sub-List object created by this step, which contains
* all the reviewable information. If this step has nothing to
* review, then return null!
*/
public List addReviewSection(List reviewList) throws SAXException,
WingException, UIException, SQLException, IOException,
AuthorizeException
{
//Create a new list section for this step (and set its heading)
List describeSection = reviewList.addList("submit-review-" + this.stepAndPage, List.TYPE_FORM);
describeSection.setHead(T_head);
//Review the values assigned to all inputs
//on this page of the Describe step.
DCInputSet inputSet = null;
try
{
inputSet = getInputsReader().getInputs(submission.getCollection().getHandle());
}
catch (DCInputsReaderException se)
{
throw new UIException(se);
}
MetadataAuthorityManager mam = MetadataAuthorityManager.getManager();
DCInput[] inputs = inputSet.getPageRows(getPage()-1, submission.hasMultipleTitles(), submission.isPublishedBefore());
for (DCInput input : inputs)
{
// If the input is invisible in this scope, then skip it.
String scope = submissionInfo.isInWorkflow() ? DCInput.WORKFLOW_SCOPE : DCInput.SUBMISSION_SCOPE;
if (!input.isVisible(scope) && !input.isReadOnly(scope))
continue;
String inputType = input.getInputType();
String pairsName = input.getPairsType();
DCValue[] values = new DCValue[0];
if (inputType.equals("qualdrop_value"))
{
values = submission.getItem().getMetadata(input.getSchema(), input.getElement(), Item.ANY, Item.ANY);
}
else
{
values = submission.getItem().getMetadata(input.getSchema(), input.getElement(), input.getQualifier(), Item.ANY);
}
if (values.length > 0)
{
for (DCValue value : values)
{
String displayValue = null;
if (inputType.equals("date"))
{
DCDate date = new DCDate(value.value);
displayValue = date.toString();
}
else if (inputType.equals("dropdown"))
{
displayValue = input.getDisplayString(pairsName,value.value);
}
else if (inputType.equals("qualdrop_value"))
{
String qualifier = value.qualifier;
String displayQual = input.getDisplayString(pairsName,qualifier);
if (displayQual!=null && displayQual.length()>0)
{
displayValue = displayQual + ":" + value.value;
}
}
else
{
displayValue = value.value;
}
//Only display this field if we have a value to display
if (displayValue!=null && displayValue.length()>0)
{
describeSection.addLabel(input.getLabel());
if (mam.isAuthorityControlled(value.schema, value.element, value.qualifier))
{
String confidence = (value.authority != null && value.authority.length() > 0) ?
Choices.getConfidenceText(value.confidence).toLowerCase() :
"blank";
org.dspace.app.xmlui.wing.element.Item authItem =
describeSection.addItem("submit-review-field-with-authority", "ds-authority-confidence cf-"+confidence);
authItem.addContent(displayValue);
}
else
describeSection.addItem(displayValue);
}
} // For each DCValue
} // If values exist
}// For each input
//return this new "describe" section
return describeSection;
}
/**
* Render a Name field to the DRI document. The name field consists of two
* text fields, one for the last name and the other for a first name (plus
* all other names).
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderNameField(List form, String fieldName, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
// The name field is a composite field containing two text fields, one
// for first name the other for last name.
Composite fullName = form.addItem().addComposite(fieldName, "submit-name");
Text lastName = fullName.addText(fieldName+"_last");
Text firstName = fullName.addText(fieldName+"_first");
// Setup the full name
fullName.setLabel(dcInput.getLabel());
fullName.setHelp(cleanHints(dcInput.getHints()));
if (dcInput.isRequired())
fullName.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
fullName.addError(dcInput.getWarning());
} else {
fullName.addError(T_required_field);
}
if (dcInput.isRepeatable() && !readonly)
fullName.enableAddOperation();
if ((dcInput.isRepeatable() || dcValues.length > 1) && !readonly)
fullName.enableDeleteOperation();
String fieldKey = MetadataAuthorityManager.makeFieldKey(dcInput.getSchema(), dcInput.getElement(), dcInput.getQualifier());
boolean isAuthorityControlled = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
if (isAuthorityControlled)
{
fullName.setAuthorityControlled();
fullName.setAuthorityRequired(MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey));
}
if (ChoiceAuthorityManager.getManager().isChoicesConfigured(fieldKey))
{
fullName.setChoices(fieldKey);
fullName.setChoicesPresentation(ChoiceAuthorityManager.getManager().getPresentation(fieldKey));
fullName.setChoicesClosed(ChoiceAuthorityManager.getManager().isClosed(fieldKey));
}
// Setup the first and last name
lastName.setLabel(T_last_name_help);
firstName.setLabel(T_first_name_help);
if (readonly)
{
lastName.setDisabled();
firstName.setDisabled();
fullName.setDisabled();
}
// Setup the field's values
if (dcInput.isRepeatable() || dcValues.length > 1)
{
for (DCValue dcValue : dcValues)
{
DCPersonName dpn = new DCPersonName(dcValue.value);
lastName.addInstance().setValue(dpn.getLastName());
firstName.addInstance().setValue(dpn.getFirstNames());
Instance fi = fullName.addInstance();
fi.setValue(dcValue.value);
if (isAuthorityControlled)
{
if (dcValue.authority == null || dcValue.authority.equals(""))
fi.setAuthorityValue("", "blank");
else
fi.setAuthorityValue(dcValue.authority, Choices.getConfidenceText(dcValue.confidence));
}
}
}
else if (dcValues.length == 1)
{
DCPersonName dpn = new DCPersonName(dcValues[0].value);
lastName.setValue(dpn.getLastName());
firstName.setValue(dpn.getFirstNames());
if (isAuthorityControlled)
{
if (dcValues[0].authority == null || dcValues[0].authority.equals(""))
lastName.setAuthorityValue("", "blank");
else
lastName.setAuthorityValue(dcValues[0].authority, Choices.getConfidenceText(dcValues[0].confidence));
}
}
}
/**
* Render a date field to the DRI document. The date field consists of
* three component fields, a 4 character text field for the year, a select
* box for the month, and a 2 character text field for the day.
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderDateField(List form, String fieldName, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
// The date field consists of three primitive fields: a text field
// for the year, followed by a select box of the months, follewed
// by a text box for the day.
Composite fullDate = form.addItem().addComposite(fieldName, "submit-date");
Text year = fullDate.addText(fieldName+"_year");
Select month = fullDate.addSelect(fieldName+"_month");
Text day = fullDate.addText(fieldName+"_day");
// Set up the full field
fullDate.setLabel(dcInput.getLabel());
fullDate.setHelp(cleanHints(dcInput.getHints()));
if (dcInput.isRequired())
fullDate.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
fullDate.addError(dcInput.getWarning());
} else {
fullDate.addError(T_required_field);
}
if (dcInput.isRepeatable() && !readonly)
fullDate.enableAddOperation();
if ((dcInput.isRepeatable() || dcValues.length > 1) && !readonly)
fullDate.enableDeleteOperation();
if (readonly)
{
year.setDisabled();
month.setDisabled();
day.setDisabled();
}
// Setup the year field
year.setLabel(T_year);
year.setSize(4,4);
// Setup the month field
month.setLabel(T_month);
month.addOption(0,"");
for (int i = 1; i < 13; i++)
{
month.addOption(i,org.dspace.content.DCDate.getMonthName(i,Locale.getDefault()));
}
// Setup the day field
day.setLabel(T_day);
day.setSize(2,2);
// Setup the field's values
if (dcInput.isRepeatable() || dcValues.length > 1)
{
for (DCValue dcValue : dcValues)
{
DCDate dcDate = new DCDate(dcValue.value);
year.addInstance().setValue(String.valueOf(dcDate.getYear()));
month.addInstance().setOptionSelected(dcDate.getMonth());
day.addInstance().setValue(String.valueOf(dcDate.getDay()));
fullDate.addInstance().setValue(dcDate.toString());
}
}
else if (dcValues.length == 1)
{
DCDate dcDate = new DCDate(dcValues[0].value);
year.setValue(String.valueOf(dcDate.getYear()));
month.setOptionSelected(dcDate.getMonth());
// Check if the day field is not specified, if so then just
// put a blank value in instead of the wiered looking -1.
if (dcDate.getDay() == -1)
day.setValue("");
else
day.setValue(String.valueOf(dcDate.getDay()));
}
}
/**
* Render a series field to the DRI document. The series field conist of
* two component text fields. When interpreted each of these fields are
* combined back together to be a single value joined together by a
* semicolen. The primary use case is for the journal or report number
* the left hand side is the journal and the right hand side in a
* unique number within the journal.
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderSeriesField(List form, String fieldName, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
// The seiries field consists of two parts, a series name (text field)
// and report or paper number (also a text field).
Composite fullSeries = form.addItem().addComposite(fieldName,"submit-"+dcInput.getInputType());
Text series = fullSeries.addText(fieldName+"_series");
Text number = fullSeries.addText(fieldName+"_number");
// Setup the full field.
fullSeries.setLabel(dcInput.getLabel());
fullSeries.setHelp(cleanHints(dcInput.getHints()));
if (dcInput.isRequired())
fullSeries.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
fullSeries.addError(dcInput.getWarning());
} else {
fullSeries.addError(T_required_field);
}
if (dcInput.isRepeatable() && !readonly)
fullSeries.enableAddOperation();
if ((dcInput.isRepeatable() || dcValues.length > 1) && !readonly)
fullSeries.enableDeleteOperation();
series.setLabel(T_series_name);
number.setLabel(T_report_no);
if (readonly)
{
fullSeries.setDisabled();
series.setDisabled();
number.setDisabled();
}
// Setup the field's values
if (dcInput.isRepeatable() || dcValues.length > 1)
{
for (DCValue dcValue : dcValues)
{
DCSeriesNumber dcSeriesNumber = new DCSeriesNumber(dcValue.value);
series.addInstance().setValue(dcSeriesNumber.getSeries());
number.addInstance().setValue(dcSeriesNumber.getNumber());
fullSeries.addInstance().setValue(dcSeriesNumber.toString());
}
}
else if (dcValues.length == 1)
{
DCSeriesNumber dcSeriesNumber = new DCSeriesNumber(dcValues[0].value);
series.setValue(dcSeriesNumber.getSeries());
number.setValue(dcSeriesNumber.getNumber());
}
}
/**
* Render a qualdrop field to the DRI document. Qualdrop fields are complicated,
* widget wise they are composed of two fields, a select and text box field.
* The select field selects the metedata's qualifier and the text box is the
* value. This means that that there is not just one metadata element that is
* represented so the confusing part is that the name can change.
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderQualdropField(List form, String fieldName, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
Composite qualdrop = form.addItem().addComposite(fieldName,"submit-qualdrop");
Select qual = qualdrop.addSelect(fieldName+"_qualifier");
Text value = qualdrop.addText(fieldName+"_value");
// Setup the full field.
qualdrop.setLabel(dcInput.getLabel());
qualdrop.setHelp(cleanHints(dcInput.getHints()));
if (dcInput.isRequired())
qualdrop.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
qualdrop.addError(dcInput.getWarning());
} else {
qualdrop.addError(T_required_field);
}
if (dcInput.isRepeatable() && !readonly)
qualdrop.enableAddOperation();
// Update delete based upon the filtered values.
if ((dcInput.isRepeatable() || dcValues.length > 1) && !readonly)
qualdrop.enableDeleteOperation();
if (readonly)
{
qualdrop.setDisabled();
qual.setDisabled();
value.setDisabled();
}
// Setup the possible options
@SuppressWarnings("unchecked") // This cast is correct
java.util.List<String> pairs = dcInput.getPairs();
for (int i = 0; i < pairs.size(); i += 2)
{
String display = pairs.get(i);
String returnValue = pairs.get(i+1);
qual.addOption(returnValue,display);
}
// Setup the field's values
if (dcInput.isRepeatable() || dcValues.length > 1)
{
for (DCValue dcValue : dcValues)
{
qual.addInstance().setOptionSelected(dcValue.qualifier);
value.addInstance().setValue(dcValue.value);
qualdrop.addInstance().setValue(dcValue.qualifier + ":" + dcValue.value);
}
}
else if (dcValues.length == 1)
{
qual.setOptionSelected(dcValues[0].qualifier);
value.setValue(dcValues[0].value);
}
}
/**
* Render a Text Area field to the DRI document. The text area is a simple
* multi row and column text field.
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderTextArea(List form, String fieldName, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
// Plain old Textarea
TextArea textArea = form.addItem().addTextArea(fieldName,"submit-textarea");
// Setup the text area
textArea.setLabel(dcInput.getLabel());
textArea.setHelp(cleanHints(dcInput.getHints()));
String fieldKey = MetadataAuthorityManager.makeFieldKey(dcInput.getSchema(), dcInput.getElement(), dcInput.getQualifier());
boolean isAuth = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
if (isAuth)
{
textArea.setAuthorityControlled();
textArea.setAuthorityRequired(MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey));
}
if (ChoiceAuthorityManager.getManager().isChoicesConfigured(fieldKey))
{
textArea.setChoices(fieldKey);
textArea.setChoicesPresentation(ChoiceAuthorityManager.getManager().getPresentation(fieldKey));
textArea.setChoicesClosed(ChoiceAuthorityManager.getManager().isClosed(fieldKey));
}
if (dcInput.isRequired())
textArea.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
textArea.addError(dcInput.getWarning());
} else {
textArea.addError(T_required_field);
}
if (dcInput.isRepeatable() && !readonly)
textArea.enableAddOperation();
if ((dcInput.isRepeatable() || dcValues.length > 1) && !readonly)
textArea.enableDeleteOperation();
if (readonly)
{
textArea.setDisabled();
}
// Setup the field's values
if (dcInput.isRepeatable() || dcValues.length > 1)
{
for (DCValue dcValue : dcValues)
{
Instance ti = textArea.addInstance();
ti.setValue(dcValue.value);
if (isAuth)
{
if (dcValue.authority == null || dcValue.authority.equals(""))
ti.setAuthorityValue("", "blank");
else
ti.setAuthorityValue(dcValue.authority, Choices.getConfidenceText(dcValue.confidence));
}
}
}
else if (dcValues.length == 1)
{
textArea.setValue(dcValues[0].value);
if (isAuth)
{
if (dcValues[0].authority == null || dcValues[0].authority.equals(""))
textArea.setAuthorityValue("", "blank");
else
textArea.setAuthorityValue(dcValues[0].authority, Choices.getConfidenceText(dcValues[0].confidence));
}
}
}
/**
* Render a dropdown field for a choice-controlled input of the
* 'select' presentation to the DRI document. The dropdown field
* consists of an HTML select box.
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderChoiceSelectField(List form, String fieldName, Collection coll, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
String fieldKey = MetadataAuthorityManager.makeFieldKey(dcInput.getSchema(), dcInput.getElement(), dcInput.getQualifier());
if (MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey))
throw new WingException("Field "+fieldKey+" has choice presentation of type \""+Params.PRESENTATION_SELECT+"\", it may NOT be authority-controlled.");
// Plain old select list.
Select select = form.addItem().addSelect(fieldName,"submit-select");
//Setup the select field
select.setLabel(dcInput.getLabel());
select.setHelp(cleanHints(dcInput.getHints()));
if (dcInput.isRequired())
select.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
select.addError(dcInput.getWarning());
} else {
select.addError(T_required_field);
}
if (dcInput.isRepeatable() || dcValues.length > 1)
{
// Use the multiple functionality from the HTML
// widget instead of DRI's version.
select.setMultiple();
select.setSize(6);
}
else
select.setSize(1);
if (readonly)
{
select.setDisabled();
}
Choices cs = ChoiceAuthorityManager.getManager().getMatches(fieldKey, "", coll.getID(), 0, 0, null);
if (dcValues.length == 0)
select.addOption(true, "", "");
for (Choice c : cs.values)
{
select.addOption(c.value, c.label);
}
// Setup the field's pre-selected values
for (DCValue dcValue : dcValues)
{
select.setOptionSelected(dcValue.value);
}
}
/**
* Render a dropdown field to the DRI document. The dropdown field consists
* of an HTML select box.
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderDropdownField(List form, String fieldName, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
// Plain old select list.
Select select = form.addItem().addSelect(fieldName,"submit-select");
//Setup the select field
select.setLabel(dcInput.getLabel());
select.setHelp(cleanHints(dcInput.getHints()));
if (dcInput.isRequired())
select.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
select.addError(dcInput.getWarning());
} else {
select.addError(T_required_field);
}
if (dcInput.isRepeatable() || dcValues.length > 1)
{
// Use the multiple functionality from the HTML
// widget instead of DRI's version.
select.setMultiple();
select.setSize(6);
}
if (readonly)
{
select.setDisabled();
}
// Setup the possible options
@SuppressWarnings("unchecked") // This cast is correct
java.util.List<String> pairs = dcInput.getPairs();
for (int i = 0; i < pairs.size(); i += 2)
{
String display = pairs.get(i);
String value = pairs.get(i+1);
select.addOption(value,display);
}
// Setup the field's pre-selected values
for (DCValue dcValue : dcValues)
{
select.setOptionSelected(dcValue.value);
}
}
/**
* Render a select-from-list field to the DRI document.
* This field consists of either a series of checkboxes
* (if repeatable) or a series of radio buttons (if not repeatable).
* <P>
* Note: This is NOT the same as a List element
* (org.dspace.app.xmlui.wing.element.List). It's just unfortunately
* similarly named.
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderSelectFromListField(List form, String fieldName, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
Field listField = null;
//if repeatable, this list of fields should be checkboxes
if (dcInput.isRepeatable())
{
listField = form.addItem().addCheckBox(fieldName);
}
else //otherwise this is a list of radio buttons
{
listField = form.addItem().addRadio(fieldName);
}
if (readonly)
{
listField.setDisabled();
}
// Setup the field
listField.setLabel(dcInput.getLabel());
listField.setHelp(cleanHints(dcInput.getHints()));
if (dcInput.isRequired())
listField.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
listField.addError(dcInput.getWarning());
} else {
listField.addError(T_required_field);
}
//Setup each of the possible options
java.util.List<String> pairs = dcInput.getPairs();
for (int i = 0; i < pairs.size(); i += 2)
{
String display = pairs.get(i);
String value = pairs.get(i+1);
if(listField instanceof CheckBox)
{
((CheckBox)listField).addOption(value, display);
}
else if(listField instanceof Radio)
{
((Radio)listField).addOption(value, display);
}
}
// Setup the field's pre-selected values
for (DCValue dcValue : dcValues)
{
if(listField instanceof CheckBox)
{
((CheckBox)listField).setOptionSelected(dcValue.value);
}
else if(listField instanceof Radio)
{
((Radio)listField).setOptionSelected(dcValue.value);
}
}
}
/**
* Render a simple text field to the DRI document
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderOneboxField(List form, String fieldName, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
// Both onebox and twobox consist a free form text field
// that the user may enter any value. The difference between
// the two is that a onebox should be rendered in one column
// as twobox should be listed in a two column format. Since this
// decision is not something the Aspect can effect we merely place
// as a render hint.
Text text = form.addItem().addText(fieldName,"submit-text");
// Setup the select field
text.setLabel(dcInput.getLabel());
text.setHelp(cleanHints(dcInput.getHints()));
String fieldKey = MetadataAuthorityManager.makeFieldKey(dcInput.getSchema(), dcInput.getElement(), dcInput.getQualifier());
boolean isAuth = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
if (isAuth)
{
text.setAuthorityControlled();
text.setAuthorityRequired(MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey));
}
if (ChoiceAuthorityManager.getManager().isChoicesConfigured(fieldKey))
{
text.setChoices(fieldKey);
text.setChoicesPresentation(ChoiceAuthorityManager.getManager().getPresentation(fieldKey));
text.setChoicesClosed(ChoiceAuthorityManager.getManager().isClosed(fieldKey));
}
if (dcInput.isRequired())
text.setRequired();
if (isFieldInError(fieldName))
if (dcInput.getWarning() != null && dcInput.getWarning().length() > 0) {
text.addError(dcInput.getWarning());
} else {
text.addError(T_required_field);
}
if (dcInput.isRepeatable() && !readonly)
text.enableAddOperation();
if ((dcInput.isRepeatable() || dcValues.length > 1) && !readonly)
text.enableDeleteOperation();
if (readonly)
{
text.setDisabled();
}
// Setup the field's values
if (dcInput.isRepeatable() || dcValues.length > 1)
{
for (DCValue dcValue : dcValues)
{
Instance ti = text.addInstance();
ti.setValue(dcValue.value);
if (isAuth)
{
if (dcValue.authority == null || dcValue.authority.equals(""))
ti.setAuthorityValue("", "blank");
else
ti.setAuthorityValue(dcValue.authority, Choices.getConfidenceText(dcValue.confidence));
}
}
}
else if (dcValues.length == 1)
{
text.setValue(dcValues[0].value);
if (isAuth)
{
if (dcValues[0].authority == null || dcValues[0].authority.equals(""))
text.setAuthorityValue("", "blank");
else
text.setAuthorityValue(dcValues[0].authority, Choices.getConfidenceText(dcValues[0].confidence));
}
}
}
/**
* Check if the given fieldname is listed as being in error.
*
* @param fieldName
* @return
*/
private boolean isFieldInError(String fieldName)
{
if(this.errorFields.contains(fieldName))
return true;
else
return false;
}
/**
* There is a problem with the way hints are handled. The class that we use to
* read the input-forms.xml configuration will append and prepend HTML to hints.
* This causes all sorts of confusion when inserting into the DRI page, so this
* method will strip that extra HTML and just leave the cleaned comments.
*
*
* However this method will not remove naughty or sexual innuendoes from the
* field's hints.
*
*
* @param dirtyHints HTML-ized hints
* @return Hints without HTML.
*/
private static final String HINT_HTML_PREFIX = "<tr><td colspan=\"4\" class=\"submitFormHelp\">";
private static final String HINT_HTML_POSTFIX = "</td></tr>";
private String cleanHints(String dirtyHints)
{
String clean = (dirtyHints!=null ? dirtyHints : "");
if (clean.startsWith(HINT_HTML_PREFIX))
{
clean = clean.substring(HINT_HTML_PREFIX.length());
}
if (clean.endsWith(HINT_HTML_POSTFIX))
{
clean = clean.substring(0,clean.length() - HINT_HTML_POSTFIX.length());
}
return clean;
}
}