]> git.argeo.org Git - lgpl/argeo-commons.git/blob - DomContentProvider.java
dc200bf3db48c10258612379efffd47f76f18c0a
[lgpl/argeo-commons.git] / DomContentProvider.java
1 package org.argeo.cms.gcr.xml;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.Iterator;
6 import java.util.List;
7
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;
13
14 import org.argeo.api.gcr.Content;
15 import org.argeo.api.gcr.ContentNotFoundException;
16 import org.argeo.api.gcr.spi.ContentProvider;
17 import org.argeo.api.gcr.spi.ProvidedSession;
18 import org.w3c.dom.Document;
19 import org.w3c.dom.Element;
20 import org.w3c.dom.NodeList;
21
22 public class DomContentProvider implements ContentProvider, NamespaceContext {
23 private Document document;
24
25 // XPath
26 // TODO centralise in some executor?
27 private final ThreadLocal<XPath> xPath;
28
29 public DomContentProvider(Document document) {
30 this.document = document;
31 this.document.normalizeDocument();
32 XPathFactory xPathFactory = XPathFactory.newInstance();
33 xPath = new ThreadLocal<>() {
34
35 @Override
36 protected XPath initialValue() {
37 // TODO set the document as namespace context?
38 XPath res= xPathFactory.newXPath();
39 res.setNamespaceContext(DomContentProvider.this);
40 return res;
41 }
42 };
43 }
44
45 // @Override
46 // public Content get() {
47 // return new DomContent(this, document.getDocumentElement());
48 // }
49
50 // public Element createElement(String name) {
51 // return document.createElementNS(null, name);
52 //
53 // }
54
55 @Override
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 /");
61
62 String xPathExpression = '/' + relativePath;
63 if ("/".equals(mountPath))
64 xPathExpression = "/cr:root" + xPathExpression;
65 try {
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);
76 }
77 }
78
79 /*
80 * NAMESPACE CONTEXT
81 */
82 @Override
83 public String getNamespaceURI(String prefix) {
84 return document.lookupNamespaceURI(prefix);
85 }
86
87 @Override
88 public String getPrefix(String namespaceURI) {
89 return document.lookupPrefix(namespaceURI);
90 }
91
92 @Override
93 public Iterator<String> getPrefixes(String namespaceURI) {
94 List<String> res = new ArrayList<>();
95 res.add(getPrefix(namespaceURI));
96 return Collections.unmodifiableList(res).iterator();
97 }
98
99 }