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 :