/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.client.utility.validate.types;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import fedora.client.utility.validate.InvalidContentModelException;
import static fedora.client.utility.validate.types.ContentModelInfo.DS_COMPOSITE_MODEL;
/**
* Parses the DS-COMPOSITE-MODEL XML document, and presents the contents in a
* way that is compatible with {@link ContentModelInfo}.
*
* @author Jim Blake
*/
public class DsCompositeModelDoc {
private static final String ELEMENT_DS_TYPE_MODEL = "dsTypeModel";
private final Set<DsTypeModel> typeModels;
/**
* Parse the datastream XML.
*
* @param pid
* used in error messages.
* @param bytes
* from the datastream of the content model.
* @throws InvalidContentModelException
*/
public DsCompositeModelDoc(String pid, byte[] bytes)
throws InvalidContentModelException {
Document doc = parseBytesToDocument(pid, bytes);
NodeList typeModelNodes =
doc.getElementsByTagName(ELEMENT_DS_TYPE_MODEL);
Set<DsTypeModel> typeModels = new HashSet<DsTypeModel>();
for (int i = 0; i < typeModelNodes.getLength(); i++) {
Element typeModelElement = (Element) typeModelNodes.item(i);
typeModels.add(new DsTypeModel(pid, typeModelElement));
}
this.typeModels = Collections.unmodifiableSet(typeModels);
}
/**
* Get the type models of the content model.
*/
public Set<ContentModelInfo.DsTypeModel> getTypeModels() {
return new HashSet<ContentModelInfo.DsTypeModel>(typeModels);
}
/**
* Create a DOM document from the original XML.
*/
private Document parseBytesToDocument(String pid, byte[] bytes)
throws InvalidContentModelException {
try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(bytes));
} catch (ParserConfigurationException e) {
throw new InvalidContentModelException(pid, "Failed to parse "
+ DS_COMPOSITE_MODEL, e);
} catch (SAXException e) {
throw new InvalidContentModelException(pid, "Failed to parse "
+ DS_COMPOSITE_MODEL, e);
} catch (IOException e) {
throw new InvalidContentModelException(pid, "Failed to parse "
+ DS_COMPOSITE_MODEL, e);
}
}
/**
* An implementation of {@link ContentModelInfo.DsTypeModel} that includes a
* constructor that parses a <dsTypeModel> tag.
*/
public static class DsTypeModel
implements ContentModelInfo.DsTypeModel {
private static final String ATTRIBUTE_ID = "ID";
private static final String ELEMENT_FORM = "form";
private final String id;
private final Set<Form> forms;
public DsTypeModel(String pid, Element typeModelElement)
throws InvalidContentModelException {
id = typeModelElement.getAttribute(ATTRIBUTE_ID);
if (id.length() == 0) {
throw new InvalidContentModelException(pid, "<"
+ ELEMENT_DS_TYPE_MODEL + "> has no '" + ATTRIBUTE_ID
+ "'");
}
NodeList formNodes =
typeModelElement.getElementsByTagName(ELEMENT_FORM);
Set<Form> forms = new HashSet<Form>();
for (int i = 0; i < formNodes.getLength(); i++) {
forms.add(new Form((Element) formNodes.item(i)));
}
this.forms = Collections.unmodifiableSet(forms);
}
public String getId() {
return id;
}
public Set<ContentModelInfo.Form> getForms() {
return new HashSet<ContentModelInfo.Form>(forms);
}
}
/**
* An implementation of {@link ContentModelInfo.DsTypeModel} that includes a
* constructor that parses a <form> tag.
*/
public static class Form
implements ContentModelInfo.Form {
private static final String ATTRIBUTE_MIME = "MIME";
private static final String ATTRIBUTE_FORMAT_URI = "FORMAT_URI";
private final String mime;
private final String formatUri;
public Form(Element formElement) {
String mime = formElement.getAttribute(ATTRIBUTE_MIME);
this.mime = mime.length() == 0 ? null : mime;
String formatUri = formElement.getAttribute(ATTRIBUTE_FORMAT_URI);
this.formatUri = formatUri.length() == 0 ? null : formatUri;
}
public String getMimeType() {
return mime;
}
public String getFormatUri() {
return formatUri;
}
@Override
public String toString() {
return "Form[mime=" + mime + ", formatUri=" + formatUri + "]";
}
}
}