/* 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 org.fcrepo.utilities;
import java.io.OutputStream;
import java.io.StringReader;
import java.util.Date;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
/**
* A DOM-based utility for generating FOXML 1.1 documents.
*
* @author Edwin Shin
* @since 3.0
* @version $Id$
*/
public class Foxml11Document {
public static final String FOXML_NS="info:fedora/fedora-system:def/foxml#";
private Document doc;
private Element rootElement;
private Element objectProperties;
private final XPath xpath;
public enum Property {
STATE("info:fedora/fedora-system:def/model#state"),
LABEL("info:fedora/fedora-system:def/model#label"),
CONTENT_MODEL("info:fedora/fedora-system:def/model#contentModel"),
CREATE_DATE("info:fedora/fedora-system:def/model#createdDate"),
MOD_DATE("info:fedora/fedora-system:def/view#lastModifiedDate");
private final String uri;
Property(String uri) {
this.uri = uri;
}
String uri() {
return uri;
}
}
public enum State {
A, I, D;
}
public enum ControlGroup {
X, M, E, R;
}
public Foxml11Document(String pid) throws Exception {
DocumentBuilder builder = null;
try {
builder = XmlTransformUtility.borrowDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
doc = impl.createDocument(FOXML_NS, "foxml:digitalObject", null);
rootElement = doc.getDocumentElement();
rootElement.setAttributeNS("http://www.w3.org/2000/xmlns/",
"xmlns:xsi",
"http://www.w3.org/1999/XMLSchema-instance");
rootElement.setAttributeNS("http://www.w3.org/1999/XMLSchema-instance",
"xsi:schemaLocation",
"info:fedora/fedora-system:def/foxml# http://www.fedora.info/definitions/1/0/foxml1-1.xsd");
rootElement.setAttribute("VERSION", "1.1");
rootElement.setAttribute("PID", pid);
} finally {
if (builder != null) {
XmlTransformUtility.returnDocumentBuilder(builder);
}
}
NamespaceContextImpl nsCtx = new NamespaceContextImpl();
nsCtx.addNamespace("foxml", FOXML_NS);
XPathFactory factory = XPathFactory.newInstance();
xpath = factory.newXPath();
xpath.setNamespaceContext(nsCtx);
}
public void addObjectProperties() {
if (objectProperties == null) {
objectProperties =
doc.createElementNS(FOXML_NS, "foxml:objectProperties");
rootElement.appendChild(objectProperties);
}
}
public void addObjectProperty(Property name, String value) {
addObjectProperties();
Element property = doc.createElementNS(FOXML_NS, "foxml:property");
property.setAttribute("NAME", name.uri);
property.setAttribute("VALUE", value);
objectProperties.appendChild(property);
}
public void addDatastream(String id,
State state,
ControlGroup controlGroup,
boolean versionable) {
Element ds = doc.createElementNS(FOXML_NS, "foxml:datastream");
ds.setAttribute("ID", id);
ds.setAttribute("STATE", state.toString());
ds.setAttribute("CONTROL_GROUP", controlGroup.toString());
ds.setAttribute("VERSIONABLE", Boolean.toString(versionable));
rootElement.appendChild(ds);
}
public void addDatastreamVersion(String dsId,
String dsvId,
String mimeType,
String label,
int size,
Date created) {
String expr = String.format("//foxml:datastream[@ID='%s']", dsId);
try {
NodeList nodes = (NodeList)xpath.evaluate(expr, doc, XPathConstants.NODESET);
Node node = nodes.item(0);
if (node == null) {
throw new IllegalArgumentException(dsId + "does not exist.");
}
Element dsv = doc.createElementNS(FOXML_NS, "foxml:datastreamVersion");
dsv.setAttribute("ID", dsvId);
dsv.setAttribute("MIMETYPE", mimeType);
dsv.setAttribute("LABEL", label);
dsv.setAttribute("SIZE", Integer.toString(size));
dsv.setAttribute("CREATED", DateUtility.convertDateToString(created));
node.appendChild(dsv);
} catch (XPathExpressionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void addXmlContent(String dsvId, String xmlContent) {
DocumentBuilder builder = null;
try {
builder = XmlTransformUtility.borrowDocumentBuilder();
Document contentDoc = builder.parse(new InputSource(new StringReader(xmlContent)));
Node importedContent = doc.adoptNode(contentDoc.getDocumentElement());
Node dsv = getDatastreamVersion(dsvId);
Element content = doc.createElementNS(FOXML_NS, "foxml:xmlContent");
dsv.appendChild(content);
content.appendChild(importedContent);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (builder != null) {
XmlTransformUtility.returnDocumentBuilder(builder);
}
}
}
public void setContentLocation(String dsvId, String ref, String type) {
String expr = String.format("//foxml:datastreamVersion[@ID='%s']/foxml:contentLocation", dsvId);
try {
NodeList nodes = (NodeList)xpath.evaluate(expr, doc, XPathConstants.NODESET);
Element location = (Element)nodes.item(0);
if (location == null) {
location = addContentLocation(dsvId);
}
location.setAttribute("REF", ref);
location.setAttribute("TYPE", type);
} catch (XPathExpressionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private Element addContentLocation(String dsvId) {
Node node = getDatastreamVersion(dsvId);
Element location = doc.createElementNS(FOXML_NS, "foxml:contentLocation");
node.appendChild(location);
return location;
}
private Node getDatastreamVersion(String dsvId) {
String expr = String.format("//foxml:datastreamVersion[@ID='%s']", dsvId);
try {
NodeList nodes = (NodeList)xpath.evaluate(expr, doc, XPathConstants.NODESET);
Node node = nodes.item(0);
if (node == null) {
throw new IllegalArgumentException(dsvId + "does not exist.");
}
return node;
} catch (XPathExpressionException e) {
throw new IllegalArgumentException(dsvId + "does not exist.");
}
}
public void serialize(OutputStream out) throws Exception {
final Transformer idTransform = XmlTransformUtility.getTransformer();
Source input = new DOMSource(doc);
Result output = new StreamResult(out);
idTransform.transform(input, output);
}
}