]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/acr/xml/DomContent.java
Use local XSD imports.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / acr / xml / DomContent.java
1 package org.argeo.cms.acr.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.acr.Content;
13 import org.argeo.api.acr.ContentName;
14 import org.argeo.api.acr.spi.AbstractContent;
15 import org.argeo.api.acr.spi.ProvidedContent;
16 import org.argeo.api.acr.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 = provider.getPrefix(namespaceURI);
59 if (contextPrefix == null)
60 throw new IllegalStateException("Namespace " + namespaceURI + " is unbound");
61 return toQName(node, namespaceURI, node.getLocalName(), provider);
62 }
63 } else {
64 String namespaceURI = node.getNamespaceURI();
65 if (namespaceURI == null)
66 namespaceURI = node.getOwnerDocument().lookupNamespaceURI(prefix);
67 if (namespaceURI == null) {
68 namespaceURI = provider.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(), provider);
74 }
75 }
76
77 protected QName toQName(Node source, String namespaceURI, String localName, NamespaceContext namespaceContext) {
78 return new ContentName(namespaceURI, localName, namespaceContext);
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 @SuppressWarnings("unchecked")
102 @Override
103 public <A> Optional<A> get(QName key, Class<A> clss) {
104 String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null
105 : key.getNamespaceURI();
106 if (element.hasAttributeNS(namespaceUriOrNull, key.getLocalPart())) {
107 String value = element.getAttributeNS(namespaceUriOrNull, key.getLocalPart());
108 if (clss.isAssignableFrom(String.class))
109 return Optional.of((A) value);
110 else
111 return Optional.empty();
112 } else
113 return null;
114 }
115
116 @Override
117 public Object put(QName key, Object value) {
118 Object previous = get(key);
119 String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null
120 : key.getNamespaceURI();
121 element.setAttributeNS(namespaceUriOrNull,
122 namespaceUriOrNull == null ? key.getLocalPart() : key.getPrefix() + ":" + key.getLocalPart(),
123 value.toString());
124 return previous;
125 }
126
127 @Override
128 public boolean hasText() {
129 // return element instanceof Text;
130 if (hasText != null)
131 return hasText;
132 NodeList nodeList = element.getChildNodes();
133 if (nodeList.getLength() > 1) {
134 hasText = false;
135 return hasText;
136 }
137 nodes: for (int i = 0; i < nodeList.getLength(); i++) {
138 Node node = nodeList.item(i);
139 if (node instanceof Text) {
140 Text text = (Text) node;
141 if (!text.isElementContentWhitespace()) {
142 hasText = true;
143 break nodes;
144 }
145 }
146 }
147 if (hasText == null)
148 hasText = false;
149 return hasText;
150 // if (text != null)
151 // return true;
152 // text = element.getTextContent();
153 // return text != null;
154 }
155
156 @Override
157 public String getText() {
158 if (hasText())
159 return element.getTextContent();
160 else
161 return null;
162 }
163
164 /*
165 * CONTENT OPERATIONS
166 */
167
168 @Override
169 public Iterator<Content> iterator() {
170 NodeList nodeList = element.getChildNodes();
171 return new ElementIterator(this, session, provider, nodeList);
172 }
173
174 @Override
175 public Content getParent() {
176 Node parent = element.getParentNode();
177 if (parent == null)
178 return null;
179 if (parent instanceof Document)
180 return null;
181 if (!(parent instanceof Element))
182 throw new IllegalStateException("Parent is not an element");
183 return new DomContent(this, (Element) parent);
184 }
185
186 @Override
187 public Content add(QName name, QName... classes) {
188 // TODO consider classes
189 Document document = this.element.getOwnerDocument();
190 String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(name.getNamespaceURI()) ? null
191 : name.getNamespaceURI();
192 Element child = document.createElementNS(namespaceUriOrNull,
193 namespaceUriOrNull == null ? name.getLocalPart() : name.getPrefix() + ":" + name.getLocalPart());
194 element.appendChild(child);
195 return new DomContent(this, child);
196 }
197
198 @Override
199 public void remove() {
200 // TODO make it more robust
201 element.getParentNode().removeChild(element);
202
203 }
204
205 @Override
206 protected void removeAttr(QName key) {
207 String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null
208 : key.getNamespaceURI();
209 element.removeAttributeNS(namespaceUriOrNull,
210 namespaceUriOrNull == null ? key.getLocalPart() : key.getPrefix() + ":" + key.getLocalPart());
211
212 }
213
214 public ProvidedSession getSession() {
215 return session;
216 }
217
218 public DomContentProvider getProvider() {
219 return provider;
220 }
221
222 }