]> git.argeo.org Git - lgpl/argeo-commons.git/blob - DomContent.java
0b68a772c623067b8a772b36579b662cea281f57
[lgpl/argeo-commons.git] / DomContent.java
1 package org.argeo.cms.gcr.xml;
2
3 import java.util.HashSet;
4 import java.util.Iterator;
5 import java.util.Optional;
6 import java.util.Set;
7
8 import javax.xml.XMLConstants;
9 import javax.xml.namespace.NamespaceContext;
10 import javax.xml.namespace.QName;
11
12 import org.argeo.api.gcr.Content;
13 import org.argeo.api.gcr.ContentName;
14 import org.argeo.api.gcr.spi.AbstractContent;
15 import org.argeo.api.gcr.spi.ProvidedContent;
16 import org.argeo.api.gcr.spi.ProvidedSession;
17 import org.w3c.dom.Attr;
18 import org.w3c.dom.Document;
19 import org.w3c.dom.Element;
20 import org.w3c.dom.NamedNodeMap;
21 import org.w3c.dom.Node;
22 import org.w3c.dom.NodeList;
23 import org.w3c.dom.Text;
24
25 public class DomContent extends AbstractContent implements ProvidedContent {
26
27 private final ProvidedSession session;
28 private final DomContentProvider provider;
29 private final Element element;
30
31 // private String text = null;
32 private Boolean hasText = null;
33
34 public DomContent(ProvidedSession session, DomContentProvider contentProvider, Element element) {
35 this.session = session;
36 this.provider = contentProvider;
37 this.element = element;
38 }
39
40 public DomContent(DomContent context, Element element) {
41 this(context.getSession(), context.getProvider(), element);
42 }
43
44 @Override
45 public QName getName() {
46 return toQName(this.element);
47 }
48
49 protected QName toQName(Node node) {
50 String prefix = node.getPrefix();
51 if (prefix == null) {
52 String namespaceURI = node.getNamespaceURI();
53 if (namespaceURI == null)
54 namespaceURI = node.getOwnerDocument().lookupNamespaceURI(null);
55 if (namespaceURI == null) {
56 return toQName(node, node.getLocalName());
57 } else {
58 String contextPrefix = session.getPrefix(namespaceURI);
59 if (contextPrefix == null)
60 throw new IllegalStateException("Namespace " + namespaceURI + " is unbound");
61 return toQName(node, namespaceURI, node.getLocalName(), session);
62 }
63 } else {
64 String namespaceURI = node.getNamespaceURI();
65 if (namespaceURI == null)
66 namespaceURI = node.getOwnerDocument().lookupNamespaceURI(prefix);
67 if (namespaceURI == null) {
68 namespaceURI = session.getNamespaceURI(prefix);
69 if (XMLConstants.NULL_NS_URI.equals(namespaceURI))
70 throw new IllegalStateException("Prefix " + prefix + " is unbound");
71 // TODO bind the prefix in the document?
72 }
73 return toQName(node, namespaceURI, node.getLocalName(), session);
74 }
75 }
76
77 protected QName toQName(Node source, String namespaceURI, String localName, NamespaceContext namespaceContext) {
78 return new ContentName(namespaceURI, localName, session);
79 }
80
81 protected QName toQName(Node source, String localName) {
82 return new ContentName(localName);
83 }
84 /*
85 * ATTRIBUTES OPERATIONS
86 */
87
88 @Override
89 public Iterable<QName> keys() {
90 // TODO implement an iterator?
91 Set<QName> result = new HashSet<>();
92 NamedNodeMap attributes = element.getAttributes();
93 for (int i = 0; i < attributes.getLength(); i++) {
94 Attr attr = (Attr) attributes.item(i);
95 QName key = toQName(attr);
96 result.add(key);
97 }
98 return result;
99 }
100
101 @Override
102 public <A> Optional<A> get(QName key, Class<A> clss) {
103 String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null
104 : key.getNamespaceURI();
105 if (element.hasAttributeNS(namespaceUriOrNull, key.getLocalPart())) {
106 String value = element.getAttributeNS(namespaceUriOrNull, key.getLocalPart());
107 if (clss.isAssignableFrom(String.class))
108 return Optional.of((A) value);
109 else
110 return Optional.empty();
111 } else
112 return null;
113 }
114
115 @Override
116 public Object put(QName key, Object value) {
117 Object previous = get(key);
118 String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null
119 : key.getNamespaceURI();
120 element.setAttributeNS(namespaceUriOrNull,
121 namespaceUriOrNull == null ? key.getLocalPart() : key.getPrefix() + ":" + key.getLocalPart(),
122 value.toString());
123 return previous;
124 }
125
126
127
128 @Override
129 public boolean hasText() {
130 // return element instanceof Text;
131 if (hasText != null)
132 return hasText;
133 NodeList nodeList = element.getChildNodes();
134 if (nodeList.getLength() > 1) {
135 hasText = false;
136 return hasText;
137 }
138 nodes: for (int i = 0; i < nodeList.getLength(); i++) {
139 Node node = nodeList.item(i);
140 if (node instanceof Text) {
141 Text text = (Text) node;
142 if (!text.isElementContentWhitespace()) {
143 hasText = true;
144 break nodes;
145 }
146 }
147 }
148 if (hasText == null)
149 hasText = false;
150 return hasText;
151 // if (text != null)
152 // return true;
153 // text = element.getTextContent();
154 // return text != null;
155 }
156
157 @Override
158 public String getText() {
159 if (hasText())
160 return element.getTextContent();
161 else
162 return null;
163 }
164
165 /*
166 * CONTENT OPERATIONS
167 */
168
169 @Override
170 public Iterator<Content> iterator() {
171 NodeList nodeList = element.getChildNodes();
172 return new ElementIterator(session, provider, nodeList);
173 }
174
175 @Override
176 public Content getParent() {
177 Node parent = element.getParentNode();
178 if (parent == null)
179 return null;
180 if (!(parent instanceof Element))
181 throw new IllegalStateException("Parent is not an element");
182 return new DomContent(this, (Element) parent);
183 }
184
185 @Override
186 public Content add(QName name, QName... classes) {
187 // TODO consider classes
188 Document document = this.element.getOwnerDocument();
189 String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(name.getNamespaceURI()) ? null
190 : name.getNamespaceURI();
191 Element child = document.createElementNS(namespaceUriOrNull,
192 namespaceUriOrNull == null ? name.getLocalPart() : name.getPrefix() + ":" + name.getLocalPart());
193 element.appendChild(child);
194 return new DomContent(this, child);
195 }
196
197 @Override
198 public void remove() {
199 // TODO make it more robust
200 element.getParentNode().removeChild(element);
201
202 }
203
204 @Override
205 protected void removeAttr(QName key) {
206 String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null
207 : key.getNamespaceURI();
208 element.removeAttributeNS(namespaceUriOrNull,
209 namespaceUriOrNull == null ? key.getLocalPart() : key.getPrefix() + ":" + key.getLocalPart());
210
211 }
212
213 public ProvidedSession getSession() {
214 return session;
215 }
216
217 public DomContentProvider getProvider() {
218 return provider;
219 }
220
221 }