ingo@1115: /* ingo@1115: * Copyright (c) 2010 by Intevation GmbH ingo@1115: * ingo@1115: * This program is free software under the LGPL (>=v2.1) ingo@1115: * Read the file LGPL.txt coming with the software for details ingo@1115: * or visit http://www.gnu.org/licenses/ if it does not exist. ingo@1115: */ ingo@1115: ingo@475: package de.intevation.gnv.artifacts.fis; ingo@475: tim@594: import java.io.IOException; tim@594: import java.io.OutputStream; tim@594: import java.util.Collection; tim@598: import java.util.HashMap; tim@594: import java.util.Iterator; tim@594: import java.util.Map; tim@594: tim@598: import javax.xml.xpath.XPathConstants; tim@598: tim@594: import org.apache.log4j.Logger; tim@594: import org.w3c.dom.Document; tim@594: import org.w3c.dom.Element; tim@594: import org.w3c.dom.Node; tim@598: import org.w3c.dom.NodeList; tim@594: tim@1028: import de.intevation.artifactdatabase.ProxyArtifact; sascha@1117: import de.intevation.artifacts.common.utils.XMLUtils; tim@1028: import de.intevation.artifacts.Artifact; tim@1028: import de.intevation.artifacts.ArtifactFactory; tim@1028: import de.intevation.artifacts.ArtifactNamespaceContext; tim@1028: import de.intevation.artifacts.CallContext; tim@1028: import de.intevation.artifacts.CallMeta; ingo@1118: import de.intevation.artifacts.GlobalContext; tim@1028: import de.intevation.gnv.artifacts.GNVArtifactBase; tim@1028: import de.intevation.gnv.artifacts.GNVDefaultArtifact; tim@1028: import de.intevation.gnv.artifacts.GNVProductArtifactFactory; tim@1028: import de.intevation.gnv.artifacts.PreSettingArtifact; tim@1028: import de.intevation.gnv.artifacts.fis.product.Product; tim@1028: import de.intevation.gnv.artifacts.ressource.RessourceFactory; tim@1028: import de.intevation.gnv.state.DefaultInputData; tim@1028: import de.intevation.gnv.state.InputData; tim@1028: ingo@475: /** ingo@792: * This artifact is used to handle to input/output at the beginning of a ingo@792: * parameterization when no product has been selected so far. After the user ingo@792: * having selected a product, this artifact is replaced by a concrete product ingo@792: * artifact. sascha@803: * sascha@780: * @author Ingo Weinzierl ingo@475: */ ingo@488: public class SelectProductArtifact extends GNVDefaultArtifact { ingo@475: tim@598: /** tim@598: * THE UID of this Class. tim@598: */ tim@598: private static final long serialVersionUID = -7952357683127758677L; tim@598: ingo@792: /** ingo@792: * Path to uuid. ingo@792: */ ingo@475: public static final String XPATH_UUID = "art:action/art:uuid/@value"; ingo@475: ingo@792: /** ingo@792: * Path to hash. ingo@792: */ ingo@475: public static final String XPATH_HASH = "art:action/art:hash/@value"; ingo@475: ingo@792: /** ingo@792: * Path to selected product. ingo@792: */ ingo@475: public static final String XPATH_INPUT_DATA_VALUE = ingo@475: "art:action/art:data/art:input[@name='product']/@value"; sascha@778: ingo@792: /** ingo@792: * Path to parameters required by the factory. ingo@792: */ sascha@778: public static final String XPATH_SETUP_PARAMETER_NODES = tim@598: "/art:action/art:factory/art:parameter"; ingo@475: ingo@475: public static final String XFORM_URL = "http://www.w3.org/2002/xforms"; ingo@792: ingo@792: /** ingo@792: * Prefix used in the user interface description part of the describe ingo@792: * document. ingo@792: */ ingo@475: public static final String XFORM_PREFIX = "xform"; ingo@475: ingo@475: private static Logger log = Logger.getLogger(SelectProductArtifact.class); ingo@475: ingo@478: private Map products; ingo@475: private Product current; ingo@475: private Artifact artifact; ingo@475: private String name; sascha@778: tim@598: private Map preSettings = null; ingo@475: ingo@792: /** ingo@792: * Constructor. ingo@792: */ ingo@475: public SelectProductArtifact() { ingo@475: super(); ingo@475: } ingo@475: ingo@475: ingo@792: /** ingo@792: * Initialize this artifact and parse all required information from ingo@792: * data document. ingo@792: * ingo@792: * @param identifier ingo@792: * @param factory ingo@792: * @param context ingo@792: * @param data ingo@792: */ ingo@475: @Override ingo@475: public void setup( ingo@475: String identifier, ingo@475: ArtifactFactory factory, tim@594: Object context, ingo@1118: CallMeta meta, ingo@1118: Document data ingo@1118: ) { tim@594: log.debug("SelectProductArtifact.setup()"); ingo@1118: super.setup(identifier, factory, context, meta, data); ingo@475: this.name = factory.getName(); sascha@778: tim@598: // Read the Parameters that should be used for the setup from the tim@598: // Data-XML.Document. sascha@778: NodeList parameterNodes = (NodeList) XMLUtils.xpath(data, tim@598: XPATH_SETUP_PARAMETER_NODES, tim@598: XPathConstants.NODESET, tim@598: ArtifactNamespaceContext.INSTANCE); tim@598: if (parameterNodes != null && parameterNodes.getLength() > 0){ tim@598: this.preSettings = new HashMap(); tim@598: for (int i = 0; i < parameterNodes.getLength(); i++){ tim@598: Element parameterNode = (Element)parameterNodes.item(i); tim@598: String name = parameterNode.getAttribute("name"); tim@598: String value = parameterNode.getAttribute("value"); tim@598: log.debug("Name: "+name); tim@598: log.debug("Value: "+value); tim@598: InputData inputData = this.preSettings.get(name); tim@598: if (inputData == null){ tim@598: inputData = new DefaultInputData(name, value); tim@598: this.preSettings.put(name, inputData); tim@598: }else{ tim@598: inputData.concartValue(value); tim@598: } tim@598: } tim@598: } sascha@778: ingo@478: } ingo@475: ingo@475: ingo@792: /** ingo@792: * ingo@815: * @param products Insert a bunch of products. ingo@792: */ ingo@478: public void setProducts(Map products) { ingo@478: this.products = products; ingo@475: } ingo@475: ingo@475: ingo@792: /** ingo@792: * Search for a selected product and create a new concrecte product artifact ingo@792: * with this information. ingo@792: * ingo@792: * @param target Document which contains the selected product. ingo@792: * @param context CallContext. ingo@792: * @return Error or success message. ingo@792: */ ingo@475: @Override ingo@475: public Document feed(Document target, CallContext context) { ingo@475: log.debug("SelectProductArtifact.feed()"); ingo@475: ingo@475: if (artifact == null) { ingo@475: Document document = XMLUtils.newDocument(); ingo@475: String productName = XMLUtils.xpathString( ingo@475: target, ingo@475: XPATH_INPUT_DATA_VALUE, ingo@475: ArtifactNamespaceContext.INSTANCE ingo@475: ); ingo@475: ingo@475: current = (Product) products.get(productName); ingo@475: ingo@475: String reportNode = null; ingo@475: String resultNode = null; ingo@475: String msg = null; ingo@475: ingo@475: if (current != null) { ingo@475: reportNode = "result"; ingo@475: resultNode = "success"; ingo@475: msg = "Feed was successfully. New Artifact created."; ingo@475: } ingo@475: else { ingo@475: reportNode = "exceptionreport"; ingo@475: resultNode = "exception"; ingo@475: msg = "Product does not exist."; ingo@475: } ingo@475: ingo@475: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@475: document, ingo@475: ArtifactNamespaceContext.NAMESPACE_URI, ingo@475: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@475: ); ingo@475: ingo@475: Element report = creator.create(reportNode); ingo@475: Element success = creator.create(resultNode); ingo@475: success.setTextContent(msg); ingo@475: report.appendChild(success); ingo@475: document.appendChild(report); ingo@475: ingo@475: return document; ingo@475: } ingo@475: else { ingo@475: return artifact.feed(target, context); ingo@475: } ingo@475: } ingo@475: ingo@475: ingo@792: /** ingo@792: * If {@link #feed(org.w3c.dom.Document, de.intevation.artifacts.CallContext)} ingo@792: * was sucessfully called before, this artifact is replaced with a concrete ingo@792: * product artifact. sascha@803: * ingo@815: * @param target The advance document. ingo@815: * @param context The CallContext. ingo@815: * @return a document with an error or success message. ingo@792: */ ingo@475: @Override ingo@475: public Document advance(Document target, CallContext context) { ingo@475: log.debug("SelectProductArtifact.advance()"); ingo@475: ingo@475: if (artifact != null) { ingo@475: Document result = artifact.advance(target, context); ingo@475: context.putContextValue(ProxyArtifact.REPLACE_PROXY, artifact); ingo@475: return result; ingo@475: } ingo@475: ingo@475: Document result = XMLUtils.newDocument(); ingo@475: if (current == null) { ingo@475: // artifact needs to be feeded first ingo@475: String msg = "Artifact is not configured properly. Call 'feed' fist."; ingo@475: log.error(msg); ingo@475: ingo@475: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@475: result, ingo@475: ArtifactNamespaceContext.NAMESPACE_URI, ingo@475: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@475: ); ingo@475: ingo@475: Element report = creator.create("exceptionreport"); ingo@475: Element exception = creator.create("exception"); ingo@475: exception.setTextContent(msg); ingo@475: report.appendChild(exception); ingo@475: result.appendChild(report); ingo@475: ingo@475: return result; ingo@475: } ingo@475: ingo@475: String uuid = XMLUtils.xpathString( ingo@475: target, XPATH_UUID, ArtifactNamespaceContext.INSTANCE ingo@475: ); ingo@475: ingo@475: String hash = XMLUtils.xpathString( ingo@475: target, XPATH_HASH, ArtifactNamespaceContext.INSTANCE ingo@475: ); ingo@475: ingo@478: // fetch ArtifactFactory from context and create a new Artifact ingo@478: ArtifactFactory factory = context.getDatabase() ingo@478: .getInternalArtifactFactory(this.name); ingo@478: factory = ((GNVProductArtifactFactory)factory) ingo@478: .getArtifactFactoryByName(current.getName()); ingo@1118: artifact = factory.createArtifact( ingo@1118: uuid, ingo@1118: (GlobalContext) context.globalContext(), ingo@1118: context.getMeta(), ingo@1118: null); ingo@475: sascha@778: tim@598: if (this.preSettings != null && artifact instanceof PreSettingArtifact){ tim@598: ((PreSettingArtifact)artifact).setPreSettings(this.preSettings); tim@598: } sascha@778: ingo@475: artifact.feed(feedDocument(uuid, hash), context); ingo@475: ingo@475: result = ((GNVArtifactBase) artifact).initialize(context); ingo@475: if (artifact instanceof GNVArtifactBase) { ingo@475: ((GNVArtifactBase) artifact).setProduct(current); ingo@475: } ingo@475: context.putContextValue(ProxyArtifact.REPLACE_PROXY, artifact); ingo@475: return result; ingo@475: } ingo@475: ingo@475: ingo@792: /** ingo@792: * Create a describe document including the user interface description. The ingo@792: * user gets the choice to select a product supported by the current fis. sascha@803: * ingo@815: * @param data The describe document. ingo@815: * @param context The CallContext. ingo@815: * @return A document with an error or success message. ingo@792: */ ingo@475: @Override ingo@475: public Document describe(Document data, CallContext context) { ingo@475: log.debug("SelectProductArtifact.describe()"); ingo@475: ingo@475: // create root node ingo@475: Document document = XMLUtils.newDocument(); ingo@475: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@475: document, ingo@475: ArtifactNamespaceContext.NAMESPACE_URI, ingo@475: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@475: ); ingo@475: ingo@475: Element rootNode = creator.create("result"); ingo@475: Element typeNode = creator.create("type"); ingo@475: creator.addAttr(typeNode, "name", "describe"); ingo@475: rootNode.appendChild(typeNode); ingo@475: ingo@475: Element uuidNode = creator.create("uuid"); ingo@475: creator.addAttr(uuidNode, "value", super.identifier); ingo@475: rootNode.appendChild(uuidNode); ingo@475: ingo@475: Element hashNode = creator.create("hash"); ingo@475: creator.addAttr(hashNode, "value", hash()); ingo@475: rootNode.appendChild(hashNode); ingo@475: ingo@475: // create output node ingo@475: Element out = creator.create("outputs"); ingo@475: rootNode.appendChild(out); ingo@475: ingo@475: // create current state ingo@475: Element state = creator.create("state"); ingo@475: creator.addAttr(state, "name", "choose-product"); ingo@475: creator.addAttr(state, "description", "Auswahl des Produktes."); ingo@475: rootNode.appendChild(state); ingo@475: ingo@475: // create reachable states ingo@475: Element rStates = creator.create("reachable-states"); ingo@475: appendProducts(document, rStates, context); ingo@475: rootNode.appendChild(rStates); ingo@475: ingo@475: // create model ingo@475: Element model = creator.create("model"); ingo@475: Element input = creator.create("input"); ingo@475: creator.addAttr(input, "name", "product"); ingo@475: creator.addAttr(input, "type", "String"); ingo@475: model.appendChild(input); ingo@475: rootNode.appendChild(model); ingo@475: ingo@475: // create ui ingo@488: Element ui = creator.create("ui"); ingo@488: Element staticNode = creator.create("static"); ingo@488: Element dynamic = creator.create("dynamic"); ingo@488: ingo@488: appendFis(document, staticNode, context, this.name); ingo@475: appendSelectProducts(document, dynamic, context.getMeta()); ingo@488: ui.appendChild(staticNode); ingo@475: ui.appendChild(dynamic); ingo@475: rootNode.appendChild(ui); ingo@475: ingo@475: document.appendChild(rootNode); ingo@488: ingo@475: return document; ingo@475: } ingo@475: ingo@475: ingo@792: /** ingo@792: * ingo@792: * @param document ingo@792: * @param out ingo@792: * @param context ingo@792: * @throws IOException ingo@792: */ ingo@475: @Override ingo@475: public void out(Document document, OutputStream out, CallContext context) ingo@475: throws IOException ingo@475: { ingo@475: log.debug("SelectProductArtifact.out()"); ingo@475: if (artifact != null) { ingo@475: artifact.out(document, out, context); ingo@475: } ingo@475: } ingo@475: ingo@475: ingo@792: /** ingo@792: * Append products to the describe document. ingo@792: * ingo@815: * @param document The describe document. ingo@815: * @param parent The node the products should be appended to. ingo@815: * @param context The CallContext object. ingo@792: */ ingo@475: protected void appendProducts( ingo@475: Document document, ingo@475: Node parent, ingo@475: Object context ingo@475: ) { tim@1028: if (products != null && !products.isEmpty()){ tim@1028: Iterator iter = products.values().iterator(); ingo@475: tim@1028: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( tim@1028: document, tim@1028: ArtifactNamespaceContext.NAMESPACE_URI, tim@1028: ArtifactNamespaceContext.NAMESPACE_PREFIX tim@1028: ); ingo@475: tim@1028: while(iter.hasNext()) { tim@1028: Product prod = (Product) iter.next(); tim@1028: String name = prod.getName(); tim@1028: tim@1028: Element current = creator.create("state"); tim@1028: creator.addAttr(current, "name", name); tim@1028: creator.addAttr(current, "description", name); tim@1028: parent.appendChild(current); tim@1028: } ingo@475: } ingo@475: } ingo@475: ingo@475: ingo@792: /** ingo@792: * Append the product select box to the user interface description of the ingo@792: * describe document. ingo@792: * ingo@815: * @param document The describe document. ingo@815: * @param node The node the products should be appended to. ingo@815: * @param callMeta The CallMeta object. ingo@792: */ ingo@475: protected void appendSelectProducts( ingo@475: Document document, ingo@475: Node node, ingo@475: CallMeta callMeta ingo@475: ) { ingo@475: RessourceFactory ressource = RessourceFactory.getInstance(); ingo@475: ingo@475: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@475: document, ingo@475: XFORM_URL, ingo@475: XFORM_PREFIX ingo@475: ); ingo@475: ingo@475: String selectboxName = "product"; ingo@475: Element selectNode = creator.create("select1"); ingo@475: creator.addAttr(selectNode, "ref", selectboxName); ingo@475: ingo@475: Element lableNode = creator.create("label"); ingo@475: lableNode.setTextContent(ressource.getRessource(callMeta.getLanguages(), ingo@475: selectboxName, ingo@475: selectboxName ingo@475: ) ingo@475: ); ingo@475: ingo@475: Element choiceNode = creator.create("choices"); ingo@475: selectNode.appendChild(lableNode); ingo@475: selectNode.appendChild(choiceNode); tim@1028: if (products != null && !products.isEmpty()){ tim@1028: Iterator it = products.values().iterator(); tim@1028: while (it.hasNext()) { tim@1028: Product p = (Product) it.next(); tim@1028: Element itemNode = creator.create("item"); tim@1028: Element choiceLableNode = creator.create("label"); tim@1028: choiceLableNode.setTextContent(ressource.getRessource( tim@1028: callMeta.getLanguages(), tim@1028: p.getName(), tim@1028: p.getName() tim@1028: )); tim@1028: itemNode.appendChild(choiceLableNode); ingo@475: tim@1028: Element choiceValueNode = creator.create("value"); tim@1028: choiceValueNode.setTextContent(p.getName()); tim@1028: itemNode.appendChild(choiceValueNode); tim@1028: choiceNode.appendChild(itemNode); tim@1028: } ingo@475: } ingo@475: ingo@475: node.appendChild(selectNode); ingo@475: } ingo@475: ingo@475: ingo@792: /** ingo@792: * Create a feed document. sascha@803: * ingo@815: * @param uuid The UUID of the current artifact. ingo@815: * @param hash The hash of the current artifact. ingo@815: * @return the feed document. ingo@792: */ ingo@475: protected Document feedDocument(String uuid, String hash) { ingo@475: Document document = XMLUtils.newDocument(); ingo@475: ingo@475: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@475: document, ingo@475: ArtifactNamespaceContext.NAMESPACE_URI, ingo@475: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@475: ); ingo@475: Element rootNode = creator.create("action"); ingo@475: ingo@475: Element typeNode = creator.create("type"); ingo@475: creator.addAttr(typeNode, "name", "feed"); ingo@475: rootNode.appendChild(typeNode); ingo@475: ingo@475: Element uuidNode = creator.create("uuid"); ingo@475: creator.addAttr(uuidNode, "value", uuid); ingo@475: rootNode.appendChild(uuidNode); ingo@475: ingo@475: Element hashNode = creator.create("hash"); ingo@475: creator.addAttr(hashNode, "value", hash); ingo@475: rootNode.appendChild(hashNode); ingo@475: ingo@475: Element dataNode = creator.create("data"); ingo@475: rootNode.appendChild(dataNode); ingo@475: ingo@475: Collection parameter = this.current.getParameter(); ingo@475: if (parameter != null) { ingo@475: Iterator parameterIt = parameter.iterator(); ingo@475: ingo@475: while (parameterIt.hasNext()) { ingo@475: InputData inputData = parameterIt.next(); ingo@475: ingo@475: Element inputNode = creator.create("input"); ingo@475: creator.addAttr(inputNode, "name", inputData.getName()); ingo@475: creator.addAttr(inputNode, "value", inputData.getValue()); ingo@475: dataNode.appendChild(inputNode); ingo@475: } ingo@475: } ingo@475: document.appendChild(rootNode); ingo@475: return document; ingo@475: } ingo@475: } ingo@792: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :