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