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();
|
|||
|
// }
|
|||
|
// }
|
|||
|
}
|