1 package org
.argeo
.cms
.acr
.xml
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Collections
;
5 import java
.util
.Iterator
;
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
;
14 import org
.argeo
.api
.acr
.Content
;
15 import org
.argeo
.api
.acr
.ContentNotFoundException
;
16 import org
.argeo
.api
.acr
.spi
.ContentProvider
;
17 import org
.argeo
.api
.acr
.spi
.ProvidedSession
;
18 import org
.w3c
.dom
.Document
;
19 import org
.w3c
.dom
.Element
;
20 import org
.w3c
.dom
.NodeList
;
22 public class DomContentProvider
implements ContentProvider
, NamespaceContext
{
23 private Document document
;
26 // TODO centralise in some executor?
27 private final ThreadLocal
<XPath
> xPath
;
29 public DomContentProvider(Document document
) {
30 this.document
= document
;
31 this.document
.normalizeDocument();
32 XPathFactory xPathFactory
= XPathFactory
.newInstance();
33 xPath
= new ThreadLocal
<>() {
36 protected XPath
initialValue() {
37 // TODO set the document as namespace context?
38 XPath res
= xPathFactory
.newXPath();
39 res
.setNamespaceContext(DomContentProvider
.this);
46 // public Content get() {
47 // return new DomContent(this, document.getDocumentElement());
50 // public Element createElement(String name) {
51 // return document.createElementNS(null, name);
56 public Content
get(ProvidedSession session
, String mountPath
, String relativePath
) {
57 if ("".equals(relativePath
))
58 return new DomContent(session
, this, document
.getDocumentElement());
59 if (relativePath
.startsWith("/"))
60 throw new IllegalArgumentException("Relative path cannot start with /");
62 String xPathExpression
= '/' + relativePath
;
63 if ("/".equals(mountPath
))
64 xPathExpression
= "/cr:root" + xPathExpression
;
66 NodeList nodes
= (NodeList
) xPath
.get().evaluate(xPathExpression
, document
, XPathConstants
.NODESET
);
67 if (nodes
.getLength() > 1)
68 throw new IllegalArgumentException(
69 "Multiple content found for " + relativePath
+ " under " + mountPath
);
70 if (nodes
.getLength() == 0)
71 throw new ContentNotFoundException("Path " + relativePath
+ " under " + mountPath
+ " was not found");
72 Element element
= (Element
) nodes
.item(0);
73 return new DomContent(session
, this, element
);
74 } catch (XPathExpressionException e
) {
75 throw new IllegalArgumentException("XPath expression " + xPathExpression
+ " cannot be evaluated", e
);
83 public String
getNamespaceURI(String prefix
) {
84 return document
.lookupNamespaceURI(prefix
);
88 public String
getPrefix(String namespaceURI
) {
89 return document
.lookupPrefix(namespaceURI
);
93 public Iterator
<String
> getPrefixes(String namespaceURI
) {
94 List
<String
> res
= new ArrayList
<>();
95 res
.add(getPrefix(namespaceURI
));
96 return Collections
.unmodifiableList(res
).iterator();