content: /**
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You 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.apache.aries.jmx.util;
  
  import static org.osgi.jmx.JmxConstants.BIGDECIMAL;
  import static org.osgi.jmx.JmxConstants.BIGINTEGER;
  import static org.osgi.jmx.JmxConstants.BOOLEAN;
  import static org.osgi.jmx.JmxConstants.BYTE;
  import static org.osgi.jmx.JmxConstants.CHARACTER;
  import static org.osgi.jmx.JmxConstants.DOUBLE;
  import static org.osgi.jmx.JmxConstants.FLOAT;
  import static org.osgi.jmx.JmxConstants.INTEGER;
  import static org.osgi.jmx.JmxConstants.LONG;
  import static org.osgi.jmx.JmxConstants.P_BOOLEAN;
  import static org.osgi.jmx.JmxConstants.P_BYTE;
  import static org.osgi.jmx.JmxConstants.P_CHAR;
  import static org.osgi.jmx.JmxConstants.P_DOUBLE;
  import static org.osgi.jmx.JmxConstants.P_FLOAT;
  import static org.osgi.jmx.JmxConstants.P_INT;
  import static org.osgi.jmx.JmxConstants.P_LONG;
  import static org.osgi.jmx.JmxConstants.P_SHORT;
  import static org.osgi.jmx.JmxConstants.SHORT;
  import static org.osgi.jmx.JmxConstants.STRING;
  import static org.osgi.jmx.JmxConstants.VERSION;
  
  import java.lang.reflect.Constructor;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.util.Dictionary;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.Map;
  
  import org.osgi.framework.Version;
  
  /**
   * This class provides common utilities related to type conversions for the MBean implementations
   *
   * @version $Rev$ $Date$
   */
  public class TypeUtils {
  
      private TypeUtils() {
          super();
      }
  
      public static Map<String, Class<? extends Object>> primitiveTypes = new HashMap<String, Class<? extends Object>>();
      public static Map<String, Class<? extends Object>> wrapperTypes = new HashMap<String, Class<? extends Object>>();
      public static Map<String, Class<? extends Object>> mathTypes = new HashMap<String, Class<? extends Object>>();
      public static Map<Class<? extends Object>, Class<? extends Object>> primitiveToWrapper = new HashMap<Class<? extends Object>, Class<? extends Object>>();
      public static Map<String, Class<? extends Object>> types = new HashMap<String, Class<? extends Object>>();
  
      static {
          primitiveTypes.put(P_FLOAT, Float.TYPE);
          primitiveTypes.put(P_INT, Integer.TYPE);
          primitiveTypes.put(P_LONG, Long.TYPE);
          primitiveTypes.put(P_DOUBLE, Double.TYPE);
          primitiveTypes.put(P_BYTE, Byte.TYPE);
          primitiveTypes.put(P_SHORT, Short.TYPE);
          primitiveTypes.put(P_CHAR, Character.TYPE);
          primitiveTypes.put(P_BOOLEAN, Boolean.TYPE);
          primitiveToWrapper.put(Float.TYPE, Float.class);
          primitiveToWrapper.put(Integer.TYPE, Integer.class);
          primitiveToWrapper.put(Long.TYPE, Long.class);
          primitiveToWrapper.put(Double.TYPE, Double.class);
          primitiveToWrapper.put(Byte.TYPE, Byte.class);
          primitiveToWrapper.put(Short.TYPE, Short.class);
          primitiveToWrapper.put(Boolean.TYPE, Boolean.class);
          wrapperTypes.put(INTEGER, Integer.class);
          wrapperTypes.put(FLOAT, Float.class);
          wrapperTypes.put(LONG, Long.class);
          wrapperTypes.put(DOUBLE, Double.class);
          wrapperTypes.put(BYTE, Byte.class);
          wrapperTypes.put(SHORT, Short.class);
          wrapperTypes.put(BOOLEAN, Boolean.class);
          wrapperTypes.put(CHARACTER, Character.class);
          wrapperTypes.put(VERSION, Version.class);
          mathTypes.put(BIGDECIMAL, BigDecimal.class);
          mathTypes.put(BIGINTEGER, BigInteger.class);
          types.put(STRING, String.class);
          types.putAll(primitiveTypes);
          types.putAll(wrapperTypes);
          types.putAll(mathTypes);
      }
  
      /**
       * Converts a <code>Dictionary</code> object to a <code>Map</code>
       *
       * @param dictionary
       * @return
       */
      public static Map<String, String> fromDictionary(Dictionary<String, String> dictionary) {
          Map<String, String> result = new HashMap<String, String>();
          Enumeration<String> keys = dictionary.keys();
          while (keys.hasMoreElements()) {
              String key = keys.nextElement();
              result.put(key, dictionary.get(key));
          }
          return result;
      }
  
      /**
       * Converts primitive long[] array to Long[]
       *
       * @param array
       * @return
       */
      public static Long[] toLong(long[] array) {
          Long[] toArray = (array == null) ? new Long[0] : new Long[array.length];
          for (int i = 0; i < toArray.length; i++) {
              toArray[i] = array[i];
          }
          return toArray;
      }
  
      /**
       * Converts Long[] array to primitive
       *
       * @param array
       * @return
       */
      public static long[] toPrimitive(Long[] array) {
          long[] toArray = (array == null) ? new long[0] : new long[array.length];
          for (int i = 0; i < toArray.length; i++) {
              toArray[i] = array[i];
          }
          return toArray;
      }
  
      /**
       * Converts a String value to an Object of the specified type
       *
       * @param type
       *            one of types listed in {@link #types}
       * @param value
       * @return instance of class <code>type</code>
       * @throws IllegalArgumentException
       *             if type or value are null or if the Class type does not support a valueOf() or cannot be converted to
       *             a wrapper type
       */
      @SuppressWarnings("unchecked")
      public static <T> T fromString(Class<T> type, String value) {
          if (type == null || !types.containsValue(type)) {
              throw new IllegalArgumentException("Cannot convert to type argument : " + type);
          }
          if (value == null || value.length() < 1) {
              throw new IllegalArgumentException("Argument value cannot be null or empty");
          }
          T result = null;
          try {
              if (type.equals(String.class)) {
                  result = (T) value;
              } else if (type.equals(Character.class) || type.equals(Character.TYPE)) {
                  result = (T) Character.valueOf(value.charAt(0));
              } else if (wrapperTypes.containsValue(type) || mathTypes.containsValue(type)) {
                  Constructor<? extends Object> constructor = type.getConstructor(String.class);
                  result = (T) constructor.newInstance(value);
              } else if (primitiveToWrapper.containsKey(type)) { // attempt to promote to wrapper and resolve to the base
                                                                 // type
                  Class<? extends Object> promotedType = primitiveToWrapper.get(type);
                  char[] simpleTypeName = type.getName().toCharArray();
                  simpleTypeName[0] = Character.toUpperCase(simpleTypeName[0]);
                  String parseMethodName = "parse" + new String(simpleTypeName);
                  Method parseMethod = promotedType.getDeclaredMethod(parseMethodName, String.class);
                  result = (T) parseMethod.invoke(null, value);
              }
          } catch (SecurityException e) {
              throw new IllegalArgumentException("Cannot convert value [" + value + "] to type [" + type + "]", e);
          } catch (NoSuchMethodException e) {
              throw new IllegalArgumentException("Cannot convert value [" + value + "] to type [" + type + "]", e);
          } catch (IllegalArgumentException e) {
              throw new IllegalArgumentException("Cannot convert value [" + value + "] to type [" + type + "]", e);
          } catch (IllegalAccessException e) {
              throw new IllegalArgumentException("Cannot convert value [" + value + "] to type [" + type + "]", e);
          } catch (InvocationTargetException e) {
              throw new IllegalArgumentException("Cannot convert value [" + value + "] to type [" + type + "]", e);
          } catch (InstantiationException e) {
              throw new IllegalArgumentException("Cannot convert value [" + value + "] to type [" + type + "]", e);
          }
          return result;
      }
  }
  