/** * 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.purl.sword.base; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import nu.xom.Element; import nu.xom.Elements; import org.apache.log4j.Logger; import org.purl.sword.atom.Generator; /** * Represents an Atom Publishing Protocol Service element, with * SWORD extensions. * * @author Neil Taylor */ public class Service extends XmlElement implements SwordElementInterface { private SwordVersion swordVersion; private SwordNoOp swordNoOp; private SwordVerbose swordVerbose; private SwordMaxUploadSize swordMaxUploadSize; /** * The details of the server software that generated the service document. */ private Generator generator; /** * List of Workspaces. */ private List<Workspace> workspaces; /** Logger */ private static Logger log = Logger.getLogger(Service.class); /** * MaxUploadSize */ @Deprecated public static final String ELEMENT_GENERATOR = "generator"; /** * Name for this element. */ @Deprecated public static final String ELEMENT_NAME = "service"; /** * The XML NAME (prefix, local name and namespace) for this element. */ private static final XmlName XML_NAME = new XmlName(Namespaces.PREFIX_APP, "service", Namespaces.NS_APP); /** * Create a new instance. */ public Service() { super(XML_NAME); initialise(); } /** * Create a new instance. * * @param version The service compliance level. */ public Service(String version) { this(); setVersion(version); } /** * Create a new instance with the specified compliance level, noOp and * verbose values. * * @param version The service compliance level. * @param noOp The noOp. * @param verbose The verbose element. */ public Service(String version, boolean noOp, boolean verbose) { this(); setVersion(version); setNoOp(noOp); setVerbose(verbose); } public static XmlName elementName() { return XML_NAME; } /** * Initialise the data structures in this tool. */ private void initialise() { workspaces = new ArrayList<Workspace>(); swordVersion = null; swordNoOp = null; swordVerbose = null; swordMaxUploadSize = null; generator = null; } /** * Get the SWORD version. * * @return The version. */ public final String getVersion() { if ( swordVersion == null ) { return null; } return swordVersion.getContent(); } /** * Set the SWORD version. * * @param version The version. */ public final void setVersion(String version) { if ( version == null ) { // clear the value swordVersion = null; return; } swordVersion = new SwordVersion(version); } /** * Get the NoOp value. * * @return The value. */ public final boolean isNoOp() { if ( swordNoOp == null ) { return false; } return swordNoOp.getContent(); } /** * Set the NoOp value. * * @param noOp The value. */ public final void setNoOp(boolean noOp) { swordNoOp = new SwordNoOp(noOp); } /** * Determine if the NoOp value has been set. This should be called to * check if an item has been programmatically set and does not have a * default value. * * @return True if it has been set programmatically. Otherwise, false. */ public final boolean isNoOpSet() { if ( swordNoOp == null ) { return false; } return swordNoOp.isSet(); } /** * Get the Verbose setting. * * @return The value. */ public final boolean isVerbose() { if ( swordVerbose == null ) { return false; } return swordVerbose.getContent(); } /** * Set the Verbose value. * * @param verbose The value. */ public final void setVerbose(boolean verbose) { swordVerbose = new SwordVerbose(verbose); } /** * Determine if the Verbose value has been set. This should be called to * check if an item has been programmatically set and does not have a * default value. * * @return True if it has been set programmatically. Otherwise, false. */ public final boolean isVerboseSet() { if ( swordVerbose == null ) { return false; } return swordVerbose.isSet(); } /** * Set the maximum file upload size in kB * * @param maxUploadSize Max upload file size in kB */ public final void setMaxUploadSize(int maxUploadSize) { swordMaxUploadSize = new SwordMaxUploadSize(maxUploadSize); } /** * Get the maximum upload file size (in kB) * * @return the maximum file upload size. If no value has been set, this will * be equal to Integer.MIN_VALUE. */ public final int getMaxUploadSize() { if ( swordMaxUploadSize == null ) { return Integer.MIN_VALUE; } return swordMaxUploadSize.getContent(); } public final Generator getGenerator() { return generator; } public final void setGenerator(Generator generator) { this.generator = generator; } /** * Get an Iterator over the workspaces. * * @return The workspace. */ public final Iterator<Workspace> getWorkspaces() { return workspaces.iterator(); } /** * Get a List of workspaces * * @return The workspaces in a List */ public final List<Workspace> getWorkspacesList() { return workspaces; } /** * Add a workspace. * * @param workspace The workspace. */ public final void addWorkspace(Workspace workspace) { this.workspaces.add(workspace); } /** * Clear the list of workspaces. */ public final void clearWorkspaces() { this.workspaces.clear(); } /** * Marshal the data in this object to an Element object. * * @return A XOM Element that holds the data for this Content element. */ public final Element marshall( ) { Element service = new Element(getQualifiedName(), Namespaces.NS_APP); service.addNamespaceDeclaration(Namespaces.PREFIX_ATOM, Namespaces.NS_ATOM); service.addNamespaceDeclaration(Namespaces.PREFIX_DC_TERMS, Namespaces.NS_DC_TERMS); service.addNamespaceDeclaration(Namespaces.PREFIX_SWORD, Namespaces.NS_SWORD); if ( swordVersion != null ) { service.appendChild(swordVersion.marshall()); } if ( swordVerbose != null ) { service.appendChild(swordVerbose.marshall()); } if ( swordNoOp != null ) { service.appendChild(swordNoOp.marshall()); } if ( swordMaxUploadSize != null ) { service.appendChild(swordMaxUploadSize.marshall()); } if ( generator != null ) { service.appendChild(generator.marshall()); } for (Workspace item : workspaces) { service.appendChild(item.marshall()); } return service; } /** * Unmarshal the content element into the data in this object. * * @throws UnmarshallException If the element does not contain a * content element or if there are problems * accessing the data. */ public final void unmarshall( Element service ) throws UnmarshallException { unmarshall(service, null); } /** * * @param service * element to unmarshall * @param validationProperties * FIXME: PLEASE DOCUMENT. * @return SWORD validation info * @throws UnmarshallException If the element does not contain a * content element or if there are problems * accessing the data. */ public final SwordValidationInfo unmarshall(Element service, Properties validationProperties) throws UnmarshallException { if (!isInstanceOf(service, xmlName)) { return handleIncorrectElement(service, validationProperties); } ArrayList<SwordValidationInfo> validationItems = new ArrayList<SwordValidationInfo>(); try { initialise(); // Retrieve all of the sub-elements Elements elements = service.getChildElements(); Element element = null; int length = elements.size(); for (int i = 0; i < length; i++ ) { element = elements.get(i); if (isInstanceOf(element, SwordVersion.elementName() ) ) { //validationItems.add(unmarshallVersion(element, validate)); if ( swordVersion == null ) { swordVersion = new SwordVersion(); validationItems.add(swordVersion.unmarshall(element, validationProperties)); } else if ( validationProperties != null ) { SwordValidationInfo info = new SwordValidationInfo(SwordVersion.elementName(), SwordValidationInfo.DUPLICATE_ELEMENT, SwordValidationInfoType.WARNING); info.setContentDescription(element.getValue()); validationItems.add(info); } } else if (isInstanceOf(element, SwordVerbose.elementName())) { if ( swordVerbose == null ) { swordVerbose = new SwordVerbose(); validationItems.add(swordVerbose.unmarshall(element, validationProperties)); } else if ( validationProperties != null ) { SwordValidationInfo info = new SwordValidationInfo(SwordVerbose.elementName(), SwordValidationInfo.DUPLICATE_ELEMENT, SwordValidationInfoType.WARNING); info.setContentDescription(element.getValue()); validationItems.add(info); } } else if (isInstanceOf(element, SwordNoOp.elementName()) ) { if ( swordNoOp == null ) { swordNoOp = new SwordNoOp(); validationItems.add(swordNoOp.unmarshall(element, validationProperties)); } else if ( validationProperties != null ) { SwordValidationInfo info = new SwordValidationInfo(SwordNoOp.elementName(), SwordValidationInfo.DUPLICATE_ELEMENT, SwordValidationInfoType.WARNING); info.setContentDescription(element.getValue()); validationItems.add(info); } } else if (isInstanceOf(element, SwordMaxUploadSize.elementName())) { if ( swordMaxUploadSize == null ) { swordMaxUploadSize = new SwordMaxUploadSize(); validationItems.add(swordMaxUploadSize.unmarshall(element, validationProperties)); } else if ( validationProperties != null ) { SwordValidationInfo info = new SwordValidationInfo(SwordNoOp.elementName(), SwordValidationInfo.DUPLICATE_ELEMENT, SwordValidationInfoType.WARNING); info.setContentDescription(element.getValue()); validationItems.add(info); } } else if (isInstanceOf(element, Generator.elementName())) { if ( generator == null ) { generator = new Generator(); validationItems.add(generator.unmarshall(element, validationProperties)); } else if ( validationProperties != null ) { SwordValidationInfo info = new SwordValidationInfo(Generator.elementName(), SwordValidationInfo.DUPLICATE_ELEMENT, SwordValidationInfoType.WARNING); info.setContentDescription(element.getValue()); validationItems.add(info); } } else if (isInstanceOf(element, Workspace.elementName() )) { Workspace workspace = new Workspace( ); validationItems.add(workspace.unmarshall(element, validationProperties)); workspaces.add(workspace); } else if ( validationProperties != null ) { // report on any additional items. They are permitted because of // the Atom/APP specification. Report the items for information XmlName name = new XmlName(element.getNamespacePrefix(), element.getLocalName(), element.getNamespaceURI()); validationItems.add(new SwordValidationInfo(name, SwordValidationInfo.UNKNOWN_ELEMENT, SwordValidationInfoType.INFO)); } } } catch ( Exception ex ) { log.error("Unable to parse an element in Service: " + ex.getMessage()); ex.printStackTrace(); throw new UnmarshallException("Unable to parse element in Service", ex); } // now process the validation information SwordValidationInfo result = null; if ( validationProperties != null ) { result = validate(validationItems, validationProperties); } return result; } public SwordValidationInfo validate(Properties validationContext) { return validate(null, validationContext); } /** * * @param existing add results to this. * @param validationContext FIXME: PLEASE DOCUMENT. * @return validation information */ protected SwordValidationInfo validate(List<SwordValidationInfo> existing, Properties validationContext) { boolean validateAll = (existing != null); SwordValidationInfo result = new SwordValidationInfo(xmlName); // process the basic rules if ( swordVersion == null ) { SwordValidationInfo info = new SwordValidationInfo(SwordVersion.elementName(), SwordValidationInfo.MISSING_ELEMENT_WARNING, SwordValidationInfoType.WARNING); result.addValidationInfo(info); } if ( generator == null ) { SwordValidationInfo info = new SwordValidationInfo(Generator.elementName(), SwordValidationInfo.MISSING_ELEMENT_WARNING, SwordValidationInfoType.WARNING); result.addValidationInfo(info); } if ( workspaces == null || workspaces.size() == 0 ) { SwordValidationInfo info = new SwordValidationInfo(Workspace.elementName(), "This element SHOULD be included unless the authenticated user does not have permission to deposit.", SwordValidationInfoType.WARNING); result.addValidationInfo(info); } if ( validateAll ) { if ( swordVersion != null ) { result.addValidationInfo(swordVersion.validate(validationContext)); } if ( swordNoOp != null ) { result.addValidationInfo(swordNoOp.validate(validationContext)); } if ( swordVerbose != null ) { result.addValidationInfo(swordVerbose.validate(validationContext)); } if ( swordMaxUploadSize != null ) { result.addValidationInfo(swordMaxUploadSize.validate(validationContext)); } if ( generator != null ) { result.addValidationInfo(generator.validate(validationContext)); } Iterator<Workspace> iterator = workspaces.iterator(); while ( iterator.hasNext() ) { result.addValidationInfo(iterator.next().validate(validationContext)); } } result.addUnmarshallValidationInfo(existing, null); return result; } }