]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/acr/xml/DomContentProvider.java
4db49343386902e40bdd2e15f7a61bf2996b823a
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / acr / xml / DomContentProvider.java
1 package org.argeo.cms.acr.xml;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.Iterator;
6 import java.util.List;
7
8 import javax.xml.namespace.NamespaceContext;
9 import javax.xml.xpath.XPath;
10 import javax.xml.xpath.XPathConstants;
11 import javax.xml.xpath.XPathExpressionException;
12 import javax.xml.xpath.XPathFactory;
13
14 import org.argeo.api.acr.Content;
15 import org.argeo.api.acr.ContentNotFoundException;
16 import org.argeo.api.acr.NamespaceUtils;
17 import org.argeo.api.acr.spi.ContentProvider;
18 import org.argeo.api.acr.spi.ProvidedSession;
19 import org.w3c.dom.Document;
20 import org.w3c.dom.Element;
21 import org.w3c.dom.NodeList;
22
23 public class DomContentProvider implements ContentProvider, NamespaceContext {
24 private Document document;
25
26 // XPath
27 // TODO centralise in some executor?
28 private final ThreadLocal<XPath> xPath;
29
30 public DomContentProvider(Document document) {
31 this.document = document;
32 this.document.normalizeDocument();
33 XPathFactory xPathFactory = XPathFactory.newInstance();
34 xPath = new ThreadLocal<>() {
35
36 @Override
37 protected XPath initialValue() {
38 // TODO set the document as namespace context?
39 XPath res = xPathFactory.newXPath();
40 res.setNamespaceContext(DomContentProvider.this);
41 return res;
42 }
43 };
44 }
45
46 // @Override
47 // public Content get() {
48 // return new DomContent(this, document.getDocumentElement());
49 // }
50
51 // public Element createElement(String name) {
52 // return document.createElementNS(null, name);
53 //
54 // }
55
56 @Override
57 public Content get(ProvidedSession session, String mountPath, String relativePath) {
58 if ("".equals(relativePath))
59 return new DomContent(session, this, document.getDocumentElement());
60 if (relativePath.startsWith("/"))
61 throw new IllegalArgumentException("Relative path cannot start with /");
62
63 String xPathExpression = '/' + relativePath;
64 if ("/".equals(mountPath))
65 xPathExpression = "/cr:root" + xPathExpression;
66 try {
67 NodeList nodes = (NodeList) xPath.get().evaluate(xPathExpression, document, XPathConstants.NODESET);
68 if (nodes.getLength() > 1)
69 throw new IllegalArgumentException(
70 "Multiple content found for " + relativePath + " under " + mountPath);
71 if (nodes.getLength() == 0)
72 throw new ContentNotFoundException("Path " + relativePath + " under " + mountPath + " was not found");
73 Element element = (Element) nodes.item(0);
74 return new DomContent(session, this, element);
75 } catch (XPathExpressionException e) {
76 throw new IllegalArgumentException("XPath expression " + xPathExpression + " cannot be evaluated", e);
77 }
78 }
79
80 /*
81 * NAMESPACE CONTEXT
82 */
83 @Override
84 public String getNamespaceURI(String prefix) {
85 String namespaceURI = NamespaceUtils.getStandardNamespaceURI(prefix);
86 if (namespaceURI != null)
87 return namespaceURI;
88 return document.lookupNamespaceURI(prefix);
89 }
90
91 @Override
92 public String getPrefix(String namespaceURI) {
93 String prefix = NamespaceUtils.getStandardPrefix(namespaceURI);
94 if (prefix != null)
95 return prefix;
96 return document.lookupPrefix(namespaceURI);
97 }
98
99 @Override
100 public Iterator<String> getPrefixes(String namespaceURI) {
101 List<String> res = new ArrayList<>();
102 res.add(getPrefix(namespaceURI));
103 return Collections.unmodifiableList(res).iterator();
104 }
105
106 }