X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Fgcr%2Fxml%2FDomContent.java;h=57e6ba7cecea5974af10b9776a98caa58d6a7458;hb=e5a22cdc7d0f4918f2740c626e1ab6384bd5ee44;hp=b42e0cf0dd8c6f76f33c424c47b0ea996082e9a9;hpb=8767858f1fca02ea7c53ca244f6c1fa745d91ac4;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/gcr/xml/DomContent.java b/org.argeo.cms/src/org/argeo/cms/gcr/xml/DomContent.java index b42e0cf0d..57e6ba7ce 100644 --- a/org.argeo.cms/src/org/argeo/cms/gcr/xml/DomContent.java +++ b/org.argeo.cms/src/org/argeo/cms/gcr/xml/DomContent.java @@ -4,57 +4,105 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; + import org.argeo.api.gcr.Content; -import org.argeo.api.gcr.ContentSystemProvider; +import org.argeo.api.gcr.ContentName; import org.argeo.api.gcr.spi.AbstractContent; +import org.argeo.api.gcr.spi.ProvidedContent; +import org.argeo.api.gcr.spi.ProvidedSession; import org.w3c.dom.Attr; +import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; -public class DomContent extends AbstractContent implements Content { +public class DomContent extends AbstractContent implements ProvidedContent { - private final DomContentSession contentSession; + private final ProvidedSession session; + private final DomContentProvider provider; private final Element element; // private String text = null; private Boolean hasText = null; - public DomContent(DomContentSession contentSession, Element element) { - this.contentSession = contentSession; + public DomContent(ProvidedSession session, DomContentProvider contentProvider, Element element) { + this.session = session; + this.provider = contentProvider; this.element = element; } - @Override - public Iterator iterator() { - NodeList nodeList = element.getChildNodes(); - return new ElementIterator(contentSession, nodeList); + public DomContent(DomContent context, Element element) { + this(context.getSession(), context.getProvider(), element); } @Override - public String getName() { - return element.getNodeName(); + public QName getName() { + return toQName(this.element); + } + + protected QName toQName(Node node) { + String prefix = node.getPrefix(); + if (prefix == null) { + String namespaceURI = node.getNamespaceURI(); + if (namespaceURI == null) + namespaceURI = node.getOwnerDocument().lookupNamespaceURI(null); + if (namespaceURI == null) { + return toQName(node, node.getLocalName()); + } else { + String contextPrefix = session.getPrefix(namespaceURI); + if (contextPrefix == null) + throw new IllegalStateException("Namespace " + namespaceURI + " is unbound"); + return toQName(node, namespaceURI, node.getLocalName(), session); + } + } else { + String namespaceURI = node.getNamespaceURI(); + if (namespaceURI == null) + namespaceURI = node.getOwnerDocument().lookupNamespaceURI(prefix); + if (namespaceURI == null) { + namespaceURI = session.getNamespaceURI(prefix); + if (XMLConstants.NULL_NS_URI.equals(namespaceURI)) + throw new IllegalStateException("Prefix " + prefix + " is unbound"); + // TODO bind the prefix in the document? + } + return toQName(node, namespaceURI, node.getLocalName(), session); + } + } + + protected QName toQName(Node source, String namespaceURI, String localName, NamespaceContext namespaceContext) { + return new ContentName(namespaceURI, localName, session); + } + + protected QName toQName(Node source, String localName) { + return new ContentName(localName); } + /* + * ATTRIBUTES OPERATIONS + */ @Override - public Iterable keys() { + public Iterable keys() { // TODO implement an iterator? - Set result = new HashSet<>(); + Set result = new HashSet<>(); NamedNodeMap attributes = element.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Attr attr = (Attr) attributes.item(i); - String attrName = attr.getNodeName(); - result.add(attrName); + QName key = toQName(attr); + result.add(key); } return result; } @Override - public A get(String key, Class clss) { - if (element.hasAttribute(key)) { - String value = element.getAttribute(key); + public A get(QName key, Class clss) { + String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null + : key.getNamespaceURI(); + if (element.hasAttributeNS(namespaceUriOrNull, key.getLocalPart())) { + String value = element.getAttributeNS(namespaceUriOrNull, key.getLocalPart()); if (clss.isAssignableFrom(String.class)) return (A) value; else @@ -63,6 +111,16 @@ public class DomContent extends AbstractContent implements Content { return null; } + @Override + public Object put(QName key, Object value) { + Object previous = get(key); + String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null + : key.getNamespaceURI(); + element.setAttributeNS(namespaceUriOrNull, + namespaceUriOrNull == null ? key.getLocalPart() : key.getPrefix() + ":" + key.getLocalPart(), + value.toString()); + return previous; + } @Override public boolean hasText() { @@ -77,7 +135,7 @@ public class DomContent extends AbstractContent implements Content { nodes: for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node instanceof Text) { - Text text =(Text) node; + Text text = (Text) node; if (!text.isElementContentWhitespace()) { hasText = true; break nodes; @@ -101,4 +159,60 @@ public class DomContent extends AbstractContent implements Content { return null; } + /* + * CONTENT OPERATIONS + */ + + @Override + public Iterator iterator() { + NodeList nodeList = element.getChildNodes(); + return new ElementIterator(session, provider, nodeList); + } + + @Override + public Content getParent() { + Node parent = element.getParentNode(); + if (parent == null) + return null; + if (!(parent instanceof Element)) + throw new IllegalStateException("Parent is not an element"); + return new DomContent(this, (Element) parent); + } + + @Override + public Content add(QName name, QName... classes) { + // TODO consider classes + Document document = this.element.getOwnerDocument(); + String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(name.getNamespaceURI()) ? null + : name.getNamespaceURI(); + Element child = document.createElementNS(namespaceUriOrNull, + namespaceUriOrNull == null ? name.getLocalPart() : name.getPrefix() + ":" + name.getLocalPart()); + element.appendChild(child); + return new DomContent(this, child); + } + + @Override + public void remove() { + // TODO make it more robust + element.getParentNode().removeChild(element); + + } + + @Override + protected void removeAttr(QName key) { + String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null + : key.getNamespaceURI(); + element.removeAttributeNS(namespaceUriOrNull, + namespaceUriOrNull == null ? key.getLocalPart() : key.getPrefix() + ":" + key.getLocalPart()); + + } + + public ProvidedSession getSession() { + return session; + } + + public DomContentProvider getProvider() { + return provider; + } + }