tim@52: /** tim@52: * tim@52: */ tim@52: package de.intevation.gnv.artifacts; tim@52: tim@73: import java.io.IOException; tim@73: import java.io.OutputStream; tim@337: import java.util.ArrayList; tim@56: import java.util.Collection; tim@52: import java.util.HashMap; tim@54: import java.util.Iterator; tim@52: import java.util.Map; tim@52: tim@71: import javax.xml.xpath.XPathConstants; tim@71: tim@52: import org.apache.log4j.Logger; 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: import de.intevation.artifactdatabase.Config; tim@52: import de.intevation.artifactdatabase.DefaultArtifact; tim@71: import de.intevation.artifactdatabase.XMLUtils; tim@70: import de.intevation.artifacts.ArtifactFactory; tim@70: import de.intevation.artifacts.ArtifactNamespaceContext; tim@73: import de.intevation.artifacts.CallContext; tim@117: import de.intevation.artifacts.CallMeta; tim@52: import de.intevation.gnv.artifacts.context.GNVArtifactContext; tim@335: import de.intevation.gnv.state.DefaultInputData; tim@335: import de.intevation.gnv.state.InputData; tim@335: import de.intevation.gnv.state.InputValue; tim@335: import de.intevation.gnv.state.OutputMode; tim@335: import de.intevation.gnv.state.OutputState; tim@335: import de.intevation.gnv.state.State; tim@335: import de.intevation.gnv.state.StateFactory; tim@335: import de.intevation.gnv.state.exception.StateException; tim@337: import de.intevation.gnv.transition.Transition; tim@337: import de.intevation.gnv.transition.TransitionFactory; tim@71: import de.intevation.gnv.utils.ArtifactXMLUtilities; tim@52: tim@52: /** tim@52: * @author Tim Englich tim@171: * tim@52: */ tim@52: public abstract class GNVArtifactBase extends DefaultArtifact { 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: 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; tim@337: tim@337: /** tim@337: * The Transitions which can switch between the different States. tim@337: */ tim@337: protected Collection transitions = null; tim@52: tim@54: /** tim@54: * The Name of the Artifact tim@54: */ tim@52: protected String name = null; tim@171: tim@71: private ArtifactXMLUtilities xmlUtilities = new ArtifactXMLUtilities(); tim@171: tim@52: /** tim@52: * Constructor tim@52: */ tim@52: public GNVArtifactBase() { tim@52: super(); tim@52: } tim@171: tim@58: /** tim@171: * @see de.intevation.artifactdatabase.DefaultArtifact#advance(org.w3c.dom.Document, tim@171: * de.intevation.artifacts.CallContext) tim@58: */ tim@58: @Override tim@73: public Document advance(Document target, CallContext context) { tim@89: log.debug("GNVArtifactBase.advance"); tim@71: Document result = XMLUtils.newDocument(); tim@88: try { tim@171: if (this.current != null) { tim@335: String stateName = this.readStateName(target); tim@335: log.debug("Statename: " + stateName); tim@337: if (this.isStateCurrentlyReachable(stateName)) { tim@220: try { tim@335: State nextStep = this.states tim@335: .get(stateName); tim@220: // 1.Ergebnisse Berechnen tim@220: this.current.advance(super.identifier, context.getMeta()); tim@220: // 2. Ergebnisse Übergeben tim@220: nextStep.putInputData(this.current.getInputData(), tim@220: super.identifier); tim@220: // 3. Umschalten auf neue Transistion tim@220: this.current = nextStep; tim@325: tim@325: // 4. Initialisieren des nächsten Schrittes == Laden der Daten tim@325: this.current.initialize(super.identifier, context.getMeta()); tim@325: tim@171: result = new ArtifactXMLUtilities() tim@220: .createSuccessReport("Advance success", tim@220: XMLUtils.newDocument()); tim@335: } catch (StateException e) { tim@220: log.error(e, e); tim@220: result = new ArtifactXMLUtilities() tim@220: .createExceptionReport(e tim@220: .getLocalizedMessage(), XMLUtils tim@171: .newDocument()); tim@58: } tim@171: } else { tim@88: String msg = "Transitionsübergang wird nicht unterstützt."; tim@88: log.error(msg); tim@171: result = new ArtifactXMLUtilities().createExceptionReport( tim@171: msg, XMLUtils.newDocument()); tim@58: } tim@171: } else { tim@335: String msg = "Kein State aktiviert."; tim@88: log.error(msg); tim@171: result = new ArtifactXMLUtilities().createExceptionReport(msg, tim@171: XMLUtils.newDocument()); tim@58: } tim@88: } catch (Exception e) { tim@171: log.error(e, e); tim@171: result = new ArtifactXMLUtilities().createExceptionReport(e tim@171: .getLocalizedMessage(), XMLUtils.newDocument()); tim@58: } tim@58: return result; tim@58: } tim@325: tim@325: tim@337: private boolean isStateCurrentlyReachable(String stateid){ tim@337: log.debug("GNVArtifactBase.isStateCurrentlyReachable "+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: } tim@337: tim@325: public Document initialize (CallContext context) { tim@325: Document result = XMLUtils.newDocument(); tim@325: try { tim@325: this.current.initialize(super.identifier, context.getMeta()); 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) { tim@171: String returnValue = Config.getStringXPath(document, tim@171: "action/target/@name"); 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@52: log.debug(xpathQuery); 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) { tim@194: Collection inputData = this.parseInputData(target, tim@194: "/action/data/input"); 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: 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(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) { 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(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@325: tim@325: tim@171: tim@222: protected Document createDescibeOutput(CallMeta callMeta, String uuid, boolean incudeUI) { tim@54: log.debug("GNVArtifactBase.createDescibeOutput"); tim@71: Document document = XMLUtils.newDocument(); tim@171: Element rootNode = this.createRootNode(document); tim@54: this.createHeader(rootNode, document, "describe"); tim@59: this.createOutputs(rootNode, document); tim@54: this.createCurrentState(rootNode, document); tim@54: this.createReachableStates(rootNode, document); tim@54: this.createModel(rootNode, document); tim@222: if (incudeUI){ tim@222: this.createUserInterface(rootNode, document, callMeta, uuid); tim@222: } tim@54: return document; tim@54: } tim@222: tim@222: protected boolean getIncludeUIFromDocument(Document document){ tim@222: String value = Config.getStringXPath(document, "action/include-ui"); 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: tim@171: protected Element createRootNode(Document document) { tim@171: Element rootNode = xmlUtilities.createArtifactElement(document, tim@171: "result"); tim@54: document.appendChild(rootNode); tim@54: return rootNode; tim@54: } tim@171: tim@171: protected void createHeader(Element parent, Document document, tim@171: String documentType) { tim@171: Element typeNode = xmlUtilities.createArtifactElement(document, "type"); tim@54: typeNode.setAttribute("name", documentType); tim@54: parent.appendChild(typeNode); tim@171: tim@171: Element uuidNode = xmlUtilities.createArtifactElement(document, "uuid"); tim@54: uuidNode.setAttribute("value", super.identifier); tim@54: parent.appendChild(uuidNode); tim@171: tim@171: Element hashNode = xmlUtilities.createArtifactElement(document, "hash"); tim@54: hashNode.setAttribute("value", this.hash()); tim@54: parent.appendChild(hashNode); tim@89: } tim@54: tim@171: protected void createReachableStates(Element parent, Document document) { tim@171: Element stateNode = xmlUtilities.createArtifactElement(document, tim@171: "reachable-states"); tim@171: if (this.current != null) { tim@337: Iterator 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)){ tim@337: Element currentNode = xmlUtilities.createArtifactElement( tim@337: document, "state"); tim@337: currentNode.setAttribute("name", tmpTransition.getTo()); tim@337: log.debug("Reachable State: " + tmpTransition.getTo()); tim@337: currentNode.setAttribute("description", tim@337: this.states.get(tmpTransition.getTo()) tim@337: .getDescription()); tim@337: stateNode.appendChild(currentNode); tim@337: } tim@54: } tim@54: } tim@54: parent.appendChild(stateNode); tim@54: } tim@171: tim@171: protected void createCurrentState(Element parent, Document document) { tim@171: Element stateNode = xmlUtilities.createArtifactElement(document, tim@171: "state"); tim@54: stateNode.setAttribute("name", this.current.getID()); tim@54: stateNode.setAttribute("description", this.current.getDescription()); tim@54: parent.appendChild(stateNode); tim@54: } tim@171: tim@171: protected void createModel(Element parent, Document document) { tim@171: Element modelNode = xmlUtilities.createArtifactElement(document, tim@171: "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(); tim@171: Element inputNode = xmlUtilities.createArtifactElement( tim@171: document, "input"); tim@56: inputNode.setAttribute("name", inputValue.getName()); tim@56: inputNode.setAttribute("type", inputValue.getType()); tim@56: modelNode.appendChild(inputNode); tim@56: } tim@56: } tim@56: } tim@54: parent.appendChild(modelNode); tim@54: } tim@171: tim@171: protected void createUserInterface(Element parent, Document document, tim@207: CallMeta callMeta, String uuid) { tim@171: Element uiNode = xmlUtilities.createArtifactElement(document, "ui"); tim@171: tim@171: if (this.current != null) { tim@207: this.current.describe(document, uiNode, callMeta, uuid); tim@61: } tim@171: tim@54: parent.appendChild(uiNode); tim@54: } tim@171: tim@171: protected void createOutputs(Element parent, Document document) { tim@64: log.debug("GNVArtifactBase.createOutputs"); tim@171: Element outputsNode = xmlUtilities.createArtifactElement(document, tim@171: "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()); tim@171: Element outputModeNode = xmlUtilities tim@171: .createArtifactElement(document, "output"); tim@64: outputModeNode.setAttribute("name", outputMode.getName()); tim@171: outputModeNode.setAttribute("description", outputMode tim@171: .getDescription()); tim@171: outputModeNode.setAttribute("mime-type", outputMode tim@171: .getMimeType()); tim@64: outputsNode.appendChild(outputModeNode); tim@171: tim@171: Collection inputParameters = outputMode tim@171: .getInputParameters(); tim@171: if (inputParameters != null) { tim@171: Element inputParametersNode = xmlUtilities tim@171: .createArtifactElement(document, "parameter"); tim@91: outputModeNode.appendChild(inputParametersNode); tim@91: Iterator it2 = inputParameters.iterator(); tim@171: while (it2.hasNext()) { tim@91: InputValue inputValue = it2.next(); tim@171: Element inputParameterNode = xmlUtilities tim@171: .createArtifactElement(document, tim@171: "parameter"); tim@91: inputParametersNode.appendChild(inputParameterNode); tim@171: inputParameterNode.setAttribute("name", inputValue tim@171: .getName()); tim@171: inputParameterNode.setAttribute("type", inputValue tim@171: .getType()); tim@171: inputParameterNode.setAttribute("value", inputValue tim@171: .getDefaultValue()); 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 parseInputData(Document document, tim@171: String xPath) { tim@57: log.debug("GNVArtifactBase.parseInputData"); tim@171: HashMap returnValue = null; tim@171: tim@71: log.debug(new ArtifactXMLUtilities().writeDocument2String(document)); tim@171: tim@171: NodeList inputElemets = (NodeList) XMLUtils.xpath(document, xPath, tim@171: XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE);// Config.getNodeSetXPath(document, tim@171: // ""); tim@171: if (inputElemets != null) { tim@171: returnValue = new HashMap(inputElemets tim@171: .getLength()); 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( tim@117: format, "/action/out/params/input"), tim@208: outputStream, super.identifier, context.getMeta()); 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: tim@171: protected String readOutputType(Document document) { tim@171: String value = Config.getStringXPath(document, "action/out/@name"); tim@68: return value; tim@68: } tim@52: }