/**
* Copyright (C) 2009 - 2016 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.ags;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import net.opengis.wps.x100.ProcessDescriptionType;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.n52.wps.ags.algorithmpackage.AlgorithmPackage;
import org.n52.wps.ags.algorithmpackage.AlgorithmParameterType;
import org.n52.wps.ags.algorithmpackage.CommandLineParameter;
import org.n52.wps.ags.algorithmpackage.PackageUtils;
import org.n52.wps.ags.workspace.AGSWorkspace;
import org.n52.wps.io.data.GenericFileDataWithGT;
import org.n52.wps.io.data.GenericFileDataConstants;
import org.n52.wps.io.data.IData;
import org.n52.wps.io.data.binding.complex.GenericFileDataWithGTBinding;
import org.n52.wps.server.IAlgorithm;
/**
* @author Matthias Mueller, TU Dresden
*
*/
public class ArcToolboxProcessDelegator implements IAlgorithm{
private static final Logger LOGGER = LoggerFactory.getLogger(ArcToolboxProcessDelegator.class);
private AGSWorkspace agsWorkspace;
private final File toolWorkspace;
private final File workspaceBase;
private AlgorithmPackage mco;
protected List<String> errors;
private String[] toolParameters;
protected ArcToolboxProcessDelegator(AlgorithmPackage templateMCO, File workspaceBase) throws IOException{
this.workspaceBase = workspaceBase;
errors = new ArrayList<String>();
mco = templateMCO.createChild(workspaceBase);
toolParameters = new String[mco.getParameters().size()];
toolWorkspace = new File(mco.getInstanceWorkspace().getCanonicalPath());
}
public Map<String, IData> run(Map<String, List<IData>> inputData) {
//initialize arcObjects
AGSProperties.getInstance().bootstrapArcobjectsJar();
//create the workspace
agsWorkspace = new AGSWorkspace(toolWorkspace);
//retrieve path to the toolbox
String toolbox = toolWorkspace.getAbsolutePath() + mco.getAlgorithmURL().getPublicPath();
//retrieve the tool
String tool = mco.getAlgorithmURL().getPrivatePath();
List<AlgorithmParameterType> params = mco.getParameters();
HashMap<String, String> outputs = new HashMap<String,String>();
System.gc();
// assign parameters
for (AlgorithmParameterType currentParam : params){
String wpsInputID = currentParam.getWpsInputID();
String wpsOutputID = currentParam.getWpsOutputID();
int positionID = currentParam.getPositionID().intValue();
CommandLineParameter cmdParam = null;
// input parameters
if(!wpsInputID.equalsIgnoreCase("")){
if(inputData.containsKey(wpsInputID)){
//open the IData list and iterate through it
List<IData> dataItemList = inputData.get(wpsInputID);
Iterator<IData> it = dataItemList.iterator();
//create CommanLineParameter Object
cmdParam = new CommandLineParameter(currentParam.getPrefixString(), currentParam.getSuffixString(), currentParam.getSeparatorString());
while (it.hasNext()){
IData currentItem = it.next();
// load as file and add to CommanLineParameter
cmdParam.addValue((PackageUtils.loadSingleDataItem(currentItem, toolWorkspace)));
}
}
} else if (!wpsOutputID.equalsIgnoreCase("")){ // output only parameters !!ONLY SINGLE OUTPUT ITEMS SUPPORTED BY WPS!!
// create CommanLineParameter Object
cmdParam = new CommandLineParameter(currentParam.getPrefixString(), currentParam.getSuffixString(), currentParam.getSeparatorString());
// retrieve the default mimeType
String mimeType = mco.getDefaultMimeType(wpsOutputID);
// prepare output filename
String extension = GenericFileDataConstants.mimeTypeFileTypeLUT().get(mimeType);
String fileName = UUID.randomUUID().toString().substring(0,7) + "." + extension; // geoprocessor can't handle points, dashes etc in output file name
// String fileName = UUID.randomUUID() + "." + extension;
fileName = toolWorkspace.getAbsolutePath() + File.separator + fileName;
cmdParam.addValue(fileName);
}
//prepare the output - files only
if (!wpsOutputID.equalsIgnoreCase("")){
String fileName = cmdParam.getAsPlainString();
outputs.put(wpsOutputID, fileName);
}
// create a new parameter in the tool's Parameter Array
if (cmdParam == null){
toolParameters[positionID] = "";
} else {
toolParameters[positionID] = cmdParam.getAsCommandString();
}
}
//execute
LOGGER.info("Executing ArcGIS tool " + toolbox + File.pathSeparator + tool + " . Parameter array contains " + toolParameters.length + " parameters.");
try {
agsWorkspace.executeGPTool(tool, toolbox, toolParameters);
} catch (IOException e1) {
LOGGER.error(e1.getMessage());
errors.add(e1.getMessage());
throw new RuntimeException(e1.getMessage()); // otherwise WPS tries to zip and return non-existing files => null pointer
}
//create the output - files only
HashMap<String, IData> result = new HashMap<String, IData>();
for (String wpsOutputID : outputs.keySet()){
// create File object
File currentFile = new File (outputs.get(wpsOutputID));
GenericFileDataWithGT outputFileData;
try {
// create the GenericFileData object
outputFileData = new GenericFileDataWithGT(currentFile, mco.getDefaultMimeType(wpsOutputID));
// put result on output map
result.put(wpsOutputID, new GenericFileDataWithGTBinding(outputFileData));
} catch (FileNotFoundException e) {
LOGGER.error("Could not read output file: " + outputs.get(wpsOutputID));
e.printStackTrace();
} catch (IOException e) {
LOGGER.error("Could not create output file from: " + outputs.get(wpsOutputID));
e.printStackTrace();
}
}
return result;
}
public List<String> getErrors() {
return errors;
}
public ProcessDescriptionType getDescription() {
return mco.getProcessDescription();
}
public String getWellKnownName() {
return mco.getProcessID();
}
public boolean processDescriptionIsValid() {
return mco.getProcessDescription().validate();
}
public Class<?> getInputDataType(String id) {
return PackageUtils.getInputDataType(mco, id);
}
public Class<?> getOutputDataType(String id) {
return PackageUtils.getOutputDataType(mco, id);
}
//delete the current workspace
protected void finalize(){
try {
FileUtils.deleteDirectory(workspaceBase);
} catch (IOException e) {
LOGGER.error("Could not delete dead workspace:\n" + workspaceBase.getAbsolutePath());
e.printStackTrace();
}
}
}