content: /**
   * ﻿Copyright (C) 2007 - 2019 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();
  				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;
  				}
  			}
  
                          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("&amp;", "");
  		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("&amp;", "&");
  			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();
  //		}
  //	}
  }
  