package org.argeo.cms.acr.xml;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.NamespaceContext;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.TransformerFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import org.argeo.api.acr.Content;
import org.argeo.api.acr.ContentNotFoundException;
import org.argeo.api.acr.CrName;
+import org.argeo.api.acr.NamespaceUtils;
import org.argeo.api.acr.spi.ContentProvider;
+import org.argeo.api.acr.spi.ProvidedContent;
import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.cms.acr.CmsContentRepository;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
public class DomContentProvider implements ContentProvider, NamespaceContext {
- private Document document;
+ private final Document document;
// XPath
// TODO centralise in some executor?
private final ThreadLocal<XPath> xPath;
- public DomContentProvider(Document document) {
+ private TransformerFactory transformerFactory;
+
+ private String mountPath;
+
+ public DomContentProvider(String mountPath, Document document) {
+ this.mountPath = mountPath;
this.document = document;
this.document.normalizeDocument();
+
+ transformerFactory = TransformerFactory.newInstance();
+
XPathFactory xPathFactory = XPathFactory.newInstance();
xPath = new ThreadLocal<>() {
@Override
protected XPath initialValue() {
// TODO set the document as namespace context?
- XPath res= xPathFactory.newXPath();
+ XPath res = xPathFactory.newXPath();
res.setNamespaceContext(DomContentProvider.this);
return res;
}
// }
@Override
- public Content get(ProvidedSession session, String mountPath, String relativePath) {
+ public ProvidedContent get(ProvidedSession session, String relativePath) {
if ("".equals(relativePath))
return new DomContent(session, this, document.getDocumentElement());
+
+ NodeList nodes = findContent(relativePath);
+ if (nodes.getLength() > 1)
+ throw new IllegalArgumentException("Multiple content found for " + relativePath + " under " + mountPath);
+ if (nodes.getLength() == 0)
+ throw new ContentNotFoundException("Path " + relativePath + " under " + mountPath + " was not found");
+ Element element = (Element) nodes.item(0);
+ return new DomContent(session, this, element);
+ }
+
+ protected NodeList findContent(String relativePath) {
if (relativePath.startsWith("/"))
throw new IllegalArgumentException("Relative path cannot start with /");
-
String xPathExpression = '/' + relativePath;
if ("/".equals(mountPath))
- xPathExpression = "/cr:root" + xPathExpression;
+ xPathExpression = "/" + CrName.root.qName() + xPathExpression;
try {
NodeList nodes = (NodeList) xPath.get().evaluate(xPathExpression, document, XPathConstants.NODESET);
- if (nodes.getLength() > 1)
- throw new IllegalArgumentException(
- "Multiple content found for " + relativePath + " under " + mountPath);
- if (nodes.getLength() == 0)
- throw new ContentNotFoundException("Path " + relativePath + " under " + mountPath + " was not found");
- Element element = (Element) nodes.item(0);
- return new DomContent(session, this, element);
+ return nodes;
} catch (XPathExpressionException e) {
throw new IllegalArgumentException("XPath expression " + xPathExpression + " cannot be evaluated", e);
}
+
+ }
+
+ @Override
+ public boolean exists(ProvidedSession session, String relativePath) {
+ if ("".equals(relativePath))
+ return true;
+ NodeList nodes = findContent(relativePath);
+ return nodes.getLength() != 0;
+ }
+
+ public void persist(ProvidedSession session) {
+ if (mountPath != null) {
+ Content mountPoint = session.getMountPoint(mountPath);
+ try (OutputStream out = mountPoint.open(OutputStream.class)) {
+ CmsContentRepository contentRepository = (CmsContentRepository) session.getRepository();
+ contentRepository.writeDom(document, out);
+ } catch (IOException e) {
+ throw new IllegalStateException("Cannot persist " + mountPath, e);
+ }
+ }
+ }
+
+ @Override
+ public String getMountPath() {
+ return mountPath;
+ }
+
+ public void registerPrefix(String prefix, String namespace) {
+ DomUtils.addNamespace(document.getDocumentElement(), prefix, namespace);
}
/*
*/
@Override
public String getNamespaceURI(String prefix) {
+ String namespaceURI = NamespaceUtils.getStandardNamespaceURI(prefix);
+ if (namespaceURI != null)
+ return namespaceURI;
return document.lookupNamespaceURI(prefix);
}
@Override
public String getPrefix(String namespaceURI) {
+ String prefix = NamespaceUtils.getStandardPrefix(namespaceURI);
+ if (prefix != null)
+ return prefix;
return document.lookupPrefix(namespaceURI);
}
return Collections.unmodifiableList(res).iterator();
}
-
+ TransformerFactory getTransformerFactory() {
+ return transformerFactory;
+ }
+
}