Introduce namespace support
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / gcr / xml / DomContentProvider.java
index d1a625e32af960c3cde8d450141b33245fc63672..dc200bf3db48c10258612379efffd47f76f18c0a 100644 (file)
@@ -1,61 +1,99 @@
 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();
        }
+
 }