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:
tim@52: package de.intevation.gnv.artifacts;
tim@52:
sascha@779: import de.intevation.artifactdatabase.Config;
sascha@779: import de.intevation.artifactdatabase.ProxyArtifact;
sascha@779: import de.intevation.artifactdatabase.XMLUtils;
sascha@779:
sascha@779: import de.intevation.artifacts.Artifact;
sascha@779: import de.intevation.artifacts.ArtifactDatabase;
sascha@779: import de.intevation.artifacts.ArtifactFactory;
sascha@779: import de.intevation.artifacts.ArtifactNamespaceContext;
sascha@779: import de.intevation.artifacts.CallContext;
sascha@779: import de.intevation.artifacts.CallMeta;
sascha@779:
sascha@779: import de.intevation.gnv.artifacts.context.GNVArtifactContext;
sascha@779:
sascha@779: import de.intevation.gnv.artifacts.fis.product.Product;
sascha@779:
sascha@779: import de.intevation.gnv.artifacts.ressource.RessourceFactory;
sascha@779:
sascha@779: import de.intevation.gnv.state.AutoResumeState;
sascha@779: import de.intevation.gnv.state.DefaultInputData;
sascha@779: import de.intevation.gnv.state.ExportMode;
sascha@779: import de.intevation.gnv.state.InputData;
sascha@779: import de.intevation.gnv.state.InputValue;
sascha@779: import de.intevation.gnv.state.OutputMode;
sascha@779: import de.intevation.gnv.state.OutputState;
sascha@779: import de.intevation.gnv.state.State;
sascha@779: import de.intevation.gnv.state.StateFactory;
sascha@779:
sascha@779: import de.intevation.gnv.state.exception.StateException;
sascha@779:
sascha@779: import de.intevation.gnv.transition.Transition;
sascha@779: import de.intevation.gnv.transition.TransitionFactory;
sascha@779:
sascha@779: import de.intevation.gnv.utils.ArtifactXMLUtilities;
sascha@779:
tim@73: import java.io.IOException;
tim@73: import java.io.OutputStream;
sascha@779:
tim@337: import java.util.ArrayList;
tim@56: import java.util.Collection;
tim@52: import java.util.HashMap;
tim@54: import java.util.Iterator;
ingo@473: import java.util.List;
ingo@725: import java.util.Locale;
tim@52: import java.util.Map;
tim@52:
tim@71: import javax.xml.xpath.XPathConstants;
tim@71:
sascha@652: import org.apache.log4j.Logger;
sascha@779:
tim@52: import org.w3c.dom.Document;
tim@54: import org.w3c.dom.Element;
tim@52: import org.w3c.dom.Node;
tim@52: import org.w3c.dom.NodeList;
tim@52:
tim@52: /**
ingo@789: * This is the major gnv artifact and handles the requests specified in
ingo@815: * de.intevation.artifactdatabase.Artifact
.
sascha@803: *
sascha@780: * @author Tim Englich
sascha@780: * @author Ingo Weinzierl
sascha@780: * @author Sascha L. Teichmann
tim@52: */
sascha@778: public abstract class GNVArtifactBase extends GNVDefaultArtifact
tim@598: implements PreSettingArtifact {
tim@598:
tim@52: /**
tim@52: * the logger, used to log exceptions and additonaly information
tim@52: */
tim@52: private static Logger log = Logger.getLogger(GNVArtifactBase.class);
tim@52: /**
tim@52: * The UID of this Class
tim@52: */
tim@52: private static final long serialVersionUID = -8907096744400741458L;
tim@171:
tim@54: /**
tim@54: * The Identifier for the Replacement of the Artifactname
tim@54: */
tim@52: public static final String XPATH_IDENTIFIER_REPLACE = "IDENTIFIER";
tim@171:
tim@52: /**
tim@52: * The XPATH to the XML-Fragment that should be used for the Configuration
tim@52: */
tim@171: public static final String XPATH_ARTIFACT_CONFIGURATION = "/artifact-database/artifacts/artifact[@name='"
tim@171: + XPATH_IDENTIFIER_REPLACE
tim@171: + "']";
tim@171:
ingo@464: public static final String XPATH_STATIC_NODE = "/art:result/art:ui/art:static";
ingo@464:
ingo@464: public static final String XPATH_INPUT_DATA = "/art:action/art:data/art:input";
ingo@464:
ingo@464: public static final String XPATH_INCLUDE_UI = "/art:action/art:include-ui";
ingo@464:
ingo@464: public static final String XPATH_TARGET_NAME = "/art:action/art:target/@name";
ingo@464:
sascha@778: public static final String XPATH_OUTPUT_NAME = "/art:action/art:out/@name";
ingo@464:
sascha@778: public static final String XPATH_OUTPUT_PARAMS = "/art:action/art:out/art:params/art:input";
ingo@464:
ingo@478: public static final String INITIAL_STATE = "product";
ingo@470:
tim@54: /**
tim@335: * The current State
tim@54: */
tim@335: protected State current = null;
tim@171:
tim@54: /**
tim@335: * The States that can be used
tim@54: */
tim@335: protected Map states = null;
sascha@778:
tim@337: /**
tim@337: * The Transitions which can switch between the different States.
tim@337: */
tim@337: protected Collection transitions = null;
tim@52:
ingo@464: /**
ingo@464: * The current product
ingo@464: */
ingo@464: protected Product product;
ingo@464:
tim@54: /**
tim@54: * The Name of the Artifact
tim@54: */
tim@52: protected String name = null;
tim@171:
tim@52: /**
tim@598: * The Presettings of InputData which can be used to
tim@598: * travel through the States in different Ways or
tim@598: * manipulate the InputData
tim@598: */
tim@598: private Map preSettings = null;
tim@598:
tim@598: /**
tim@52: * Constructor
tim@52: */
tim@52: public GNVArtifactBase() {
tim@52: super();
tim@52: }
tim@171:
ingo@470:
ingo@789: /**
ingo@789: * This method handles request for changing the current state of an
ingo@789: * artifact. It is possible to step forward, backward, or to the initial
ingo@789: * state for choosing a fis.
ingo@789: */
tim@58: @Override
tim@73: public Document advance(Document target, CallContext context) {
ingo@470: log.debug("GNVArtifactBase.advance()");
ingo@470:
ingo@470: Document result = XMLUtils.newDocument();
ingo@470: String targetState = XMLUtils.xpathString(
ingo@470: target, XPATH_TARGET_NAME, ArtifactNamespaceContext.INSTANCE
ingo@470: );
ingo@470:
ingo@470: // no current state...
ingo@470: if (current == null) {
ingo@614: log.warn("No current state. Advance not possible.");
ingo@470:
ingo@470: result = createReport(
ingo@470: result,
ingo@470: "exceptionreport",
ingo@470: "exception",
ingo@470: "No State activated."
ingo@470: );
ingo@470:
ingo@470: return result;
ingo@470: }
ingo@470:
ingo@470: State next = null;
ingo@470:
tim@88: try {
ingo@470:
ingo@470: // step forward
ingo@470: if (isStateCurrentlyReachable(targetState)) {
ingo@614:
ingo@470: next = states.get(targetState);
ingo@470:
tim@735: boolean success = go2NextState(context, result, next);
sascha@778:
tim@735: if (success){
tim@735: result = createReport(
tim@735: result, "result", "success", "Advance success"
tim@735: );
tim@735: }else{
tim@735: result = ArtifactXMLUtilities.
sascha@778: createExceptionReport("Error while going to next State.",
tim@735: XMLUtils.newDocument());
sascha@481: }
tim@58: }
ingo@470:
ingo@470: // step backward
ingo@1062: else if((next = getPreviousState(current, targetState, context))
ingo@1062: != null)
ingo@1062: {
ingo@473:
sascha@481: if (current != null) {
sascha@481: current.endOfLife(context.globalContext());
sascha@481: }
sascha@481:
ingo@470: current = next;
ingo@470:
ingo@614: // 2. Transfer Results
ingo@614: current.reset(identifier);
ingo@614:
ingo@470: result = createReport(
ingo@470: result, "result", "success", "Advance success"
ingo@470: );
ingo@470: }
ingo@470:
ingo@470: // goto initial step
ingo@470: else if(targetState.equals(INITIAL_STATE)) {
ingo@478:
ingo@478: String fis = product.getArtifactFactory();
ingo@478: ArtifactDatabase db = context.getDatabase();
ingo@478: GNVProductArtifactFactory fac = (GNVProductArtifactFactory)
ingo@478: db.getInternalArtifactFactory(fis);
ingo@478:
tim@594: Artifact select = fac.createArtifact(identifier, context, null);
ingo@470: context.putContextValue(ProxyArtifact.REPLACE_PROXY, select);
ingo@470:
ingo@470: result = createReport(
ingo@470: result, "result", "success", "Advance success"
ingo@470: );
ingo@470: }
ingo@470:
ingo@470: // advance not possible
ingo@470: else {
ingo@470: log.warn("advance not possible for target: " + targetState);
ingo@470: result = createReport(
ingo@470: result,
ingo@470: "exceptionreport",
ingo@470: "exception",
ingo@470: "Statetransition not supported"
ingo@470: );
ingo@470: }
tim@58: }
ingo@470: catch (StateException se) {
ingo@470: log.error(se, se);
ingo@470: result = createReport(
ingo@470: result,
ingo@470: "exceptionreport",
ingo@470: "exception",
ingo@470: se.getLocalizedMessage()
ingo@470: );
ingo@470: }
ingo@470:
tim@58: return result;
tim@58: }
ingo@470:
ingo@470:
tim@735: private boolean go2NextState(CallContext context, Document result,
tim@735: State next) throws StateException {
tim@735: // 2. Transfer Results
tim@735: next.putInputData(current.getInputData(), identifier);
tim@735: next.setParent(current);
tim@735: next.setPreSettings(this.preSettings);
tim@735:
tim@735: // 3. Switch to next State
tim@735: current = next;
tim@735:
tim@735: // 4. Initialize next Step
tim@735: current.initialize(identifier, context);
tim@735:
tim@735: return true;
tim@735: }
tim@735:
tim@735:
ingo@470: protected Document createReport(
ingo@470: Document document,
ingo@470: String nodeName,
ingo@470: String state,
ingo@470: String msg
ingo@470: ) {
ingo@470: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator(
ingo@470: document,
ingo@470: ArtifactNamespaceContext.NAMESPACE_URI,
ingo@470: ArtifactNamespaceContext.NAMESPACE_PREFIX
ingo@470: );
ingo@470:
ingo@470: Element reportNode = creator.create(nodeName);
ingo@470: Element stateNode = creator.create(state);
ingo@470:
ingo@470: stateNode.setTextContent(msg);
ingo@470: reportNode.appendChild(stateNode);
ingo@470: document.appendChild(reportNode);
ingo@470:
ingo@470: return document;
ingo@470:
ingo@470: }
ingo@470:
ingo@470:
ingo@789: /**
ingo@789: * Step back to the previous state specified by name
.
ingo@789: */
ingo@1062: protected State getPreviousState(
ingo@1062: State current, String name, CallContext context)
ingo@1062: {
ingo@470: if (current == null) {
ingo@470: return null;
ingo@470: }
ingo@470:
ingo@470: if (current.getID().equals(name)) {
ingo@470: return current;
ingo@470: }
ingo@470: else {
ingo@1062: current.endOfLife(context);
ingo@1062: return getPreviousState(current.getParent(), name, context);
ingo@470: }
ingo@470: }
ingo@470:
ingo@470:
tim@337: private boolean isStateCurrentlyReachable(String stateid){
tim@337: Iterator it = this.transitions.iterator();
tim@337: String from = this.current.getID();
tim@337: while (it.hasNext()){
tim@337: Transition transition = it.next();
tim@337: if (transition.getFrom().equals(from)){
tim@337: if (transition.getTo().equals(stateid) && transition.isValid(this.current)){
tim@337: return true;
tim@337: }
tim@337: }
tim@337: }
tim@337: return false;
tim@337: }
sascha@778:
ingo@815:
ingo@789: public Document initialize(CallContext context) {
tim@325: Document result = XMLUtils.newDocument();
tim@325: try {
ingo@493: this.current.initialize(super.identifier, context);
sascha@778:
tim@735: if (this.current instanceof AutoResumeState){
tim@735: // Jump to next State using the Transitions.
tim@735: State next = this.getNextReachableState(this.current);
tim@735: if (next != null){
tim@735: boolean success = go2NextState(context, result, next);
tim@735: if (success){
tim@735: result = ArtifactXMLUtilities
tim@735: .createSuccessReport("Initialize success",
tim@735: XMLUtils.newDocument());
tim@735: }else{
tim@735: result = ArtifactXMLUtilities.
tim@735: createExceptionReport(
sascha@778: "Error while going to next State.",
tim@735: XMLUtils.newDocument());
tim@735: }
tim@735: }else{
tim@735: result = ArtifactXMLUtilities.
sascha@778: createExceptionReport("No propper State found.",
tim@735: XMLUtils.newDocument());
tim@735: }
tim@735: }else{
tim@735: result = ArtifactXMLUtilities
tim@735: .createSuccessReport("Initialize success",
tim@735: XMLUtils.newDocument());
tim@735: }
tim@335: } catch (StateException e) {
tim@325: log.error(e,e);
tim@735: result = ArtifactXMLUtilities.createExceptionReport(e
tim@325: .getLocalizedMessage(), XMLUtils.newDocument());
tim@325: }
tim@325: return result;
tim@325: }
sascha@778:
ingo@789: /**
ingo@789: * Step forward to the next reachable state.
ingo@789: * @param current Current state.
ingo@789: * @return Reachable state.
ingo@789: */
tim@735: protected State getNextReachableState(State current){
tim@735: Iterator it = this.transitions.iterator();
tim@735: String from = current.getID();
tim@735: while (it.hasNext()){
tim@735: Transition transition = it.next();
tim@735: if (transition.getFrom().equals(from)){
tim@735: if (transition.isValid(current)){
tim@735: return this.states.get(transition.getTo());
tim@735: }
tim@735: }
tim@735: }
tim@735: return null;
tim@735: }
tim@58:
ingo@815:
tim@335: protected String readStateName(Document document) {
ingo@464: String returnValue = XMLUtils.xpathString(
ingo@464: document, XPATH_TARGET_NAME, ArtifactNamespaceContext.INSTANCE);
tim@58: return returnValue;
tim@58: }
tim@58:
ingo@815:
tim@171: protected Node getConfigurationFragment(Document document) {
tim@52: log.debug("GNVArtifactBase.getConfigurationFragment");
tim@171: String xpathQuery = XPATH_ARTIFACT_CONFIGURATION.replaceAll(
tim@171: XPATH_IDENTIFIER_REPLACE, this.name);
sascha@778:
tim@204: Element configurationNode = (Element)Config.getNodeXPath(document, xpathQuery);
sascha@778:
tim@204: String link = configurationNode.getAttribute("xlink:href");
tim@204: if (link != null ){
tim@204: String absolutFileName = Config.replaceConfigDir(link);
tim@217: configurationNode = (Element)new ArtifactXMLUtilities().readConfiguration(absolutFileName);
tim@204: }
sascha@778:
tim@204: return configurationNode;
tim@204: }
tim@171:
tim@52: /**
ingo@789: * Insert new data included in target
into the current state.
ingo@789: * @param target XML document which contains data.
ingo@789: * @param context CallContext
ingo@789: * @return XML document with success or error message.
tim@57: */
tim@57: @Override
tim@73: public Document feed(Document target, CallContext context) {
tim@89: log.debug("GNVArtifactBase.feed");
ingo@725: RessourceFactory fac = RessourceFactory.getInstance();
ingo@725: Locale[] locales = fac.getLocales();
ingo@725: Locale locale = context.getMeta().getPreferredLocale(locales);
ingo@725: Document result = XMLUtils.newDocument();
ingo@725:
tim@57: try {
tim@171: if (this.current != null) {
ingo@464: Collection inputData = this.parseInputData(
ingo@464: target,
ingo@464: XPATH_INPUT_DATA);
ingo@464:
tim@194: if (!inputData.isEmpty()){
ingo@725: result = current.feed(context, inputData, super.identifier);
tim@194: }else{
ingo@725: //String msg = "No Inputdata given. Please select at least one Entry.";
ingo@725: String msg = fac.getRessource(
ingo@725: locale,
ingo@725: EXCEPTION_NO_INPUT,
ingo@725: EXCEPTION_NO_INPUT);
ingo@725:
tim@194: log.warn(msg);
tim@735: result = ArtifactXMLUtilities.createInputExceptionReport(
ingo@725: msg,
ingo@725: XMLUtils.newDocument());
tim@194: }
tim@171: } else {
tim@335: String msg = "No State instantiated";
tim@89: log.warn(msg);
tim@735: result = ArtifactXMLUtilities.createExceptionReport(msg,
tim@171: XMLUtils.newDocument());
tim@57: }
tim@335: } catch (StateException e) {
tim@171: log.error(e, e);
tim@735: result = ArtifactXMLUtilities.createExceptionReport(e
tim@171: .getLocalizedMessage(), XMLUtils.newDocument());
tim@57: }
tim@57: return result;
tim@57: }
tim@171:
ingo@464:
ingo@464: /**
ingo@789: * Describe the current artifact.
ingo@789: * @return The description of the current artifact.
ingo@464: */
ingo@464: @Override
ingo@464: public Document describe(Document data, CallContext context) {
ingo@464: log.debug("GNVArtifactBase.describe");
ingo@464:
ingo@464: Document document = createDescibeOutput(
ingo@488: context,
ingo@464: identifier,
ingo@464: getIncludeUIFromDocument(data)
ingo@464: );
ingo@464:
ingo@464: return document;
ingo@464: }
ingo@464:
tim@57: /**
ingo@789: * Initialse this artifact and insert some data if data
ingo@789: * contains necessary information for this artifact.
tim@52: */
tim@52: @Override
sascha@778: public void setup(String identifier, ArtifactFactory factory,
tim@594: Object context,Document data) {
tim@52: log.debug("GNVArtifactBase.setup");
tim@594: super.setup(identifier, factory, context, data);
tim@171:
tim@77: Object localContext = context;
tim@171: if (context instanceof CallContext) {
tim@171: localContext = ((CallContext) context).globalContext();
tim@171:
tim@77: }
tim@171:
tim@171: if (localContext instanceof GNVArtifactContext) {
tim@171: GNVArtifactContext gnvContext = (GNVArtifactContext) localContext;
tim@52: Document doc = gnvContext.getConfig();
tim@52: Node artifactNode = this.getConfigurationFragment(doc);
sascha@778:
tim@335: NodeList stateList = Config.getNodeSetXPath(artifactNode,
tim@335: "states/state");
tim@335: this.states = new HashMap(stateList
tim@171: .getLength());
tim@335: for (int i = 0; i < stateList.getLength(); i++) {
tim@335: State tmpState = StateFactory.getInstance()
tim@335: .createState(stateList.item(i));
tim@335: if (tmpState != null) {
ingo@470: log.debug("Initiate new state: " + tmpState.getID());
tim@335: this.states.put(tmpState.getID(), tmpState);
tim@171: if (this.current == null) {
tim@335: this.current = tmpState;
tim@52: }
tim@52: }
tim@52: }
sascha@778:
tim@337: NodeList transitionList = Config.getNodeSetXPath(artifactNode,
tim@337: "states/transition");
tim@337: this.transitions = new ArrayList(transitionList.getLength());
tim@337: for (int i = 0; i < transitionList.getLength(); i++) {
tim@337: Transition tmpTransition = TransitionFactory.getInstance()
tim@337: .createTransition(transitionList.item(i));
tim@337: if (tmpTransition != null) {
tim@337: this.transitions.add(tmpTransition);
tim@337: }
tim@337: }
tim@171:
tim@52: }
tim@52: }
tim@171:
ingo@488:
ingo@789: /**
ingo@789: * Create the xml document returned in {@link #describe(org.w3c.dom.Document,
ingo@789: * de.intevation.artifacts.CallContext)}
ingo@789: */
ingo@488: protected Document createDescibeOutput(
ingo@488: CallContext context,
ingo@488: String uuid,
ingo@488: boolean incudeUI
ingo@488: ) {
tim@54: log.debug("GNVArtifactBase.createDescibeOutput");
tim@71: Document document = XMLUtils.newDocument();
ingo@488:
ingo@464: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator(
ingo@464: document,
ingo@464: ArtifactNamespaceContext.NAMESPACE_URI,
ingo@464: ArtifactNamespaceContext.NAMESPACE_PREFIX
ingo@464: );
ingo@470: Element rootNode = this.createRootNode(creator, document);
ingo@464: this.createHeader(creator, rootNode, document, "describe");
ingo@464: this.createOutputs(creator, rootNode, document);
ingo@464: this.createCurrentState(creator, rootNode, document);
ingo@464: this.createReachableStates(creator, rootNode, document);
ingo@464: this.createModel(creator, rootNode, document);
tim@222: if (incudeUI){
ingo@488: this.createUserInterface(creator, rootNode, document, context, uuid);
tim@222: }
ingo@464:
tim@54: return document;
tim@54: }
sascha@778:
ingo@789: /**
ingo@789: * Determine the wish to append the user interface description to the
ingo@789: * describe document.
sascha@803: *
ingo@789: * @return True, if the user interface description should be appended,
ingo@789: * otherwise false.
ingo@789: */
tim@222: protected boolean getIncludeUIFromDocument(Document document){
ingo@464: String value = XMLUtils.xpathString(
ingo@464: document, XPATH_INCLUDE_UI, ArtifactNamespaceContext.INSTANCE);
ingo@464:
tim@222: boolean includeUI = false;
tim@222: if (value != null){
tim@222: includeUI = Boolean.parseBoolean(value);
tim@222: }
tim@222: return includeUI;
tim@222: }
tim@171:
ingo@815:
ingo@470: protected Element createRootNode(
ingo@470: XMLUtils.ElementCreator creator,
ingo@470: Document document
ingo@470: ) {
ingo@470: Element rootNode = creator.create("result");
tim@54: document.appendChild(rootNode);
tim@54: return rootNode;
tim@54: }
tim@171:
ingo@789: /**
ingo@789: * Append information about the current artifact (uuid, hash).
ingo@789: */
ingo@464: protected void createHeader(
ingo@464: XMLUtils.ElementCreator creator,
ingo@464: Element parent,
ingo@464: Document document,
ingo@464: String documentType
ingo@478: ) {
ingo@464: Element typeNode = creator.create("type");
ingo@464: creator.addAttr(typeNode, "name", documentType);
tim@54: parent.appendChild(typeNode);
tim@171:
ingo@464: Element uuidNode = creator.create("uuid");
ingo@464: creator.addAttr(uuidNode, "value", super.identifier);
tim@54: parent.appendChild(uuidNode);
tim@171:
ingo@464: Element hashNode = creator.create("hash");
ingo@464: creator.addAttr(hashNode, "value", this.hash());
tim@54: parent.appendChild(hashNode);
tim@89: }
tim@54:
ingo@789: /**
ingo@789: * Create the fis select box.
ingo@789: */
ingo@464: protected Element createSelectBox(
ingo@478: XMLUtils.ElementCreator artCreator,
ingo@464: XMLUtils.ElementCreator creator,
ingo@464: Document document,
ingo@464: CallContext context
ingo@464: ) {
ingo@464: RessourceFactory resource = RessourceFactory.getInstance();
ingo@464: CallMeta callMeta = (CallMeta) context.getMeta();
ingo@478: String productName = product.getName();
ingo@464:
ingo@464: Element selectNode = creator.create("select1");
ingo@464: creator.addAttr(selectNode, "ref", "product");
ingo@478: artCreator.addAttr(selectNode, "state", INITIAL_STATE, true);
ingo@478:
ingo@464:
ingo@464: Element labelNode = creator.create("label");
ingo@464: labelNode.setTextContent(
ingo@464: resource.getRessource(callMeta.getLanguages(), "product", "product")
ingo@464: );
ingo@464:
ingo@464: Element choicesNode = creator.create("choices");
ingo@464:
ingo@464: Element itemNode = creator.create("item");
ingo@464: creator.addAttr(itemNode, "selected", "true");
ingo@464:
ingo@464: Element choiceLabel = creator.create("label");
ingo@464: choiceLabel.setTextContent(resource.getRessource(
ingo@464: callMeta.getLanguages(),
ingo@464: productName,
ingo@464: productName
ingo@464: ));
ingo@464:
ingo@464: Element choiceValue = creator.create("value");
ingo@464: choiceValue.setTextContent(productName);
ingo@464:
ingo@464: itemNode.appendChild(choiceLabel);
ingo@464: itemNode.appendChild(choiceValue);
ingo@464: choicesNode.appendChild(itemNode);
ingo@464:
ingo@464: selectNode.appendChild(labelNode);
ingo@464: selectNode.appendChild(choicesNode);
ingo@464:
ingo@464: return selectNode;
ingo@464: }
ingo@464:
ingo@488:
ingo@789: /**
ingo@789: * Insert all reachable states into the describe document returned by
ingo@789: * {@link #describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)}
ingo@789: */
ingo@464: protected void createReachableStates(
ingo@464: XMLUtils.ElementCreator creator,
ingo@464: Element parent,
ingo@464: Document document
ingo@464: ) {
ingo@464: Element stateNode = creator.create("reachable-states");
tim@171: if (this.current != null) {
ingo@473:
ingo@473: // add future states
tim@337: Iterator transitions = this.transitions.iterator();
tim@337: while (transitions.hasNext()) {
tim@337: Transition tmpTransition = transitions.next();
ingo@614: if (tmpTransition.getFrom().equals(current.getID()) &&
tim@337: tmpTransition.isValid(this.current)){
ingo@464: Element currentNode = creator.create("state");
ingo@464: creator.addAttr(currentNode, "name", tmpTransition.getTo());
ingo@464: creator.addAttr(
ingo@464: currentNode,
ingo@464: "description",
ingo@464: this.states.get(tmpTransition.getTo()).getDescription());
tim@337: stateNode.appendChild(currentNode);
tim@337: }
tim@54: }
ingo@473:
ingo@473:
ingo@473: // add old states
ingo@473: appendOldReachableStates(creator, stateNode, current);
tim@54: }
tim@54: parent.appendChild(stateNode);
tim@54: }
tim@171:
ingo@473:
ingo@789: /**
ingo@789: * Insert states which have been visited by this artifact into the xml
ingo@789: * document returned by {@link #describe(org.w3c.dom.Document,
ingo@789: * de.intevation.artifacts.CallContext)}
ingo@789: */
ingo@473: protected void appendOldReachableStates(
ingo@473: XMLUtils.ElementCreator creator,
ingo@473: Element parent,
ingo@473: State state
ingo@473: ) {
ingo@473: if (state == null)
ingo@473: return;
ingo@473:
ingo@473: while (state != null) {
ingo@473: Element currentNode = creator.create("state");
ingo@473: creator.addAttr(currentNode, "name", state.getID());
ingo@473: creator.addAttr(currentNode, "description", state.getDescription());
ingo@473: parent.appendChild(currentNode);
ingo@473:
ingo@473: state = state.getParent();
ingo@473: }
ingo@473: }
ingo@473:
ingo@473:
ingo@789: /**
ingo@789: * Insert the current state into the xml document returned by
ingo@789: * {@link #describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)}
ingo@789: */
ingo@464: protected void createCurrentState(
ingo@464: XMLUtils.ElementCreator creator,
ingo@464: Element parent,
ingo@464: Document document
ingo@464: ) {
ingo@464: Element stateNode = creator.create("state");
ingo@464: creator.addAttr(stateNode, "name", this.current.getID());
ingo@464: creator.addAttr(stateNode, "description", this.current.getDescription());
tim@54: parent.appendChild(stateNode);
tim@54: }
tim@171:
ingo@815:
ingo@464: protected void createModel(
ingo@464: XMLUtils.ElementCreator creator,
ingo@464: Element parent,
ingo@464: Document document
ingo@464: ) {
ingo@464: Element modelNode = creator.create("model");
tim@171: if (this.current != null) {
tim@171: Collection inputValues = this.current
tim@171: .getRequiredInputValues();
tim@171: if (inputValues != null) {
tim@56: Iterator it = inputValues.iterator();
tim@171: while (it.hasNext()) {
tim@56: InputValue inputValue = it.next();
ingo@464: Element inputNode = creator.create("input");
ingo@464: creator.addAttr(inputNode, "name", inputValue.getName());
ingo@464: creator.addAttr(inputNode, "type", inputValue.getType());
tim@56: modelNode.appendChild(inputNode);
tim@56: }
tim@56: }
tim@56: }
tim@54: parent.appendChild(modelNode);
tim@54: }
tim@171:
ingo@789: /**
ingo@789: * Append the user interface description to the document returned by
ingo@789: * {@link #describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)}
ingo@789: * @param creator XML element creator.
ingo@789: * @param parent New elements are appended to this node.
ingo@789: * @param document Current document.
ingo@789: * @param context CallContext
ingo@789: * @param uuid The uuid of the artifact.
ingo@789: */
ingo@464: protected void createUserInterface(
ingo@464: XMLUtils.ElementCreator creator,
ingo@464: Element parent,
ingo@464: Document document,
ingo@488: CallContext context,
ingo@488: String uuid
ingo@464: ) {
ingo@488: XMLUtils.ElementCreator xCreator = new XMLUtils.ElementCreator(
ingo@488: document,
ingo@488: XMLUtils.XFORM_URL,
ingo@488: XMLUtils.XFORM_PREFIX
ingo@488: );
ingo@488:
ingo@488: Element uiNode = creator.create("ui");
ingo@488: Element staticNode = creator.create("static");
ingo@488: Element dynamic = creator.create("dynamic");
ingo@488:
ingo@488: uiNode.appendChild(staticNode);
ingo@488: uiNode.appendChild(dynamic);
ingo@488:
ingo@488: parent.appendChild(uiNode);
ingo@488:
ingo@488: // append fis to dynamic part
ingo@488: appendFis(document, staticNode, context, product.getArtifactFactory());
tim@171:
tim@171: if (this.current != null) {
ingo@488: Element staticUI = createSelectBox(
ingo@488: creator, xCreator, document, context
ingo@488: );
ingo@488: staticNode.appendChild(staticUI);
ingo@488:
ingo@478: this.current.describe(
ingo@493: document, uiNode, context, uuid
ingo@478: );
tim@61: }
tim@54: }
tim@171:
ingo@478:
ingo@789: /**
ingo@789: * Append possible output targets to the document returned by
ingo@789: * {@link #describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)}
ingo@789: * @param creator Used to create xml elements.
ingo@789: * @param parent New elements are appended to this node.
ingo@789: * @param document The current document.
ingo@789: */
ingo@464: protected void createOutputs(
ingo@464: XMLUtils.ElementCreator creator,
ingo@464: Element parent,
ingo@464: Document document
ingo@464: ) {
tim@64: log.debug("GNVArtifactBase.createOutputs");
ingo@464: Element outputsNode = creator.create("outputs");
tim@335: if (this.current instanceof OutputState) {
tim@335: Collection outputModes = ((OutputState) this.current)
tim@171: .getOutputModes();
tim@171: if (outputModes != null) {
tim@64: Iterator it = outputModes.iterator();
tim@171: while (it.hasNext()) {
tim@64: OutputMode outputMode = it.next();
tim@171: log.debug("Write Outputnode for " + outputMode.toString());
ingo@464: Element outputModeNode = creator.create("output");
ingo@464: creator.addAttr(
ingo@464: outputModeNode, "name", outputMode.getName());
ingo@464: creator.addAttr(
ingo@464: outputModeNode, "description", outputMode.getDescription());
ingo@464: creator.addAttr(
ingo@464: outputModeNode, "mime-type", outputMode.getMimeType());
tim@64: outputsNode.appendChild(outputModeNode);
tim@171:
tim@171: Collection inputParameters = outputMode
tim@171: .getInputParameters();
tim@171: if (inputParameters != null) {
ingo@464: Element inputParametersNode = creator.create("parameter");
tim@91: outputModeNode.appendChild(inputParametersNode);
tim@91: Iterator it2 = inputParameters.iterator();
tim@171: while (it2.hasNext()) {
tim@91: InputValue inputValue = it2.next();
ingo@464: Element inputParameterNode =
ingo@464: creator.create("parameter");
ingo@464: creator.addAttr(
ingo@464: inputParameterNode, "name", inputValue.getName());
ingo@464: creator.addAttr(
ingo@464: inputParameterNode, "type", inputValue.getType());
ingo@464: creator.addAttr(
ingo@464: inputParameterNode, "value", inputValue.getDefaultValue());
tim@91: inputParametersNode.appendChild(inputParameterNode);
tim@91: }
tim@91: }
ingo@626:
ingo@626: // append export modes
ingo@626: List exportModes = outputMode.getExportModes();
ingo@626: if (exportModes != null) {
ingo@626: Element exports = creator.create("exports");
ingo@626: outputModeNode.appendChild(exports);
ingo@626:
ingo@626: for (ExportMode exp: exportModes) {
ingo@626: Element export = creator.create("export");
ingo@626: creator.addAttr(
ingo@626: export, "name", exp.getName());
ingo@626: creator.addAttr(
ingo@626: export, "description", exp.getDescription());
ingo@626: creator.addAttr(
ingo@626: export, "mime-type", exp.getMimeType());
ingo@626:
ingo@626: exports.appendChild(export);
ingo@626: }
ingo@626: }
tim@64: }
tim@171: } else {
tim@64: log.warn("No Outputmodes given.");
tim@64: }
tim@64: }
tim@54: parent.appendChild(outputsNode);
tim@54: }
tim@54:
ingo@789: /**
ingo@789: * Parse input data from feed-document.
ingo@789: * @param document Feed-document
ingo@789: * @param xPath Path to input data.
ingo@789: * @return A collection with InputData objects.
ingo@789: */
tim@171: protected Collection parseInputData(Document document,
tim@171: String xPath) {
tim@171: HashMap returnValue = null;
tim@171:
tim@171: NodeList inputElemets = (NodeList) XMLUtils.xpath(document, xPath,
ingo@464: XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE);
tim@171: if (inputElemets != null) {
ingo@464: returnValue = new HashMap();
ingo@464:
tim@171: for (int i = 0; i < inputElemets.getLength(); i++) {
tim@204: Element inputDataNode = (Element)inputElemets.item(i);
tim@204: String name = inputDataNode.getAttribute("name");
tim@204: String value = inputDataNode.getAttribute("value");
tim@171:
tim@171: if (returnValue.containsKey(name)) {
tim@78: InputData inputData = returnValue.get(name);
tim@78: inputData.concartValue(value);
tim@78: log.debug(inputData.toString());
tim@78: returnValue.put(name, inputData);
tim@171: } else {
tim@171: InputData inputData = new DefaultInputData(name, value);
tim@171:
tim@171: returnValue.put(name, inputData);
tim@78: }
tim@57: }
tim@57: }
tim@78: return returnValue.values();
tim@57: }
tim@99:
tim@73: /**
ingo@789: * Call an output target (e.g. chart, wms, etc.)
ingo@789: * @param format XML document which contains some further information about
ingo@789: * the desired output.
ingo@789: * @param outputStream Stream used for writing the output.
ingo@789: * @param context CallContext
ingo@789: * @throws IOException If an error occured while writing the result to the
ingo@789: * output stream.
tim@73: */
tim@73: @Override
tim@117: public void out(Document format, OutputStream outputStream,
tim@117: CallContext context) throws IOException {
tim@68: log.debug("TGNVArtifactBase.out");
tim@68: try {
tim@117:
tim@335: if (current != null && current instanceof OutputState) {
tim@335: ((OutputState) current)
ingo@299: .out(format, this.parseInputData(
ingo@464: format, XPATH_OUTPUT_PARAMS),
ingo@358: outputStream, super.identifier, context);
tim@68: }
tim@335: } catch (StateException e) {
tim@117: log.error(e, e);
tim@89: throw new IOException(e.getMessage());
tim@68: }
tim@68: }
tim@73:
ingo@815:
sascha@481: protected static String readOutputType(Document document) {
ingo@464: String value = XMLUtils.xpathString(
ingo@464: document, XPATH_OUTPUT_NAME, ArtifactNamespaceContext.INSTANCE);
tim@68: return value;
tim@68: }
ingo@464:
ingo@464:
ingo@789: /**
ingo@789: * The the current product.
ingo@789: * @param product New product.
ingo@789: */
ingo@464: public void setProduct(Product product) {
tim@598: this.product = product;
ingo@464: }
sascha@481:
ingo@789: /**
ingo@789: * Call endOfLife of parent class and the current state.
ingo@789: */
ingo@789: @Override
sascha@481: public void endOfLife(Object globalContext) {
sascha@481: super.endOfLife(globalContext);
sascha@481:
sascha@481: if (current != null) {
sascha@481: current.endOfLife(globalContext);
sascha@481: }
sascha@481: }
sascha@778:
tim@598: /**
ingo@789: * Retrieves a map with given InputData which have been inserted into the
ingo@789: * current artifact before the parameterization began.
tim@598: */
tim@598: public Map getPreSettings() {
tim@598: return this.preSettings;
tim@598: }
sascha@778:
tim@598: /**
ingo@789: * Set InputData which are used in later states.
tim@598: */
tim@598: public void setPreSettings(Map preSettings) {
tim@598: this.preSettings = preSettings;
tim@598: if (this.current != null){
tim@598: this.current.setPreSettings(preSettings);
tim@598: }
tim@598: }
tim@52: }
ingo@789: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :