]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/acr/xml/DomContentProvider.java
Introduce CMS JShell
[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.io.IOException;
4 import java.io.OutputStream;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.Iterator;
8 import java.util.List;
9
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;
16
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;
28
29 public class DomContentProvider implements ContentProvider, NamespaceContext {
30 private final Document document;
31
32 // XPath
33 // TODO centralise in some executor?
34 private final ThreadLocal<XPath> xPath;
35
36 private TransformerFactory transformerFactory;
37
38 private String mountPath;
39
40 public DomContentProvider(String mountPath, Document document) {
41 this.mountPath = mountPath;
42 this.document = document;
43 this.document.normalizeDocument();
44
45 transformerFactory = TransformerFactory.newInstance();
46
47 XPathFactory xPathFactory = XPathFactory.newInstance();
48 xPath = new ThreadLocal<>() {
49
50 @Override
51 protected XPath initialValue() {
52 // TODO set the document as namespace context?
53 XPath res = xPathFactory.newXPath();
54 res.setNamespaceContext(DomContentProvider.this);
55 return res;
56 }
57 };
58 }
59
60 // @Override
61 // public Content get() {
62 // return new DomContent(this, document.getDocumentElement());
63 // }
64
65 // public Element createElement(String name) {
66 // return document.createElementNS(null, name);
67 //
68 // }
69
70 @Override
71 public ProvidedContent get(ProvidedSession session, String relativePath) {
72 if ("".equals(relativePath))
73 return new DomContent(session, this, document.getDocumentElement());
74
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);
83 }
84
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;
91 try {
92 NodeList nodes = (NodeList) xPath.get().evaluate(xPathExpression, document, XPathConstants.NODESET);
93 return nodes;
94 } catch (XPathExpressionException e) {
95 throw new IllegalArgumentException("XPath expression " + xPathExpression + " cannot be evaluated", e);
96 }
97
98 }
99
100 @Override
101 public boolean exists(ProvidedSession session, String relativePath) {
102 if ("".equals(relativePath))
103 return true;
104 NodeList nodes = findContent(relativePath);
105 return nodes.getLength() != 0;
106 }
107
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);
116 }
117 }
118 }
119
120 @Override
121 public String getMountPath() {
122 return mountPath;
123 }
124
125 public void registerPrefix(String prefix, String namespace) {
126 DomUtils.addNamespace(document.getDocumentElement(), prefix, namespace);
127 }
128
129 /*
130 * NAMESPACE CONTEXT
131 */
132 @Override
133 public String getNamespaceURI(String prefix) {
134 String namespaceURI = NamespaceUtils.getStandardNamespaceURI(prefix);
135 if (namespaceURI != null)
136 return namespaceURI;
137 return document.lookupNamespaceURI(prefix);
138 }
139
140 @Override
141 public String getPrefix(String namespaceURI) {
142 String prefix = NamespaceUtils.getStandardPrefix(namespaceURI);
143 if (prefix != null)
144 return prefix;
145 return document.lookupPrefix(namespaceURI);
146 }
147
148 @Override
149 public Iterator<String> getPrefixes(String namespaceURI) {
150 List<String> res = new ArrayList<>();
151 res.add(getPrefix(namespaceURI));
152 return Collections.unmodifiableList(res).iterator();
153 }
154
155 TransformerFactory getTransformerFactory() {
156 return transformerFactory;
157 }
158
159 }