ingo@464: package de.intevation.gnv.artifacts.fis; ingo@464: ingo@464: import java.io.IOException; ingo@464: import java.io.OutputStream; ingo@464: import java.util.ArrayList; ingo@464: import java.util.Collection; ingo@464: import java.util.HashMap; ingo@464: import java.util.Iterator; ingo@464: import javax.xml.xpath.XPathConstants; ingo@464: ingo@464: import org.apache.log4j.Logger; ingo@464: import org.w3c.dom.Document; ingo@464: import org.w3c.dom.Element; ingo@464: import org.w3c.dom.Node; ingo@464: import org.w3c.dom.NodeList; ingo@464: ingo@464: import de.intevation.artifactdatabase.DefaultArtifact; ingo@464: import de.intevation.artifactdatabase.ProxyArtifact; ingo@464: import de.intevation.artifactdatabase.XMLUtils; ingo@464: import de.intevation.artifacts.Artifact; ingo@464: import de.intevation.artifacts.ArtifactFactory; ingo@464: import de.intevation.artifacts.ArtifactNamespaceContext; ingo@464: import de.intevation.artifacts.CallContext; ingo@464: import de.intevation.artifacts.CallMeta; ingo@464: import de.intevation.gnv.artifacts.GNVArtifactBase; ingo@464: import de.intevation.gnv.artifacts.context.GNVArtifactContext; ingo@464: import de.intevation.gnv.artifacts.fis.product.DefaultProduct; ingo@464: import de.intevation.gnv.artifacts.fis.product.Product; ingo@464: import de.intevation.gnv.artifacts.ressource.RessourceFactory; ingo@464: import de.intevation.gnv.state.DefaultInputData; ingo@464: import de.intevation.gnv.state.InputData; ingo@464: import de.intevation.gnv.utils.ArtifactFactoryUtilities; ingo@464: ingo@464: ingo@464: /** ingo@464: * @author Ingo Weinzierl ingo@464: */ ingo@464: public class FISSelectArtifact extends DefaultArtifact { ingo@464: ingo@464: public static final String XPATH_IDENTIFIER_REPLACE = "IDENTIFIER"; ingo@464: ingo@464: public static final String XPATH_ARTIFACT_CONFIGURATION = ingo@464: "/artifact-database/artifacts/artifact[@name='" ingo@464: + XPATH_IDENTIFIER_REPLACE + "']"; ingo@464: ingo@464: public static final String XPATH_UUID = "art:action/art:uuid/@value"; ingo@464: ingo@464: public static final String XPATH_HASH = "art:action/art:hash/@value"; ingo@464: ingo@464: public static final String XPATH_INPUT_DATA_VALUE = ingo@464: "art:action/art:data/art:input[@name='product']/@value"; ingo@464: ingo@464: /** ingo@464: * this xpath is related to the config.xml document which doesn't have any ingo@464: * prefixes yet ingo@464: */ ingo@464: public static final String XPATH_PRODUCTS = "products/product"; ingo@464: ingo@464: /** ingo@464: * this xpath is related to the config.xml document which doesn't have any ingo@464: * prefixes yet ingo@464: */ ingo@464: public static final String XPATH_PRODUCT_PARAMETER = "parameters/parameter"; ingo@464: ingo@464: public static final String XFORM_URL = "http://www.w3.org/2002/xforms"; ingo@464: public static final String XFORM_PREFIX = "xform"; ingo@464: ingo@464: private static Logger log = Logger.getLogger(FISSelectArtifact.class); ingo@464: ingo@464: private HashMap products; ingo@464: private Product current; ingo@464: private Artifact artifact; ingo@464: private String name; ingo@464: ingo@464: public FISSelectArtifact() { ingo@464: super(); ingo@464: } ingo@464: ingo@464: ingo@464: @Override ingo@464: public void setup( ingo@464: String identifier, ingo@464: ArtifactFactory factory, ingo@464: Object context ingo@464: ) { ingo@464: log.debug("setup()"); ingo@464: super.setup(identifier, factory, context); ingo@464: this.name = factory.getName(); ingo@464: ingo@464: if (context instanceof GNVArtifactContext) { ingo@464: GNVArtifactContext gnvContext = (GNVArtifactContext) context; ingo@464: Document doc = gnvContext.getConfig(); ingo@464: Node artifactNode = getConfigurationFragment(doc); ingo@464: ingo@464: NodeList products = (NodeList) XMLUtils.xpath( ingo@464: artifactNode, XPATH_PRODUCTS, XPathConstants.NODESET); ingo@464: ingo@464: if (products != null) { ingo@464: this.products = new HashMap(products.getLength()); ingo@464: ingo@464: for (int i = 0; i < products.getLength(); i++) { ingo@464: Element productNode = (Element)products.item(i); ingo@464: String productName = productNode.getAttribute("name"); ingo@464: NodeList parameterNodes = (NodeList) XMLUtils.xpath( ingo@464: productNode, ingo@464: XPATH_PRODUCT_PARAMETER, ingo@464: XPathConstants.NODESET ingo@464: ); ingo@464: ingo@464: Collection parameter = null; ingo@464: if (parameterNodes != null) { ingo@464: parameter = new ArrayList(parameterNodes.getLength()); ingo@464: ingo@464: for (int j = 0; j < parameterNodes.getLength(); j++) { ingo@464: Element parameterNode = (Element)parameterNodes.item(j); ingo@464: String name = parameterNode.getAttribute("name"); ingo@464: String value = parameterNode.getAttribute("value"); ingo@464: parameter.add(new DefaultInputData(name, value)); ingo@464: } ingo@464: } ingo@464: Node artifactFactoryNode = (Node) XMLUtils.xpath( ingo@464: productNode, "artifact-factory", XPathConstants.NODE ingo@464: ); ingo@464: ingo@464: ArtifactFactory artifactFactory = ingo@464: new ArtifactFactoryUtilities().createArtitfactFactor( ingo@464: doc, artifactFactoryNode ingo@464: ); ingo@464: ingo@464: this.products.put(productName, new DefaultProduct( ingo@464: productName, parameter, artifactFactory) ingo@464: ); ingo@464: } ingo@464: } ingo@464: } ingo@464: } ingo@464: ingo@464: ingo@464: @Override ingo@464: public Document feed(Document target, CallContext context) { ingo@464: log.debug("FISSelectArtifact.feed()"); ingo@464: ingo@464: if (artifact == null) { ingo@464: Document document = XMLUtils.newDocument(); ingo@464: String productName = XMLUtils.xpathString( ingo@464: target, ingo@464: XPATH_INPUT_DATA_VALUE, ingo@464: ArtifactNamespaceContext.INSTANCE ingo@464: ); ingo@464: ingo@464: current = (Product) products.get(productName); ingo@464: ingo@464: String reportNode = null; ingo@464: String resultNode = null; ingo@464: String msg = null; ingo@464: ingo@464: if (current != null) { ingo@464: reportNode = "result"; ingo@464: resultNode = "success"; ingo@464: msg = "Feed was successfully. New Artifact created."; ingo@464: } ingo@464: else { ingo@464: reportNode = "exceptionreport"; ingo@464: resultNode = "exception"; ingo@464: msg = "Product does not exist."; ingo@464: } ingo@464: ingo@464: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@464: document, ingo@464: ArtifactNamespaceContext.NAMESPACE_URI, ingo@464: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@464: ); ingo@464: ingo@464: Element report = creator.create(reportNode); ingo@464: Element success = creator.create(resultNode); ingo@464: success.setTextContent(msg); ingo@464: report.appendChild(success); ingo@464: document.appendChild(report); ingo@464: ingo@464: return document; ingo@464: } ingo@464: else { ingo@464: return artifact.feed(target, context); ingo@464: } ingo@464: } ingo@464: ingo@464: ingo@464: @Override ingo@464: public Document advance(Document target, CallContext context) { ingo@464: log.debug("FISSelectArtifact.advance()"); ingo@464: ingo@464: if (artifact != null) { ingo@464: Document result = artifact.advance(target, context); ingo@464: context.putContextValue(ProxyArtifact.REPLACE_PROXY, artifact); ingo@464: return result; ingo@464: } ingo@464: ingo@464: Document result = XMLUtils.newDocument(); ingo@464: if (current == null) { ingo@464: // artifact needs to be feeded first ingo@464: String msg = "Artifact is not configured properly. Call 'feed' fist."; ingo@464: log.error(msg); ingo@464: ingo@464: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@464: result, ingo@464: ArtifactNamespaceContext.NAMESPACE_URI, ingo@464: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@464: ); ingo@464: ingo@464: Element report = creator.create("exceptionreport"); ingo@464: Element exception = creator.create("exception"); ingo@464: exception.setTextContent(msg); ingo@464: report.appendChild(exception); ingo@464: result.appendChild(report); ingo@464: ingo@464: return result; ingo@464: } ingo@464: ingo@464: String uuid = XMLUtils.xpathString( ingo@464: target, XPATH_UUID, ArtifactNamespaceContext.INSTANCE ingo@464: ); ingo@464: ingo@464: String hash = XMLUtils.xpathString( ingo@464: target, XPATH_HASH, ArtifactNamespaceContext.INSTANCE ingo@464: ); ingo@464: ingo@464: artifact = current.getArtifactFactory().createArtifact( ingo@464: uuid, context ingo@464: ); ingo@464: ingo@464: Document feedDocument = feedDocument(uuid, hash); ingo@464: artifact.feed(feedDocument(uuid, hash), context); ingo@464: ingo@464: result = ((GNVArtifactBase) artifact).initialize(context); ingo@464: if (artifact instanceof GNVArtifactBase) { ingo@464: ((GNVArtifactBase) artifact).setProduct(current); ingo@464: } ingo@464: context.putContextValue(ProxyArtifact.REPLACE_PROXY, artifact); ingo@464: return result; ingo@464: } ingo@464: ingo@464: ingo@464: @Override ingo@464: public Document describe(Document data, CallContext context) { ingo@464: log.debug("FISSelectArtifact.describe()"); ingo@464: ingo@464: // create root node ingo@464: Document document = XMLUtils.newDocument(); ingo@464: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@464: document, ingo@464: ArtifactNamespaceContext.NAMESPACE_URI, ingo@464: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@464: ); ingo@464: ingo@464: Element rootNode = creator.create("result"); ingo@464: Element typeNode = creator.create("type"); ingo@464: creator.addAttr(typeNode, "name", "describe"); ingo@464: rootNode.appendChild(typeNode); ingo@464: ingo@464: Element uuidNode = creator.create("uuid"); ingo@464: creator.addAttr(uuidNode, "value", super.identifier); ingo@464: rootNode.appendChild(uuidNode); ingo@464: ingo@464: Element hashNode = creator.create("hash"); ingo@464: creator.addAttr(hashNode, "value", hash()); ingo@464: rootNode.appendChild(hashNode); ingo@464: ingo@464: // create output node ingo@464: Element out = creator.create("outputs"); ingo@464: rootNode.appendChild(out); ingo@464: ingo@464: // create current state ingo@464: Element state = creator.create("state"); ingo@464: creator.addAttr(state, "name", "choose-product"); ingo@464: creator.addAttr(state, "description", "Auswahl des Produktes."); ingo@464: rootNode.appendChild(state); ingo@464: ingo@464: // create reachable states ingo@464: Element rStates = creator.create("reachable-states"); ingo@464: appendProducts(document, rStates, context); ingo@464: rootNode.appendChild(rStates); ingo@464: ingo@464: // create model ingo@464: Element model = creator.create("model"); ingo@464: Element input = creator.create("input"); ingo@464: creator.addAttr(input, "name", "product"); ingo@464: creator.addAttr(input, "type", "String"); ingo@464: model.appendChild(input); ingo@464: rootNode.appendChild(model); ingo@464: ingo@464: // create ui ingo@464: Element ui = creator.create("ui"); ingo@464: Element dynamic = creator.create("dynamic"); ingo@464: appendSelectProducts(document, dynamic, context.getMeta()); ingo@464: ui.appendChild(dynamic); ingo@464: rootNode.appendChild(ui); ingo@464: ingo@464: document.appendChild(rootNode); ingo@464: return document; ingo@464: } ingo@464: ingo@464: ingo@464: @Override ingo@464: public void out(Document document, OutputStream out, CallContext context) ingo@464: throws IOException ingo@464: { ingo@464: log.debug("FISSelectArtifact.out()"); ingo@464: if (artifact != null) { ingo@464: artifact.out(document, out, context); ingo@464: } ingo@464: } ingo@464: ingo@464: ingo@464: protected void appendProducts( ingo@464: Document document, ingo@464: Node parent, ingo@464: Object context ingo@464: ) { ingo@464: Iterator iter = products.values().iterator(); ingo@464: ingo@464: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@464: document, ingo@464: ArtifactNamespaceContext.NAMESPACE_URI, ingo@464: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@464: ); ingo@464: ingo@464: while(iter.hasNext()) { ingo@464: Product prod = (Product) iter.next(); ingo@464: String name = prod.getName(); ingo@464: ingo@464: Element current = creator.create("state"); ingo@464: creator.addAttr(current, "name", name); ingo@464: creator.addAttr(current, "description", name); ingo@464: parent.appendChild(current); ingo@464: } ingo@464: } ingo@464: ingo@464: ingo@464: protected void appendSelectProducts( ingo@464: Document document, ingo@464: Node node, ingo@464: CallMeta callMeta ingo@464: ) { ingo@464: RessourceFactory ressource = RessourceFactory.getInstance(); ingo@464: ingo@464: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@464: document, ingo@464: XFORM_URL, ingo@464: XFORM_PREFIX ingo@464: ); ingo@464: ingo@464: String selectboxName = "product"; ingo@464: Element selectNode = creator.create("select1"); ingo@464: creator.addAttr(selectNode, "ref", selectboxName); ingo@464: ingo@464: Element lableNode = creator.create("label"); ingo@464: lableNode.setTextContent(ressource.getRessource(callMeta.getLanguages(), ingo@464: selectboxName, ingo@464: selectboxName ingo@464: ) ingo@464: ); ingo@464: ingo@464: Element choiceNode = creator.create("choices"); ingo@464: selectNode.appendChild(lableNode); ingo@464: selectNode.appendChild(choiceNode); ingo@464: ingo@464: Iterator it = products.values().iterator(); ingo@464: while (it.hasNext()) { ingo@464: Product p = (Product) it.next(); ingo@464: Element itemNode = creator.create("item"); ingo@464: Element choiceLableNode = creator.create("label"); ingo@464: choiceLableNode.setTextContent(ressource.getRessource( ingo@464: callMeta.getLanguages(), ingo@464: p.getName(), ingo@464: p.getName() ingo@464: )); ingo@464: itemNode.appendChild(choiceLableNode); ingo@464: ingo@464: Element choiceValueNode = creator.create("value"); ingo@464: choiceValueNode.setTextContent(p.getName()); ingo@464: itemNode.appendChild(choiceValueNode); ingo@464: choiceNode.appendChild(itemNode); ingo@464: } ingo@464: ingo@464: node.appendChild(selectNode); ingo@464: } ingo@464: ingo@464: ingo@464: protected Node getConfigurationFragment(Document document) { ingo@464: String xpathQuery = XPATH_ARTIFACT_CONFIGURATION.replaceAll( ingo@464: XPATH_IDENTIFIER_REPLACE, name ingo@464: ); ingo@464: ingo@464: return (Node) XMLUtils.xpath(document, xpathQuery, XPathConstants.NODE); ingo@464: } ingo@464: ingo@464: ingo@464: protected Document feedDocument(String uuid, String hash) { ingo@464: Document document = XMLUtils.newDocument(); ingo@464: ingo@464: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@464: document, ingo@464: ArtifactNamespaceContext.NAMESPACE_URI, ingo@464: ArtifactNamespaceContext.NAMESPACE_PREFIX ingo@464: ); ingo@464: Element rootNode = creator.create("action"); ingo@464: ingo@464: Element typeNode = creator.create("type"); ingo@464: creator.addAttr(typeNode, "name", "feed"); ingo@464: rootNode.appendChild(typeNode); ingo@464: ingo@464: Element uuidNode = creator.create("uuid"); ingo@464: creator.addAttr(uuidNode, "value", uuid); ingo@464: rootNode.appendChild(uuidNode); ingo@464: ingo@464: Element hashNode = creator.create("hash"); ingo@464: creator.addAttr(hashNode, "value", hash); ingo@464: rootNode.appendChild(hashNode); ingo@464: ingo@464: Element dataNode = creator.create("data"); ingo@464: rootNode.appendChild(dataNode); ingo@464: ingo@464: Collection parameter = this.current.getParameter(); ingo@464: if (parameter != null) { ingo@464: Iterator parameterIt = parameter.iterator(); ingo@464: ingo@464: while (parameterIt.hasNext()) { ingo@464: InputData inputData = parameterIt.next(); ingo@464: ingo@464: Element inputNode = creator.create("input"); ingo@464: creator.addAttr(inputNode, "name", inputData.getName()); ingo@464: creator.addAttr(inputNode, "value", inputData.getValue()); ingo@464: dataNode.appendChild(inputNode); ingo@464: } ingo@464: } ingo@464: document.appendChild(rootNode); ingo@464: return document; ingo@464: } ingo@464: } ingo@464: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: