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

net.sf.mmm.util.value.ValueConverter Maven / Gradle / Ivy

The newest version!
/* $Id: ValueConverter.java 384 2007-12-20 10:18:29Z hohwille $
 * Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0 */
package net.sf.mmm.util.value;

import java.util.Date;

import javax.annotation.Resource;

import net.sf.mmm.util.NumericUtil;
import net.sf.mmm.util.StringUtil;
import net.sf.mmm.util.component.AlreadyInitializedException;
import net.sf.mmm.util.date.Iso8601Util;

/**
 * This is a utility class providing support for dealing with values (e.g. when
 * reading configurations).
 * 
 * @author Joerg Hohwiller (hohwille at users.sourceforge.net)
 */
public class ValueConverter {

  /** @see #getInstance() */
  private static ValueConverter instance;

  /** @see #getIso8601Util() */
  private Iso8601Util iso8601Util;

  /**
   * The constructor.
   */
  public ValueConverter() {

    super();
  }

  /**
   * This method gets the singleton instance of this {@link ValueConverter}.
* This design is the best compromise between easy access (via this * indirection you have direct, static access to all offered functionality) * and IoC-style design which allows extension and customization.
* For IoC usage, simply ignore all static {@link #getInstance()} methods and * construct new instances via the container-framework of your choice (like * plexus, pico, springframework, etc.). To wire up the dependent components * everything is properly annotated using common-annotations (JSR-250). If * your container does NOT support this, you should consider using a better * one. * * @return the singleton instance. */ public static ValueConverter getInstance() { if (instance == null) { synchronized (ValueConverter.class) { if (instance == null) { instance = new ValueConverter(); instance.setIso8601Util(Iso8601Util.getInstance()); } } } return instance; } /** * This method gets the util used to parse and format date and time according * to the standard ISO-8601. * * @return the iso8601Util */ protected Iso8601Util getIso8601Util() { return this.iso8601Util; } /** * This method sets the {@link #getIso8601Util() Iso8601Util}. * * @param iso8601Util the iso8601Util to set */ @Resource public void setIso8601Util(Iso8601Util iso8601Util) { if (this.iso8601Util != null) { throw new AlreadyInitializedException(); } this.iso8601Util = iso8601Util; } /** * This method parses a numeric value. * * @param numberValue is the number value as string. * @param valueSource describes the source of the value. This may be the * filename where the value was read from, an XPath where the value was * located in an XML document, etc. It is used in exceptions thrown if * something goes wrong. This will help to find the problem easier. * @return the value as number. * @throws WrongValueTypeException if the given string is no number. */ private static Number parseNumber(String numberValue, Object valueSource) throws WrongValueTypeException { try { Double d = Double.valueOf(numberValue); return NumericUtil.getInstance().toSimplestNumber(d); } catch (NumberFormatException e) { // TODO: valueSource as first arg, booleanValue as additional arg! throw new WrongValueTypeException(numberValue, valueSource, Number.class, e); } } /** * This method converts the given {@link String}-value to the * given type. * * @param value is the value to convert. It may be null. * @param valueSource describes the source of the value. This may be the * filename where the value was read from, an XPath where the value was * located in an XML document, etc. It is used in exceptions thrown if * something goes wrong. This will help to find the problem easier. * @param type is the type the value should be converted to. * @param defaultValue is returned if the given value is * null. It may also be null. * @param is the type the value should be converted to. * @return the value converted to type or the * defaultValue if value was * null. It will only return null if * both value and defaultValue are * null. * @throws WrongValueTypeException if the given value is NOT * null but can NOT be converted to the given * type (e.g. if value is "12x" and * type is Integer.class). */ public final V convertValue(String value, Object valueSource, Class type, V defaultValue) throws WrongValueTypeException { if (value == null) { return defaultValue; } else { return convertValue(value, valueSource, type); } } /** * This method converts the given value to a numeric type and * also validates that it is in the given range from minimum to * maximum. * * @param value is the value to convert. * @param valueSource describes the source of the value. This may be the * filename where the value was read from, an XPath where the value was * located in an XML document, etc. It is used in exceptions thrown if * something goes wrong. This will help to find the problem easier. * @param minimum is the minimum number allowed. Use MIN_VALUE (e.g. * {@link Double#MIN_VALUE}) if unbound. * @param maximum is the maximum number allowed. Use MAX_VALUE (e.g. * {@link Long#MAX_VALUE}) if unbound. * * @param is the templated numeric value type. * @return the requested value in the given range from minimum * and maximum. * @throws ValueNotSetException if the given value is * null. * @throws WrongValueTypeException if the value is NO number. * @throws ValueOutOfRangeException if the value is NOT in the given range * from minimum to maximum. */ @SuppressWarnings("unchecked") public T convertValue(String value, Object valueSource, T minimum, T maximum) throws ValueNotSetException, WrongValueTypeException, ValueOutOfRangeException { T result = (T) convertValue(value, valueSource, minimum.getClass()); checkRange(result, valueSource, minimum, maximum); return result; } /** * This method checks that the given value is in the inclusive * range from minimum to maximum. * * @param value is the value to check. * @param valueSource describes the source of the value. This may be the * filename where the value was read from, an XPath where the value was * located in an XML document, etc. It is used in exceptions thrown if * something goes wrong. This will help to find the problem easier. * @param minimum is the minimum number allowed. * @param maximum is the maximum number allowed. */ private void checkRange(Number value, Object valueSource, Number minimum, Number maximum) { double d = value.doubleValue(); if ((d < minimum.doubleValue()) || (d > maximum.doubleValue())) { throw new ValueOutOfRangeException(value, valueSource, minimum, maximum); } } /** * This method gets a numeric value and also validates that it is in the given * range from minimum to maximum. * * @param is the templated numeric value type. * @param value is the value to convert. * @param valueSource describes the source of the value. This may be the * filename where the value was read from, an XPath where the value was * located in an XML document, etc. It is used in exceptions thrown if * something goes wrong. This will help to find the problem easier. * @param minimum is the minimum number allowed. Use MIN_VALUE (e.g. * {@link Double#MIN_VALUE}) if unbound. * @param maximum is the maximum number allowed. Use MAX_VALUE (e.g. * {@link Long#MAX_VALUE}) if unbound. * @param defaultValue is the default returned if value is * null. It may be null. Else it must * be in the given range from minimum to * maximum. * @return the given value converted to {@literal } in the * range from minimum to maximum or the * defaultValue if value is * null. Will only be null if both * value and defaultValue are * null. * @throws WrongValueTypeException if the value is NO number. * @throws ValueOutOfRangeException if the value is NOT in the given range * from minimum to maximum. */ public T convertValue(String value, Object valueSource, T minimum, T maximum, T defaultValue) throws WrongValueTypeException, ValueOutOfRangeException { if (defaultValue != null) { checkRange(defaultValue, valueSource, minimum, maximum); } if (value == null) { return defaultValue; } else { return convertValue(value, valueSource, minimum, maximum); } } /** * This method converts the given {@link String}-value to the * given type. * * @param value is the value to convert. * @param valueSource describes the source of the value. This may be the * filename where the value was read from, an XPath where the value was * located in an XML document, etc. It is used in exceptions thrown if * something goes wrong. This will help to find the problem easier. * @param type is the type the value should be converted to. * @param is the type the value should be converted to. * @return the value converted to type. * @throws ValueNotSetException if the given value is * null. * @throws WrongValueTypeException if the given value is NOT * null but can NOT be converted to the given * type (e.g. if value is "12x" and * type is Integer.class). */ @SuppressWarnings("unchecked") public final V convertValue(String value, Object valueSource, Class type) throws ValueNotSetException, WrongValueTypeException { if (value == null) { throw new ValueNotSetException(valueSource); } Object result; try { if (type.isEnum()) { result = Enum.valueOf((Class) type, value); } else if (type.isAssignableFrom(String.class)) { result = value; } else if ((type == boolean.class) || (type == Boolean.class)) { result = StringUtil.getInstance().parseBoolean(value); if (result == null) { throw new WrongValueTypeException(value, valueSource, type); } } else if ((type == int.class) || (type == Integer.class)) { result = Integer.valueOf(value); } else if ((type == long.class) || (type == Long.class)) { result = Long.valueOf(value); } else if ((type == double.class) || (type == Double.class)) { result = Double.valueOf(value); } else if (type == Class.class) { result = Class.forName(value); } else if ((type == float.class) || (type == Float.class)) { result = Float.valueOf(value); } else if ((type == short.class) || (type == Short.class)) { result = Short.valueOf(value); } else if ((type == byte.class) || (type == Byte.class)) { result = Byte.valueOf(value); } else if (type == Number.class) { result = parseNumber(value, valueSource); } else if (type == Date.class) { result = this.iso8601Util.parseDate(value); } else if ((type == Character.class) || ((type == char.class))) { if (value.length() == 1) { result = Character.valueOf(value.charAt(0)); } else { throw new WrongValueTypeException(value, valueSource, type); } } else if (type == Class.class) { result = Class.forName(value); } else { return convertUnknownValue(value, type, valueSource); } } catch (NumberFormatException e) { throw new WrongValueTypeException(value, valueSource, type, e); } catch (ClassNotFoundException e) { throw new WrongValueTypeException(value, valueSource, type, e); } // ATTENTION: cast does NOT work if type is primitive // return type.cast(result); return (V) result; } /** * This method converts the given {@link String}-value to the * given type. It is called from * {@link #convertValue(String, Object, Class)} if the given type * is unknown. This default implementation simply throws a new * {@link WrongValueTypeException}. You can extend this class and override * this method in order to support the conversion for additional types. You * should first handle the conversion for all value types you like. Then for * all other types you should delegate to the super method * implementation. * * @param value is the value to convert. * @param type is the type the value should be converted to. * @param valueSource describes the source of the value. This may be the * filename where the value was read from, an XPath where the value was * located in an XML document, etc. It is used in exceptions thrown if * something goes wrong. This will help to find the problem easier. * * @param is the type the value should be converted to. * @return the value converted to type. * @throws ValueNotSetException if the given value is * null. * @throws WrongValueTypeException if the given value is NOT * null but can NOT be converted to the given * type (e.g. if value is "12x" and * type is Integer.class). */ protected V convertUnknownValue(String value, Class type, Object valueSource) throws ValueNotSetException, WrongValueTypeException { // throw new UnknownValueType(); throw new WrongValueTypeException(value, valueSource, type); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy