Package net.sourceforge.javautil.common.coersion.impl

Source Code of net.sourceforge.javautil.common.coersion.impl.StandardCoersionProvider

package net.sourceforge.javautil.common.coersion.impl;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import net.sourceforge.javautil.common.ReflectionUtil;
import net.sourceforge.javautil.common.coersion.ICoersion;
import net.sourceforge.javautil.common.coersion.CoersionException;
import net.sourceforge.javautil.common.coersion.ICoersionProvider;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
import net.sourceforge.javautil.common.io.IVirtualDirectory;
import net.sourceforge.javautil.common.io.IVirtualFile;
import net.sourceforge.javautil.common.io.impl.SystemDirectory;
import net.sourceforge.javautil.common.io.impl.SystemFile;

/**
* The standard provider for common coersion.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: StandardCoersionProvider.java 2297 2010-06-16 00:13:14Z ponderator $
*/
public class StandardCoersionProvider implements ICoersionProvider {
 
  protected final List<ICoersion> external = new CopyOnWriteArrayList<ICoersion>();
  protected final List<ICoersion> internal = new CopyOnWriteArrayList<ICoersion>();
 
  public StandardCoersionProvider () {
    this.internal.add(new CoersionUtilDate());
    this.internal.add(new CoersionSQLDate());
    this.internal.add(new CoersionVirtualArtifact());
    this.internal.add(new CoersionURL());
  }
 
  public <T> T coerce(Object original, Class<T> targetType) throws CoersionException {
    if (targetType == void.class) return null;
    if (original == null && !targetType.isPrimitive()) return null;
    if (original == null && targetType.isPrimitive()) return (T) ReflectionUtil.getPrimitiveDefault(targetType);

    if (targetType.isAssignableFrom( original.getClass() )) return (T) original;
    if ("".equals(original) && targetType.isPrimitive()) return (T) ReflectionUtil.getPrimitiveDefault(targetType);
   
    if (targetType.isPrimitive() && ReflectionUtil.isBoxedType(original.getClass()) &&
        ReflectionUtil.getPrimitiveType(original.getClass()) == targetType) return (T) original;

    if (external.size() > 0) {
      Iterator<ICoersion> external = this.external.iterator();
      while (external.hasNext()) {
        ICoersion coersion = external.next();
        if (coersion.isCanCoerce(original, targetType)) return (T) coersion.coerce(original, targetType);
      }
    }

    Iterator<ICoersion> internal = this.internal.iterator();
    while (internal.hasNext()) {
      ICoersion coersion = internal.next();
      if (coersion.isCanCoerce(original, targetType)) return (T) coersion.coerce(original, targetType);
    }
   
    if (original instanceof CharSequence) {
      return (T) this.coerceCharSequence((CharSequence)original, targetType);
    }
   
    if (original instanceof Number && (Number.class.isAssignableFrom(targetType) ||
        (targetType.isPrimitive() && Number.class.isAssignableFrom(ReflectionUtil.getBoxedType(targetType) )))) {
      return (T) this.coerceNumber((Number)original, targetType);
    }

    if (CharSequence.class.isAssignableFrom(targetType)) {
      if (original.getClass().isArray()) {
        if (original.getClass() == char[].class) return (T) this.coerceToStringType(new String( (char[]) original ), targetType);
        else if (original.getClass() == byte[].class) return (T) this.coerceToStringType(new String( (byte[]) original ), targetType);
      } else
        return (T) this.coerceToStringType(String.valueOf(original), targetType);
    }
   
    try {
      // Last Attempt, try to coerce to a string and then to the target type
      return this.coerce(this.coerce(original, String.class), targetType);
    } catch (CoersionException e) {
      throw new CoersionException("Cannot coerce: " + original + " to " + targetType, e);
    }
  }

  public synchronized void register(ICoersion... coersions) {
    this.external.addAll( Arrays.asList(coersions) );
  }
 
  public synchronized void unregister(ICoersion... coersions) {
    this.external.removeAll( Arrays.asList(coersions) );
  }
 
  protected Number coerceNumber (Number number1, Class numberType) {
    if (numberType.isPrimitive()) numberType = ReflectionUtil.getBoxedType(numberType);
   
    if (Float.class == numberType) return number1.floatValue();
    if (Integer.class == numberType) return number1.intValue();
    if (Byte.class == numberType) return number1.byteValue();
    if (Double.class == numberType) return number1.doubleValue();
    if (Short.class == numberType) return number1.shortValue();
    if (Long.class == numberType) return number1.longValue();
    if (BigDecimal.class == numberType) return new BigDecimal(number1.toString());
    if (BigInteger.class == numberType) return new BigInteger(number1.toString());
   
    throw new UnsupportedOperationException("Could not convert: " + number1 + " to a " + numberType);
  }

  /**
   * @param <T> The type to coerce to
   * @param str The string to coerce
   * @param target The class of the type
   * @return The coerced char sequence type
   */
  protected <T extends CharSequence> T coerceToStringType (String str, Class target) {
    if (target == String.class) return (T) str;
    if (target == StringBuffer.class) return (T) new StringBuffer(str);
    if (target == StringBuilder.class) return (T) new StringBuilder(str);

    for (Class type : new Class[] { CharSequence.class, String.class }) {
      try {
        Constructor c = target.getConstructor(type);
        return (T) c.newInstance(str);
      } catch (Exception e) {}
    }
   
    throw new CoersionException("Unsupported char sequence type: " + target);
  }
 
  /**
   * @param original The original string
   * @param type The type to coerce the string to
   * @return The coerced object
   */
  protected Object coerceCharSequence (CharSequence chars, Class type) {
    String original = String.valueOf(chars);
   
    if (type == boolean.class || type == Boolean.class) return Boolean.parseBoolean(original);
    else if (type == char.class || type == Character.class) return new Character(original.charAt(0));
    else if (type == int.class || type == Integer.class) return Integer.parseInt(original);
    else if (type == long.class || type == Long.class) return Long.parseLong(original);
    else if (type == double.class || type == Double.class) return Double.parseDouble(original);
    else if (type == float.class || type == Float.class) return Float.parseFloat(original);
    else if (type == short.class || type == Short.class) return Short.parseShort(original);
    else if (type == byte.class || type == Byte.class) return Byte.parseByte(original);
    else if (type == byte[].class) return original.getBytes();
    else if (type == char[].class) {
      char[] data = new char[original.length()];
      original.getChars(0, original.length(), data, 0);
      return data;
    }
    else if (type == StringBuffer.class) return new StringBuffer().append(original);
    else if (type == InputStream.class) return new ByteArrayInputStream(original.getBytes());
    else if (Enum.class.isAssignableFrom(type)) {
      try {
        String name = original.toString().toUpperCase();
        for (Object constant : type.getEnumConstants()) {
          if (constant.toString().toUpperCase().equals(name)) return constant;
        }
        return Enum.valueOf(type, original);
      } catch (IllegalArgumentException e) {
        return Enum.valueOf(type, original.toUpperCase());
      }
    }
    else {
      try {
        Constructor c = type.getConstructor(String.class);
        return c.newInstance(original);
      } catch (Exception e) {
        throw new CoersionException("Could not coerce: " + original + " to type " + type, e);
      }
    }
  }

}
TOP

Related Classes of net.sourceforge.javautil.common.coersion.impl.StandardCoersionProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.