/**
* Copyright (C) 2007 - 2014 52°North Initiative for Geospatial Open Source
* Software GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* If the program is linked with libraries which are licensed under one of
* the following licenses, the combination of the program with the linked
* library is not considered a "derivative work" of the program:
*
* • Apache License, version 2.0
* • Apache Software License, version 1.0
* • GNU Lesser General Public License, version 3
* • Mozilla Public License, versions 1.0, 1.1 and 2.0
* • Common Development and Distribution License (CDDL), version 1.0
*
* Therefore the distribution of the program linked with libraries licensed
* under the aforementioned licenses, is permitted by the copyright holders
* if the distribution is compliant with both the GNU General Public
* License version 2 and the aforementioned licenses.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*/
package org.n52.wps.transactional.algorithm;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import net.opengis.ows.x11.ExceptionReportDocument;
import net.opengis.wps.x100.ExecuteDocument;
import net.opengis.wps.x100.InputDescriptionType;
import net.opengis.wps.x100.OutputDescriptionType;
import net.opengis.wps.x100.ProcessDescriptionType;
import net.opengis.wps.x100.ProcessDescriptionsDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xpath.XPathAPI;
import org.n52.wps.PropertyDocument.Property;
import org.n52.wps.commons.WPSConfig;
import org.n52.wps.io.data.GenericFileDataWithGT;
import org.n52.wps.io.data.IData;
import org.n52.wps.io.data.binding.complex.GTRasterDataBinding;
import org.n52.wps.io.data.binding.complex.GTVectorDataBinding;
import org.n52.wps.io.data.binding.complex.GenericFileDataWithGTBinding;
import org.n52.wps.io.data.binding.literal.LiteralBooleanBinding;
import org.n52.wps.io.data.binding.literal.LiteralDoubleBinding;
import org.n52.wps.io.data.binding.literal.LiteralIntBinding;
import org.n52.wps.io.data.binding.literal.LiteralStringBinding;
import org.n52.wps.server.AbstractTransactionalAlgorithm;
import org.n52.wps.transactional.deploy.IProcessManager;
import org.n52.wps.transactional.service.TransactionalHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class GenericTransactionalAlgorithm extends AbstractTransactionalAlgorithm{
private List<String> errors;
private static Logger LOGGER = LoggerFactory.getLogger(GenericTransactionalAlgorithm.class);
private ProcessDescriptionType processDescription;
private String workspace;
private static final String OGC_OWS_URI = "http://www.opengeospatial.net/ows";
public GenericTransactionalAlgorithm(String processID, Class<?> registeredRepository){
super(processID);
WPSConfig wpsConfig = WPSConfig.getInstance();
Property[] properties = wpsConfig.getPropertiesForRepositoryClass(registeredRepository.getName());
this.workspace = wpsConfig.getPropertyForKey(properties,"WorkspaceLocationRoot").getStringValue();
this.errors = new ArrayList<String>();
processDescription = initializeDescription();
}
public ProcessDescriptionType getDescription() {
return processDescription;
}
public HashMap<String, IData> run(ExecuteDocument payload){
Document responseDocument;
HashMap<String,IData> resultHash = new HashMap<String,IData>();
try {
//forward request
//TODO get deploy manager class from config
IProcessManager deployManager = TransactionalHelper.getProcessManagerForSchema("BPELProfile.xsd");
responseDocument = deployManager.invoke(payload, getAlgorithmID());
//1.parse results;
//TODO make temporaryfile
//writeXmlFile(responseDocument,workspace+"\\BPEL\\serverside.xml");
File tempFile = File.createTempFile("wpsbpelresult", ".xml", null);
File tempFile2 = File.createTempFile("wpsbpelresult", ".xml", null);
//
writeXmlFile(responseDocument,tempFile2);
Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(tempFile2);
GenericFileDataWithGT data = new GenericFileDataWithGT(tempFile, "text/xml");
Node gml = XPathAPI.selectSingleNode(d, "//Output/Data/ComplexData/FeatureCollection");
String identifier = XPathAPI.selectSingleNode(d, "//Output/Identifier").getFirstChild().getNodeValue().trim();
writeXmlFile(gml, tempFile);
GenericFileDataWithGTBinding binding = new GenericFileDataWithGTBinding(data);
resultHash.put(identifier, binding);
//ExecuteResponseDocument executeResponseDocument = ExecuteResponseDocument.Factory.parse(new File(workspace+"\\BPEL\\serverside.xml"));
// ExecuteResponseDocument executeResponseDocument = ExecuteResponseDocument.Factory.parse(tempFile);
//
// // 2.look at each Output Element
// OutputDataType[] resultValues = executeResponseDocument.getExecuteResponse().getProcessOutputs().getOutputArray();
// for(int i = 0; i<resultValues.length;i++){
// OutputDataType ioElement = resultValues[i];
// //3.get the identifier as key
// String key = ioElement.getIdentifier().getStringValue();
// //4.the the literal value as String
// if(ioElement.getData().getLiteralData()!=null){
// resultHash.put(key, OutputParser.handleLiteralValue(ioElement));
// }
// //5.parse the complex value
// if(ioElement.getData().getComplexData()!=null){
//
// resultHash.put(key, OutputParser.handleComplexValue(ioElement, getDescription()));
//
//
// }
// //6.parse the complex value reference
// if(ioElement.getReference()!=null){
// //TODO handle this
// //download the data, parse it and put it in the hashmap
// //resultHash.put(key, OutputParser.handleComplexValueReference(ioElement));
// }
//
// //7.parse Bounding Box value
// if(ioElement.getData().getBoundingBoxData()!=null){
// resultHash.put(key, OutputParser.handleBBoxValue(ioElement));
// }
//
//
// }
} catch (Exception e) {
String error = "Could not create ExecuteResponseDocument";
errors.add(error);
LOGGER.warn(error + " Reason: " +e.getMessage());
throw new RuntimeException(error,e);
}
//add response id
return resultHash;
}
public List<String> getErrors() {
return errors;
}
protected ProcessDescriptionType initializeDescription() {
String fullPath = GenericTransactionalAlgorithm.class.getProtectionDomain().getCodeSource().getLocation().toString();
int searchIndex= fullPath.indexOf("WEB-INF");
String subPath = fullPath.substring(0, searchIndex);
subPath = subPath.replaceFirst("file:/", "");
String processID = getAlgorithmID();
//sanitize processID: strip version number and namespace if passed in
if (processID.contains("-"))
processID = processID.split("-")[0];
if (processID.contains("}"))
processID = processID.split("}")[1];
try {
File xmlDesc = new File(subPath+File.separator+"WEB-INF"+File.separator+"ProcessDescriptions"+File.separator+processID+".xml");
XmlOptions option = new XmlOptions();
option.setLoadTrimTextBuffer();
ProcessDescriptionsDocument doc = ProcessDescriptionsDocument.Factory.parse(xmlDesc, option);
if(doc.getProcessDescriptions().getProcessDescriptionArray().length == 0) {
LOGGER.warn("ProcessDescription does not contain any description");
return null;
}
doc.getProcessDescriptions().getProcessDescriptionArray(0).getIdentifier().setStringValue(processID);
return doc.getProcessDescriptions().getProcessDescriptionArray(0);
}
catch(IOException e) {
LOGGER.warn("Could not initialize algorithm, parsing error: " + getAlgorithmID(), e);
}
catch(XmlException e) {
LOGGER.warn("Could not initialize algorithm, parsing error: " +getAlgorithmID(), e);
}
return null;
}
public boolean processDescriptionIsValid() {
return processDescription.validate();
}
private Document checkResultDocument(Document doc){
if(getFirstElementNode(doc.getFirstChild()).getNodeName().equals("ExceptionReport") && getFirstElementNode(doc.getFirstChild()).getNamespaceURI().equals(OGC_OWS_URI)) {
try {
ExceptionReportDocument exceptionDoc = ExceptionReportDocument.Factory.parse(doc);
throw new RuntimeException("Error occured while executing query");
}
catch(Exception e) {
throw new RuntimeException("Error while parsing ExceptionReport retrieved from server", e);
}
}
return doc;
}
private Node getFirstElementNode(Node node) {
if(node == null) {
return null;
}
if(node.getNodeType() == Node.ELEMENT_NODE) {
return node;
}
else {
return getFirstElementNode(node.getNextSibling());
}
}
//private static void writeXmlFile(Document doc, String filename) {
private static void writeXmlFile(Document doc, File file) {
try {
// if(filename==null){
// filename = "C:\\BPEL\\serverside.xml";
// }
// Prepare the DOM document for writing
Source source = new DOMSource(doc);
// Prepare the output file
//File file = new File(filename);
//file.createNewFile();
//Result result = new StreamResult(file);
Result result = new StreamResult(file.toURI().getPath());
// Write the DOM document to the file
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(source, result);
} catch (TransformerConfigurationException e) {
System.out.println("error");
} catch (TransformerException e) {
System.out.println("error");
} catch (Exception e) {
System.out.println("error");
}
}
private static void writeXmlFile(Node n, File file) {
try {
// if(filename==null){
// filename = "C:\\BPEL\\serverside.xml";
// }
// Prepare the DOM document for writing
Source source = new DOMSource(n);
// Prepare the output file
// File file = new File(filename);
// file.createNewFile();
// Result result = new StreamResult(file);
Result result = new StreamResult(file.toURI().getPath());
// Write the DOM document to the file
Transformer xformer = TransformerFactory.newInstance()
.newTransformer();
xformer.transform(source, result);
} catch (TransformerConfigurationException e) {
System.out.println("error");
} catch (TransformerException e) {
System.out.println("error");
} catch (Exception e) {
System.out.println("error");
}
}
public String getWellKnownName() {
return "";
}
public Class getInputDataType(String id) {
InputDescriptionType[] inputs = processDescription.getDataInputs().getInputArray();
for(InputDescriptionType input : inputs){
if(input.getIdentifier().getStringValue().equals(id)){
if(input.isSetLiteralData()){
String datatype = input.getLiteralData().getDataType().getStringValue();
if(datatype.contains("tring")){
return LiteralStringBinding.class;
}
if(datatype.contains("ollean")){
return LiteralBooleanBinding.class;
}
if(datatype.contains("loat") || datatype.contains("ouble")){
return LiteralDoubleBinding.class;
}
if(datatype.contains("nt")){
return LiteralIntBinding.class;
}
}
if(input.isSetComplexData()){
String mimeType = input.getComplexData().getDefault().getFormat().getMimeType();
if(mimeType.contains("xml") || (mimeType.contains("XML"))){
return GTVectorDataBinding.class;
}else{
return GTRasterDataBinding.class;
}
}
}
}
throw new RuntimeException("Could not determie internal inputDataType");
}
public Class getOutputDataType(String id) {
OutputDescriptionType[] outputs = processDescription.getProcessOutputs().getOutputArray();
for(OutputDescriptionType output : outputs){
if(output.isSetLiteralOutput()){
String datatype = output.getLiteralOutput().getDataType().getStringValue();
if(datatype.contains("tring")){
return LiteralStringBinding.class;
}
if(datatype.contains("ollean")){
return LiteralBooleanBinding.class;
}
if(datatype.contains("loat") || datatype.contains("ouble")){
return LiteralDoubleBinding.class;
}
if(datatype.contains("nt")){
return LiteralIntBinding.class;
}
}
if(output.isSetComplexOutput()){
String mimeType = output.getComplexOutput().getDefault().getFormat().getMimeType();
if(mimeType.contains("xml") || (mimeType.contains("XML"))){
return GenericFileDataWithGTBinding.class;
}else{
return GenericFileDataWithGTBinding.class;
}
}
}
throw new RuntimeException("Could not determie internal inputDataType");
}
public Map<String, IData> run(Map<String, List<IData>> inputData) {
// TODO Auto-generated method stub
return null;
}
}