ingo@32: package de.intevation.flys.client.server; ingo@32: ingo@32: import org.w3c.dom.Document; ingo@32: ingo@32: import de.intevation.artifacts.common.ArtifactNamespaceContext; ingo@32: import de.intevation.artifacts.common.utils.ClientProtocolUtils; ingo@32: import de.intevation.artifacts.common.utils.XMLUtils; ingo@32: ingo@32: import de.intevation.artifacts.httpclient.exceptions.ConnectionException; ingo@32: import de.intevation.artifacts.httpclient.http.HttpClient; ingo@32: import de.intevation.artifacts.httpclient.http.HttpClientImpl; ingo@32: import de.intevation.artifacts.httpclient.http.response.DocumentResponseHandler; ingo@32: ingo@32: import de.intevation.flys.client.shared.model.Artifact; ingo@32: import de.intevation.flys.client.shared.model.ArtifactDescription; ingo@32: import de.intevation.flys.client.shared.model.Data; ingo@32: import de.intevation.flys.client.shared.model.DataItem; ingo@32: import de.intevation.flys.client.client.services.StepForwardService; ingo@32: ingo@32: ingo@32: /** ingo@32: * This interface provides a method that bundles the artifact specific ingo@32: * operations FEED and ADVANCE. ingo@32: * ingo@32: * @author Ingo Weinzierl ingo@32: */ ingo@32: public class StepForwardServiceImpl ingo@32: extends AdvanceServiceImpl ingo@32: implements StepForwardService ingo@32: { ingo@32: /** XPath that points to the result text of a feed or advance operation.*/ ingo@32: public static final String XPATH_RESULT = "/art:result/text()"; ingo@32: ingo@32: /** A constant that marks errors.*/ ingo@32: public static final String OPERATION_FAILURE = "FAILED"; ingo@32: ingo@32: ingo@32: /** ingo@32: * This method wraps the artifact operations FEED and ADVANCE. FEED is ingo@32: * always triggerd, ADVANCE only, if there is at least one reachable state. ingo@32: * ingo@32: * @param serverUrl The url of the artifact server. ingo@32: * @param artifact The artifact that needs to be fed. ingo@32: * @param data An array of Data objects that contain the information that ingo@32: * ingo@32: * @return the modified artifact. ingo@32: */ ingo@32: public Artifact go(String serverUrl, Artifact artifact, Data[] data) { ingo@32: Artifact afterFeed = feed(serverUrl, artifact, data); ingo@32: ingo@32: if (afterFeed == null) { ingo@32: System.err.println("StepForwardService.feed() - FAILED"); ingo@32: // XXX Better handling here! ingo@32: return null; ingo@32: } ingo@32: ingo@32: ArtifactDescription desc = afterFeed.getArtifactDescription(); ingo@32: String[] reachable = desc.getReachableStates(); ingo@32: ingo@32: if (reachable == null || reachable.length == 0) { ingo@32: System.out.println("Did not find any reachable state."); ingo@32: return afterFeed; ingo@32: } ingo@32: ingo@32: // We use the first reachable state as default target, maybe we need to ingo@32: // change this later. ingo@32: return advance(serverUrl, afterFeed, reachable[0]); ingo@32: } ingo@32: ingo@32: ingo@32: /** ingo@32: * This method triggers the FEED operation. ingo@32: * ingo@32: * @param serverUrl The url of the artifact server. ingo@32: * @param artifact The artifact that needs to be fed. ingo@32: * @param data An array of Data objects that contain the information that ingo@32: * are used for the FEED operation. ingo@32: * ingo@32: * @return a new artifact parsed from the description of FEED. ingo@32: */ ingo@32: protected Artifact feed(String serverUrl, Artifact artifact, Data[] data) { ingo@32: Document feed = ClientProtocolUtils.newFeedDocument( ingo@32: artifact.getUuid(), ingo@32: artifact.getHash(), ingo@32: createKVP(data)); ingo@32: ingo@32: HttpClient client = new HttpClientImpl(serverUrl); ingo@32: ingo@32: try { ingo@32: Document description = (Document) client.feed( ingo@32: new de.intevation.artifacts.httpclient.objects.Artifact( ingo@32: artifact.getUuid(), ingo@32: artifact.getHash()), ingo@32: feed, ingo@32: new DocumentResponseHandler()); ingo@32: ingo@32: if (description == null) { ingo@32: System.err.println("StepForwardService.feed() - FAILED"); ingo@32: return artifact; ingo@32: } ingo@32: ingo@32: String result = XMLUtils.xpathString( ingo@32: description, ingo@32: XPATH_RESULT, ingo@32: ArtifactNamespaceContext.INSTANCE); ingo@32: ingo@32: if (result == null || !result.equals(OPERATION_FAILURE)) { ingo@32: System.out.println("StepForwardService.feed() - SUCCESS"); ingo@32: return (Artifact) new FLYSArtifactCreator().create(description); ingo@32: } ingo@32: } ingo@32: catch (ConnectionException ce) { ingo@32: System.err.println(ce.getLocalizedMessage()); ingo@32: } ingo@32: ingo@32: System.err.println("StepForwardService.feed() - FAILED"); ingo@32: ingo@32: return artifact; ingo@32: } ingo@32: ingo@32: ingo@32: /** ingo@32: * This method creates an array of key/value pairs from an array of Data ingo@32: * objects. The string array is used as parameter for the feed() operation. ingo@32: * ingo@32: * @param data The data that should be transformed into the string array. ingo@32: * ingo@32: * @return a string array that contains key/value pairs. ingo@32: */ ingo@32: protected String[][] createKVP(Data[] data) { ingo@32: String[][] kvp = new String[data.length][]; ingo@32: ingo@32: int i = 0; ingo@32: ingo@32: for (Data d: data) { ingo@32: DataItem[] items = d.getItems(); ingo@32: String key = d.getLabel(); ingo@32: String value = items[0].getStringValue(); ingo@32: ingo@32: kvp[i++] = new String[] { key, value }; ingo@32: } ingo@32: ingo@32: return kvp; ingo@32: } ingo@32: } ingo@32: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :