/** * Copyright (C) 2008 - 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.server.sextante; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import net.opengis.ows.x11.AllowedValuesDocument.AllowedValues; import net.opengis.ows.x11.DomainMetadataType; import net.opengis.ows.x11.RangeType; import net.opengis.wps.x100.ComplexDataCombinationType; import net.opengis.wps.x100.ComplexDataCombinationsType; import net.opengis.wps.x100.ComplexDataDescriptionType; import net.opengis.wps.x100.InputDescriptionType; import net.opengis.wps.x100.LiteralInputType; import net.opengis.wps.x100.OutputDescriptionType; import net.opengis.wps.x100.ProcessDescriptionType; import net.opengis.wps.x100.ProcessDescriptionType.DataInputs; import net.opengis.wps.x100.ProcessDescriptionType.ProcessOutputs; import net.opengis.wps.x100.SupportedComplexDataInputType; import net.opengis.wps.x100.SupportedComplexDataType; import org.n52.wps.FormatDocument.Format; import org.n52.wps.io.GeneratorFactory; import org.n52.wps.io.IGenerator; import org.n52.wps.io.IOHandler; import org.n52.wps.io.IParser; import org.n52.wps.io.ParserFactory; import org.n52.wps.io.data.binding.complex.GTVectorDataBinding; import es.unex.sextante.additionalInfo.AdditionalInfoMultipleInput; import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue; import es.unex.sextante.additionalInfo.AdditionalInfoRasterLayer; import es.unex.sextante.additionalInfo.AdditionalInfoSelection; import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer; import es.unex.sextante.core.GeoAlgorithm; import es.unex.sextante.core.OutputObjectsSet; import es.unex.sextante.core.ParametersSet; import es.unex.sextante.exceptions.NullParameterAdditionalInfoException; import es.unex.sextante.outputs.Output; import es.unex.sextante.outputs.OutputChart; import es.unex.sextante.outputs.OutputRasterLayer; import es.unex.sextante.outputs.OutputTable; import es.unex.sextante.outputs.OutputText; import es.unex.sextante.outputs.OutputVectorLayer; import es.unex.sextante.parameters.Parameter; import es.unex.sextante.parameters.ParameterBand; import es.unex.sextante.parameters.ParameterBoolean; import es.unex.sextante.parameters.ParameterFixedTable; import es.unex.sextante.parameters.ParameterMultipleInput; import es.unex.sextante.parameters.ParameterNumericalValue; import es.unex.sextante.parameters.ParameterPoint; import es.unex.sextante.parameters.ParameterRasterLayer; import es.unex.sextante.parameters.ParameterSelection; import es.unex.sextante.parameters.ParameterString; import es.unex.sextante.parameters.ParameterTableField; import es.unex.sextante.parameters.ParameterVectorLayer; public class SextanteProcessDescriptionCreator implements SextanteConstants{ public ProcessDescriptionType createDescribeProcessType(GeoAlgorithm algorithm) throws NullParameterAdditionalInfoException, UnsupportedGeoAlgorithmException{ ProcessDescriptionType pdt = ProcessDescriptionType.Factory.newInstance(); pdt.setStatusSupported(true); pdt.setStoreSupported(true); pdt.addNewAbstract().setStringValue(algorithm.getName()); pdt.addNewTitle().setStringValue(algorithm.getName()); pdt.addNewIdentifier().setStringValue(algorithm.getCommandLineName()); pdt.setProcessVersion("1.0.0"); //inputs DataInputs inputs = pdt.addNewDataInputs(); ParametersSet params = algorithm.getParameters(); for (int i = 0; i < params.getNumberOfParameters(); i++) { Parameter param = params.getParameter(i); addParameter(inputs, param); } //grid extent for raster layers (if needed) if (algorithm.getUserCanDefineAnalysisExtent()){ addGridExtent(inputs, algorithm.requiresRasterLayers()); } //outputs ProcessOutputs outputs = pdt.addNewProcessOutputs(); OutputObjectsSet ooset = algorithm.getOutputObjects(); for (int i = 0; i < ooset.getOutputObjectsCount(); i++) { Output out = ooset.getOutput(i); addOutput(outputs, out); } return pdt; } private void addGridExtent(DataInputs inputs, boolean bOptional){ addDoubleValue(inputs, GRID_EXTENT_X_MIN, "xMin", bOptional); addDoubleValue(inputs, GRID_EXTENT_X_MAX, "xMax", bOptional); addDoubleValue(inputs, GRID_EXTENT_Y_MIN, "yMin", bOptional); addDoubleValue(inputs, GRID_EXTENT_Y_MAX, "yMax", bOptional); addDoubleValue(inputs, GRID_EXTENT_CELLSIZE, "cellsize", bOptional); } private void addDoubleValue(DataInputs inputs, String name, String description, boolean bOptional){ int iMinOccurs = 1; if (bOptional){ iMinOccurs = 0; } InputDescriptionType input = inputs.addNewInput(); input.addNewAbstract().setStringValue(description); input.addNewTitle().setStringValue(description); input.addNewIdentifier().setStringValue(name); LiteralInputType literal = input.addNewLiteralData(); DomainMetadataType dataType = literal.addNewDataType(); dataType.setReference("xs:double"); literal.setDataType(dataType); input.setMinOccurs(BigInteger.valueOf(iMinOccurs)); input.setMaxOccurs(BigInteger.valueOf(1)); literal.setDefaultValue("0"); } private void addOutput(ProcessOutputs outputs, Output out) { OutputDescriptionType output = outputs.addNewOutput(); output.addNewAbstract().setStringValue(out.getDescription()); output.addNewIdentifier().setStringValue(out.getName()); output.addNewTitle().setStringValue(out.getDescription()); if (out instanceof OutputRasterLayer){ SupportedComplexDataType complexOutput = output.addNewComplexOutput(); complexOutput.addNewDefault().addNewFormat().setMimeType("image/tiff"); ComplexDataDescriptionType supportedFormat = complexOutput.addNewSupported().addNewFormat(); supportedFormat.setMimeType("image/tiff"); supportedFormat.setEncoding("base64"); } else if (out instanceof OutputVectorLayer){ SupportedComplexDataType complexOutput = output.addNewComplexOutput(); addVectorOutputFormats(complexOutput); /*ComplexDataDescriptionType deafult = complexOutput.addNewDefault().addNewFormat(); deafult.setMimeType(IOHandler.DEFAULT_MIMETYPE); deafult.setSchema("http://geoserver.itc.nl:8080/wps/schemas/gml/2.1.2/gmlpacket.xsd"); ComplexDataCombinationsType supported = complexOutput.addNewSupported(); ComplexDataDescriptionType supportedFormat = supported.addNewFormat(); supportedFormat.setMimeType(IOHandler.DEFAULT_MIMETYPE); supportedFormat.setSchema("http://schemas.opengis.net/gml/2.1.2/feature.xsd"); supportedFormat = supported.addNewFormat(); supportedFormat.setMimeType(IOHandler.MIME_TYPE_ZIPPED_SHP); supportedFormat.setEncoding(IOHandler.ENCODING_BASE64);*/ } else if (out instanceof OutputTable){ //TODO: } else if (out instanceof OutputText){ output.addNewComplexOutput().addNewDefault().addNewFormat().setMimeType("text/html"); } else if (out instanceof OutputChart){ //TODO: } } private void addParameter(DataInputs inputs, Parameter param) throws NullParameterAdditionalInfoException, UnsupportedGeoAlgorithmException { InputDescriptionType input = inputs.addNewInput(); input.addNewAbstract().setStringValue(param.getParameterDescription()); input.addNewTitle().setStringValue(param.getParameterDescription()); input.addNewIdentifier().setStringValue(param.getParameterName()); if (param instanceof ParameterRasterLayer){ AdditionalInfoRasterLayer ai = (AdditionalInfoRasterLayer) param.getParameterAdditionalInfo(); SupportedComplexDataInputType complex = input.addNewComplexData(); ComplexDataCombinationsType supported = complex.addNewSupported(); ComplexDataDescriptionType format = supported.addNewFormat(); format.setMimeType("image/tiff"); format = supported.addNewFormat(); format.setMimeType("image/tiff"); format.setEncoding(IOHandler.ENCODING_BASE64); ComplexDataDescriptionType defaultFormat = complex.addNewDefault().addNewFormat(); defaultFormat.setMimeType("image/tiff"); if (ai.getIsMandatory()){ input.setMinOccurs(BigInteger.valueOf(1)); } else{ input.setMinOccurs(BigInteger.valueOf(0)); } input.setMaxOccurs(BigInteger.valueOf(1)); }else if (param instanceof ParameterVectorLayer){ //TODO:add shape type AdditionalInfoVectorLayer ai = (AdditionalInfoVectorLayer) param.getParameterAdditionalInfo(); SupportedComplexDataInputType complex = input.addNewComplexData(); /*CComplexDataCombinationsType supported = complex.addNewSupported(); omplexDataDescriptionType format = supported.addNewFormat(); format.setMimeType(IOHandler.DEFAULT_MIMETYPE); format.setSchema("http://schemas.opengis.net/gml/2.1.2/feature.xsd"); format = supported.addNewFormat(); format.setEncoding(IOHandler.ENCODING_BASE64); format.setMimeType(IOHandler.MIME_TYPE_ZIPPED_SHP); ComplexDataDescriptionType defaultFormat = complex.addNewDefault().addNewFormat(); defaultFormat.setMimeType(IOHandler.DEFAULT_MIMETYPE); defaultFormat.setSchema("http://geoserver.itc.nl:8080/wps/schemas/gml/2.1.2/gmlpacket.xsd"); */ if (ai.getIsMandatory()){ input.setMinOccurs(BigInteger.valueOf(1)); } else{ input.setMinOccurs(BigInteger.valueOf(0)); } input.setMaxOccurs(BigInteger.valueOf(1)); addVectorInputsFormats(complex); } else if (param instanceof ParameterNumericalValue){ AdditionalInfoNumericalValue ai = (AdditionalInfoNumericalValue) param.getParameterAdditionalInfo(); LiteralInputType literal = input.addNewLiteralData(); DomainMetadataType dataType = literal.addNewDataType(); dataType.setReference("xs:double"); literal.setDataType(dataType); input.setMinOccurs(BigInteger.valueOf(1)); input.setMaxOccurs(BigInteger.valueOf(1)); RangeType range = literal.addNewAllowedValues().addNewRange(); range.addNewMaximumValue().setStringValue("" + Double.POSITIVE_INFINITY); range.addNewMinimumValue().setStringValue("" + Double.NEGATIVE_INFINITY); literal.setDefaultValue(Double.toString(ai.getDefaultValue())); } else if (param instanceof ParameterString){ LiteralInputType literal = input.addNewLiteralData(); input.setMinOccurs(BigInteger.valueOf(1)); input.setMaxOccurs(BigInteger.valueOf(1)); literal.addNewAnyValue(); DomainMetadataType dataType = literal.addNewDataType(); dataType.setReference("xs:string"); literal.setDataType(dataType); } else if (param instanceof ParameterMultipleInput){ AdditionalInfoMultipleInput ai = (AdditionalInfoMultipleInput) param.getParameterAdditionalInfo(); SupportedComplexDataInputType complex = input.addNewComplexData(); switch (ai.getDataType()){ case AdditionalInfoMultipleInput.DATA_TYPE_RASTER: complex.addNewDefault().addNewFormat().setMimeType("image/tiff"); if (ai.getIsMandatory()){ input.setMinOccurs(BigInteger.valueOf(1)); } else{ input.setMinOccurs(BigInteger.valueOf(0)); } input.setMaxOccurs(BigInteger.valueOf(1)); break; case AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_ANY: addVectorInputsFormats(complex); if (ai.getIsMandatory()){ input.setMinOccurs(BigInteger.valueOf(1)); } else{ input.setMinOccurs(BigInteger.valueOf(0)); } input.setMaxOccurs(BigInteger.valueOf(1)); break; case AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_LINE: addVectorInputsFormats(complex); if (ai.getIsMandatory()){ input.setMinOccurs(BigInteger.valueOf(1)); } else{ input.setMinOccurs(BigInteger.valueOf(0)); } input.setMaxOccurs(BigInteger.valueOf(1)); break; case AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_POINT: addVectorInputsFormats(complex); if (ai.getIsMandatory()){ input.setMinOccurs(BigInteger.valueOf(1)); } else{ input.setMinOccurs(BigInteger.valueOf(0)); } input.setMaxOccurs(BigInteger.valueOf(1)); break; case AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_POLYGON: addVectorInputsFormats(complex); if (ai.getIsMandatory()){ input.setMinOccurs(BigInteger.valueOf(1)); } else{ input.setMinOccurs(BigInteger.valueOf(0)); } input.setMaxOccurs(BigInteger.valueOf(1)); break; default: throw new UnsupportedGeoAlgorithmException(); } } else if (param instanceof ParameterSelection){ AdditionalInfoSelection ai = (AdditionalInfoSelection) param.getParameterAdditionalInfo(); String[] values = ai.getValues(); LiteralInputType literal = input.addNewLiteralData(); input.setMinOccurs(BigInteger.valueOf(1)); input.setMaxOccurs(BigInteger.valueOf(1)); AllowedValues allowedValues = literal.addNewAllowedValues(); for (int i = 0; i < values.length; i++) { allowedValues.addNewValue().setStringValue(values[i]); } DomainMetadataType dataType = literal.addNewDataType(); dataType.setReference("xs:string"); } else if (param instanceof ParameterTableField ){ //This has to be improved, to add the information about the parent parameter //the value is the zero-based index of the field LiteralInputType literal = input.addNewLiteralData(); input.setMinOccurs(BigInteger.valueOf(1)); input.setMaxOccurs(BigInteger.valueOf(1)); RangeType range = literal.addNewAllowedValues().addNewRange(); range.addNewMinimumValue().setStringValue("0"); range.addNewMaximumValue().setStringValue("" + Integer.MAX_VALUE); literal.setDefaultValue("0"); DomainMetadataType dataType = literal.addNewDataType(); dataType.setReference("xs:int"); } else if (param instanceof ParameterBand){ //This has to be improved, to add the information about the parent parameter LiteralInputType literal = input.addNewLiteralData(); input.setMinOccurs(BigInteger.valueOf(1)); input.setMaxOccurs(BigInteger.valueOf(1)); RangeType range = literal.addNewAllowedValues().addNewRange(); range.addNewMinimumValue().setStringValue("0"); range.addNewMaximumValue().setStringValue("" + Integer.MAX_VALUE); literal.setDefaultValue("0"); DomainMetadataType dataType = literal.addNewDataType(); dataType.setReference("xs:int"); } else if (param instanceof ParameterPoint){ //points are entered as x and y coordinates separated by a comma (any idea //about how to better do this?) LiteralInputType literal = input.addNewLiteralData(); input.setMinOccurs(BigInteger.valueOf(1)); input.setMaxOccurs(BigInteger.valueOf(1)); literal.setDefaultValue("0, 0"); DomainMetadataType dataType = literal.addNewDataType(); dataType.setReference("xs:string"); } else if (param instanceof ParameterBoolean){ LiteralInputType literal = input.addNewLiteralData(); input.setMinOccurs(BigInteger.valueOf(1)); DomainMetadataType dataType = literal.addNewDataType(); dataType.setReference("xs:boolean"); literal.setDataType(dataType); literal.addNewAnyValue(); input.setMinOccurs(BigInteger.valueOf(1)); input.setMaxOccurs(BigInteger.valueOf(1)); literal.setDefaultValue("false"); } else if (param instanceof ParameterFixedTable){ //TODO: throw new UnsupportedGeoAlgorithmException(); } } private void addVectorInputsFormats(SupportedComplexDataInputType complex) { List<IParser> parsers = ParserFactory.getInstance().getAllParsers(); List<IParser> foundParsers = new ArrayList<IParser>(); for(IParser parser : parsers) { Class<?>[] supportedClasses = parser.getSupportedDataBindings(); for(Class<?> clazz : supportedClasses){ if(clazz.equals(GTVectorDataBinding.class)){ foundParsers.add(parser); } } } ComplexDataCombinationsType supportedInputFormat = complex.addNewSupported(); for (int i = 0; i < foundParsers.size(); i++) { IParser parser = foundParsers.get(i); Format[] supportedFullFormats = parser.getSupportedFullFormats(); if (complex.getDefault() == null) { ComplexDataCombinationType defaultInputFormat = complex .addNewDefault(); /* * default format will be the first config format */ Format format = supportedFullFormats[0]; ComplexDataDescriptionType defaultFormat = defaultInputFormat .addNewFormat(); defaultFormat.setMimeType(format.getMimetype()); String encoding = format.getEncoding(); if (encoding != null && !encoding.equals("")) { defaultFormat.setEncoding(encoding); } String schema = format.getSchema(); if (schema != null && !schema.equals("")) { defaultFormat.setSchema(schema); } } for (int j = 0; j < supportedFullFormats.length; j++) { /* * create supportedFormat for each mimetype, encoding, schema * composition mimetypes can have several encodings and schemas */ Format format1 = supportedFullFormats[j]; /* * add one format for this mimetype */ ComplexDataDescriptionType supportedFormat = supportedInputFormat .addNewFormat(); supportedFormat.setMimeType(format1.getMimetype()); if (format1.getEncoding() != null) { supportedFormat.setEncoding(format1.getEncoding()); } if (format1.getSchema() != null) { supportedFormat.setSchema(format1.getSchema()); } } } // ComplexDataCombinationsType supported = complex.addNewSupported(); // for(int i = 0; i<foundParsers.size(); i++){ // IParser parser = foundParsers.get(i); // String[] supportedFormats = parser.getSupportedFormats(); // String[] supportedSchemas = parser.getSupportedSchemas(); // if(supportedSchemas == null){ // supportedSchemas = new String[0]; // } // String[] supportedEncodings = parser.getSupportedEncodings(); // // for(int j=0; j<supportedFormats.length;j++){ // for(int k=0; k<supportedEncodings.length;k++){ // if(j==0 && k==0 && i == 0){ // String supportedFormat = supportedFormats[j]; // ComplexDataDescriptionType defaultFormat = complex.addNewDefault().addNewFormat(); // // defaultFormat.setMimeType(supportedFormat); // defaultFormat.setEncoding(supportedEncodings[k]); // for(int t = 0; t<supportedSchemas.length;t++){ // if(t==0){ // defaultFormat.setSchema(supportedSchemas[t]); // } // } // }else{ // // String supportedFormat = supportedFormats[j]; // ComplexDataDescriptionType supportedCreatedFormat = supported.addNewFormat(); // supportedCreatedFormat.setMimeType(supportedFormat); // supportedCreatedFormat.setEncoding(supportedEncodings[k]); // for(int t = 0; t<supportedSchemas.length;t++){ // if(t==0){ // supportedCreatedFormat.setSchema(supportedSchemas[t]); // } // if(t>0){ // ComplexDataDescriptionType supportedCreatedFormatAdditional = supported.addNewFormat(); // supportedCreatedFormatAdditional.setEncoding(supportedEncodings[k]); // supportedCreatedFormatAdditional.setMimeType(supportedFormat); // supportedCreatedFormatAdditional.setSchema(supportedSchemas[t]); // } // } // } // } // } // } } private void addVectorOutputFormats(SupportedComplexDataType complex){ List<IGenerator> generators = GeneratorFactory.getInstance().getAllGenerators(); List<IGenerator> foundGenerators = new ArrayList<IGenerator>(); for(IGenerator generator : generators) { Class<?>[] supportedClasses = generator.getSupportedDataBindings(); for(Class<?> clazz : supportedClasses){ if(clazz.equals(GTVectorDataBinding.class)){ foundGenerators.add(generator); } } } ComplexDataCombinationsType supporteOutputFormat = complex.addNewSupported(); for (int i = 0; i < foundGenerators.size(); i++) { IGenerator generator = foundGenerators.get(i); Format[] supportedFullFormats = generator.getSupportedFullFormats(); if (complex.getDefault() == null) { ComplexDataCombinationType defaultInputFormat = complex .addNewDefault(); /* * default format will be the first config format */ Format format = supportedFullFormats[0]; ComplexDataDescriptionType defaultFormat = defaultInputFormat .addNewFormat(); defaultFormat.setMimeType(format.getMimetype()); String encoding = format.getEncoding(); if (encoding != null && !encoding.equals("")) { defaultFormat.setEncoding(encoding); } String schema = format.getSchema(); if (schema != null && !schema.equals("")) { defaultFormat.setSchema(schema); } } for (int j = 0; j < supportedFullFormats.length; j++) { /* * create supportedFormat for each mimetype, encoding, schema * composition mimetypes can have several encodings and schemas */ Format format1 = supportedFullFormats[j]; /* * add one format for this mimetype */ ComplexDataDescriptionType supportedFormat = supporteOutputFormat .addNewFormat(); supportedFormat.setMimeType(format1.getMimetype()); if (format1.getEncoding() != null) { supportedFormat.setEncoding(format1.getEncoding()); } if (format1.getSchema() != null) { supportedFormat.setSchema(format1.getSchema()); } } } // ComplexDataCombinationsType supported = complex.addNewSupported(); // for(int i = 0; i<foundGenerators.size(); i++){ // IGenerator generator = foundGenerators.get(i); // String[] supportedFormats = generator.getSupportedFormats(); // String[] supportedSchemas = generator.getSupportedSchemas(); // if(supportedSchemas == null){ // supportedSchemas = new String[0]; // } // String[] supportedEncodings = generator.getSupportedEncodings(); // // for(int j=0; j<supportedFormats.length;j++){ // for(int k=0; k<supportedEncodings.length;k++){ // if(j==0 && k==0 && i == 0){ // String supportedFormat = supportedFormats[j]; // ComplexDataDescriptionType defaultFormat = complex.addNewDefault().addNewFormat(); // defaultFormat.setMimeType(supportedFormat); // defaultFormat.setEncoding(supportedEncodings[k]); // for(int t = 0; t<supportedSchemas.length;t++){ // if(t==0){ // defaultFormat.setSchema(supportedSchemas[t]); // } // } // }else{ // // String supportedFormat = supportedFormats[j]; // ComplexDataDescriptionType supportedCreatedFormat = supported.addNewFormat(); // supportedCreatedFormat.setMimeType(supportedFormat); // supportedCreatedFormat.setEncoding(supportedEncodings[k]); // for(int t = 0; t<supportedSchemas.length;t++){ // if(t==0){ // supportedCreatedFormat.setSchema(supportedSchemas[t]); // } // if(t>0){ // ComplexDataDescriptionType supportedCreatedFormatAdditional = supported.addNewFormat(); // supportedCreatedFormatAdditional.setMimeType(supportedFormat); // supportedCreatedFormatAdditional.setSchema(supportedSchemas[t]); // supportedCreatedFormatAdditional.setEncoding(supportedEncodings[k]); // } // } // } // } // } // } } //This class is thrown when there is any problem creating the XML //WPS file from a geoalgorithm, due to some yet unsupported feature //or parameter public class UnsupportedGeoAlgorithmException extends Exception{ /** * */ private static final long serialVersionUID = 1017100163300095362L; } }