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
.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
;
23 public class DomContentProvider
implements ContentProvider
, NamespaceContext
{
24 private Document document
;
27 // TODO centralise in some executor?
28 private final ThreadLocal
<XPath
> xPath
;
30 public DomContentProvider(Document document
) {
31 this.document
= document
;
32 this.document
.normalizeDocument();
33 XPathFactory xPathFactory
= XPathFactory
.newInstance();
34 xPath
= new ThreadLocal
<>() {
37 protected XPath
initialValue() {
38 // TODO set the document as namespace context?
39 XPath res
= xPathFactory
.newXPath();
40 res
.setNamespaceContext(DomContentProvider
.this);
47 // public Content get() {
48 // return new DomContent(this, document.getDocumentElement());
51 // public Element createElement(String name) {
52 // return document.createElementNS(null, name);
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 /");
63 String xPathExpression
= '/' + relativePath
;
64 if ("/".equals(mountPath
))
65 xPathExpression
= "/cr:root" + xPathExpression
;
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
);
84 public String
getNamespaceURI(String prefix
) {
85 String namespaceURI
= NamespaceUtils
.getStandardNamespaceURI(prefix
);
86 if (namespaceURI
!= null)
88 return document
.lookupNamespaceURI(prefix
);
92 public String
getPrefix(String namespaceURI
) {
93 String prefix
= NamespaceUtils
.getStandardPrefix(namespaceURI
);
96 return document
.lookupPrefix(namespaceURI
);
100 public Iterator
<String
> getPrefixes(String namespaceURI
) {
101 List
<String
> res
= new ArrayList
<>();
102 res
.add(getPrefix(namespaceURI
));
103 return Collections
.unmodifiableList(res
).iterator();