ingo@1022: /*
ingo@1022: * Copyright (c) 2010 by Intevation GmbH
ingo@1022: *
ingo@1022: * This program is free software under the LGPL (>=v2.1)
ingo@1022: * Read the file LGPL.txt coming with the software for details
ingo@1022: * or visit http://www.gnu.org/licenses/ if it does not exist.
ingo@1022: */
ingo@1022:
tim@2: package de.intevation.gnv.artifactdatabase.client;
tim@2:
tim@1005: import java.io.IOException;
tim@1005: import java.io.InputStream;
tim@1005: import java.io.InputStreamReader;
tim@1005: import java.io.OutputStream;
tim@1005: import java.io.OutputStreamWriter;
tim@1005: import java.util.ArrayList;
tim@1005: import java.util.Collection;
tim@1005: import java.util.HashMap;
tim@1005: import java.util.Iterator;
tim@1005: import java.util.List;
tim@1005: import java.util.Locale;
tim@1005: import java.util.Map;
tim@1005:
tim@1005: import org.apache.log4j.Logger;
tim@1005: import org.restlet.Client;
ingo@1027: import org.restlet.Request;
ingo@1027: import org.restlet.Response;
tim@1005: import org.restlet.data.ClientInfo;
tim@1005: import org.restlet.data.Language;
tim@1005: import org.restlet.data.Method;
tim@1005: import org.restlet.data.Preference;
tim@1005: import org.restlet.data.Protocol;
tim@1005: import org.restlet.representation.Representation;
tim@1005: import org.restlet.representation.StringRepresentation;
tim@1005: import org.w3c.dom.Document;
tim@1005: import org.w3c.dom.Element;
tim@1005: import org.w3c.dom.Node;
tim@1005: import org.w3c.dom.NodeList;
tim@1005:
tim@2: import de.intevation.gnv.artifactdatabase.client.exception.ArtifactDatabaseClientException;
ingo@665: import de.intevation.gnv.artifactdatabase.client.exception.ArtifactDatabaseInputException;
tim@7: import de.intevation.gnv.artifactdatabase.objects.Artifact;
tim@9: import de.intevation.gnv.artifactdatabase.objects.ArtifactDescription;
tim@2: import de.intevation.gnv.artifactdatabase.objects.ArtifactFactory;
tim@2: import de.intevation.gnv.artifactdatabase.objects.ArtifactObject;
tim@164: import de.intevation.gnv.artifactdatabase.objects.ArtifactStatisticsSet;
tim@32: import de.intevation.gnv.artifactdatabase.objects.DefaultArtifactStatisticValue;
tim@164: import de.intevation.gnv.artifactdatabase.objects.DefaultArtifactStatisticsSet;
ingo@573: import de.intevation.gnv.artifactdatabase.objects.DefaultExportMode;
tim@30: import de.intevation.gnv.artifactdatabase.objects.DefaultOutputMode;
tim@30: import de.intevation.gnv.artifactdatabase.objects.DefaultOutputParameter;
ingo@573: import de.intevation.gnv.artifactdatabase.objects.ExportMode;
tim@12: import de.intevation.gnv.artifactdatabase.objects.InputParameter;
tim@30: import de.intevation.gnv.artifactdatabase.objects.OutputMode;
tim@30: import de.intevation.gnv.artifactdatabase.objects.OutputParameter;
tim@558: import de.intevation.gnv.artifactdatabase.objects.ParametrizedArtifactFactory;
tim@558: import de.intevation.gnv.artifactdatabase.objects.ParametrizedArtifactObject;
tim@558: import de.intevation.gnv.artifactdatabase.objects.map.Layer;
tim@402: import de.intevation.gnv.artifactdatabase.objects.map.MapService;
tim@23: import de.intevation.gnv.propertiesreader.PropertiesReader;
tim@23: import de.intevation.gnv.propertiesreader.PropertiesReaderFactory;
tim@2: import de.intevation.gnv.util.XMLUtils;
tim@2:
tim@2: /**
ingo@690: * The default implementation of ArtifactDatabaseClient
which
ingo@690: * implements methods to communicate via HTTP protocol with the artifact server.
sascha@699: *
sascha@684: * @author Tim Englich
sascha@684: * @author Ingo Weinzierl
tim@2: */
tim@2: public class DefaultArtifactDatabaseClient implements ArtifactDatabaseClient {
tim@2: /**
tim@7: * The URI of the namespace of the artifacts.
tim@7: */
tim@7: public final static String NAMESPACE_URI = "http://www.intevation.de/2009/artifacts";
tim@36:
tim@7: /**
tim@7: * The XML prefix for the artifacts namespace.
tim@7: */
tim@7: public final static String NAMESPACE_PREFIX = "art";
tim@7:
tim@7: /**
ingo@665: * Xpath expression to get general exception messages related to server
ingo@665: * errors.
ingo@665: */
ingo@665: public static final String EXCEPTION_GENERAL =
ingo@665: "/art:exceptionreport/art:exception/text()";
ingo@665:
ingo@665: /**
ingo@665: * Xpath expression to get exception messages related to invalid user input.
ingo@665: */
ingo@665: public static final String EXCEPTION_USER_INPUT =
ingo@665: "/art:exceptionreport/art:exception/art:input/text()";
ingo@665:
ingo@665: /**
tim@2: * the logger, used to log exceptions and additonaly information
tim@2: */
tim@36: private static Logger log = Logger
tim@36: .getLogger(DefaultArtifactDatabaseClient.class);
tim@36:
tim@25: /**
tim@25: * The Databases which could be used
tim@25: */
tim@25: private static Collection artifactDatabases = null;
tim@36:
tim@25: /**
tim@25: * Is the Class initialized?
tim@25: */
tim@2: private static boolean initialized = false;
tim@36:
tim@2: /**
tim@40: * Request locale
tim@40: */
tim@40: private Locale locale;
tim@40:
tim@40:
tim@40: /**
tim@2: * Constructor
tim@2: */
tim@2: public DefaultArtifactDatabaseClient() {
sascha@681:
tim@2: }
tim@2:
tim@36: public Collection getArtifactFactories()
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@2: Collection resultValues = null;
tim@36: if (!initialized) {
tim@2: this.initialize();
tim@2: }
tim@2: try {
tim@2: log.debug("DefaultArtifactDatabaseClient.getArtifactFactories");
tim@25: Iterator it = artifactDatabases.iterator();
tim@36: while (it.hasNext()) {
tim@2: String server = it.next();
tim@36: String url = server + "/factories";
tim@9: Document document = this.doGetRequest(url);
tim@36: if (resultValues == null) {
tim@565: resultValues = this.getArtifactFactories(document, server,null);
tim@36: } else {
tim@36: resultValues.addAll(this.getArtifactFactories(document,
tim@565: server,null));
tim@2: }
tim@2: }
tim@2: } catch (IOException e) {
tim@36: log.error(e, e);
tim@47: throw new ArtifactDatabaseClientException(e);
tim@2: }
tim@2: return resultValues;
tim@2: }
tim@2:
ingo@690:
ingo@690: /**
ingo@690: * Returns a collection of artifact factories retrieved by server.
sascha@699: *
ingo@690: * @param document
ingo@690: * @param server
ingo@690: * @param geometry
ingo@690: * @return a collection of factories.
ingo@690: */
tim@36: private Collection getArtifactFactories(Document document,
tim@565: String server,
tim@565: String geometry) {
ingo@690: NodeList artifactFactories = XMLUtils.getNodeSetXPath(document,
ingo@389: "/art:result/art:factories/art:factory");
tim@36: Collection resultValues = new ArrayList(
tim@36: artifactFactories.getLength());
tim@36: if (artifactFactories != null) {
tim@36: for (int i = 0; i < artifactFactories.getLength(); i++) {
tim@36: Node artifactFactoryNode = artifactFactories.item(i);
ingo@690: String name = XMLUtils.getStringXPath(artifactFactoryNode,
ingo@389: "@art:name");
ingo@690: String description = XMLUtils.getStringXPath(
ingo@389: artifactFactoryNode, "@art:description");
sascha@681:
ingo@690: NodeList parameterNodeList = XMLUtils.getNodeSetXPath(
tim@558: artifactFactoryNode,
tim@558: "art:parameter");
sascha@681:
sascha@681: if ((parameterNodeList != null &&
sascha@681: parameterNodeList.getLength() > 0) ||
tim@565: geometry != null){
sascha@681: Collection parameters =
tim@558: new ArrayList(parameterNodeList.getLength());
tim@558: for (int j = 0; j < parameterNodeList.getLength(); j++){
tim@558: Element parameterNode = (Element)parameterNodeList.item(j);
tim@558: parameters.add(parameterNode.getAttribute("id"));
tim@558: }
sascha@681: ParametrizedArtifactObject pao =
sascha@681: new ParametrizedArtifactFactory(name,
tim@558: description,
tim@558: server);
tim@558: pao.addParameters("parameter", parameters);
tim@558: resultValues.add(pao);
tim@565: if (geometry != null){
tim@565: Collection geometryList = new ArrayList(1);
tim@565: geometryList.add(geometry);
tim@565: pao.addParameters("geometry",geometryList);
tim@565: }
tim@558: }else{
tim@558: ArtifactObject artifactFactory = new ArtifactFactory(name,
tim@558: description,
tim@558: server);
tim@558: resultValues.add(artifactFactory);
tim@558: }
tim@2: }
tim@2: }
ingo@389: log.debug("Artifact Factories: " + resultValues.size());
tim@2: return resultValues;
tim@2: }
tim@36:
ingo@690:
ingo@665: private Document doGetRequest(String requestUrl)
ingo@665: throws IOException, ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@13: return this.doGetRequest(requestUrl, null);
tim@13: }
tim@36:
ingo@690:
tim@36: private Document doGetRequest(String requestUrl, Document requestBody)
ingo@665: throws IOException, ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@25: XMLUtils xmlUtils = new XMLUtils();
tim@13: Representation output = doGetRequestInternal(requestUrl, requestBody);
ingo@690: Document document = XMLUtils.readDocument(output.getStream());
tim@25: this.check4ExceptionReport(document);
tim@25: return document;
tim@13: }
tim@13:
tim@40: protected Request initialize(Request request) {
tim@40: return initialize(request, locale);
tim@40: }
tim@40:
ingo@690: /**
ingo@690: * Initialize the ClientInfo
object of request with the
ingo@690: * given locale.
ingo@690: *
ingo@690: * @param request The request object.
ingo@690: * @param locale The locale.
ingo@690: * @return the prepared request object.
ingo@690: */
tim@40: protected Request initialize(Request request, Locale locale) {
tim@40: if (locale != null) {
tim@40: ClientInfo clientInfo = request.getClientInfo();
tim@40: String lang = locale.getLanguage();
tim@40: Language language = new Language(lang);
tim@40: List> acceptedLanguages =
tim@40: new ArrayList>(2);
tim@40: acceptedLanguages.add(new Preference(language, 1.0f));
tim@40: acceptedLanguages.add(new Preference(Language.ALL, 0.5f));
tim@40: clientInfo.setAcceptedLanguages(acceptedLanguages);
tim@40: }
tim@40: return request;
tim@40: }
tim@40:
ingo@690:
tim@13: private Representation doGetRequestInternal(String requestUrl,
tim@47: Document requestBody) throws IOException {
tim@13: Client client = new Client(Protocol.HTTP);
tim@40: Request request = initialize(new Request(Method.GET, requestUrl));
tim@36: if (requestBody != null) {
ingo@690: String documentBody = XMLUtils
tim@36: .writeDocument2String(requestBody);
tim@36: Representation representation = new StringRepresentation(
tim@36: documentBody);
tim@13: request.setEntity(representation);
tim@13: }
tim@13: Response response = client.handle(request);
tim@47: if (response.getStatus().getCode() != 200){
tim@47: throw new IOException(response.getStatus().getDescription());
tim@47: }
tim@13: Representation output = response.getEntity();
tim@13: return output;
tim@13: }
tim@36:
ingo@690:
tim@36: private InputStream doPostRequest(String requestUrl, Document requestBody)
tim@38: throws IOException {
tim@1005:
tim@1005: log.debug("URL: "+ requestUrl);
tim@1005: log.debug("Body");
tim@1005: log.debug(XMLUtils.writeDocument2String(requestBody));
tim@1005:
tim@7: Client client = new Client(Protocol.HTTP);
tim@40: Request request = initialize(new Request(Method.POST, requestUrl));
ingo@690: String documentBody = XMLUtils.writeDocument2String(requestBody);
tim@7: Representation representation = new StringRepresentation(documentBody);
tim@7: request.setEntity(representation);
tim@7: Response response = client.handle(request);
tim@47: if (response.getStatus().getCode() != 200){
tim@47: throw new IOException(response.getStatus().getDescription());
tim@47: }
tim@7: Representation output = response.getEntity();
tim@7: return output.getStream();
tim@7: }
tim@36:
tim@36: private synchronized void initialize() {
tim@36: if (!initialized) {
tim@36: PropertiesReader pr = PropertiesReaderFactory.getInstance()
tim@36: .getPropertiesReader();
tim@36: int count = Integer.parseInt(pr.getPropertieValue(
tim@36: ARTIFACTDATABASE_COUNT_ID, "0"));
tim@25: artifactDatabases = new ArrayList(count);
tim@36: for (int i = 0; i < count; i++) {
tim@36: artifactDatabases.add(pr.getPropertieValue(
tim@36: ARTIFACTDATABASE_URL_ID + "." + (i + 1), "N/N"));
tim@23: }
tim@2: initialized = true;
tim@2: }
tim@36:
tim@2: }
tim@7:
ingo@690:
tim@7: /**
ingo@690: * Creates a new artifact with the given artifactFactory. A POST call
ingo@690: * is sent to the artifact server which creates a new artifact.
ingo@690: *
ingo@690: * @param artifactFactory The artifact factory used to create a new
ingo@690: * artifact.
ingo@690: * @return the created artifact of the artifact server.
ingo@690: * @throws ArtifactDatabaseClientException
ingo@690: * @throws ArtifactDatabaseInputException
tim@7: */
tim@7: public ArtifactObject createNewArtifact(ArtifactObject artifactFactory)
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@36:
tim@7: try {
tim@558: Document request = this.createCreateRequestBody(artifactFactory);
tim@9: Document result = doPostRequest(artifactFactory, request, "create");
tim@7: return this.getArtifact(result);
tim@7: } catch (IOException e) {
tim@36: log.error(e, e);
tim@7: throw new ArtifactDatabaseClientException(e);
tim@7: }
tim@7: }
tim@36:
ingo@690: /**
ingo@690: * Returns a new artifact defined by uuid and hash values of the document
ingo@690: * returned by the artifact server after creating a new artifact.
sascha@699: *
ingo@690: * @param document Contains information about the server-side created
ingo@690: * artifact.
ingo@690: * @return a new artifact object.
ingo@690: */
tim@36: private ArtifactObject getArtifact(Document document) {
tim@35: XMLUtils xmlUtils = new XMLUtils();
ingo@690: String uuid = XMLUtils.getStringXPath(document, "/art:result/art:uuid/@value");
ingo@690: String hash = XMLUtils.getStringXPath(document, "/art:result/art:hash/@value");
tim@36: log.info("NEW Artifact: " + uuid + " / " + hash);
tim@7: return new Artifact(uuid, hash);
tim@7: }
tim@36:
tim@558: private Document createCreateRequestBody(ArtifactObject artifactFactory) {
ingo@690: Document document = XMLUtils.newDocument();
tim@36: Node rootNode = this.createRootNode(document);
tim@7: Element typeNode = this.createArtifactElement(document, "type");
tim@7: typeNode.setAttribute("name", "create");
tim@7: rootNode.appendChild(typeNode);
tim@36:
tim@558: Element factoryNode = this.createArtifactElement(document, "factory");
tim@558: factoryNode.setAttribute("name", artifactFactory.getId());
tim@558: rootNode.appendChild(factoryNode);
sascha@681:
tim@558: if (artifactFactory instanceof ParametrizedArtifactObject){
sascha@681: Map> parameterMap =
tim@558: ((ParametrizedArtifactObject)artifactFactory).getParameters();
tim@558: if (parameterMap != null && !parameterMap.isEmpty() ){
tim@558: Iterator keyIt = parameterMap.keySet().iterator();
tim@558: while (keyIt.hasNext()){
tim@558: String key = keyIt.next();
tim@558: Iterator valueIt = parameterMap.get(key).iterator();
tim@558: while (valueIt.hasNext()){
tim@558: String value = valueIt.next();
sascha@681: Element parameterNode =
tim@558: this.createArtifactElement(document, "parameter");
tim@558: parameterNode.setAttribute("name", key);
tim@558: parameterNode.setAttribute("value", value);
tim@558: factoryNode.appendChild(parameterNode);
tim@558: }
tim@558: }
tim@558: }
tim@558: }
tim@7: return document;
tim@7: }
tim@36:
tim@36: private Element createRootNode(Document document) {
tim@36: Element rootNode = this.createArtifactElement(document, "action");
tim@7: document.appendChild(rootNode);
tim@7: return rootNode;
tim@7: }
tim@36:
ingo@690:
tim@7: private Element createArtifactElement(Document document, String name) {
ingo@391: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator(
ingo@391: document,
ingo@391: NAMESPACE_URI,
ingo@391: NAMESPACE_PREFIX
ingo@391: );
ingo@391:
ingo@391: return creator.create(name);
tim@7: }
tim@9:
ingo@690:
tim@25: private Document doPostRequest(ArtifactObject artifactFactory,
ingo@665: Document request, String suburl)
ingo@665: throws IOException, ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@25: XMLUtils xmlUtils = new XMLUtils();
tim@36: String url = ((ArtifactFactory) artifactFactory).getDataBaseUrl();
tim@36: InputStream is = this.doPostRequest(url + "/" + suburl, request);
ingo@690: Document result = XMLUtils.readDocument(is);
tim@25: this.check4ExceptionReport(result);
tim@25: return result;
tim@25: }
tim@9:
ingo@690:
tim@9: /**
ingo@690: * Retrieve the current artifact description after calling the describe
ingo@690: * operation of the artifact server.
sascha@699: *
ingo@690: * @param artifactFactory
ingo@690: * @param currentArtifact
ingo@690: * @param includeUI Set this option to true, if the user interface
ingo@690: * description is required.
ingo@690: * @return the artifact description.
ingo@690: * @throws ArtifactDatabaseClientException
ingo@690: * @throws ArtifactDatabaseInputException
tim@9: */
tim@36: public ArtifactDescription getCurrentStepDescription(
ingo@665: ArtifactObject artifactFactory,
ingo@665: ArtifactObject currentArtifact,
ingo@665: boolean includeUI)
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@9: try {
tim@12: String url = this.getArtifactUrl(artifactFactory, currentArtifact);
tim@157: Document request = this.createDescribeRequestBody(currentArtifact,
tim@157: includeUI);
tim@157: InputStream describeResult = this.doPostRequest(url, request);
sascha@681:
ingo@690: return this.readDescription(XMLUtils.readDocument(describeResult),
tim@157: currentArtifact);
tim@9: } catch (IOException e) {
tim@36: log.error(e, e);
tim@9: throw new ArtifactDatabaseClientException(e);
tim@9: }
tim@9: }
sascha@681:
sascha@681:
tim@157: private Document createDescribeRequestBody(ArtifactObject currentArtifact,
tim@157: boolean includeUI){
ingo@690: Document document = XMLUtils.newDocument();
tim@157: Node rootNode = this.createRootNode(document);
tim@157:
tim@157: Element typeNode = this.createArtifactElement(document, "type");
tim@157: typeNode.setAttribute("name", "describe");
tim@157: rootNode.appendChild(typeNode);
tim@157:
tim@157: Element uuidNode = this.createArtifactElement(document, "uuid");
tim@157: uuidNode.setAttribute("value", currentArtifact.getId());
tim@157: rootNode.appendChild(uuidNode);
tim@157:
tim@157: Element hashNode = this.createArtifactElement(document, "hash");
tim@157: hashNode.setAttribute("value", currentArtifact.getHash());
tim@157: rootNode.appendChild(hashNode);
tim@157: Element includeUINode = this.createArtifactElement(document, "include-ui");
tim@157: includeUINode.appendChild(document.createTextNode(""+includeUI));
tim@157: rootNode.appendChild(includeUINode);
tim@157: return document;
tim@157: }
tim@12:
ingo@690:
tim@12: private String getArtifactUrl(ArtifactObject artifactFactory,
tim@38: ArtifactObject currentArtifact) {
tim@36: String url = ((ArtifactFactory) artifactFactory).getDataBaseUrl()
tim@38: + "/artifact/" + currentArtifact.getId();
tim@12: return url;
tim@12: }
tim@36:
tim@36: private ArtifactDescription readDescription(Document document,
ingo@665: ArtifactObject artifact)
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@36: // Check if there was an Error or Exception reported from the
tim@36: // ArtifactDatabase
tim@25: this.check4ExceptionReport(document);
tim@36: if (artifact instanceof ArtifactDescription) {
tim@36: ArtifactDescription ad = (ArtifactDescription) artifact;
ingo@690: Node uiNode = XMLUtils.getNodeXPath(document, "/art:result/art:ui");
ingo@690: Node outputNode = XMLUtils
ingo@389: .getNodeXPath(document, "/art:result/art:outputs");
tim@36:
tim@30: Map outputModes = null;
tim@36: if (outputNode != null) {
ingo@690: NodeList outputModesNodes = XMLUtils.getNodeSetXPath(
ingo@389: outputNode, "art:output");
tim@36: if (outputModesNodes != null) {
tim@36: outputModes = new HashMap(
tim@36: outputModesNodes.getLength());
tim@36: for (int i = 0; i < outputModesNodes.getLength(); i++) {
tim@30: Node outputModeNode = outputModesNodes.item(i);
ingo@690: String name = XMLUtils.getStringXPath(outputModeNode,
tim@36: "@name");
ingo@690: String mimeType = XMLUtils.getStringXPath(
tim@36: outputModeNode, "@mime-type");
tim@36:
ingo@690: NodeList parameterNodes = XMLUtils.getNodeSetXPath(
ingo@389: outputModeNode, "art:parameter/art:parameter");
tim@30: Collection parameter = null;
tim@36: if (parameterNodes != null) {
tim@36: parameter = new ArrayList(
tim@36: parameterNodes.getLength());
tim@36: for (int j = 0; j < parameterNodes.getLength(); j++) {
tim@36: Node outputParameterNode = parameterNodes
tim@36: .item(j);
tim@36: parameter.add(new DefaultOutputParameter(
ingo@690: XMLUtils.getStringXPath(
tim@36: outputParameterNode, "@name"),
ingo@690: XMLUtils.getStringXPath(
tim@36: outputParameterNode, "@value"),
ingo@690: XMLUtils.getStringXPath(
tim@36: outputParameterNode, "@name"),
ingo@690: XMLUtils.getStringXPath(
tim@36: outputParameterNode, "@type")));
tim@30: }
tim@30: }
ingo@573:
ingo@690: NodeList exportNodes = XMLUtils.getNodeSetXPath(
ingo@573: outputModeNode, "art:exports/art:export");
ingo@573: Map exports = null;
sascha@681:
ingo@573: if (exportNodes != null) {
ingo@573: int size = exportNodes.getLength();
ingo@573: exports = new HashMap(size);
ingo@573:
ingo@573: for (int k = 0; k < size; k++) {
ingo@573: Node export = exportNodes.item(k);
ingo@690: String expName = XMLUtils.getStringXPath(
ingo@573: export, "@name");
ingo@573: exports.put(expName, new DefaultExportMode(
ingo@573: expName,
ingo@690: XMLUtils.getStringXPath(export, "@description"),
ingo@690: XMLUtils.getStringXPath(export, "@mime-type")));
ingo@573: }
ingo@573: }
ingo@573:
tim@36: outputModes.put(name, new DefaultOutputMode(name,
ingo@573: mimeType, parameter, exports));
tim@30: }
tim@36:
tim@30: }
tim@30: }
tim@36:
ingo@690: String currentState = XMLUtils.getStringXPath(document,
ingo@389: "/art:result/art:state/@name");
ingo@690: NodeList statesList = XMLUtils.getNodeSetXPath(document,
ingo@389: "/art:result/art:reachable-states/art:state/@name");
tim@36: Collection reachableStates = new ArrayList(
tim@36: statesList.getLength());
tim@36: for (int i = 0; i < statesList.getLength(); i++) {
tim@9: reachableStates.add(statesList.item(i).getNodeValue());
tim@9: }
tim@36:
ingo@690: NodeList inputNodes = XMLUtils.getNodeSetXPath(document,
ingo@389: "/art:result/art:model/art:input");
tim@36: if (inputNodes != null) {
tim@36: Collection inputParameter = new ArrayList(
tim@36: inputNodes.getLength());
tim@36: for (int i = 0; i < inputNodes.getLength(); i++) {
tim@12: Node inputNode = inputNodes.item(i);
ingo@690: String name = XMLUtils.getStringXPath(inputNode, "@name");
tim@12: inputParameter.add(name);
tim@12: }
tim@12: ad.setInputParameter(inputParameter);
tim@12: }
tim@36:
tim@30: ad.setOutputModes(outputModes);
tim@9: ad.setCurrentOut(outputNode);
tim@9: ad.setCurrentUI(uiNode);
tim@9: ad.setCurrentState(currentState);
tim@9: ad.setReachableStates(reachableStates);
tim@9: return ad;
tim@36: } else {
tim@9: log.error("Artifact must be Instance of ArtifactDescription");
tim@36: throw new ArtifactDatabaseClientException(
tim@36: "Artifact must be Instance of ArtifactDescription");
tim@9: }
tim@36:
tim@9: }
tim@12:
ingo@690:
tim@12: /**
ingo@690: * Feed, advance and describe in one single method.
sascha@699: *
ingo@690: * @param artifactFactory The factory which created the current artifact.
ingo@690: * @param currentArtifact The current artifact.
ingo@690: * @param target The target state for advance.
ingo@690: * @param inputParameter Input data for feed.
ingo@690: * @return the artifact description after calling feed and advance.
ingo@690: * @throws ArtifactDatabaseClientException if a general error occured in
ingo@690: * the artifact server.
ingo@690: * @throws ArtifactDatabaseInputException if the input data was invalid used
ingo@690: * for feed.
tim@12: */
tim@38: public ArtifactDescription doNextStep(
ingo@665: ArtifactObject artifactFactory,
ingo@665: ArtifactObject currentArtifact,
ingo@665: String target,
ingo@665: Collection inputParameter)
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@36:
tim@12: try {
tim@12: // 1 Feed
tim@13: this.doFeed(artifactFactory, currentArtifact, inputParameter);
sascha@681:
tim@157: // 2. Noch einmal Describe um das jetzt zu erreichende Ziel zu ermitteln
ingo@394: ArtifactDescription ad = getCurrentStepDescription(
ingo@394: artifactFactory,
ingo@394: new Artifact(currentArtifact.getId(),
ingo@394: currentArtifact.getHash()),
ingo@394: false
ingo@394: );
ingo@394:
tim@157: target = ad.getReachableStates().iterator().next();
sascha@681:
tim@157: // 3 Advance
ingo@394: doAdvance(artifactFactory, currentArtifact, target);
sascha@681:
tim@25: // 3 Describe
tim@36: return this.getCurrentStepDescription(artifactFactory,
tim@157: currentArtifact,true);
tim@12: } catch (IOException e) {
tim@36: log.error(e, e);
tim@12: throw new ArtifactDatabaseClientException(e);
tim@12: }
tim@12: }
tim@36:
ingo@394:
ingo@690: /**
ingo@690: * Call the advance operation of the artifact server to step to the next
ingo@690: * step of the parameterization.
ingo@690: *
ingo@690: * @param factory The artifact factory which created the current artifact.
ingo@690: * @param artifact The current artifact.
ingo@690: * @param target The target state.
ingo@690: * @throws IOException if an error occured while reading/writing from/to
ingo@690: * stream.
ingo@690: * @throws ArtifactDatabaseClientException if a general error occured in
ingo@690: * the artifact server.
ingo@690: * @throws ArtifactDatabaseInputException if the input data was invalid.
ingo@690: */
ingo@394: public void doAdvance(
ingo@394: ArtifactObject factory,
ingo@394: ArtifactObject artifact,
ingo@665: String target)
ingo@665: throws IOException, ArtifactDatabaseClientException, ArtifactDatabaseInputException {
ingo@394: String url = getArtifactUrl(factory, artifact);
ingo@394: Document advanceDocument = createAdvanceRequestBody(artifact, target);
ingo@394: InputStream advanceResult = doPostRequest(url, advanceDocument);
ingo@690: check4ExceptionReport(XMLUtils.readDocument(advanceResult));
ingo@394: }
ingo@394:
tim@38: private Document createFeedRequestBody(
tim@38: ArtifactObject currentArtifact,
tim@38: Collection inputParameter) {
ingo@690: Document document = XMLUtils.newDocument();
tim@36: Node rootNode = this.createRootNode(document);
tim@36:
tim@12: Element typeNode = this.createArtifactElement(document, "type");
tim@12: typeNode.setAttribute("name", "feed");
tim@12: rootNode.appendChild(typeNode);
tim@36:
tim@12: Element uuidNode = this.createArtifactElement(document, "uuid");
tim@12: uuidNode.setAttribute("value", currentArtifact.getId());
tim@12: rootNode.appendChild(uuidNode);
tim@36:
tim@12: Element hashNode = this.createArtifactElement(document, "hash");
tim@12: hashNode.setAttribute("value", currentArtifact.getHash());
tim@12: rootNode.appendChild(hashNode);
tim@36:
tim@36: Node dataNode = this.createParameterNodes(inputParameter, document,
tim@36: "data");
tim@12: rootNode.appendChild(dataNode);
tim@36:
tim@13: return document;
tim@13: }
tim@13:
ingo@690:
tim@36: private Node createParameterNodes(
tim@38: Collection inputParameter,
tim@38: Document document, String nodeName) {
tim@13: Element dataNode = this.createArtifactElement(document, nodeName);
tim@36:
tim@36: if (inputParameter != null) {
tim@12: Iterator it = inputParameter.iterator();
tim@36: while (it.hasNext()) {
tim@12: InputParameter ip = it.next();
tim@12: String name = ip.getName();
tim@12: String[] values = ip.getValues();
tim@36: if (values != null) {
tim@36: for (int i = 0; i < values.length; i++) {
tim@12: String value = values[i];
tim@36: Element inputNode = this.createArtifactElement(
tim@36: document, "input");
tim@12: inputNode.setAttribute("name", name);
tim@12: inputNode.setAttribute("value", value);
tim@12: dataNode.appendChild(inputNode);
tim@12: }
tim@12: }
tim@12: }
tim@12: }
tim@13: return dataNode;
tim@12: }
tim@36:
ingo@690:
ingo@690: /**
ingo@690: * Creates the xml body for the advance request.
ingo@690: *
ingo@690: * @param currentArtifact
ingo@690: * @param target
ingo@690: * @return the advance xml document.
ingo@690: */
tim@36: private Document createAdvanceRequestBody(ArtifactObject currentArtifact,
tim@38: String target) {
ingo@690: Document document = XMLUtils.newDocument();
tim@36: Node rootNode = this.createRootNode(document);
tim@36:
tim@36: Element typeNode = this.createArtifactElement(document, "type");
tim@36: typeNode.setAttribute("name", "advance");
tim@36: rootNode.appendChild(typeNode);
tim@36:
tim@36: Element uuidNode = this.createArtifactElement(document, "uuid");
tim@36: uuidNode.setAttribute("value", currentArtifact.getId());
tim@36: rootNode.appendChild(uuidNode);
tim@36:
tim@36: Element hashNode = this.createArtifactElement(document, "hash");
tim@36: hashNode.setAttribute("value", currentArtifact.getHash());
tim@36: rootNode.appendChild(hashNode);
tim@36: Element targetNode = this.createArtifactElement(document, "target");
tim@36: targetNode.setAttribute("name", target);
tim@36: rootNode.appendChild(targetNode);
tim@36: return document;
tim@12: }
tim@13:
tim@13: /**
ingo@690: * Call the out operation of the artifact server and writes the result to
ingo@690: * stream.
ingo@690: *
ingo@690: * @param exportMode
ingo@690: * @param inputParameter
tim@13: */
ingo@583: public void doOutput(
ingo@583: ArtifactObject artifactFactory,
ingo@583: ArtifactObject currentArtifact,
ingo@583: OutputStream stream,
ingo@583: String targetName,
ingo@583: String exportMode,
ingo@583: String mimeType,
ingo@583: Collection inputParameter)
ingo@583: throws ArtifactDatabaseClientException
ingo@583: {
tim@13: try {
ingo@583: Document requestBody = this.createOutRequestBody(
ingo@583: currentArtifact,
ingo@583: targetName,
ingo@583: exportMode,
ingo@583: mimeType,
ingo@583: inputParameter);
tim@36:
tim@36: String requestUrl = this.getArtifactUrl(artifactFactory,
tim@36: currentArtifact)
tim@38: + "/" + targetName;
tim@36: InputStream is = this.doPostRequest(requestUrl, requestBody);
tim@36:
tim@13: byte[] b = new byte[4096];
tim@36: int i = -1;
tim@36: while ((i = is.read(b)) > 0) {
tim@13: stream.write(b, 0, i);
tim@13: }
tim@36: } catch (IOException e) {
tim@36: log.error(e, e);
tim@13: throw new ArtifactDatabaseClientException(e);
tim@13: }
tim@13: }
tim@36:
ingo@670:
ingo@690: /**
ingo@690: * Call the out method of the artifact server with a specific export mode.
sascha@699: *
ingo@690: * @param artifactFactory
ingo@690: * @param currentArtifact
ingo@690: * @param out
ingo@690: * @throws ArtifactDatabaseClientException if an error occured while
ingo@690: * reading/writing from/to stream.
ingo@690: */
ingo@670: public void doExport(
ingo@670: ArtifactObject artifactFactory,
ingo@670: ArtifactObject currentArtifact,
ingo@670: OutputStream out)
ingo@670: throws ArtifactDatabaseClientException
ingo@670: {
ingo@678: InputStreamReader reader = null;
ingo@678: OutputStreamWriter writer = null;
ingo@678:
ingo@670: try {
ingo@670: String url = ((ArtifactFactory) artifactFactory).getDataBaseUrl();
ingo@670: url += "/export/" + currentArtifact.getId();
ingo@670:
ingo@678: Representation response = doGetRequestInternal(url, null);
ingo@678: InputStream in = response.getStream();
ingo@678:
ingo@678: reader = new InputStreamReader(in);
ingo@678: writer = new OutputStreamWriter(out);
ingo@678:
ingo@679: int c;
ingo@679: char[] buffer = new char[512];
ingo@679: while ((c = reader.read(buffer)) > 0) {
ingo@679: writer.write(buffer, 0, c);
ingo@678: }
ingo@678:
ingo@670: }
ingo@670: catch (Exception e) {
ingo@670: log.error(e, e);
ingo@670: throw new ArtifactDatabaseClientException(e);
ingo@670: }
ingo@678: finally {
ingo@678: try {
ingo@678: reader.close();
ingo@678: } catch (IOException ioe) {}
ingo@670:
ingo@678: try {
ingo@678: writer.flush();
ingo@678: } catch (IOException ioe) {}
ingo@678:
ingo@678: try {
ingo@678: writer.close();
ingo@678: } catch (IOException ioe) {}
ingo@678: }
ingo@670: }
ingo@670:
ingo@670:
ingo@690: /**
ingo@690: * Start to import an artifact from xml document.
ingo@690: *
ingo@690: * @param factory
ingo@690: * @param document The artifact as xml document.
ingo@690: * @return A status description of the operation (success or failure).
ingo@690: * @throws ArtifactDatabaseClientException
ingo@690: * @throws IOException
ingo@690: */
ingo@673: public Document doImport(
ingo@673: ArtifactFactory factory,
ingo@673: Document document)
ingo@673: throws ArtifactDatabaseClientException, IOException
ingo@673: {
ingo@673: String url = factory.getDataBaseUrl() + "/import";
ingo@673: InputStream response = doPostRequest(url, document);
ingo@673:
ingo@673: return XMLUtils.readDocument(response);
ingo@673: }
ingo@673:
ingo@673:
ingo@690: /**
ingo@690: * Creates the xml request body used for an out-call of the artifact server.
sascha@699: *
ingo@690: * @param currentArtifact
ingo@690: * @param target
ingo@690: * @param exportMode
ingo@690: * @param mimeType
ingo@690: * @param inputParameter
ingo@690: * @return the request body.
ingo@690: */
tim@38: private Document createOutRequestBody(
ingo@583: ArtifactObject currentArtifact,
ingo@583: String target,
ingo@583: String exportMode,
ingo@583: String mimeType,
ingo@583: Collection inputParameter)
ingo@583: {
ingo@690: Document document = XMLUtils.newDocument();
tim@36: Node rootNode = this.createRootNode(document);
tim@36:
tim@13: Element typeNode = this.createArtifactElement(document, "type");
tim@13: typeNode.setAttribute("name", "out");
tim@13: rootNode.appendChild(typeNode);
tim@36:
tim@13: Element uuidNode = this.createArtifactElement(document, "uuid");
tim@13: uuidNode.setAttribute("value", currentArtifact.getId());
tim@13: rootNode.appendChild(uuidNode);
tim@36:
tim@13: Element hashNode = this.createArtifactElement(document, "hash");
tim@13: hashNode.setAttribute("value", currentArtifact.getHash());
tim@13: rootNode.appendChild(hashNode);
tim@36:
tim@13: Element outNode = this.createArtifactElement(document, "out");
tim@13: outNode.setAttribute("name", target);
tim@13: rootNode.appendChild(outNode);
tim@36:
ingo@583: Element exportNode = this.createArtifactElement(document, "export");
ingo@583: exportNode.setAttribute("name", exportMode);
ingo@583: outNode.appendChild(exportNode);
ingo@583:
ingo@281: Element mimeTypeNode = this.createArtifactElement(document, "mime-type");
tim@13: mimeTypeNode.setAttribute("value", mimeType);
tim@13: outNode.appendChild(mimeTypeNode);
tim@36:
tim@36: Node parameterNode = this.createParameterNodes(inputParameter,
tim@36: document, "params");
tim@13: outNode.appendChild(parameterNode);
tim@36:
tim@13: return document;
tim@36: }
tim@13:
ingo@690:
tim@13: /**
ingo@690: * Calls the feed operation of the artifact server.
ingo@690: *
ingo@690: * @param artifactFactory The artifact factory which created the current
ingo@690: * artifact.
ingo@690: * @param currentArtifact The current artifact.
ingo@690: * @param inputParameter The user input.
ingo@690: * @throws ArtifactDatabaseClientException
ingo@690: * @throws ArtifactDatabaseInputException
tim@13: */
ingo@665: public void doFeed(
ingo@665: ArtifactObject artifactFactory,
ingo@665: ArtifactObject currentArtifact,
ingo@665: Collection inputParameter)
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@36:
tim@13: try {
tim@36: Document feedDocument = this.createFeedRequestBody(currentArtifact,
tim@36: inputParameter);
tim@13: String url = this.getArtifactUrl(artifactFactory, currentArtifact);
tim@13: InputStream feedResult = this.doPostRequest(url, feedDocument);
ingo@690: Document feedResultDocument = XMLUtils
tim@36: .readDocument(feedResult);
tim@25: this.check4ExceptionReport(feedResultDocument);
tim@13: } catch (IOException e) {
tim@36: log.error(e, e);
tim@25: throw new ArtifactDatabaseClientException(e);
tim@13: }
tim@13: }
tim@36:
tim@36: private void check4ExceptionReport(Document document)
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
ingo@690: String message = XMLUtils.getStringXPath(document,
ingo@665: EXCEPTION_GENERAL);
tim@36: if (message != null) {
tim@25: throw new ArtifactDatabaseClientException(message);
tim@25: }
tim@36:
ingo@665: String input = XMLUtils.getStringXPath(document, EXCEPTION_USER_INPUT);
ingo@665: if (input != null) {
ingo@665: throw new ArtifactDatabaseInputException(input);
ingo@665: }
tim@25: }
tim@32:
ingo@690:
ingo@690: /**
ingo@690: * Call the specific wms export mode of the out operation of the artifact
ingo@690: * server.
sascha@699: *
ingo@690: * @param factory
ingo@690: * @param artifact
ingo@690: * @param inputParameter
ingo@690: * @return a document that contains information about the wms service and
ingo@690: * the created layer.
ingo@690: * @throws ArtifactDatabaseClientException
ingo@690: * @throws ArtifactDatabaseInputException
ingo@690: */
ingo@668: public Document publishWMS(
ingo@668: ArtifactObject factory,
ingo@668: ArtifactObject artifact,
ingo@668: Collection inputParameter
tim@676: ) throws ArtifactDatabaseClientException, ArtifactDatabaseInputException{
ingo@570: log.debug("Start wms publishing...");
ingo@570:
ingo@570: String target = "wms";
ingo@570: String requestURL = getArtifactUrl(factory, artifact) + "/" + target;
ingo@570: Document request = createOutRequestBody(
ingo@668: artifact, target, "", "text/xml", inputParameter);
ingo@570: try {
ingo@570: InputStream input = doPostRequest(requestURL, request);
ingo@570: Document result = XMLUtils.readDocument(input);
tim@676: this.check4ExceptionReport(result);
ingo@585: return result;
ingo@570: }
ingo@570: catch (IOException ioe) {
ingo@570: log.error(ioe, ioe);
tim@676: throw new ArtifactDatabaseClientException(ioe);
ingo@570: }
ingo@570: }
ingo@570:
sascha@699:
tim@164: public Collection calculateStatistics(
ingo@570: ArtifactObject artifactFactory,
ingo@570: ArtifactObject currentArtifact)
ingo@570: throws ArtifactDatabaseClientException
ingo@570: {
tim@36: log.debug("DefaultArtifactDatabaseClient.calculateStatistics");
tim@164: Collection resultValues = null;
sascha@681:
tim@32: try {
tim@32: String targetName = "statistics";
tim@36: String requestUrl = this.getArtifactUrl(artifactFactory,
tim@164: currentArtifact) + "/" + targetName;
tim@36: Document requestBody = this.createOutRequestBody(currentArtifact,
ingo@583: targetName, "", "text/xml", null);
tim@32: XMLUtils xmlUtils = new XMLUtils();
tim@36: InputStream is = this.doPostRequest(requestUrl, requestBody);
ingo@690: Document resultDocument = XMLUtils.readDocument(is);
tim@36: if (resultDocument != null) {
sascha@681:
ingo@690: NodeList statisticSetNodes = XMLUtils.getNodeSetXPath(resultDocument,
ingo@389: "/art:statistics/art:statistic");
tim@164: resultValues = new ArrayList
tim@164: (statisticSetNodes.getLength());
tim@164: for (int i = 0; i < statisticSetNodes.getLength(); i++) {
tim@164: Element statisticSetNode = (Element)statisticSetNodes.item(i);
tim@164: String name = statisticSetNode.getAttribute("name");
sascha@681: ArtifactStatisticsSet set =
tim@164: new DefaultArtifactStatisticsSet(name);
ingo@690: NodeList resultNodes = XMLUtils.getNodeSetXPath(statisticSetNode,
ingo@389: "art:statistic-value");
tim@164: if (resultNodes != null) {
tim@164: for (int j = 0; j < resultNodes.getLength(); j++) {
tim@164: Element statisticNode = (Element)resultNodes.item(j);
tim@164: String statisticName = statisticNode.
tim@164: getAttribute("name");
tim@164: String statisticValue = statisticNode.
tim@164: getAttribute("value");
tim@164: set.addStatisticValues(
tim@164: new DefaultArtifactStatisticValue
tim@164: (statisticName,statisticValue));
tim@164: }
tim@32: }
tim@164: resultValues.add(set);
tim@32: }
tim@32: }
tim@32: } catch (IOException e) {
tim@36: log.error(e, e);
tim@35: throw new ArtifactDatabaseClientException(e);
tim@32: }
tim@36:
tim@164: return resultValues;
tim@32: }
tim@40:
tim@40: public void setLocale(Locale locale) {
tim@40: this.locale = locale;
tim@40: }
tim@402:
ingo@703: public Locale getLocale() {
ingo@703: return locale;
ingo@703: }
ingo@703:
ingo@690:
tim@558: public Collection getArtifactFactoryMetaInformation(
ingo@665: Collection mapServices,
ingo@665: String geometry,
ingo@665: String srs)
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@558: log.debug("DefaultArtifactDatabaseClient.getArtifactFactories");
tim@558: Collection resultValues = null;
tim@558: try {
tim@558: this.initialize();
tim@558: Iterator it = artifactDatabases.iterator();
sascha@681: Document requestBody = this.createMetaDataRequestBody(mapServices,
sascha@681: geometry,
tim@558: srs);
tim@558: while (it.hasNext()) {
tim@558: String server = it.next();
tim@558: String url = server + "/service/metadata/";
tim@558: log.debug(url);
sascha@681:
tim@558: InputStream resultStream = this.doPostRequest(url, requestBody);
tim@565: resultValues = this.parseMetaDataResult(resultStream, server,geometry);
tim@558: }
tim@558: } catch (IOException e) {
tim@558: log.error(e,e);
tim@558: }
tim@558: return resultValues;
tim@558: }
sascha@681:
tim@558: private Collection parseMetaDataResult(
sascha@681: InputStream inputStream,
ingo@665: String server,
ingo@665: String geometry)
ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException {
tim@558: XMLUtils xmlUtils = new XMLUtils();
ingo@690: Document document = XMLUtils.readDocument(inputStream);
tim@558: this.check4ExceptionReport(document);
tim@565: return this.getArtifactFactories(document, server,geometry);
tim@558: }
sascha@681:
tim@558: private Document createMetaDataRequestBody(Collection mapServices,
tim@558: String geometry,
tim@558: String srs){
tim@558: log.debug("DefaultArtifactDatabaseClient.createMetaDataRequestBody");
ingo@690: Document document = XMLUtils.newDocument();
tim@558: Node rootNode = this.createArtifactElement(document, "GetMetaData");
tim@558: document.appendChild(rootNode);
sascha@681:
tim@1005: if (geometry != null){
tim@1005: Element locationNode = this.createArtifactElement(document, "location");
tim@1005: locationNode.setAttribute("srs", srs);
tim@1005: locationNode.appendChild(document.createTextNode(geometry));
tim@1005: rootNode.appendChild(locationNode);
tim@1005: }
tim@558: Element mapServicesNode = this.createArtifactElement(document,
tim@558: "mapservices");
tim@558: Iterator it = mapServices.iterator();
tim@558: while (it.hasNext()){
tim@558: MapService mapService = it.next();
tim@558: Element mapServiceNode = this.createArtifactElement(document,
tim@558: "mapservice");
tim@558: mapServiceNode.setAttribute("id", mapService.getID());
tim@558: mapServiceNode.setAttribute("type", mapService.getType());
tim@558: mapServiceNode.setAttribute("url", mapService.getURL());
tim@561: if (mapService.getLayer() != null){
tim@561: Iterator layer = mapService.getLayer().iterator();
tim@561: while (layer.hasNext()){
tim@561: Layer tmpLayer = layer.next();
tim@561: Element layerNode = this.createArtifactElement(document,
tim@561: "layer");
tim@561: layerNode.setAttribute("id", tmpLayer.getID());
tim@561: layerNode.setAttribute("name", tmpLayer.getName());
tim@561: layerNode.setAttribute("isgrouplayer",
tim@561: ""+tmpLayer.isGroupLayer());
tim@561: layerNode.setAttribute("parentid", tmpLayer.parentID());
tim@561: mapServiceNode.appendChild(layerNode);
tim@561: }
tim@558: }
tim@558: mapServicesNode.appendChild(mapServiceNode);
tim@558: }
tim@558: rootNode.appendChild(mapServicesNode);
tim@558: return document;
tim@402: }
tim@13: }
sascha@700: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :