1330 lines
50 KiB
Java
1330 lines
50 KiB
Java
/**
|
||
* Copyright (C) 2007 - 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.request;
|
||
|
||
import java.io.ByteArrayInputStream;
|
||
import java.io.File;
|
||
import java.io.FileInputStream;
|
||
import java.io.IOException;
|
||
import java.math.BigInteger;
|
||
import java.util.ArrayList;
|
||
import java.util.HashMap;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.UUID;
|
||
|
||
import javax.xml.transform.TransformerException;
|
||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||
|
||
import net.opengis.ows.x11.BoundingBoxType;
|
||
import net.opengis.ows.x11.DomainMetadataType;
|
||
import net.opengis.ows.x11.RangeType;
|
||
import net.opengis.ows.x11.ValueType;
|
||
import net.opengis.wps.x100.ComplexDataDescriptionType;
|
||
import net.opengis.wps.x100.ComplexDataType;
|
||
import net.opengis.wps.x100.InputDescriptionType;
|
||
import net.opengis.wps.x100.InputReferenceType;
|
||
import net.opengis.wps.x100.InputType;
|
||
import net.opengis.wps.x100.ProcessDescriptionType;
|
||
|
||
import org.apache.commons.io.FileUtils;
|
||
import org.apache.commons.lang.StringUtils;
|
||
import org.n52.wps.commons.XMLUtil;
|
||
import org.n52.wps.io.BasicXMLTypeFactory;
|
||
import org.n52.wps.io.IOHandler;
|
||
import org.n52.wps.io.IParser;
|
||
import org.n52.wps.io.ParserFactory;
|
||
import org.n52.wps.io.data.IData;
|
||
import org.n52.wps.io.data.binding.bbox.BoundingBoxData;
|
||
import org.n52.wps.io.data.binding.literal.AbstractLiteralDataBinding;
|
||
import org.n52.wps.io.data.binding.literal.LiteralByteBinding;
|
||
import org.n52.wps.io.data.binding.literal.LiteralDoubleBinding;
|
||
import org.n52.wps.io.data.binding.literal.LiteralFloatBinding;
|
||
import org.n52.wps.io.data.binding.literal.LiteralIntBinding;
|
||
import org.n52.wps.io.data.binding.literal.LiteralLongBinding;
|
||
import org.n52.wps.io.data.binding.literal.LiteralShortBinding;
|
||
import org.n52.wps.server.ExceptionReport;
|
||
import org.n52.wps.server.RepositoryManager;
|
||
import org.n52.wps.server.handler.DataInputInterceptors;
|
||
import org.n52.wps.server.handler.DataInputInterceptors.DataInputInterceptorImplementations;
|
||
import org.n52.wps.server.handler.DataInputInterceptors.InterceptorInstance;
|
||
import org.n52.wps.server.request.strategy.ReferenceInputStream;
|
||
import org.n52.wps.server.request.strategy.ReferenceStrategyRegister;
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
import org.w3c.dom.Node;
|
||
|
||
import com.google.common.primitives.Doubles;
|
||
|
||
/**
|
||
* Handles the input of the client and stores it into a Map.
|
||
*/
|
||
public class InputHandler {
|
||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(InputHandler.class);
|
||
private static final BigInteger INT_MAX
|
||
= BigInteger.valueOf(Integer.MAX_VALUE);
|
||
private static final BigInteger INT_MIN
|
||
= BigInteger.valueOf(Integer.MIN_VALUE);
|
||
private Map<String, List<IData>> inputData = new HashMap<String, List<IData>>();
|
||
private ProcessDescriptionType processDesc;
|
||
private String algorithmIdentifier = null; // Needed to take care of handling a conflict between different parsers.
|
||
|
||
public static class Builder {
|
||
protected InputType[] inputs;
|
||
protected String algorithmIdentifier = null;
|
||
|
||
public Builder(InputType[] inputs, String algorithmIdentifier) {
|
||
this.inputs = inputs;
|
||
this.algorithmIdentifier = algorithmIdentifier;
|
||
}
|
||
|
||
public Builder inputs(InputType[] val) {
|
||
inputs = val;
|
||
return this;
|
||
}
|
||
|
||
public Builder algorithmIdentifier(String val) {
|
||
algorithmIdentifier = val;
|
||
return this;
|
||
}
|
||
|
||
public InputHandler build() throws ExceptionReport {
|
||
return new InputHandler(this);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Initializes a parser that handles each (line of) input based on the type of input.
|
||
* @see #handleComplexData(IOValueType)
|
||
* @see #handleComplexValueReference(IOValueType)
|
||
* @see #handleLiteralData(IOValueType)
|
||
* @see #handleBBoxValue(IOValueType)
|
||
* @param builder
|
||
* @throws ExceptionReport
|
||
*/
|
||
private InputHandler(Builder builder) throws ExceptionReport {
|
||
this.algorithmIdentifier = builder.algorithmIdentifier;
|
||
this.processDesc = RepositoryManager.getInstance().getProcessDescription(algorithmIdentifier);
|
||
|
||
if (processDesc == null) {
|
||
throw new ExceptionReport("Error while accessing the process description for " + algorithmIdentifier,
|
||
ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
|
||
Map<String, InterceptorInstance> inputInterceptors = resolveInputInterceptors(algorithmIdentifier);
|
||
|
||
for (InputType input : builder.inputs) {
|
||
String inputId = input.getIdentifier().getStringValue().trim();
|
||
if (inputInterceptors.containsKey(inputId)) {
|
||
InterceptorInstance interceptor = inputInterceptors.get(inputId);
|
||
List<IData> result = interceptor.applyInterception(input);
|
||
|
||
if (result != null && !result.isEmpty()) {
|
||
this.inputData.put(inputId, result);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if(input.getData() != null) {
|
||
if(input.getData().getComplexData() != null) {
|
||
handleComplexData(input, inputId);
|
||
}
|
||
else if(input.getData().getLiteralData() != null) {
|
||
handleLiteralData(input);
|
||
}
|
||
else if(input.getData().getBoundingBoxData() != null) {
|
||
handleBBoxValue(input);
|
||
}
|
||
}
|
||
else if(input.getReference() != null) {
|
||
handleComplexValueReference(input);
|
||
}
|
||
else {
|
||
throw new ExceptionReport("Error while accessing the inputValue: " + inputId,
|
||
ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
}
|
||
}
|
||
|
||
Map<String, InterceptorInstance> resolveInputInterceptors(String algorithmClassName) {
|
||
Map<String,InterceptorInstance> result = new HashMap<String, InterceptorInstance>();
|
||
Class<?> clazz;
|
||
|
||
try {
|
||
clazz = Class.forName(algorithmClassName, false, getClass().getClassLoader());
|
||
} catch (ClassNotFoundException e) {
|
||
LOGGER.warn("Could not find class {}", algorithmClassName);
|
||
return result;
|
||
}
|
||
|
||
DataInputInterceptorImplementations annotation = clazz.getAnnotation(DataInputInterceptors.DataInputInterceptorImplementations.class);
|
||
if (annotation != null) {
|
||
Class<?> interceptorClazz;
|
||
try {
|
||
interceptorClazz = Class.forName(annotation.value());
|
||
} catch (ClassNotFoundException e) {
|
||
LOGGER.warn("Could not find class "+ annotation.value(), e);
|
||
return result;
|
||
}
|
||
|
||
if (DataInputInterceptors.class.isAssignableFrom(interceptorClazz)) {
|
||
DataInputInterceptors instance;
|
||
try {
|
||
instance = (DataInputInterceptors) interceptorClazz.newInstance();
|
||
} catch (InstantiationException e) {
|
||
LOGGER.warn("Could not instantiate class "+ interceptorClazz, e);
|
||
return result;
|
||
} catch (IllegalAccessException e) {
|
||
LOGGER.warn("Could not access class "+ interceptorClazz, e);
|
||
return result;
|
||
}
|
||
|
||
return instance.getInterceptors();
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
InputDescriptionType getInputReferenceDescriptionType(String inputId) {
|
||
for (InputDescriptionType tempDesc : this.processDesc.getDataInputs().getInputArray()) {
|
||
if (inputId.equals(tempDesc.getIdentifier().getStringValue())) {
|
||
return tempDesc;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
ComplexDataDescriptionType getNonDefaultFormat(InputDescriptionType inputRefDesc, String dataMimeType, String dataSchema, String dataEncoding) {
|
||
if (inputRefDesc.getComplexData() == null) {
|
||
return null; // No complex data within inputs
|
||
}
|
||
|
||
ComplexDataDescriptionType[] formats = inputRefDesc.getComplexData().getSupported().getFormatArray();
|
||
for (ComplexDataDescriptionType potentialFormat : formats) {
|
||
String pFormatSchema = potentialFormat.getSchema();
|
||
String pFormatEncoding = potentialFormat.getEncoding();
|
||
if (potentialFormat.getMimeType().equalsIgnoreCase(dataMimeType)) {
|
||
if (dataSchema != null && dataEncoding == null) {
|
||
if (dataSchema.equalsIgnoreCase(pFormatSchema)) {
|
||
return potentialFormat;
|
||
}
|
||
}
|
||
if (dataSchema == null && dataEncoding != null) {
|
||
if (dataEncoding.equalsIgnoreCase(pFormatEncoding)) {
|
||
return potentialFormat;
|
||
}
|
||
|
||
}
|
||
if (dataSchema != null && dataEncoding != null) {
|
||
if (dataSchema.equalsIgnoreCase(pFormatSchema)
|
||
&& dataEncoding.equalsIgnoreCase(pFormatEncoding)) {
|
||
return potentialFormat;
|
||
}
|
||
|
||
}
|
||
if (dataSchema == null && dataEncoding == null) {
|
||
return potentialFormat;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
protected String getComplexValueNodeString(Node complexValueNode) {
|
||
String complexValue;
|
||
try {
|
||
//handle different contents of complexdata
|
||
if(complexValueNode.getChildNodes().getLength() > 1){
|
||
complexValue = complexValueNode.getChildNodes().item(1).getNodeValue();
|
||
if(complexValue == null){
|
||
return XMLUtil.nodeToString(complexValueNode.getChildNodes().item(1));
|
||
}
|
||
}else{
|
||
complexValue = complexValueNode.getFirstChild().getNodeValue();
|
||
}
|
||
if(complexValue == null){
|
||
return XMLUtil.nodeToString(complexValueNode.getFirstChild());
|
||
}
|
||
} catch (TransformerFactoryConfigurationError e1) {
|
||
throw new TransformerFactoryConfigurationError("Could not parse inline data. Reason " + e1);
|
||
} catch (TransformerException e1) {
|
||
throw new TransformerFactoryConfigurationError("Could not parse inline data. Reason " + e1);
|
||
}
|
||
return complexValue;
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* Handles the complexValue, which in this case should always include XML
|
||
* which can be parsed into a FeatureCollection.
|
||
* @param input The client input
|
||
* @param inputId
|
||
* @throws ExceptionReport If error occured while parsing XML
|
||
*/
|
||
protected void handleComplexData(InputType input, String inputId) throws ExceptionReport{
|
||
String complexValue;
|
||
InputDescriptionType inputReferenceDesc;
|
||
ComplexDataType data;
|
||
Node complexValueNode;
|
||
ComplexDataDescriptionType format = null;
|
||
String dataSchema;
|
||
String dataEncoding;
|
||
String dataMimeType = null;
|
||
String formatSchema = null;
|
||
String formatEncoding = null;
|
||
String potentialFormatSchema = null;
|
||
String potentialFormatEncoding = null;
|
||
|
||
inputReferenceDesc = getInputReferenceDescriptionType(inputId);
|
||
if(inputReferenceDesc == null) {
|
||
LOGGER.debug("Input cannot be found in description for " + processDesc.getIdentifier().getStringValue() + "," + inputId);
|
||
}
|
||
|
||
data = input.getData().getComplexData();
|
||
|
||
dataSchema = data.getSchema();
|
||
dataMimeType = data.getMimeType();
|
||
dataEncoding = data.getEncoding();
|
||
|
||
complexValueNode = input.getData().getComplexData().getDomNode();
|
||
complexValue = getComplexValueNodeString(complexValueNode);
|
||
|
||
//select parser
|
||
//1. mimeType set?
|
||
//yes--> set it
|
||
//1.1 schema/encoding set?
|
||
//yes-->set it
|
||
//not-->set default values for parser with matching mime type
|
||
|
||
//no--> schema or/and encoding are set?
|
||
//yes-->use it, look if only one mime type can be found;
|
||
//not-->use default values
|
||
|
||
// overwrite with data format from request if appropriate
|
||
if (data.isSetMimeType() && dataMimeType != null){
|
||
format = findComplexDataDescriptionType(inputReferenceDesc, dataMimeType, dataSchema, dataEncoding, potentialFormatSchema, potentialFormatEncoding);
|
||
|
||
if(format == null){
|
||
throw new ExceptionReport("Could not determine intput format", ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
|
||
dataMimeType = format.getMimeType();
|
||
|
||
//no encoding provided--> select default one for mimeType
|
||
if(format.isSetEncoding()){
|
||
formatEncoding = format.getEncoding();
|
||
}
|
||
|
||
//no encoding provided--> select default one for mimeType
|
||
if(format.isSetSchema()){
|
||
formatSchema = format.getSchema();
|
||
}
|
||
} else {
|
||
//mimeType not in request
|
||
if(StringUtils.isBlank(dataMimeType) && !data.isSetEncoding() && !data.isSetSchema()){
|
||
//nothing set, use default values
|
||
formatSchema = inputReferenceDesc.getComplexData().getDefault().getFormat().getSchema();
|
||
dataMimeType = inputReferenceDesc.getComplexData().getDefault().getFormat().getMimeType();
|
||
formatEncoding = inputReferenceDesc.getComplexData().getDefault().getFormat().getEncoding();
|
||
}else{
|
||
//do a smart search an look if a mimeType can be found for either schema and/or encoding
|
||
if(StringUtils.isBlank(dataMimeType)){
|
||
|
||
if(data.isSetEncoding() && !data.isSetSchema()){
|
||
//encoding set only
|
||
int foundCount = 0;
|
||
String defaultEncoding = inputReferenceDesc.getComplexData().getDefault().getFormat().getEncoding();
|
||
ComplexDataDescriptionType encodingFormat = null;
|
||
String foundEncoding = null;
|
||
if(defaultEncoding.equalsIgnoreCase(data.getEncoding())){
|
||
foundEncoding = inputReferenceDesc.getComplexData().getDefault().getFormat().getEncoding();
|
||
encodingFormat = inputReferenceDesc.getComplexData().getDefault().getFormat();
|
||
foundCount++;
|
||
}else{
|
||
ComplexDataDescriptionType[] formats = inputReferenceDesc.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType tempFormat : formats){
|
||
if(tempFormat.getEncoding().equalsIgnoreCase(data.getEncoding())){
|
||
foundEncoding = tempFormat.getEncoding();
|
||
encodingFormat = tempFormat;
|
||
foundCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(foundCount == 1){
|
||
formatEncoding = foundEncoding;
|
||
dataMimeType = encodingFormat.getMimeType();
|
||
if(encodingFormat.isSetSchema()){
|
||
formatSchema = encodingFormat.getSchema();
|
||
}
|
||
}else{
|
||
throw new ExceptionReport("Request incomplete. Could not determine a suitable input format based on the given input [mime Type missing and given encoding not unique]", ExceptionReport.MISSING_PARAMETER_VALUE);
|
||
}
|
||
|
||
} else if(data.isSetSchema() && !data.isSetEncoding()){
|
||
//schema set only
|
||
ComplexDataDescriptionType schemaFormat = null;
|
||
String defaultSchema = inputReferenceDesc.getComplexData().getDefault().getFormat().getSchema();
|
||
int found = 0;
|
||
String foundSchema = null;
|
||
//TODO: please review change
|
||
//Old version causes NullPointerException if default input is given by mimetype and not by schema:
|
||
/*
|
||
if(defaultSchema != null && defaultSchema.equalsIgnoreCase(data.getSchema())){
|
||
...
|
||
}
|
||
|
||
* */
|
||
if(!StringUtils.isBlank(defaultSchema) && defaultSchema.equalsIgnoreCase(data.getSchema())){
|
||
foundSchema = inputReferenceDesc.getComplexData().getDefault().getFormat().getSchema();
|
||
schemaFormat = inputReferenceDesc.getComplexData().getDefault().getFormat();
|
||
found++;
|
||
}else{
|
||
ComplexDataDescriptionType[] formats = inputReferenceDesc.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType tempFormat : formats){
|
||
//TODO: please review change
|
||
//Old if-clause wouldn't be true ever and causes NullPointerException if one of the supported types is given by mimetype and not by schema:
|
||
/*
|
||
if(tempFormat.getEncoding().equalsIgnoreCase(data.getSchema())){
|
||
foundSchema = tempFormat.getSchema();
|
||
schemaFormat =tempFormat;
|
||
found = found +1;
|
||
}
|
||
|
||
*/
|
||
if(tempFormat.isSetSchema() && tempFormat.getSchema().equalsIgnoreCase(data.getSchema())){
|
||
foundSchema = tempFormat.getSchema();
|
||
schemaFormat =tempFormat;
|
||
found++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(found == 1){
|
||
formatSchema = foundSchema;
|
||
dataMimeType = schemaFormat.getMimeType();
|
||
if(schemaFormat.isSetEncoding()){
|
||
formatEncoding = schemaFormat.getEncoding();
|
||
}
|
||
}else{
|
||
throw new ExceptionReport("Request incomplete. Could not determine a suitable input format based on the given input [mime Type missing and given schema not unique]", ExceptionReport.MISSING_PARAMETER_VALUE);
|
||
}
|
||
|
||
} else if(data.isSetEncoding() && data.isSetSchema()){
|
||
//schema and encoding set
|
||
//encoding
|
||
String defaultEncoding = inputReferenceDesc.getComplexData().getDefault().getFormat().getEncoding();
|
||
|
||
List<ComplexDataDescriptionType> foundEncodingList = new ArrayList<ComplexDataDescriptionType>();
|
||
if(defaultEncoding.equalsIgnoreCase(data.getEncoding())){
|
||
foundEncodingList.add(inputReferenceDesc.getComplexData().getDefault().getFormat());
|
||
}else{
|
||
ComplexDataDescriptionType[] formats = inputReferenceDesc.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType tempFormat : formats){
|
||
if(tempFormat.getEncoding().equalsIgnoreCase(data.getEncoding())){
|
||
foundEncodingList.add(tempFormat);
|
||
}
|
||
}
|
||
|
||
//schema
|
||
List<ComplexDataDescriptionType> foundSchemaList = new ArrayList<ComplexDataDescriptionType>();
|
||
String defaultSchema = inputReferenceDesc.getComplexData().getDefault().getFormat().getSchema();
|
||
//TODO: please review change
|
||
//Old version causes NullPointerException if default input is given by mimetype and not by schema:
|
||
//
|
||
//if(defaultSchema.equalsIgnoreCase(data.getSchema())){...
|
||
//
|
||
if(defaultSchema!= null && defaultSchema.equalsIgnoreCase(data.getSchema())){
|
||
foundSchemaList.add(inputReferenceDesc.getComplexData().getDefault().getFormat());
|
||
}else{
|
||
formats = inputReferenceDesc.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType tempFormat : formats){
|
||
/*
|
||
* TODO please review Change
|
||
* Old if-clause wouldn't be true ever and causes NullPointerException if one of the supported types is given by mimetype and not by schema:
|
||
*
|
||
* old code:
|
||
if(tempFormat.getEncoding().equalsIgnoreCase(data.getSchema())){
|
||
foundSchemaList.add(tempFormat);
|
||
}
|
||
*/
|
||
if(tempFormat.getSchema()!=null && tempFormat.getSchema().equalsIgnoreCase(data.getSchema())){
|
||
foundSchemaList.add(tempFormat);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//results
|
||
ComplexDataDescriptionType foundCommonFormat = null;
|
||
for(ComplexDataDescriptionType encodingFormat : foundEncodingList){
|
||
for(ComplexDataDescriptionType schemaFormat : foundSchemaList){
|
||
if(encodingFormat.equals(schemaFormat)){
|
||
foundCommonFormat = encodingFormat;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(foundCommonFormat!=null){
|
||
dataMimeType = foundCommonFormat.getMimeType();
|
||
if(foundCommonFormat.isSetEncoding()){
|
||
formatEncoding = foundCommonFormat.getEncoding();
|
||
}
|
||
if(foundCommonFormat.isSetSchema()){
|
||
formatSchema = foundCommonFormat.getSchema();
|
||
}
|
||
}else{
|
||
throw new ExceptionReport("Request incomplete. Could not determine a suitable input format based on the given input [mime Type missing and given encoding and schema are not unique]", ExceptionReport.MISSING_PARAMETER_VALUE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
IParser parser = null;
|
||
try {
|
||
LOGGER.debug("Looking for matching Parser ..." +
|
||
" schema: " + formatSchema +
|
||
" mimeType: " + dataMimeType +
|
||
" encoding: " + formatEncoding);
|
||
|
||
Class<?> algorithmInput = RepositoryManager.getInstance().getInputDataTypeForAlgorithm(this.algorithmIdentifier, inputId);
|
||
parser = ParserFactory.getInstance().getParser(formatSchema, dataMimeType, formatEncoding, algorithmInput);
|
||
} catch (RuntimeException e) {
|
||
throw new ExceptionReport("Error obtaining input data", ExceptionReport.NO_APPLICABLE_CODE, e);
|
||
}
|
||
|
||
if(parser == null) {
|
||
throw new ExceptionReport("Error. No applicable parser found for " + formatSchema + "," + dataMimeType + "," + formatEncoding, ExceptionReport.NO_APPLICABLE_CODE);
|
||
}
|
||
|
||
IData collection = parseComplexValue(formatEncoding, complexValue, dataMimeType, formatSchema, parser);
|
||
|
||
//enable maxoccurs of parameters with the same name.
|
||
List<IData> list = new ArrayList<IData>();
|
||
if(inputData.containsKey(inputId)) {
|
||
list = inputData.get(inputId);
|
||
}
|
||
list.add(collection);
|
||
inputData.put(inputId, list);
|
||
}
|
||
|
||
protected ComplexDataDescriptionType findComplexDataDescriptionType(InputDescriptionType inputReferenceDesc, String dataMimeType, String dataSchema, String dataEncoding, String potentialFormatSchema, String potentialFormatEncoding) {
|
||
ComplexDataDescriptionType result = null;
|
||
boolean canUseDefault = false;
|
||
String defaultMimeType = inputReferenceDesc.getComplexData().getDefault().getFormat().getMimeType();
|
||
|
||
if(defaultMimeType.equalsIgnoreCase(dataMimeType)){
|
||
ComplexDataDescriptionType potentialFormat = inputReferenceDesc.getComplexData().getDefault().getFormat();
|
||
LOGGER.debug("FindComplexDataDescriptionType->data schema: "+dataSchema+" data encoding "+dataEncoding);
|
||
LOGGER.debug("FindComplexDataDescriptionType->potential format schema : "+potentialFormatSchema);
|
||
//added by Gianpaolo Coro on 17/07/15
|
||
if (dataSchema!= null && dataSchema.trim().length()==0)
|
||
dataSchema = null;
|
||
|
||
if(dataSchema != null && dataEncoding == null){
|
||
if(dataSchema.equalsIgnoreCase(potentialFormatSchema)){
|
||
canUseDefault = true;
|
||
result = potentialFormat;
|
||
}
|
||
} else if(dataSchema != null && dataEncoding != null) {
|
||
if(dataSchema.equalsIgnoreCase(potentialFormatSchema)
|
||
&& dataEncoding.equalsIgnoreCase(potentialFormatEncoding)){
|
||
canUseDefault = true;
|
||
result = potentialFormat;
|
||
}
|
||
} else if(dataSchema == null && dataEncoding != null){
|
||
if(dataEncoding.equalsIgnoreCase(potentialFormatEncoding)){
|
||
canUseDefault = true;
|
||
result = potentialFormat;
|
||
}
|
||
} else {
|
||
canUseDefault = true;
|
||
result = potentialFormat;
|
||
}
|
||
}
|
||
LOGGER.debug("FindComplexDataDescriptionType->canUseDefault: "+canUseDefault);
|
||
LOGGER.debug("FindComplexDataDescriptionType->result: "+result);
|
||
|
||
if (!canUseDefault) {
|
||
result = getNonDefaultFormat(inputReferenceDesc, dataMimeType, dataSchema, dataEncoding);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
protected IData parseComplexValue(String formatEncoding, String complexValue, String dataMimeType, String formatSchema, IParser parser) throws ExceptionReport {
|
||
IData idata;
|
||
String complexValueCopy = complexValue.toString();
|
||
// encoding is UTF-8 (or nothing and we default to UTF-8)
|
||
// everything that goes to this condition should be inline xml data
|
||
if (StringUtils.isBlank(formatEncoding) || formatEncoding.equalsIgnoreCase(IOHandler.DEFAULT_ENCODING)){
|
||
try {
|
||
if(!complexValueCopy.contains("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")){
|
||
complexValueCopy = complexValueCopy.replace("xsi:schemaLocation", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation");
|
||
}
|
||
idata = parser.parse(new ByteArrayInputStream(complexValueCopy.getBytes()), dataMimeType, formatSchema);
|
||
} catch(RuntimeException e) {
|
||
throw new ExceptionReport("Error occured, while XML parsing", ExceptionReport.NO_APPLICABLE_CODE, e);
|
||
}
|
||
} else if (formatEncoding.equalsIgnoreCase(IOHandler.ENCODING_BASE64)){
|
||
// in case encoding is base64
|
||
// everything that goes to this condition should be inline base64 data
|
||
idata = getBase64EncodedData(complexValue, parser, dataMimeType, formatSchema);
|
||
} else {
|
||
throw new ExceptionReport("Unable to generate encoding " + formatEncoding, ExceptionReport.NO_APPLICABLE_CODE);
|
||
}
|
||
return idata;
|
||
}
|
||
|
||
//TODO-- Needs testing
|
||
protected IData getBase64EncodedData(String complexValue, IParser parser, String dataMimeType, String formatSchema) throws ExceptionReport {
|
||
File f = null;
|
||
String complexValueCopy = complexValue.toString();
|
||
|
||
try {
|
||
f = File.createTempFile("wps" + UUID.randomUUID(), "tmp");
|
||
|
||
if (complexValueCopy.startsWith("<xml-fragment")) {
|
||
int startIndex = complexValueCopy.indexOf(">");
|
||
complexValueCopy = complexValueCopy.substring(startIndex + 1);
|
||
|
||
int endIndex = complexValueCopy.indexOf("</xml-fragment");
|
||
complexValueCopy = complexValueCopy.substring(0, endIndex);
|
||
}
|
||
|
||
FileUtils.write(f, complexValueCopy);
|
||
|
||
return parser.parseBase64(new FileInputStream(f), dataMimeType, formatSchema);
|
||
|
||
} catch (IOException e) {
|
||
throw new ExceptionReport("Error occured, while Base64 extracting", ExceptionReport.NO_APPLICABLE_CODE, e);
|
||
} finally {
|
||
FileUtils.deleteQuietly(f);
|
||
System.gc();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Handles the literalData
|
||
* @param input The client's input
|
||
* @throws ExceptionReport If the type of the parameter is invalid.
|
||
*/
|
||
private void handleLiteralData(InputType input) throws ExceptionReport {
|
||
String inputID = input.getIdentifier().getStringValue();
|
||
String parameter = input.getData().getLiteralData().getStringValue();
|
||
String xmlDataType = input.getData().getLiteralData().getDataType();
|
||
String uom = input.getData().getLiteralData().getUom();
|
||
|
||
InputDescriptionType inputDesc = null;
|
||
for(InputDescriptionType tempDesc : this.processDesc.getDataInputs().getInputArray()) {
|
||
if(inputID.equals(tempDesc.getIdentifier().getStringValue())) {
|
||
inputDesc = tempDesc;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(xmlDataType == null) {
|
||
DomainMetadataType dataType = inputDesc.getLiteralData().getDataType();
|
||
xmlDataType = dataType != null ? dataType.getReference() : null;
|
||
}
|
||
//still null, assume string as default
|
||
if(xmlDataType == null) {
|
||
xmlDataType = BasicXMLTypeFactory.STRING_URI;
|
||
} else if(xmlDataType.contains("http://www.w3.org/TR/xmlschema-2#")){
|
||
xmlDataType = xmlDataType.replace("http://www.w3.org/TR/xmlschema-2#","xs:");
|
||
}
|
||
xmlDataType = xmlDataType.toLowerCase();
|
||
|
||
IData parameterObj = null;
|
||
try {
|
||
parameterObj = BasicXMLTypeFactory.getBasicJavaObject(xmlDataType, parameter);
|
||
}
|
||
catch(RuntimeException e) {
|
||
throw new ExceptionReport("The passed parameterValue: " + parameter + " for input " + inputID + " is not of type: " + xmlDataType, ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
|
||
//validate allowed values.
|
||
if(inputDesc.getLiteralData().isSetAllowedValues()){
|
||
if((!inputDesc.getLiteralData().isSetAnyValue())){
|
||
ValueType[] allowedValues = inputDesc.getLiteralData().getAllowedValues().getValueArray();
|
||
boolean foundAllowedValue = false;
|
||
for(ValueType allowedValue : allowedValues){
|
||
if(input.getData().getLiteralData().getStringValue().equals(allowedValue.getStringValue())){
|
||
foundAllowedValue = true;
|
||
|
||
}
|
||
}
|
||
RangeType[] allowedRanges = {};
|
||
if(parameterObj instanceof LiteralIntBinding || parameterObj instanceof LiteralDoubleBinding || parameterObj instanceof LiteralShortBinding || parameterObj instanceof LiteralFloatBinding || parameterObj instanceof LiteralLongBinding || parameterObj instanceof LiteralByteBinding){
|
||
|
||
allowedRanges = inputDesc.getLiteralData().getAllowedValues().getRangeArray();
|
||
for(RangeType allowedRange : allowedRanges){
|
||
foundAllowedValue = checkRange(parameterObj, allowedRange);
|
||
}
|
||
}
|
||
|
||
if(!foundAllowedValue && (allowedValues.length!=0 || allowedRanges.length!=0)){
|
||
throw new ExceptionReport("Input with ID " + inputID + " does not contain an allowed value. See ProcessDescription.", ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
if(parameterObj == null) {
|
||
throw new ExceptionReport("XML datatype as LiteralParameter is not supported by the server: dataType " + xmlDataType,
|
||
ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
|
||
if(uom != null && !uom.equals("")){
|
||
if(parameterObj instanceof AbstractLiteralDataBinding){
|
||
((AbstractLiteralDataBinding)parameterObj).setUnitOfMeasurement(uom);
|
||
}
|
||
}
|
||
|
||
//enable maxxoccurs of parameters with the same name.
|
||
if(inputData.containsKey(inputID)) {
|
||
List<IData> list = inputData.get(inputID);
|
||
list.add(parameterObj);
|
||
}
|
||
else {
|
||
List<IData> list = new ArrayList<IData>();
|
||
list.add(parameterObj);
|
||
inputData.put(inputID, list);
|
||
}
|
||
|
||
}
|
||
|
||
private boolean checkRange(IData parameterObj, RangeType allowedRange){
|
||
|
||
List<?> l = allowedRange.getRangeClosure();
|
||
|
||
/*
|
||
* no closure info or RangeClosure is "closed", so include boundaries
|
||
*/
|
||
if(l == null || l.isEmpty() || l.get(0).equals("closed")){
|
||
|
||
if((parameterObj instanceof LiteralIntBinding)){
|
||
int min = new Integer(allowedRange.getMinimumValue().getStringValue());
|
||
int max = new Integer(allowedRange.getMaximumValue().getStringValue());
|
||
if((Integer)(parameterObj.getPayload())>=min && (Integer)parameterObj.getPayload()<=max){
|
||
return true;
|
||
}
|
||
}
|
||
if((parameterObj instanceof LiteralDoubleBinding)){
|
||
Double min = new Double(allowedRange.getMinimumValue().getStringValue());
|
||
Double max = new Double(allowedRange.getMaximumValue().getStringValue());
|
||
if((Double)(parameterObj.getPayload())>=min && (Double)parameterObj.getPayload()<=max){
|
||
return true;
|
||
}
|
||
}
|
||
if((parameterObj instanceof LiteralShortBinding)){
|
||
Short min = new Short(allowedRange.getMinimumValue().getStringValue());
|
||
Short max = new Short(allowedRange.getMaximumValue().getStringValue());
|
||
if((Short)(parameterObj.getPayload())>=min && (Short)parameterObj.getPayload()<=max){
|
||
return true;
|
||
}
|
||
}
|
||
if((parameterObj instanceof LiteralFloatBinding)){
|
||
Float min = new Float(allowedRange.getMinimumValue().getStringValue());
|
||
Float max = new Float(allowedRange.getMaximumValue().getStringValue());
|
||
if((Float)(parameterObj.getPayload())>=min && (Float)parameterObj.getPayload()<=max){
|
||
return true;
|
||
}
|
||
}
|
||
if((parameterObj instanceof LiteralLongBinding)){
|
||
Long min = new Long(allowedRange.getMinimumValue().getStringValue());
|
||
Long max = new Long(allowedRange.getMaximumValue().getStringValue());
|
||
if((Long)(parameterObj.getPayload())>=min && (Long)parameterObj.getPayload()<=max){
|
||
return true;
|
||
}
|
||
}
|
||
if((parameterObj instanceof LiteralByteBinding)){
|
||
Byte min = new Byte(allowedRange.getMinimumValue().getStringValue());
|
||
Byte max = new Byte(allowedRange.getMaximumValue().getStringValue());
|
||
if((Byte)(parameterObj.getPayload())>=min && (Byte)parameterObj.getPayload()<=max){
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/*
|
||
* TODO:implement other closure cases
|
||
*/
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Handles the ComplexValueReference
|
||
* @param input The client input
|
||
* @throws ExceptionReport If the input (as url) is invalid, or there is an error while parsing the XML.
|
||
*/
|
||
private void handleComplexValueReference(InputType input) throws ExceptionReport{
|
||
String inputID = input.getIdentifier().getStringValue();
|
||
|
||
ReferenceStrategyRegister register = ReferenceStrategyRegister.getInstance();
|
||
ReferenceInputStream stream = register.resolveReference(input);
|
||
|
||
String dataURLString = input.getReference().getHref();
|
||
//dataURLString = URLDecoder.decode(dataURLString);
|
||
//dataURLString = dataURLString.replace("&", "");
|
||
LOGGER.debug("Loading data from: " + dataURLString);
|
||
|
||
|
||
/**
|
||
* initialize data format with default values defaults and overwrite with defaults from request if applicable
|
||
*/
|
||
InputDescriptionType inputPD = null;
|
||
for(InputDescriptionType tempDesc : this.processDesc.getDataInputs().getInputArray()) {
|
||
if(inputID.equals(tempDesc.getIdentifier().getStringValue())) {
|
||
inputPD = tempDesc;
|
||
break;
|
||
}
|
||
}
|
||
if(inputPD == null) { // check if there is a corresponding input identifier in the process description
|
||
LOGGER.debug("Input cannot be found in description for " + this.processDesc.getIdentifier().getStringValue() + "," + inputID);
|
||
throw new RuntimeException("Input cannot be found in description for " + this.processDesc.getIdentifier().getStringValue() + "," + inputID);
|
||
}
|
||
|
||
//select parser
|
||
|
||
//1. mimeType set?
|
||
//yes--> set it
|
||
//1.1 schema/encoding set?
|
||
//yes-->set it
|
||
//not-->set default values for parser with matching mime type
|
||
|
||
//no--> look in http stream
|
||
//2. mimeType set in http stream
|
||
//yes -->set it
|
||
//2.1 schema/encoding set?
|
||
//yes-->set it
|
||
//not-->set default values for parser with matching mime type
|
||
//no--> schema or/and encoding are set?
|
||
//yes-->use it, look if only one mime type can be found
|
||
//not-->use default values
|
||
|
||
|
||
|
||
String schema = null;
|
||
String mimeType = null;
|
||
String encoding = null;
|
||
|
||
// overwrite with data format from request if appropriate
|
||
InputReferenceType referenceData = input.getReference();
|
||
|
||
if (referenceData.isSetMimeType() && referenceData.getMimeType() != null){
|
||
//mime type in request
|
||
mimeType = referenceData.getMimeType();
|
||
ComplexDataDescriptionType format = null;
|
||
|
||
String defaultMimeType = inputPD.getComplexData().getDefault().getFormat().getMimeType();
|
||
|
||
boolean canUseDefault = false;
|
||
if(defaultMimeType.equalsIgnoreCase(mimeType)){
|
||
ComplexDataDescriptionType potentialFormat = inputPD.getComplexData().getDefault().getFormat();
|
||
if(referenceData.getSchema() != null && referenceData.getEncoding() == null){
|
||
if(referenceData.getSchema().equalsIgnoreCase(potentialFormat.getSchema())){
|
||
canUseDefault = true;
|
||
format = potentialFormat;
|
||
}
|
||
}
|
||
if(referenceData.getSchema() == null && referenceData.getEncoding() != null){
|
||
if(referenceData.getEncoding().equalsIgnoreCase(potentialFormat.getEncoding())){
|
||
canUseDefault = true;
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(referenceData.getSchema() != null && referenceData.getEncoding() != null){
|
||
if(referenceData.getSchema().equalsIgnoreCase(potentialFormat.getSchema()) && referenceData.getEncoding().equalsIgnoreCase(potentialFormat.getEncoding())){
|
||
canUseDefault = true;
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(referenceData.getSchema() == null && referenceData.getEncoding() == null){
|
||
canUseDefault = true;
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(!canUseDefault){
|
||
ComplexDataDescriptionType[] formats = inputPD.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType potentialFormat : formats){
|
||
if(potentialFormat.getMimeType().equalsIgnoreCase(mimeType)){
|
||
if(referenceData.getSchema() != null && referenceData.getEncoding() == null){
|
||
if(referenceData.getSchema().equalsIgnoreCase(potentialFormat.getSchema())){
|
||
format = potentialFormat;
|
||
}
|
||
}
|
||
if(referenceData.getSchema() == null && referenceData.getEncoding() != null){
|
||
if(referenceData.getEncoding().equalsIgnoreCase(potentialFormat.getEncoding())){
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(referenceData.getSchema() != null && referenceData.getEncoding() != null){
|
||
if(referenceData.getSchema().equalsIgnoreCase(potentialFormat.getSchema()) && referenceData.getEncoding().equalsIgnoreCase(potentialFormat.getEncoding())){
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(referenceData.getSchema() == null && referenceData.getEncoding() == null){
|
||
format = potentialFormat;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if(format == null){
|
||
throw new ExceptionReport("Possibly multiple or none matching generators found for the input data with id = \"" + inputPD.getIdentifier().getStringValue() + "\". Is the MimeType (\"" + referenceData.getMimeType() + "\") correctly set?", ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
//throw new ExceptionReport("Could not determine format of the input data (id= \"" + inputPD.getIdentifier().getStringValue() + "\"), given the mimetype \"" + referenceData.getMimeType() + "\"", ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
|
||
}
|
||
|
||
mimeType = format.getMimeType();
|
||
|
||
if(format.isSetEncoding()){
|
||
//no encoding provided--> select default one for mimeType
|
||
encoding = format.getEncoding();
|
||
}
|
||
|
||
if(format.isSetSchema()){
|
||
//no encoding provided--> select default one for mimeType
|
||
schema = format.getSchema();
|
||
}
|
||
|
||
}else{
|
||
// mimeType not in request, fetch mimetype from reference response
|
||
mimeType = stream.getMimeType();
|
||
if(mimeType.contains("GML2")){
|
||
mimeType = "text/xml; subtype=gml/2.0.0";
|
||
}
|
||
if(mimeType.contains("GML3")){
|
||
mimeType = "text/xml; subtype=gml/3.0.0";
|
||
}
|
||
ComplexDataDescriptionType format = null;
|
||
|
||
if(mimeType != null){
|
||
String defaultMimeType = inputPD.getComplexData().getDefault().getFormat().getMimeType();
|
||
|
||
boolean canUseDefault = false;
|
||
if(defaultMimeType.equalsIgnoreCase(mimeType)){
|
||
ComplexDataDescriptionType potentialFormat = inputPD.getComplexData().getDefault().getFormat();
|
||
if(referenceData.getSchema() != null && referenceData.getEncoding() == null){
|
||
if(referenceData.getSchema().equalsIgnoreCase(potentialFormat.getSchema())){
|
||
canUseDefault = true;
|
||
format = potentialFormat;
|
||
}
|
||
}
|
||
if(referenceData.getSchema() == null && referenceData.getEncoding() != null){
|
||
if(referenceData.getEncoding().equalsIgnoreCase(potentialFormat.getEncoding())){
|
||
canUseDefault = true;
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(referenceData.getSchema() != null && referenceData.getEncoding() != null){
|
||
if(referenceData.getSchema().equalsIgnoreCase(potentialFormat.getSchema()) && referenceData.getEncoding().equalsIgnoreCase(potentialFormat.getEncoding())){
|
||
canUseDefault = true;
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(referenceData.getSchema() == null && referenceData.getEncoding() == null){
|
||
canUseDefault = true;
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(!canUseDefault){
|
||
ComplexDataDescriptionType[] formats = inputPD.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType potentialFormat : formats){
|
||
if(!StringUtils.isBlank(potentialFormat.getMimeType()) && potentialFormat.getMimeType().equalsIgnoreCase(mimeType)){
|
||
if(referenceData.getSchema() != null && referenceData.getEncoding() == null){
|
||
if(referenceData.getSchema().equalsIgnoreCase(potentialFormat.getSchema())){
|
||
format = potentialFormat;
|
||
}
|
||
}
|
||
if(referenceData.getSchema() == null && referenceData.getEncoding() != null){
|
||
if(referenceData.getEncoding().equalsIgnoreCase(potentialFormat.getEncoding())){
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(referenceData.getSchema() != null && referenceData.getEncoding() != null){
|
||
if(referenceData.getSchema().equalsIgnoreCase(potentialFormat.getSchema()) && referenceData.getEncoding().equalsIgnoreCase(potentialFormat.getEncoding())){
|
||
format = potentialFormat;
|
||
}
|
||
|
||
}
|
||
if(referenceData.getSchema() == null && referenceData.getEncoding() == null){
|
||
format = potentialFormat;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if(format == null){
|
||
//throw new ExceptionReport("Could not determine intput format. Possibly multiple or none matching generators found. MimeType Set?", ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
// TODO Review error message
|
||
throw new ExceptionReport("Could not determine input format because none of the supported formats match the given schema (\"" + referenceData.getSchema() + "\") and encoding (\"" + referenceData.getEncoding() + "\"). (A mimetype was not specified)", ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
|
||
}
|
||
|
||
mimeType = format.getMimeType();
|
||
|
||
if(format.isSetEncoding()){
|
||
//no encoding provided--> select default one for mimeType
|
||
encoding = format.getEncoding();
|
||
}
|
||
|
||
if(format.isSetSchema()){
|
||
//no encoding provided--> select default one for mimeType
|
||
schema = format.getSchema();
|
||
}
|
||
}
|
||
|
||
if(mimeType==null && !referenceData.isSetEncoding() && !referenceData.isSetSchema()){
|
||
//nothing set, use default values
|
||
schema = inputPD.getComplexData().getDefault().getFormat().getSchema();
|
||
mimeType = inputPD.getComplexData().getDefault().getFormat().getMimeType();
|
||
encoding = inputPD.getComplexData().getDefault().getFormat().getEncoding();
|
||
|
||
}else{
|
||
//do a smart search an look if a mimeType can be found for either schema and/or encoding
|
||
|
||
if(mimeType==null){
|
||
if(referenceData.isSetEncoding() && !referenceData.isSetSchema()){
|
||
//encoding set only
|
||
ComplexDataDescriptionType encodingFormat = null;
|
||
String defaultEncoding = inputPD.getComplexData().getDefault().getFormat().getEncoding();
|
||
int found = 0;
|
||
String foundEncoding = null;
|
||
if(defaultEncoding.equalsIgnoreCase(referenceData.getEncoding())){
|
||
foundEncoding = inputPD.getComplexData().getDefault().getFormat().getEncoding();
|
||
encodingFormat = inputPD.getComplexData().getDefault().getFormat();
|
||
found += 1;
|
||
}else{
|
||
ComplexDataDescriptionType[] formats = inputPD.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType tempFormat : formats){
|
||
if(tempFormat.getEncoding().equalsIgnoreCase(referenceData.getEncoding())){
|
||
foundEncoding = tempFormat.getEncoding();
|
||
encodingFormat = tempFormat;
|
||
found += 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(found == 1){
|
||
encoding = foundEncoding;
|
||
mimeType = encodingFormat.getMimeType();
|
||
if(encodingFormat.isSetSchema()){
|
||
schema = encodingFormat.getSchema();
|
||
}
|
||
}else{
|
||
throw new ExceptionReport("Request incomplete. Could not determine a suitable input format based on the given input [mime Type missing and given encoding not unique]", ExceptionReport.MISSING_PARAMETER_VALUE);
|
||
}
|
||
|
||
}
|
||
if(referenceData.isSetSchema() && !referenceData.isSetEncoding()){
|
||
//schema set only
|
||
ComplexDataDescriptionType schemaFormat = null;
|
||
String defaultSchema = inputPD.getComplexData().getDefault().getFormat().getSchema();
|
||
int found = 0;
|
||
String foundSchema = null;
|
||
if(defaultSchema.equalsIgnoreCase(referenceData.getSchema())){
|
||
foundSchema = inputPD.getComplexData().getDefault().getFormat().getSchema();
|
||
schemaFormat = inputPD.getComplexData().getDefault().getFormat();
|
||
found += 1;
|
||
}else{
|
||
ComplexDataDescriptionType[] formats = inputPD.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType tempFormat : formats){
|
||
if(tempFormat.getEncoding().equalsIgnoreCase(referenceData.getSchema())){
|
||
foundSchema = tempFormat.getSchema();
|
||
schemaFormat =tempFormat;
|
||
found += 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(found == 1){
|
||
schema = foundSchema;
|
||
mimeType = schemaFormat.getMimeType();
|
||
if(schemaFormat.isSetEncoding()){
|
||
encoding = schemaFormat.getEncoding();
|
||
}
|
||
}else{
|
||
throw new ExceptionReport("Request incomplete. Could not determine a suitable input format based on the given input [mime Type missing and given schema not unique]", ExceptionReport.MISSING_PARAMETER_VALUE);
|
||
}
|
||
|
||
}
|
||
if(referenceData.isSetEncoding() && referenceData.isSetSchema()){
|
||
//schema and encoding set
|
||
|
||
|
||
//encoding
|
||
String defaultEncoding = inputPD.getComplexData().getDefault().getFormat().getEncoding();
|
||
|
||
List<ComplexDataDescriptionType> foundEncodingList = new ArrayList<ComplexDataDescriptionType>();
|
||
if(defaultEncoding.equalsIgnoreCase(referenceData.getEncoding())){
|
||
foundEncodingList.add(inputPD.getComplexData().getDefault().getFormat());
|
||
|
||
|
||
}else{
|
||
ComplexDataDescriptionType[] formats = inputPD.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType tempFormat : formats){
|
||
if(tempFormat.getEncoding().equalsIgnoreCase(referenceData.getEncoding())){
|
||
foundEncodingList.add(tempFormat);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
//schema
|
||
List<ComplexDataDescriptionType> foundSchemaList = new ArrayList<ComplexDataDescriptionType>();
|
||
String defaultSchema = inputPD.getComplexData().getDefault().getFormat().getSchema();
|
||
if(defaultSchema.equalsIgnoreCase(referenceData.getSchema())){
|
||
foundSchemaList.add(inputPD.getComplexData().getDefault().getFormat());
|
||
}else{
|
||
formats = inputPD.getComplexData().getSupported().getFormatArray();
|
||
for(ComplexDataDescriptionType tempFormat : formats){
|
||
if(tempFormat.getEncoding().equalsIgnoreCase(referenceData.getSchema())){
|
||
foundSchemaList.add(tempFormat);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//results
|
||
ComplexDataDescriptionType foundCommonFormat = null;
|
||
for(ComplexDataDescriptionType encodingFormat : foundEncodingList){
|
||
for(ComplexDataDescriptionType schemaFormat : foundSchemaList){
|
||
if(encodingFormat.equals(schemaFormat)){
|
||
foundCommonFormat = encodingFormat;
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
if(foundCommonFormat!=null){
|
||
mimeType = foundCommonFormat.getMimeType();
|
||
if(foundCommonFormat.isSetEncoding()){
|
||
encoding = foundCommonFormat.getEncoding();
|
||
}
|
||
if(foundCommonFormat.isSetSchema()){
|
||
schema = foundCommonFormat.getSchema();
|
||
}
|
||
}else{
|
||
throw new ExceptionReport("Request incomplete. Could not determine a suitable input format based on the given input [mime Type missing and given encoding and schema are not unique]", ExceptionReport.MISSING_PARAMETER_VALUE);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
LOGGER.debug("Loading parser for: schema = \""+ schema
|
||
+ "\" , mimetype = \"" + mimeType
|
||
+ "\", encoding = \"" + encoding + "\"");
|
||
|
||
IParser parser = null;
|
||
try {
|
||
Class<?> algorithmInputClass = RepositoryManager.getInstance().getInputDataTypeForAlgorithm(this.algorithmIdentifier, inputID);
|
||
if(algorithmInputClass == null) {
|
||
throw new RuntimeException("Could not determine internal input class for input" + inputID);
|
||
}
|
||
LOGGER.info("Looking for matching Parser ..." +
|
||
" schema: \"" + schema +
|
||
"\", mimeType: \"" + mimeType +
|
||
"\", encoding: \"" + encoding + "\"");
|
||
|
||
parser = ParserFactory.getInstance().getParser(schema, mimeType, encoding, algorithmInputClass);
|
||
|
||
if(parser == null) {
|
||
throw new ExceptionReport("Error. No applicable parser found for schema=\"" + schema + "\", mimeType=\"" + mimeType + "\", encoding=\"" + encoding + "\"", ExceptionReport.NO_APPLICABLE_CODE);
|
||
}
|
||
} catch (RuntimeException e) {
|
||
throw new ExceptionReport("Error obtaining input data", ExceptionReport.NO_APPLICABLE_CODE, e);
|
||
}
|
||
|
||
|
||
/****PROXY*****/
|
||
/*String decodedURL = URLDecoder.decode(dataURLString);
|
||
decodedURL = decodedURL.replace("&", "&");
|
||
if(decodedURL.indexOf("&BBOX")==-1){
|
||
decodedURL = decodedURL.replace("BBOX", "&BBOX");
|
||
decodedURL = decodedURL.replace("outputFormat", "&outputFormat");
|
||
decodedURL = decodedURL.replace("SRS", "&SRS");
|
||
decodedURL = decodedURL.replace("REQUEST", "&REQUEST");
|
||
decodedURL = decodedURL.replace("VERSION", "&VERSION");
|
||
decodedURL = decodedURL.replace("SERVICE", "&SERVICE");
|
||
decodedURL = decodedURL.replace("format", "&format");
|
||
}*/
|
||
|
||
|
||
//TODO lookup WFS -- we can't do that here.
|
||
// if(dataURLString.toUpperCase().contains("REQUEST=GETFEATURE") &&
|
||
// dataURLString.toUpperCase().contains("SERVICE=WFS")){
|
||
// if(parser instanceof SimpleGMLParser){
|
||
// parser = new GML2BasicParser();
|
||
// }
|
||
// if(parser instanceof GML2BasicParser && !dataURLString.toUpperCase().contains("OUTPUTFORMAT=GML2")){
|
||
// //make sure we get GML2
|
||
// dataURLString = dataURLString+"&outputFormat=GML2";
|
||
// }
|
||
// if(parser instanceof GML3BasicParser && !dataURLString.toUpperCase().contains("OUTPUTFORMAT=GML3")){
|
||
// //make sure we get GML3
|
||
// dataURLString = dataURLString+"&outputFormat=GML3";
|
||
// }
|
||
// }
|
||
|
||
|
||
|
||
IData parsedInputData = parser.parse(stream, mimeType, schema);
|
||
|
||
//enable maxxoccurs of parameters with the same name.
|
||
if(inputData.containsKey(inputID)) {
|
||
List<IData> list = inputData.get(inputID);
|
||
list.add(parsedInputData);
|
||
inputData.put(inputID, list);
|
||
}
|
||
else {
|
||
List<IData> list = new ArrayList<IData>();
|
||
list.add(parsedInputData);
|
||
inputData.put(inputID, list);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
/**
|
||
* Handles BBoxValue
|
||
* @param input The client input
|
||
*/
|
||
private void handleBBoxValue(InputType input)
|
||
throws ExceptionReport {
|
||
|
||
IData envelope = parseBoundingBox(input.getData().getBoundingBoxData());
|
||
|
||
List<IData> resultList = inputData.get(input.getIdentifier()
|
||
.getStringValue());
|
||
if (resultList == null) {
|
||
inputData.put(input.getIdentifier().getStringValue(), resultList
|
||
= new ArrayList<IData>(1));
|
||
}
|
||
resultList.add(envelope);
|
||
|
||
}
|
||
|
||
private IData parseBoundingBox(BoundingBoxType bbt)
|
||
throws ExceptionReport {
|
||
final BigInteger dim = bbt.getDimensions();
|
||
final double[] lower, upper;
|
||
|
||
if (dim != null && (dim.compareTo(INT_MAX) > 0 ||
|
||
dim.compareTo(INT_MIN) < 0)) {
|
||
throw new ExceptionReport(
|
||
String.format("Unsupported BoundingBox dimension %s. Has to be betweeen %s and %s!",
|
||
dim, INT_MIN, INT_MAX),
|
||
ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
|
||
try {
|
||
lower = parseCoordinate(bbt.getLowerCorner());
|
||
} catch (NumberFormatException e) {
|
||
throw new ExceptionReport("Invalid lower corner",
|
||
ExceptionReport.INVALID_PARAMETER_VALUE, e);
|
||
}
|
||
|
||
try {
|
||
upper = parseCoordinate(bbt.getUpperCorner());
|
||
} catch (NumberFormatException e) {
|
||
throw new ExceptionReport("Invalid upper corner",
|
||
ExceptionReport.INVALID_PARAMETER_VALUE, e);
|
||
}
|
||
|
||
if (upper.length != lower.length) {
|
||
throw new ExceptionReport(
|
||
String.format("Mismatching BoundingBox dimensions: %s vs %s!",
|
||
upper.length, lower.length),
|
||
ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
|
||
if (dim != null && lower.length != dim.intValue()) {
|
||
throw new ExceptionReport(
|
||
String.format("Mismatching BoundingBox dimensions: %s vs %s!",
|
||
dim.intValue(), lower.length),
|
||
ExceptionReport.INVALID_PARAMETER_VALUE);
|
||
}
|
||
return new BoundingBoxData(lower, upper, bbt.getCrs());
|
||
}
|
||
|
||
private double[] parseCoordinate(List<?> ordinates)
|
||
throws NumberFormatException {
|
||
List<Number> coordinate = new ArrayList<Number>(ordinates.size());
|
||
for (Object o : ordinates) {
|
||
if (o instanceof Number) {
|
||
coordinate.add((Number) o);
|
||
} else {
|
||
coordinate.add(Double.parseDouble(String.valueOf(o)));
|
||
}
|
||
}
|
||
return Doubles.toArray(coordinate);
|
||
}
|
||
|
||
/**
|
||
* Gets the resulting InputLayers from the parser
|
||
* @return A map with the parsed input
|
||
*/
|
||
public Map<String, List<IData>> getParsedInputData(){
|
||
return inputData;
|
||
}
|
||
|
||
|
||
// private InputStream retrievingZippedContent(URLConnection conn) throws IOException{
|
||
// String contentType = conn.getContentEncoding();
|
||
// if(contentType != null && contentType.equals("gzip")) {
|
||
// return new GZIPInputStream(conn.getInputStream());
|
||
// }
|
||
// else{
|
||
// return conn.getInputStream();
|
||
// }
|
||
// }
|
||
}
|