
org.dspace.app.util.DCInputsReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dspace-api Show documentation
Show all versions of dspace-api Show documentation
DSpace core data model and service APIs.
The newest version!
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.util;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import org.apache.commons.lang3.StringUtils;
import org.dspace.content.Collection;
import org.dspace.content.MetadataSchemaEnum;
import org.dspace.core.Utils;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.submit.factory.SubmissionServiceFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Submission form generator for DSpace. Reads and parses the installation
* form definitions file, submission-forms.xml, from the configuration directory.
* A forms definition details the page and field layout of the metadata
* collection pages used by the submission process. Each forms definition
* starts with a unique name that gets associated with that form set.
*
* The file also specifies which collections use which form sets. At a
* minimum, the definitions file must define a default mapping from the
* placeholder collection #0 to the distinguished form 'default'. Any
* collections that use a custom form set are listed paired with the name
* of the form set they use.
*
* The definitions file also may contain sets of value pairs. Each value pair
* will contain one string that the user reads, and a paired string that will
* supply the value stored in the database if its sibling display value gets
* selected from a choice list.
*
* @author Brian S. Hughes
* @version $Revision$
*/
public class DCInputsReader {
/**
* The ID of the default collection. Will never be the ID of a named
* collection
*/
public static final String DEFAULT_COLLECTION = "default";
/**
* Name of the form definition XML file
*/
static final String FORM_DEF_FILE = "submission-forms.xml";
/**
* Keyname for storing dropdown value-pair set name
*/
static final String PAIR_TYPE_NAME = "value-pairs-name";
/**
* Reference to the forms definitions map, computed from the forms
* definition file
*/
private Map>>> formDefns = null;
/**
* Reference to the value-pairs map, computed from the forms definition file
*/
private Map> valuePairs = null; // Holds display/storage pairs
/**
* Mini-cache of last DCInputSet requested. If submissions are not typically
* form-interleaved, there will be a modest win.
*/
private DCInputSet lastInputSet = null;
/**
* Parse an XML encoded submission forms template file, and create a hashmap
* containing all the form information. This hashmap will contain three top
* level structures: a map between collections and forms, the definition for
* each page of each form, and lists of pairs of values that populate
* selection boxes.
*
* @throws DCInputsReaderException if input reader error
*/
public DCInputsReader()
throws DCInputsReaderException {
// Load from default file
String defsFile = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty("dspace.dir")
+ File.separator + "config" + File.separator + FORM_DEF_FILE;
buildInputs(defsFile);
}
public DCInputsReader(String fileName)
throws DCInputsReaderException {
buildInputs(fileName);
}
private void buildInputs(String fileName)
throws DCInputsReaderException {
formDefns = new HashMap>>>();
valuePairs = new HashMap>();
String uri = "file:" + new File(fileName).getAbsolutePath();
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder db = factory.newDocumentBuilder();
Document doc = db.parse(uri);
doNodes(doc);
checkValues();
} catch (FactoryConfigurationError fe) {
throw new DCInputsReaderException("Cannot create Submission form parser", fe);
} catch (Exception e) {
throw new DCInputsReaderException("Error creating submission forms: " + e);
}
}
public Iterator getPairsNameIterator() {
return valuePairs.keySet().iterator();
}
public List getPairs(String name) {
return valuePairs.get(name);
}
/**
* Returns the set of DC inputs used for a particular collection, or the
* default set if no inputs defined for the collection
*
* @param collection collection for which search the set of DC inputs
* @return DC input set
* @throws DCInputsReaderException if no default set defined
*/
public List getInputsByCollection(Collection collection)
throws DCInputsReaderException {
SubmissionConfig config;
try {
config = SubmissionServiceFactory.getInstance().getSubmissionConfigService()
.getSubmissionConfigByCollection(collection);
String formName = config.getSubmissionName();
if (formName == null) {
throw new DCInputsReaderException("No form designated as default");
}
List results = new ArrayList();
for (int idx = 0; idx < config.getNumberOfSteps(); idx++) {
SubmissionStepConfig step = config.getStep(idx);
if (SubmissionStepConfig.INPUT_FORM_STEP_NAME.equals(step.getType())) {
results.add(getInputsByFormName(step.getId()));
}
}
return results;
} catch (SubmissionConfigReaderException e) {
throw new DCInputsReaderException("No form designated as default", e);
}
}
public List getInputsBySubmissionName(String name)
throws DCInputsReaderException {
SubmissionConfig config;
try {
config = SubmissionServiceFactory.getInstance().getSubmissionConfigService()
.getSubmissionConfigByName(name);
String formName = config.getSubmissionName();
if (formName == null) {
throw new DCInputsReaderException("No form designated as default");
}
List results = new ArrayList();
for (int idx = 0; idx < config.getNumberOfSteps(); idx++) {
SubmissionStepConfig step = config.getStep(idx);
if (SubmissionStepConfig.INPUT_FORM_STEP_NAME.equals(step.getType())) {
results.add(getInputsByFormName(step.getId()));
}
}
return results;
} catch (SubmissionConfigReaderException e) {
throw new DCInputsReaderException("No form designated as default", e);
}
}
/**
* Returns the set of DC inputs used for a particular input form
*
* @param formName input form unique name
* @return DC input set
* @throws DCInputsReaderException if not found
*/
public DCInputSet getInputsByFormName(String formName)
throws DCInputsReaderException {
// check mini-cache, and return if match
if (lastInputSet != null && lastInputSet.getFormName().equals(formName)) {
return lastInputSet;
}
// cache miss - construct new DCInputSet
List>> pages = formDefns.get(formName);
if (pages == null) {
throw new DCInputsReaderException("Missing the " + formName + " form");
}
lastInputSet = new DCInputSet(formName,
pages, valuePairs);
return lastInputSet;
}
/**
* @return the number of defined input forms
*/
public int countInputs() {
return formDefns.size();
}
/**
* Returns all the Input forms with pagination
*
* @param limit max number of Input Forms to return
* @param offset number of Input form to skip in the return
* @return the list of input forms
* @throws DCInputsReaderException
*/
public List getAllInputs(Integer limit, Integer offset) throws DCInputsReaderException {
int idx = 0;
int count = 0;
List subConfigs = new LinkedList();
for (String key : formDefns.keySet()) {
if (offset == null || idx >= offset) {
count++;
subConfigs.add(getInputsByFormName(key));
}
idx++;
if (count >= limit) {
break;
}
}
return subConfigs;
}
/**
* Process the top level child nodes in the passed top-level node. These
* should correspond to the collection-form maps, the form definitions, and
* the display/storage word pairs.
*
* @param n top-level DOM node
*/
private void doNodes(Node n)
throws SAXException, DCInputsReaderException {
if (n == null) {
return;
}
Node e = getElement(n);
NodeList nl = e.getChildNodes();
int len = nl.getLength();
boolean foundDefs = false;
for (int i = 0; i < len; i++) {
Node nd = nl.item(i);
if ((nd == null) || isEmptyTextNode(nd)) {
continue;
}
String tagName = nd.getNodeName();
if (tagName.equals("form-definitions")) {
processDefinition(nd);
foundDefs = true;
} else if (tagName.equals("form-value-pairs")) {
processValuePairs(nd);
}
// Ignore unknown nodes
}
if (!foundDefs) {
throw new DCInputsReaderException("No form definition found");
}
}
/**
* Process the form-definitions section of the XML file. Each element is
* formed thusly: Each rows
* subsection is formed: ...fields...
Each field
* is formed from: dc-element, dc-qualifier, label, hint, input-type name,
* required text, and repeatable flag.
*/
private void processDefinition(Node e)
throws SAXException, DCInputsReaderException {
int numForms = 0;
NodeList nl = e.getChildNodes();
int len = nl.getLength();
for (int i = 0; i < len; i++) {
Node nd = nl.item(i);
// process each form definition
if (nd.getNodeName().equals("form")) {
numForms++;
String formName = getAttribute(nd, "name");
if (formName == null) {
throw new SAXException("form element has no name attribute");
}
List>> rows = new ArrayList>>(); // the form
// contains rows of fields
formDefns.put(formName, rows);
NodeList pl = nd.getChildNodes();
int lenpg = pl.getLength();
for (int j = 0; j < lenpg; j++) {
Node npg = pl.item(j);
if (npg.getNodeName().equals("row")) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy