ingo@113: /* ingo@113: * Copyright (c) 2011 by Intevation GmbH ingo@113: * ingo@113: * This program is free software under the LGPL (>=v2.1) ingo@113: * Read the file LGPL.txt coming with the software for details ingo@113: * or visit http://www.gnu.org/licenses/ if it does not exist. ingo@113: */ ingo@113: package de.intevation.artifacts.common.utils; ingo@113: ingo@114: import javax.xml.xpath.XPathConstants; ingo@114: ingo@113: import org.w3c.dom.Document; ingo@113: import org.w3c.dom.Element; ingo@114: import org.w3c.dom.Node; ingo@114: import org.w3c.dom.NodeList; ingo@113: ingo@113: import de.intevation.artifacts.common.ArtifactNamespaceContext; ingo@113: ingo@113: ingo@113: /** ingo@113: * This class provides methods that help creating the artifact protocol ingo@113: * documents DESCRIBE, FEED, ADVANCE and OUT. ingo@113: * ingo@113: * @author Ingo Weinzierl ingo@113: */ ingo@113: public class ClientProtocolUtils { ingo@113: ingo@114: /** The XPath to the current state in the DESCRIBE document.*/ ingo@114: public static final String XPATH_CURRENT_STATE = "/art:result/art:state"; ingo@114: ingo@114: /** The XPath to the static UI part in the DESCRIBE document.*/ ingo@114: public static final String XPATH_STATIC = "/art:result/art:ui/art:static"; ingo@114: ingo@114: /** The XPath to the dynamic UI part in the DESCRIBE document.*/ ingo@114: public static final String XPATH_DYNAMIC = "/art:result/art:ui/art:dynamic"; ingo@114: ingo@114: /** The XPath to the reachable states part in the DESCRIBE document.*/ ingo@114: public static final String XPATH_STATES = ingo@114: "/art:result/art:reachable-states"; ingo@114: ingo@211: /** The XPath to the output modes in the DESCRIBE document.*/ ingo@211: public static final String XPATH_OUTPUT_MODES = ingo@211: "/art:result/art:outputmodes/art:output"; ingo@211: ingo@211: ingo@114: /** The XPath to the select node relative to the dynamic UI node in the ingo@114: * DESCRIBE document.*/ ingo@114: public static final String XPATH_DATA_SELECT = "art:select"; ingo@114: ingo@114: /** The XPath to the choices nodes relative to the select node in the ingo@114: * DESCRIBE document.*/ ingo@114: public static final String XPATH_DATA_ITEMS = "art:choices/art:item"; ingo@114: ingo@114: /** The XPath to a label in the artifact's DESCRIBE document.*/ ingo@114: public static final String XPATH_LABEL = "art:label/text()"; ingo@114: ingo@114: /** The XPath to a value in the artifact's DESCRIBE document.*/ ingo@114: public static final String XPATH_VALUE = "art:value/text()"; ingo@114: ingo@114: ingo@113: /** ingo@113: * It should not be necessary to create instances of this class. ingo@113: */ ingo@113: private ClientProtocolUtils() { ingo@113: } ingo@113: ingo@113: ingo@113: /** ingo@113: * This method creates a new CREATE document. ingo@113: * ingo@113: * @return the CREATE document. ingo@113: */ ingo@113: public static Document newCreateDocument(String factory) { ingo@113: Document doc = XMLUtils.newDocument(); ingo@113: ingo@113: XMLUtils.ElementCreator cr = new XMLUtils.ElementCreator( ingo@113: doc, ingo@113: ArtifactNamespaceContext.NAMESPACE_URI, ingo@113: ArtifactNamespaceContext.NAMESPACE_PREFIX); ingo@113: ingo@113: Element action = cr.create("action"); ingo@113: Element type = cr.create("type"); ingo@113: Element fac = cr.create("factory"); ingo@113: ingo@113: type.setAttribute("name", "create"); ingo@113: fac.setAttribute("name", factory); ingo@113: ingo@113: action.appendChild(type); ingo@113: action.appendChild(fac); ingo@113: ingo@113: doc.appendChild(action); ingo@113: ingo@113: return doc; ingo@113: } ingo@114: ingo@114: ingo@114: /** ingo@203: * This method creates a new FEED document. ingo@203: * ingo@203: * @param theUuid The identifier of the artifact. ingo@203: * @param theHash The hash of the artifact. ingo@203: * @param theData An array that contains key/value pairs that represent the ingo@203: * data that should be included in the FEED document. ingo@203: * ingo@203: * @return the FEED document. ingo@203: */ ingo@203: public static Document newFeedDocument( ingo@203: String theUuid, ingo@203: String theHash, ingo@203: String[][] theData) ingo@203: { ingo@203: Document doc = XMLUtils.newDocument(); ingo@203: ingo@203: XMLUtils.ElementCreator cr = new XMLUtils.ElementCreator( ingo@203: doc, ingo@203: ArtifactNamespaceContext.NAMESPACE_URI, ingo@203: ArtifactNamespaceContext.NAMESPACE_PREFIX); ingo@203: ingo@203: Element action = cr.create("action"); ingo@203: Element type = cr.create("type"); ingo@203: Element uuid = cr.create("uuid"); ingo@203: Element hash = cr.create("hash"); ingo@203: Element data = cr.create("data"); ingo@203: ingo@203: // XXX It is not nice that the type has no attribute namespace, but to ingo@203: // be backward compatible, we don't change this now. ingo@203: cr.addAttr(type, "name", "feed", false); ingo@203: cr.addAttr(uuid, "value", theUuid, true); ingo@203: cr.addAttr(hash, "value", theHash, true); ingo@203: ingo@203: for (String[] kvp: theData) { ingo@203: Element input = cr.create("input"); ingo@203: cr.addAttr(input, "name", kvp[0], true); ingo@203: cr.addAttr(input, "value", kvp[1], true); ingo@203: ingo@203: data.appendChild(input); ingo@203: } ingo@203: ingo@203: action.appendChild(type); ingo@203: action.appendChild(uuid); ingo@203: action.appendChild(hash); ingo@203: action.appendChild(data); ingo@203: ingo@203: doc.appendChild(action); ingo@203: ingo@203: return doc; ingo@203: } ingo@203: ingo@203: ingo@203: /** ingo@204: * This method creates a new ADVANCE document. ingo@204: * ingo@204: * @param theUuid The identifier of the artifact. ingo@204: * @param theHash The hash of the artifact. ingo@204: * @param theTarget The target state identifier. ingo@204: * ingo@204: * @return the ADVANCE document. ingo@204: */ ingo@204: public static Document newAdvanceDocument( ingo@204: String theUuid, ingo@204: String theHash, ingo@204: String theTarget) ingo@204: { ingo@204: Document doc = XMLUtils.newDocument(); ingo@204: ingo@204: XMLUtils.ElementCreator cr = new XMLUtils.ElementCreator( ingo@204: doc, ingo@204: ArtifactNamespaceContext.NAMESPACE_URI, ingo@204: ArtifactNamespaceContext.NAMESPACE_PREFIX); ingo@204: ingo@204: Element action = cr.create("action"); ingo@204: Element type = cr.create("type"); ingo@204: Element uuid = cr.create("uuid"); ingo@204: Element hash = cr.create("hash"); ingo@204: Element target = cr.create("target"); ingo@204: ingo@204: // XXX It is not nice that the type has no attribute namespace, but to ingo@204: // be backward compatible, we don't change this now. ingo@204: cr.addAttr(type, "name", "advance", false); ingo@204: cr.addAttr(uuid, "value", theUuid, true); ingo@204: cr.addAttr(hash, "value", theHash, true); ingo@204: cr.addAttr(target, "name", theTarget, true); ingo@204: ingo@204: action.appendChild(type); ingo@204: action.appendChild(uuid); ingo@204: action.appendChild(hash); ingo@204: action.appendChild(target); ingo@204: ingo@204: doc.appendChild(action); ingo@204: ingo@204: return doc; ingo@204: } ingo@204: ingo@204: ingo@204: /** ingo@172: * This method creates a new document that is used to create new artifact ingo@172: * collections in the artifact server. ingo@172: * ingo@172: * @param name Optional name of the collection. ingo@172: * ingo@172: * @return the document to create new collections. ingo@172: */ ingo@172: public static Document newCreateCollectionDocument(String name) { ingo@172: Document doc = XMLUtils.newDocument(); ingo@172: ingo@172: XMLUtils.ElementCreator cr = new XMLUtils.ElementCreator( ingo@172: doc, ingo@172: ArtifactNamespaceContext.NAMESPACE_URI, ingo@172: ArtifactNamespaceContext.NAMESPACE_PREFIX); ingo@172: ingo@172: Element action = cr.create("action"); ingo@172: Element type = cr.create("type"); ingo@172: Element collection = cr.create("artifact-collection"); ingo@172: ingo@172: cr.addAttr(type, "name", "create"); ingo@172: cr.addAttr(collection, "name", name != null ? name : ""); ingo@172: ingo@172: action.appendChild(type); ingo@172: action.appendChild(collection); ingo@172: ingo@172: doc.appendChild(action); ingo@172: ingo@172: return doc; ingo@172: } ingo@172: ingo@172: ingo@172: /** ingo@114: * Returns string value found by {@link XPATH_LABEL} relative to ingo@114: * node. ingo@114: * ingo@114: * @param node A node. ingo@114: * ingo@114: * @return the string value found by {@link XPATH_LABEL}. ingo@114: */ ingo@114: public static String getLabel(Node node) { ingo@114: return (String) XMLUtils.xpath( ingo@114: node, ingo@114: XPATH_LABEL, ingo@114: XPathConstants.STRING, ingo@114: ArtifactNamespaceContext.INSTANCE); ingo@114: } ingo@114: ingo@114: ingo@114: /** ingo@114: * Returns string value found by {@link XPATH_VALUE} relative to ingo@114: * node. ingo@114: * ingo@114: * @param node A node. ingo@114: * ingo@114: * @return the string value found by {@link XPATH_VALUE}. ingo@114: */ ingo@114: public static String getValue(Node node) { ingo@114: return (String) XMLUtils.xpath( ingo@114: node, ingo@114: XPATH_VALUE, ingo@114: XPathConstants.STRING, ingo@114: ArtifactNamespaceContext.INSTANCE); ingo@114: } ingo@114: ingo@114: ingo@114: /** ingo@114: * This method returns the static UI part of the artifact's DESCRIBE ingo@114: * document. ingo@114: * ingo@114: * @param description The document returned by the artifact server's ingo@114: * DESCRIBE operation. ingo@114: * ingo@114: * @return the static UI node. ingo@114: */ ingo@114: public static Node getStaticUI(Document description) { ingo@114: return (Node) XMLUtils.xpath( ingo@114: description, ingo@114: XPATH_STATIC, ingo@114: XPathConstants.NODE, ingo@114: ArtifactNamespaceContext.INSTANCE); ingo@114: } ingo@114: ingo@114: ingo@114: /** ingo@114: * This method returns the dynamic UI part of the artifact's DESCRIBE ingo@114: * document. ingo@114: * ingo@114: * @param description The document returned by the artifact server's ingo@114: * DESCRIBE operation. ingo@114: * ingo@114: * @return the dynamic UI node. ingo@114: */ ingo@114: public static Node getDynamicUI(Document description) { ingo@114: return (Node) XMLUtils.xpath( ingo@114: description, ingo@114: XPATH_DYNAMIC, ingo@114: XPathConstants.NODE, ingo@114: ArtifactNamespaceContext.INSTANCE); ingo@114: } ingo@114: ingo@114: ingo@114: /** ingo@114: * This method returns the current state node contained in the DESCRIBE ingo@114: * document. ingo@114: * ingo@114: * @param description The document returned by the artifact server's ingo@114: * DESCRIBE operation. ingo@114: * ingo@114: * @return the node containing information about the current state. ingo@114: */ ingo@114: public static Node getCurrentState(Document description) { ingo@114: return (Node) XMLUtils.xpath( ingo@114: description, ingo@114: XPATH_CURRENT_STATE, ingo@114: XPathConstants.NODE, ingo@114: ArtifactNamespaceContext.INSTANCE); ingo@114: } ingo@114: ingo@114: ingo@114: /** ingo@114: * This method returns the node that contains information about the ingo@114: * reachable states of the artifact in the artifact's DESCRIBE document. ingo@114: * ingo@114: * @param description The document returned by the artifact server's ingo@114: * DESCRIBE operation. ingo@114: * ingo@114: * @return the node that contains the reachable states. ingo@114: */ ingo@114: public static Node getReachableStates(Document description) { ingo@114: return (Node) XMLUtils.xpath( ingo@114: description, ingo@114: XPATH_STATES, ingo@114: XPathConstants.NODE, ingo@114: ArtifactNamespaceContext.INSTANCE); ingo@114: } ingo@114: ingo@114: ingo@114: /** ingo@211: * This method returns the output mode nodes of the DESCRIBE document. ingo@211: * ingo@211: * @param description The document returned by the artifact server's ingo@211: * DESCRIBE operation. ingo@211: * ingo@211: * @return the node that contains the output modes. ingo@211: */ ingo@211: public static NodeList getOutputModes(Document description) { ingo@211: return (NodeList) XMLUtils.xpath( ingo@211: description, ingo@211: XPATH_OUTPUT_MODES, ingo@211: XPathConstants.NODESET, ingo@211: ArtifactNamespaceContext.INSTANCE); ingo@211: } ingo@211: ingo@211: ingo@211: /** ingo@114: * Returns the node found by {@link XPATH_DATA_SELECT}. ingo@114: * ingo@114: * @param dynamicNode The dynamic UI node of the DESCRIBE document. ingo@114: * ingo@114: * @return the select node found in the dynamic UI node. ingo@114: */ ingo@208: public static NodeList getSelectNode(Node dynamicNode) { ingo@208: return (NodeList) XMLUtils.xpath( ingo@114: dynamicNode, ingo@114: XPATH_DATA_SELECT, ingo@208: XPathConstants.NODESET, ingo@114: ArtifactNamespaceContext.INSTANCE); ingo@114: } ingo@114: ingo@114: ingo@114: /** ingo@114: * Returns the items that could be found in the node. ingo@114: * ingo@114: * @param node A select node. ingo@114: * ingo@114: * @return the choices nodes as node list. ingo@114: */ ingo@114: public static NodeList getItemNodes(Node node) { ingo@114: return (NodeList) XMLUtils.xpath( ingo@114: node, ingo@114: XPATH_DATA_ITEMS, ingo@114: XPathConstants.NODESET, ingo@114: ArtifactNamespaceContext.INSTANCE); ingo@114: } ingo@113: } ingo@113: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :