tim@52: /**
tim@52:  *
tim@52:  */
tim@52: package de.intevation.gnv.artifacts;
tim@52: 
sascha@479: import de.intevation.artifactdatabase.Config;
sascha@479: import de.intevation.artifactdatabase.ProxyArtifact;
sascha@479: import de.intevation.artifactdatabase.XMLUtils;
sascha@479: 
sascha@479: import de.intevation.artifacts.Artifact;
sascha@479: import de.intevation.artifacts.ArtifactDatabase;
sascha@479: import de.intevation.artifacts.ArtifactFactory;
sascha@479: import de.intevation.artifacts.ArtifactNamespaceContext;
sascha@479: import de.intevation.artifacts.CallContext;
sascha@479: import de.intevation.artifacts.CallMeta;
sascha@479: 
sascha@479: import de.intevation.gnv.artifacts.cache.CacheFactory;
sascha@479: 
sascha@479: import de.intevation.gnv.artifacts.context.GNVArtifactContext;
sascha@479: 
sascha@479: import de.intevation.gnv.artifacts.fis.product.Product;
sascha@479: 
sascha@479: import de.intevation.gnv.artifacts.ressource.RessourceFactory;
sascha@479: 
sascha@479: import de.intevation.gnv.state.DefaultInputData;
sascha@479: import de.intevation.gnv.state.InputData;
sascha@479: import de.intevation.gnv.state.InputValue;
sascha@479: import de.intevation.gnv.state.OutputMode;
sascha@479: import de.intevation.gnv.state.OutputState;
sascha@479: import de.intevation.gnv.state.State;
sascha@479: import de.intevation.gnv.state.StateBase;
sascha@479: import de.intevation.gnv.state.StateFactory;
sascha@479: 
sascha@479: import de.intevation.gnv.state.exception.StateException;
sascha@479: 
sascha@479: import de.intevation.gnv.transition.Transition;
sascha@479: import de.intevation.gnv.transition.TransitionFactory;
sascha@479: 
sascha@479: import de.intevation.gnv.utils.ArtifactXMLUtilities;
sascha@479: 
tim@73: import java.io.IOException;
tim@73: import java.io.OutputStream;
sascha@479: 
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;
tim@52: import java.util.Map;
tim@52: 
tim@71: import javax.xml.xpath.XPathConstants;
tim@71: 
ingo@473: import net.sf.ehcache.Cache;
ingo@473: 
tim@52: import org.apache.log4j.Logger;
sascha@479: 
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: /**
sascha@481:  * @author Tim Englich         (tim.englich@intevation.de)
sascha@481:  * @author Ingo Weinzierl      (ingo.weinzierl@intevation.de)
sascha@481:  * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
tim@52:  */
ingo@488: public abstract class GNVArtifactBase extends GNVDefaultArtifact {
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: 
ingo@464:     public static final String XPATH_OUTPUT_NAME = "/art:action/art:out/@name"; 
ingo@464: 
ingo@464:     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<String, State> states = null;
tim@337:     
tim@337:     /**
tim@337:      * The Transitions which can switch between the different States.
tim@337:      */
tim@337:     protected Collection<Transition> transitions = null;
tim@52: 
ingo@464: 
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@52:      * Constructor
tim@52:      */
tim@52:     public GNVArtifactBase() {
tim@52:         super();
tim@52:     }
tim@171: 
ingo@470: 
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@470:             log.debug("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@470:                 next = states.get(targetState);
ingo@470: 
ingo@470:                 // 2. Transfer Results
ingo@470:                 next.putInputData(current.getInputData(), identifier);
ingo@470:                 next.setParent(current);
ingo@470: 
sascha@481:                 if (current != null) {
sascha@481:                     current.endOfLife(context.globalContext());
sascha@481:                 }
sascha@481: 
ingo@470:                 // 3. Switch to next State
ingo@470:                 current = next;
ingo@470: 
ingo@470:                 // 4. Initialize next Step
ingo@493:                 current.initialize(identifier, context);
ingo@470: 
ingo@470:                 result = createReport(
ingo@470:                     result, "result", "success", "Advance success"
ingo@470:                 );
tim@58:             }
ingo@470: 
ingo@470:             // step backward
ingo@470:             else if((next = getPreviousState(current, targetState)) != null) {
ingo@473: 
ingo@473:                 // reset input data
ingo@470:                 resetFutureStates(current, targetState);
ingo@473: 
ingo@473:                 // remove data from future states from cache
ingo@473:                 resetDescribeData(current, identifier, targetState);
ingo@478: 
sascha@481:                 if (current != null) {
sascha@481:                     current.endOfLife(context.globalContext());
sascha@481:                 }
sascha@481: 
ingo@470:                 current = next;
ingo@470: 
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: 
ingo@478:                 Artifact select = fac.createArtifact(identifier, context);
ingo@470:                 context.putContextValue(ProxyArtifact.REPLACE_PROXY, select);
ingo@470: 
ingo@478:                 resetDescribeData(current, identifier, INITIAL_STATE);
ingo@478: 
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: 
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@470:     protected State getPreviousState(State current, String name) {
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@470:             return getPreviousState(current.getParent(), name);
ingo@470:         }
ingo@470:     }
ingo@470: 
ingo@473:     public void resetDescribeData(State state, String uuid, String target) {
ingo@473:         CacheFactory factory = CacheFactory.getInstance();
ingo@473:         
ingo@473:         if (factory.isInitialized()) {
ingo@473:             Cache  cache = factory.getCache();
ingo@473:             String key   = uuid + StateBase.DESCRIBEDATAKEY;
ingo@473: 
ingo@473:             net.sf.ehcache.Element value = cache.get(key);
ingo@473:             if (value == null)
ingo@473:                 return;
ingo@473: 
ingo@473:             List data = (List) value.getObjectValue();
ingo@473:             while(!target.equals(state.getID())) {
ingo@473:                 data.remove(data.size()-1);
ingo@473:                 state = state.getParent();
ingo@478: 
ingo@478:                 if (state == null)
ingo@478:                     break;
ingo@473:             }
ingo@473: 
ingo@473:             cache.put(new net.sf.ehcache.Element(key, data));
ingo@473:         }
ingo@473:     }
ingo@473: 
ingo@470: 
ingo@470:     protected void resetFutureStates(State current, String name) {
ingo@470:         if (current == null) {
ingo@470:             return;
ingo@470:         }
ingo@470: 
ingo@470:         if (current.getID().equals(name)) {
ingo@470:             return;
ingo@470:         }
ingo@470:         else {
ingo@470:             current.reset(identifier);
ingo@470:             resetFutureStates(current.getParent(), name);
ingo@470:         }
ingo@470:     }
ingo@470: 
ingo@470: 
tim@337:     private boolean isStateCurrentlyReachable(String stateid){
tim@337:         Iterator<Transition> 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:     }
tim@337:     
tim@325:     public Document initialize (CallContext context) {
tim@325:         Document result = XMLUtils.newDocument();
tim@325:         try {
ingo@493:             this.current.initialize(super.identifier, context);
tim@325:             result = new ArtifactXMLUtilities()
tim@325:             .createSuccessReport("Initialize success",
tim@325:                     XMLUtils.newDocument());
tim@335:         } catch (StateException e) {
tim@325:             log.error(e,e);
tim@325:             result = new ArtifactXMLUtilities().createExceptionReport(e
tim@325:                     .getLocalizedMessage(), XMLUtils.newDocument());
tim@325:         }
tim@325:         return result;
tim@325:     }
tim@58: 
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: 
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);
tim@204:         
tim@204:         Element configurationNode = (Element)Config.getNodeXPath(document, xpathQuery);
tim@204:         
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:         }
tim@204:         
tim@204:         return configurationNode;
tim@204:     }
tim@171: 
tim@52:     /**
tim@171:      * @see de.intevation.artifactdatabase.DefaultArtifact#feed(org.w3c.dom.Document,
tim@171:      *      de.intevation.artifacts.CallContext)
tim@57:      */
tim@57:     @Override
tim@73:     public Document feed(Document target, CallContext context) {
tim@89:         log.debug("GNVArtifactBase.feed");
tim@71:         Document result = XMLUtils.newDocument();
tim@57:         try {
tim@171:             if (this.current != null) {
ingo@464:                 Collection<InputData> inputData = this.parseInputData(
ingo@464:                     target,
ingo@464:                     XPATH_INPUT_DATA);
ingo@464: 
tim@194:                 if (!inputData.isEmpty()){
tim@208:                     this.current.putInputData(inputData, super.identifier);
tim@194:                     result = new ArtifactXMLUtilities().createSuccessReport(
tim@194:                             "Feed success", XMLUtils.newDocument());
tim@194:                 }else{
tim@194:                     String msg = "No Inputdata given. Please select at least one Entry.";
tim@194:                     log.warn(msg);
tim@194:                     result = new ArtifactXMLUtilities().createExceptionReport(msg,
tim@194:                             XMLUtils.newDocument());
tim@194:                 }
tim@171:             } else {
tim@335:                 String msg = "No State instantiated";
tim@89:                 log.warn(msg);
tim@171:                 result = new ArtifactXMLUtilities().createExceptionReport(msg,
tim@171:                         XMLUtils.newDocument());
tim@57:             }
tim@335:         } catch (StateException e) {
tim@171:             log.error(e, e);
tim@171:             result = new ArtifactXMLUtilities().createExceptionReport(e
tim@171:                     .getLocalizedMessage(), XMLUtils.newDocument());
tim@57:         }
tim@57:         return result;
tim@57:     }
tim@171: 
ingo@464: 
ingo@464:     /**
ingo@464:      * @see de.intevation.artifactdatabase.DefaultArtifact#describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)
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:         // insert node for rendering product field
ingo@464:         Element staticNode = (Element) XMLUtils.xpath(
ingo@464:             document,
ingo@464:             XPATH_STATIC_NODE,
ingo@464:             XPathConstants.NODE,
ingo@464:             ArtifactNamespaceContext.INSTANCE
ingo@464:         );
ingo@464: 
ingo@464:         XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator(
ingo@464:             document,
ingo@464:             XMLUtils.XFORM_URL,
ingo@464:             XMLUtils.XFORM_PREFIX
ingo@464:         );
ingo@464: 
ingo@478:         XMLUtils.ElementCreator artCreator = new XMLUtils.ElementCreator(
ingo@478:             document,
ingo@478:             ArtifactNamespaceContext.NAMESPACE_URI,
ingo@478:             ArtifactNamespaceContext.NAMESPACE_PREFIX
ingo@478:         );
ingo@478: 
ingo@464:         return document;
ingo@464:     }
ingo@464: 
tim@57:     /**
tim@171:      * @see de.intevation.artifactdatabase.DefaultArtifact#setup(java.lang.String,
tim@171:      *      java.lang.Object)
tim@52:      */
tim@52:     @Override
tim@70:     public void setup(String identifier, ArtifactFactory factory, Object context) {
tim@52:         log.debug("GNVArtifactBase.setup");
tim@70:         super.setup(identifier, factory, context);
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);
tim@204:                         
tim@335:             NodeList stateList = Config.getNodeSetXPath(artifactNode,
tim@335:                     "states/state");
tim@335:             this.states = new HashMap<String, State>(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:             }
tim@337:             
tim@337:             NodeList transitionList = Config.getNodeSetXPath(artifactNode,
tim@337:             "states/transition");
tim@337:             this.transitions = new ArrayList<Transition>(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@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:     }
tim@222:     
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@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@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@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@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<Transition> transitions = this.transitions.iterator();
tim@337:             while (transitions.hasNext()) {
tim@337:                 Transition tmpTransition = transitions.next();
tim@337:                 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@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@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@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<InputValue> inputValues = this.current
tim@171:                     .getRequiredInputValues();
tim@171:             if (inputValues != null) {
tim@56:                 Iterator<InputValue> 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@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@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<OutputMode> outputModes = ((OutputState) this.current)
tim@171:                     .getOutputModes();
tim@171:             if (outputModes != null) {
tim@64:                 Iterator<OutputMode> 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<InputValue> 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<InputValue> 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:                     }
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: 
tim@171:     protected Collection<InputData> parseInputData(Document document,
tim@171:                                                    String xPath) {
tim@171:         HashMap<String, InputData> 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<String, InputData>();
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:     /**
tim@117:      * @see de.intevation.artifactdatabase.DefaultArtifact#out(org.w3c.dom.Document,
tim@117:      *      java.io.OutputStream, de.intevation.artifacts.CallContext)
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: 
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@464:     public void setProduct(Product product) {
ingo@464:         this.product = product;        
ingo@464:     }
sascha@481: 
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:     }
tim@52: }
ingo@464: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: