1 package org
.argeo
.cms
.acr
.xml
;
3 import java
.io
.IOException
;
4 import java
.io
.OutputStream
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Collections
;
7 import java
.util
.Iterator
;
10 import javax
.xml
.namespace
.NamespaceContext
;
11 import javax
.xml
.transform
.TransformerFactory
;
12 import javax
.xml
.xpath
.XPath
;
13 import javax
.xml
.xpath
.XPathConstants
;
14 import javax
.xml
.xpath
.XPathExpressionException
;
15 import javax
.xml
.xpath
.XPathFactory
;
17 import org
.argeo
.api
.acr
.Content
;
18 import org
.argeo
.api
.acr
.ContentNotFoundException
;
19 import org
.argeo
.api
.acr
.CrName
;
20 import org
.argeo
.api
.acr
.NamespaceUtils
;
21 import org
.argeo
.api
.acr
.spi
.ContentProvider
;
22 import org
.argeo
.api
.acr
.spi
.ProvidedContent
;
23 import org
.argeo
.api
.acr
.spi
.ProvidedSession
;
24 import org
.argeo
.cms
.acr
.CmsContentRepository
;
25 import org
.w3c
.dom
.Document
;
26 import org
.w3c
.dom
.Element
;
27 import org
.w3c
.dom
.NodeList
;
29 public class DomContentProvider
implements ContentProvider
, NamespaceContext
{
30 private final Document document
;
33 // TODO centralise in some executor?
34 private final ThreadLocal
<XPath
> xPath
;
36 private TransformerFactory transformerFactory
;
38 private String mountPath
;
40 public DomContentProvider(String mountPath
, Document document
) {
41 this.mountPath
= mountPath
;
42 this.document
= document
;
43 this.document
.normalizeDocument();
45 transformerFactory
= TransformerFactory
.newInstance();
47 XPathFactory xPathFactory
= XPathFactory
.newInstance();
48 xPath
= new ThreadLocal
<>() {
51 protected XPath
initialValue() {
52 // TODO set the document as namespace context?
53 XPath res
= xPathFactory
.newXPath();
54 res
.setNamespaceContext(DomContentProvider
.this);
61 // public Content get() {
62 // return new DomContent(this, document.getDocumentElement());
65 // public Element createElement(String name) {
66 // return document.createElementNS(null, name);
71 public ProvidedContent
get(ProvidedSession session
, String relativePath
) {
72 if ("".equals(relativePath
))
73 return new DomContent(session
, this, document
.getDocumentElement());
75 NodeList nodes
= findContent(relativePath
);
76 if (nodes
.getLength() > 1)
77 throw new IllegalArgumentException("Multiple content found for " + relativePath
+ " under " + mountPath
);
78 if (nodes
.getLength() == 0)
79 throw new ContentNotFoundException(session
, mountPath
+ "/" + relativePath
,
80 "Path " + relativePath
+ " under " + mountPath
+ " was not found");
81 Element element
= (Element
) nodes
.item(0);
82 return new DomContent(session
, this, element
);
85 protected NodeList
findContent(String relativePath
) {
86 if (relativePath
.startsWith("/"))
87 throw new IllegalArgumentException("Relative path cannot start with /");
88 String xPathExpression
= '/' + relativePath
;
89 if ("/".equals(mountPath
))
90 xPathExpression
= "/" + CrName
.root
.qName() + xPathExpression
;
92 NodeList nodes
= (NodeList
) xPath
.get().evaluate(xPathExpression
, document
, XPathConstants
.NODESET
);
94 } catch (XPathExpressionException e
) {
95 throw new IllegalArgumentException("XPath expression " + xPathExpression
+ " cannot be evaluated", e
);
101 public boolean exists(ProvidedSession session
, String relativePath
) {
102 if ("".equals(relativePath
))
104 NodeList nodes
= findContent(relativePath
);
105 return nodes
.getLength() != 0;
108 public void persist(ProvidedSession session
) {
109 if (mountPath
!= null) {
110 Content mountPoint
= session
.getMountPoint(mountPath
);
111 try (OutputStream out
= mountPoint
.open(OutputStream
.class)) {
112 CmsContentRepository contentRepository
= (CmsContentRepository
) session
.getRepository();
113 contentRepository
.writeDom(document
, out
);
114 } catch (IOException e
) {
115 throw new IllegalStateException("Cannot persist " + mountPath
, e
);
121 public String
getMountPath() {
125 public void registerPrefix(String prefix
, String namespace
) {
126 DomUtils
.addNamespace(document
.getDocumentElement(), prefix
, namespace
);
133 public String
getNamespaceURI(String prefix
) {
134 String namespaceURI
= NamespaceUtils
.getStandardNamespaceURI(prefix
);
135 if (namespaceURI
!= null)
137 return document
.lookupNamespaceURI(prefix
);
141 public String
getPrefix(String namespaceURI
) {
142 String prefix
= NamespaceUtils
.getStandardPrefix(namespaceURI
);
145 return document
.lookupPrefix(namespaceURI
);
149 public Iterator
<String
> getPrefixes(String namespaceURI
) {
150 List
<String
> res
= new ArrayList
<>();
151 res
.add(getPrefix(namespaceURI
));
152 return Collections
.unmodifiableList(res
).iterator();
155 TransformerFactory
getTransformerFactory() {
156 return transformerFactory
;