content: /**
   * ﻿Copyright (C) 2007 - 2019 52°North Initiative for Geospatial Open Source
   * Software GmbH
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.n52.wps.io;
  
  import java.net.URI;
  import java.net.URISyntaxException;
  import java.util.Date;
  
  import javax.xml.datatype.DatatypeConfigurationException;
  import javax.xml.datatype.DatatypeFactory;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.apache.xmlbeans.impl.util.Base64;
  import org.n52.wps.io.data.IData;
  import org.n52.wps.io.data.ILiteralData;
  import org.n52.wps.io.data.binding.literal.LiteralAnyURIBinding;
  import org.n52.wps.io.data.binding.literal.LiteralBase64BinaryBinding;
  import org.n52.wps.io.data.binding.literal.LiteralBooleanBinding;
  import org.n52.wps.io.data.binding.literal.LiteralByteBinding;
  import org.n52.wps.io.data.binding.literal.LiteralDateTimeBinding;
  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.io.data.binding.literal.LiteralStringBinding;
  
  public class BasicXMLTypeFactory {
  
  	private final static Logger LOGGER = LoggerFactory.getLogger(BasicXMLTypeFactory.class);
      
  	// List of supported basic XML datatypes.
  	public static final String DOUBLE_URI = "xs:double";
  	public static final String FLOAT_URI = "xs:float";
  	public static final String INTEGER_URI = "xs:integer";
  	public static final String LONG_URI = "xs:long";
  	public static final String INT_URI = "xs:int";
  	public static final String SHORT_URI = "xs:short";
  	public static final String BYTE_URI = "xs:byte";
  	public static final String BOOLEAN_URI = "xs:boolean";
  	public static final String STRING_URI = "xs:string";
  	public static final String DATETIME_URI = "xs:dateTime";
  	public static final String DATE_URI = "xs:date";
  	public static final String BASE64BINARY_URI = "xs:base64Binary";
      public static final String ANYURI_URI = "xs:anyURI";
      
      private final static DatatypeFactory DATATYPE_FACTORY;
  
      static {
          DatatypeFactory datatypeFactory = null;
          try {
              // Is this thread safe?
              // bah, a checked exception on factory instantiation?
              datatypeFactory = DatatypeFactory.newInstance();
          } catch (DatatypeConfigurationException ex) {
              LOGGER.error("Error creating DatatypeFactory for xs:datTime and xs:dateParsing");
          }
          DATATYPE_FACTORY = datatypeFactory;
      }
  	
  	private BasicXMLTypeFactory(){
  		
  	}
  	
  	/**
  	 * This is a helper method to create always the correct Java Type out of a string.
  	 * It is based on the basic schema datatypes.
  	 * If xmlDataTypeURI is null, string dataType will be assumed.
  	 * @param xmlDataTypeURI the expected XML basicDataType
  	 * @param obj the XML object String
  	 */
  	public static IData getBasicJavaObject(String xmlDataTypeURI, String obj) {
  		obj = obj.replace('\n', ' ').replace('\t', ' ').trim();
  		if (xmlDataTypeURI == null) {
  			return new LiteralStringBinding(obj);
  		} else if (xmlDataTypeURI.equalsIgnoreCase(FLOAT_URI)) {
  			return new LiteralFloatBinding(Float.parseFloat(obj));
  		} else if (xmlDataTypeURI.equalsIgnoreCase(DOUBLE_URI)) {
  			return new LiteralDoubleBinding(Double.parseDouble(obj));
  		} else if (xmlDataTypeURI.equalsIgnoreCase(LONG_URI)) {
  			return new LiteralLongBinding(Long.parseLong(obj));
  		} else if (xmlDataTypeURI.equalsIgnoreCase(INT_URI) || xmlDataTypeURI.equalsIgnoreCase(INTEGER_URI)) {
  			return new LiteralIntBinding(Integer.parseInt(obj));
  		} else if (xmlDataTypeURI.equalsIgnoreCase(SHORT_URI)) {
  			return new LiteralShortBinding(Short.parseShort(obj));
  		} else if (xmlDataTypeURI.equalsIgnoreCase(BYTE_URI)) {
  			return new LiteralByteBinding(Byte.parseByte(obj));
  		} else if (xmlDataTypeURI.equalsIgnoreCase(BOOLEAN_URI)) {
  			return new LiteralBooleanBinding(Boolean.parseBoolean(obj));
  		} else if (xmlDataTypeURI.equalsIgnoreCase(STRING_URI)) {
  			return new LiteralStringBinding(obj);
  		} else if (xmlDataTypeURI.equalsIgnoreCase(DATETIME_URI) || xmlDataTypeURI.equalsIgnoreCase(DATE_URI)) {
              try {
                  return new LiteralDateTimeBinding(DATATYPE_FACTORY.newXMLGregorianCalendar(obj).toGregorianCalendar().getTime());
              } catch (Exception e) {
  				LOGGER.error("Could not parse xs:dateTime or xs:date data", e);
  				return null;
              }
  		} else if (xmlDataTypeURI.equalsIgnoreCase(BASE64BINARY_URI)) {
  			return new LiteralBase64BinaryBinding(Base64.decode(obj.getBytes()));
  		} else if (xmlDataTypeURI.equalsIgnoreCase(ANYURI_URI)) {
              try {
                  return new LiteralAnyURIBinding(new URI(obj));
              } catch (URISyntaxException e) {
  				LOGGER.error("Could not parse anyURI data", e);
  				return null;
              }
  		} else {
              return null;
          }
  	}
  
     public static String getStringRepresentation(String xmlDataTypeURI, IData obj) {
  	   return obj.getPayload().toString();
     }
     
     public static Class<? extends ILiteralData> getBindingForPayloadType(Class<?> payloadType) {
          if (payloadType.equals(float.class) || payloadType.equals(Float.class)) {
              return LiteralFloatBinding.class;
          }
          if (payloadType.equals(double.class) || payloadType.equals(Double.class)) {
              return LiteralDoubleBinding.class;
          }
          if (payloadType.equals(long.class) || payloadType.equals(Long.class)) {
              return LiteralLongBinding.class;
          }
          if (payloadType.equals(int.class) || payloadType.equals(Integer.class)) {
              return LiteralIntBinding.class;
          }
          if (payloadType.equals(short.class) || payloadType.equals(Short.class)) {
              return LiteralShortBinding.class;
          }
          if (payloadType.equals(byte.class) || payloadType.equals(Byte.class)) {
              return LiteralByteBinding.class;
          }
          if (payloadType.equals(boolean.class) || payloadType.equals(Boolean.class)) {
              return LiteralBooleanBinding.class;
          }
          if (payloadType.equals(String.class)) {
              return LiteralStringBinding.class;
          }
          if (payloadType.equals(Date.class)) {
              return LiteralDateTimeBinding.class;
          }
          if (payloadType.equals(byte[].class)) {
              return LiteralBase64BinaryBinding.class;
          }
          if (payloadType.equals(URI.class)) {
              return LiteralAnyURIBinding.class;
          }
          return null;
      }
  
      public static String getXMLDataTypeforBinding(Class<? extends ILiteralData> clazz) {
          if (LiteralFloatBinding.class.isAssignableFrom(clazz)) {
              return FLOAT_URI;
          } else if (LiteralDoubleBinding.class.isAssignableFrom(clazz)) {
              return DOUBLE_URI;
          } else if (LiteralLongBinding.class.isAssignableFrom(clazz)) {
              return LONG_URI;
          } else if (LiteralIntBinding.class.isAssignableFrom(clazz)) {
              return INT_URI;
  //            return INTEGER_URI;
          } else if (LiteralShortBinding.class.isAssignableFrom(clazz)) {
              return SHORT_URI;
          } else if (LiteralByteBinding.class.isAssignableFrom(clazz)) {
              return BYTE_URI;
          } else if (LiteralBooleanBinding.class.isAssignableFrom(clazz)) {
              return BOOLEAN_URI;
          } else if (LiteralStringBinding.class.isAssignableFrom(clazz)) {
              return STRING_URI;
          } else if (LiteralDateTimeBinding.class.isAssignableFrom(clazz)) {
              return DATETIME_URI;
  //            return DATE_URI;
          } else if (LiteralBase64BinaryBinding.class.isAssignableFrom(clazz)) {
              return  BASE64BINARY_URI;
          } else if (LiteralAnyURIBinding.class.isAssignableFrom(clazz)) {
              return ANYURI_URI;
          }
          return null;
      }
  
  }
  