All Downloads are FREE. Search and download functionalities are using the official Maven repository.

microsoft.exchange.webservices.data.misc.MapiTypeConverter Maven / Gradle / Ivy

The newest version!
/*
 * The MIT License
 * Copyright (c) 2012 Microsoft Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package microsoft.exchange.webservices.data.misc;

import microsoft.exchange.webservices.data.core.EwsUtilities;
import microsoft.exchange.webservices.data.core.ILazyMember;
import microsoft.exchange.webservices.data.core.LazyMember;
import microsoft.exchange.webservices.data.core.enumeration.property.MapiPropertyType;
import microsoft.exchange.webservices.data.core.exception.misc.FormatException;
import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlDeserializationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Utility class to convert between MAPI Property type values and strings.
 */
public class MapiTypeConverter {

  private static final Log LOG = LogFactory.getLog(MapiTypeConverter.class);

  private static final IFunction DATE_TIME_PARSER = new IFunction() {
    public Object func(final String s) {
      return parseDateTime(s);
    }
  };

  private static final IFunction MAPI_VALUE_PARSER = new IFunction() {
    public Object func(final String s) {
      return MapiTypeConverter.parseMapiIntegerValue(s);
    }
  };

  /**
   * The mapi type converter map.
   */
  private static final LazyMember MAPI_TYPE_CONVERTER_MAP =
      new LazyMember(new ILazyMember() {
         @Override
         public MapiTypeConverterMap createInstance() {
           MapiTypeConverterMap map = new MapiTypeConverterMap();

           map.put(MapiPropertyType.ApplicationTime, new MapiTypeConverterMapEntry(Double.class));

           MapiTypeConverterMapEntry mapitype = new MapiTypeConverterMapEntry(Double.class);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.ApplicationTimeArray, mapitype);

           mapitype = new MapiTypeConverterMapEntry(Byte[].class);
           mapitype.setParse(IFunctions.Base64Decoder.INSTANCE);
           mapitype.setConvertToString(IFunctions.Base64Encoder.INSTANCE);
           map.put(MapiPropertyType.Binary, mapitype);

           mapitype = new MapiTypeConverterMapEntry(Byte[].class);
           mapitype.setParse(IFunctions.Base64Decoder.INSTANCE);
           mapitype.setConvertToString(IFunctions.Base64Encoder.INSTANCE);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.BinaryArray, mapitype);

           mapitype = new MapiTypeConverterMapEntry(Boolean.class);
           mapitype.setParse(IFunctions.ToBoolean.INSTANCE);
           mapitype.setConvertToString(IFunctions.ToLowerCase.INSTANCE);
           map.put(MapiPropertyType.Boolean, mapitype);

           mapitype = new MapiTypeConverterMapEntry(UUID.class);
           mapitype.setParse(IFunctions.ToUUID.INSTANCE);
           mapitype.setConvertToString(IFunctions.ToString.INSTANCE);
           map.put(MapiPropertyType.CLSID, mapitype);

           mapitype = new MapiTypeConverterMapEntry(UUID.class);
           mapitype.setParse(IFunctions.ToUUID.INSTANCE);
           mapitype.setConvertToString(IFunctions.ToString.INSTANCE);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.CLSIDArray, mapitype);

           map.put(MapiPropertyType.Currency, new MapiTypeConverterMapEntry(Long.class));

           mapitype = new MapiTypeConverterMapEntry(Long.class);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.CurrencyArray, mapitype);

           map.put(MapiPropertyType.Double, new MapiTypeConverterMapEntry(Double.class));

           mapitype = new MapiTypeConverterMapEntry(Double.class);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.DoubleArray, mapitype);

           map.put(MapiPropertyType.Error, new MapiTypeConverterMapEntry(Integer.class));
           map.put(MapiPropertyType.Float, new MapiTypeConverterMapEntry(Float.class));

           mapitype = new MapiTypeConverterMapEntry(Float.class);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.FloatArray, mapitype);

           mapitype = new MapiTypeConverterMapEntry(Integer.class);
           mapitype.setParse(MAPI_VALUE_PARSER);
           map.put(MapiPropertyType.Integer, mapitype);

           mapitype = new MapiTypeConverterMapEntry(Integer.class);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.IntegerArray, mapitype);

           map.put(MapiPropertyType.Long, new MapiTypeConverterMapEntry(Long.class));

           mapitype = new MapiTypeConverterMapEntry(Long.class);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.LongArray, mapitype);

           mapitype = new MapiTypeConverterMapEntry(String.class);
           mapitype.setParse(IFunctions.StringToObject.INSTANCE);
           map.put(MapiPropertyType.Object, mapitype);

           mapitype = new MapiTypeConverterMapEntry(String.class);
           mapitype.setParse(IFunctions.StringToObject.INSTANCE);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.ObjectArray, mapitype);

           map.put(MapiPropertyType.Short, new MapiTypeConverterMapEntry(Short.class));

           mapitype = new MapiTypeConverterMapEntry(Short.class);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.ShortArray, mapitype);

           mapitype = new MapiTypeConverterMapEntry(String.class);
           mapitype.setParse(IFunctions.StringToObject.INSTANCE);
           map.put(MapiPropertyType.String, mapitype);

           mapitype = new MapiTypeConverterMapEntry(String.class);
           mapitype.setParse(IFunctions.StringToObject.INSTANCE);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.StringArray, mapitype);

           mapitype = new MapiTypeConverterMapEntry(Date.class);
           mapitype.setParse(DATE_TIME_PARSER);
           mapitype.setConvertToString(IFunctions.DateTimeToXSDateTime.INSTANCE);
           map.put(MapiPropertyType.SystemTime, mapitype);

           mapitype = new MapiTypeConverterMapEntry(Date.class);
           mapitype.setParse(DATE_TIME_PARSER);
           mapitype.setConvertToString(IFunctions.DateTimeToXSDateTime.INSTANCE);
           mapitype.setIsArray(true);
           map.put(MapiPropertyType.SystemTimeArray, mapitype);

           return map;
         }
  });


  /**
   * Converts the string list to array.
   *
   * @param mapiPropType Type of the MAPI property.
   * @param strings      the strings
   * @return Array of objects.
   * @throws Exception the exception
   */
  public static List convertToValue(MapiPropertyType mapiPropType, Iterator strings) throws Exception {
    EwsUtilities.validateParam(strings, "strings");

    MapiTypeConverterMapEntry typeConverter = getMapiTypeConverterMap()
        .get(mapiPropType);
    List array = new ArrayList();

    int index = 0;

    while (strings.hasNext()) {
      Object value = typeConverter.convertToValueOrDefault(strings.next());
      array.add(index, value);
    }
    return array;
  }

  /**
   * Converts a string to value consistent with MAPI type.
   *
   * @param mapiPropType the mapi prop type
   * @param stringValue  the string value
   * @return the object
   * @throws ServiceXmlDeserializationException                  the service xml deserialization exception
   * @throws FormatException the format exception
   */
  public static Object convertToValue(MapiPropertyType mapiPropType, String stringValue) throws ServiceXmlDeserializationException, FormatException {
    return getMapiTypeConverterMap().get(mapiPropType).convertToValue(
        stringValue);

  }

  /**
   * Converts a value to a string.
   *
   * @param mapiPropType the mapi prop type
   * @param value        the value
   * @return String value.
   */
  public static String convertToString(MapiPropertyType mapiPropType, Object value) {
                /*
		 * if(! (value instanceof FuncInterface)){ return null; }
		 */
    return (value == null) ? "" : getMapiTypeConverterMap().get(
        mapiPropType).getConvertToString().func(value);
  }

  /**
   * Change value to a value of compatible type.
   *
   * @param mapiType the mapi type
   * @param value    the value
   * @return the object
   * @throws Exception the exception
   */
  public static Object changeType(MapiPropertyType mapiType, Object value)
      throws Exception {
    EwsUtilities.validateParam(value, "value");

    return getMapiTypeConverterMap().get(mapiType).changeType(value);
  }

  /**
   * Converts a MAPI Integer value.
   * Usually the value is an integer but there are cases where the value has been "schematized" to an
   * Enumeration value (e.g. NoData) which we have no choice but to fallback and represent as a string.
   *
   * @param s The string value.
   * @return Integer value or the original string if the value could not be parsed as such.
   */
  protected static Object parseMapiIntegerValue(String s) {
    int intValue;
    try {
      intValue = Integer.parseInt(s.trim());
      return Integer.valueOf(intValue);
    } catch (NumberFormatException e) {
      return s;
    }
  }

  /**
   * Determines whether MapiPropertyType is an array type.
   *
   * @param mapiType the mapi type
   * @return true, if is array type
   */
  public static boolean isArrayType(MapiPropertyType mapiType) {
    return getMapiTypeConverterMap().get(mapiType).getIsArray();
  }

  /**
   * Gets the MAPI type converter map.
   *
   * @return the mapi type converter map
   */
  public static Map
  getMapiTypeConverterMap() {

    return MAPI_TYPE_CONVERTER_MAP.getMember();
  }


  private static Object parseDateTime(String s) {
    String utcPattern = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    String errMsg = String.format("Date String %s not in " + "valid UTC/local format", s);
    DateFormat utcFormatter = new SimpleDateFormat(utcPattern);
    Date dt;

    if (s.endsWith("Z")) {
      try {
        dt = utcFormatter.parse(s);
      } catch (ParseException e) {
        s = s.substring(0, 10) + "T12:00:00Z";
        try {
          dt = utcFormatter.parse(s);
        } catch (ParseException e1) {
          LOG.error(e);
          throw new IllegalArgumentException(
              errMsg, e);
        }
      }
    } else if (s.endsWith("z")) {
      // String in UTC format yyyy-MM-ddTHH:mm:ssZ
      utcFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'z'");
      try {
        dt = utcFormatter.parse(s);
      } catch (ParseException e) {
        throw new IllegalArgumentException(e);
      }
    } else {
      utcFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
      try {
        dt = utcFormatter.parse(s);
      } catch (ParseException e) {
        throw new IllegalArgumentException(e);
      }
    }
    return dt;
  }

}