package org.argeo.cms.gcr.xml;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
import org.argeo.api.gcr.Content;
-import org.argeo.api.gcr.ContentUtils;
+import org.argeo.api.gcr.ContentNotFoundException;
import org.argeo.api.gcr.spi.ContentProvider;
+import org.argeo.api.gcr.spi.ProvidedSession;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
-public class DomContentProvider implements ContentProvider {
+public class DomContentProvider implements ContentProvider, NamespaceContext {
private Document document;
+ // XPath
+ // TODO centralise in some executor?
+ private final ThreadLocal<XPath> xPath;
+
public DomContentProvider(Document document) {
this.document = document;
this.document.normalizeDocument();
+ XPathFactory xPathFactory = XPathFactory.newInstance();
+ xPath = new ThreadLocal<>() {
+
+ @Override
+ protected XPath initialValue() {
+ // TODO set the document as namespace context?
+ XPath res= xPathFactory.newXPath();
+ res.setNamespaceContext(DomContentProvider.this);
+ return res;
+ }
+ };
}
+// @Override
+// public Content get() {
+// return new DomContent(this, document.getDocumentElement());
+// }
+
+// public Element createElement(String name) {
+// return document.createElementNS(null, name);
+//
+// }
+
@Override
- public Content get() {
- return new DomContent(this, document.getDocumentElement());
- }
+ public Content get(ProvidedSession session, String mountPath, String relativePath) {
+ if ("".equals(relativePath))
+ return new DomContent(session, this, document.getDocumentElement());
+ if (relativePath.startsWith("/"))
+ throw new IllegalArgumentException("Relative path cannot start with /");
- public Element createElement(String name) {
- return document.createElement(name);
+ String xPathExpression = '/' + relativePath;
+ if ("/".equals(mountPath))
+ xPathExpression = "/cr:root" + 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);
+ } catch (XPathExpressionException e) {
+ throw new IllegalArgumentException("XPath expression " + xPathExpression + " cannot be evaluated", e);
+ }
}
+ /*
+ * NAMESPACE CONTEXT
+ */
@Override
- public Content get(String relativePath) {
- // TODO Auto-generated method stub
- return null;
+ public String getNamespaceURI(String prefix) {
+ return document.lookupNamespaceURI(prefix);
}
- public static void main(String args[]) throws Exception {
- HashMap<String, Object> map = new HashMap<>();
- map.put(null, "test");
- System.out.println(map.get(null));
-
- Set<String> set = new HashSet<>();
- set.add(null);
-
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder dBuilder = factory.newDocumentBuilder();
- Path testFile;
- testFile = Paths.get(System.getProperty("user.home") + "/dev/git/unstable/argeo-commons/pom.xml");
- testFile = Paths.get(System.getProperty("user.home") + "/tmp/test.xml");
- Document doc = dBuilder.parse(Files.newInputStream(testFile));
-
- DomContentProvider contentSession = new DomContentProvider(doc);
- ContentUtils.traverse(contentSession.get(), (c, d) -> ContentUtils.print(c, System.out, d, true));
+ @Override
+ public String getPrefix(String namespaceURI) {
+ return document.lookupPrefix(namespaceURI);
+ }
+ @Override
+ public Iterator<String> getPrefixes(String namespaceURI) {
+ List<String> res = new ArrayList<>();
+ res.add(getPrefix(namespaceURI));
+ return Collections.unmodifiableList(res).iterator();
}
+
}