package org.openflexo.model;
import java.awt.Color;
import java.awt.Font;
import java.awt.Point;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Hashtable;
import java.util.Map;
import java.util.StringTokenizer;
import org.openflexo.model.exceptions.InvalidDataException;
import org.openflexo.model.factory.ModelFactory;
import com.google.common.primitives.Primitives;
public class StringConverterLibrary {
private static final StringConverterLibrary instance = new StringConverterLibrary();
public static StringConverterLibrary getInstance() {
return instance;
}
private Map<Class<?>, Converter<?>> converters;
private Map<Class<?>, Converter<?>> unmodifiableConverters;
public StringConverterLibrary() {
converters = new Hashtable<Class<?>, Converter<?>>();
unmodifiableConverters = Collections.unmodifiableMap(converters);
addConverter(new BooleanConverter());
addConverter(new IntegerConverter());
addConverter(new ShortConverter());
addConverter(new LongConverter());
addConverter(new FloatConverter());
addConverter(new DoubleConverter());
addConverter(new StringConverter());
addConverter(new DateConverter());
addConverter(new URLConverter());
addConverter(new FileConverter());
addConverter(new ClassConverter());
addConverter(new PointConverter());
addConverter(new ColorConverter());
addConverter(new FontConverter());
addConverter(new NumberConverter());
}
public Map<Class<?>, Converter<?>> getConverters() {
return unmodifiableConverters;
}
public <T> Converter<T> getConverter(Class<T> type) {
return (Converter<T>) converters.get(type);
}
public boolean hasConverter(Class<?> type) {
return converters.containsKey(type);
}
synchronized void addConverter(Converter<?> converter) {
converters.put(converter.getConverterClass(), converter);
if (Primitives.isWrapperType(converter.getConverterClass())) {
converters.put(Primitives.unwrap(converter.getConverterClass()), converter);
}
}
/**
* Abstract class defining a converter to and from a String for a given class
*
* @author sguerin
*/
public static abstract class Converter<T> {
protected Class<T> converterClass;
public Converter(Class<T> aClass) {
super();
converterClass = aClass;
}
public Class<T> getConverterClass() {
return converterClass;
}
public abstract T convertFromString(String value, ModelFactory factory) throws InvalidDataException;
public abstract String convertToString(T value);
}
/**
* Class defining how to convert Boolean from/to String
*
* @author sguerin
*/
private static class BooleanConverter extends Converter<Boolean> {
private BooleanConverter() {
super(Boolean.class);
}
@Override
public Boolean convertFromString(String value, ModelFactory factory) {
return Boolean.valueOf(value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"));
}
@Override
public String convertToString(Boolean value) {
return value.toString();
}
}
/**
* Class defining how to convert Integer from/to String
*
* @author sguerin
*/
private static class NumberConverter extends Converter<Number> {
private NumberConverter() {
super(Number.class);
}
@Override
public Number convertFromString(String value, ModelFactory factory) {
try {
Number returned = Integer.parseInt(value);
// System.out.println("Build a integer: "+value);
return returned;
} catch (NumberFormatException e1) {
try {
Number returned = Long.parseLong(value);
// System.out.println("Build a long: "+value);
return returned;
} catch (NumberFormatException e2) {
try {
Number returned = Float.parseFloat(value);
// System.out.println("Build a float: "+value);
return returned;
} catch (NumberFormatException e3) {
try {
Number returned = Double.parseDouble(value);
// System.out.println("Build a double: "+value);
return returned;
} catch (NumberFormatException e4) {
}
}
}
}
return null;
}
@Override
public String convertToString(Number value) {
return value.toString();
}
}
/**
* Class defining how to convert Integer from/to String
*
* @author sguerin
*/
private static class IntegerConverter extends Converter<Integer> {
private IntegerConverter() {
super(Integer.class);
}
@Override
public Integer convertFromString(String value, ModelFactory factory) {
return Integer.valueOf(value);
}
@Override
public String convertToString(Integer value) {
return value.toString();
}
}
/**
* Class defining how to convert Short from/to String
*
* @author sguerin
*/
private static class ShortConverter extends Converter<Short> {
private ShortConverter() {
super(Short.class);
}
@Override
public Short convertFromString(String value, ModelFactory factory) {
return Short.valueOf(value);
}
@Override
public String convertToString(Short value) {
return value.toString();
}
}
/**
* Class defining how to convert Long from/to String
*
* @author sguerin
*/
private static class LongConverter extends Converter<Long> {
protected LongConverter() {
super(Long.class);
}
@Override
public Long convertFromString(String value, ModelFactory factory) {
return Long.valueOf(value);
}
@Override
public String convertToString(Long value) {
return value.toString();
}
}
/**
* Class defining how to convert Float from/to String
*
* @author sguerin
*/
private static class FloatConverter extends Converter<Float> {
protected FloatConverter() {
super(Float.class);
}
@Override
public Float convertFromString(String value, ModelFactory factory) {
return Float.valueOf(value);
}
@Override
public String convertToString(Float value) {
return value.toString();
}
}
/**
* Class defining how to convert Double from/to String
*
* @author sguerin
*/
private static class DoubleConverter extends Converter<Double> {
protected DoubleConverter() {
super(Double.class);
}
@Override
public Double convertFromString(String value, ModelFactory factory) {
return Double.valueOf(value);
}
@Override
public String convertToString(Double value) {
return value.toString();
}
}
/**
* Class defining how to convert String from/to String (easy !)
*
* @author sguerin
*/
private static class StringConverter extends Converter<String> {
protected StringConverter() {
super(String.class);
}
@Override
public String convertFromString(String value, ModelFactory factory) {
return value;
}
@Override
public String convertToString(String value) {
return value;
}
}
/**
* Class defining how to convert String from/to Date
*
* @author sguerin
*/
private static class DateConverter extends Converter<Date> {
/** Specify date format */
protected String _dateFormat = new SimpleDateFormat().toPattern();
private DateConverter() {
super(Date.class);
}
@Override
public Date convertFromString(String value, ModelFactory factory) {
try {
return tryToConvertFromString(value);
} catch (ParseException e) {
SimpleDateFormat formatter = new SimpleDateFormat(_dateFormat);
Date currentTime = new Date();
String dateString = formatter.format(currentTime);
System.err.println("Supplied value is not parsable as a date. " + " Date format should be for example " + dateString);
return null;
}
}
public Date tryToConvertFromString(String value) throws ParseException {
Date returned = null;
StringTokenizer st = new StringTokenizer(value, ",");
String dateFormat = _dateFormat;
String dateAsString = null;
if (st.hasMoreTokens()) {
dateFormat = st.nextToken();
}
if (st.hasMoreTokens()) {
dateAsString = st.nextToken();
}
if (dateAsString != null) {
try {
returned = new SimpleDateFormat(dateFormat).parse(dateAsString);
} catch (IllegalArgumentException e) {
throw new ParseException("While parsing supposed date format: " + e.getMessage(), 0);
}
}
if (returned == null) {
throw new ParseException("Cannot parse as a date " + value, 0);
}
return returned;
}
@Override
public String convertToString(Date date) {
if (date != null) {
return _dateFormat + "," + new SimpleDateFormat(_dateFormat).format(date);
} else {
return null;
}
}
/**
* Return a string representation of a date, according to valid date format
*/
public String getDateRepresentation(Date date) {
if (date != null) {
return new SimpleDateFormat(_dateFormat).format(date);
} else {
return null;
}
}
}
/**
* Class defining how to convert String from/to URL
*
* @author sguerin
*/
private static class URLConverter extends Converter<URL> {
private URLConverter() {
super(URL.class);
}
@Override
public URL convertFromString(String value, ModelFactory factory) {
try {
return new URL(value);
} catch (MalformedURLException e) {
System.err.println("Supplied value is not parsable as an URL:" + value);
return null;
}
}
@Override
public String convertToString(URL anURL) {
if (anURL != null) {
return anURL.toExternalForm();
} else {
return null;
}
}
}
/**
* Class defining how to convert String from/to File
*
* @author sguerin
*/
private static class FileConverter extends Converter<File> {
private FileConverter() {
super(File.class);
}
@Override
public File convertFromString(String value, ModelFactory factory) {
return new File(value);
}
@Override
public String convertToString(File aFile) {
if (aFile != null) {
return aFile.getAbsolutePath();
} else {
return null;
}
}
}
/**
* Class defining how to convert String from/to Class
*
* @author sguerin
*/
private static class ClassConverter extends Converter<Class> {
private ClassConverter() {
super(Class.class);
}
@Override
public Class<?> convertFromString(String value, ModelFactory factory) throws InvalidDataException {
try {
return Class.forName(value);
} catch (ClassNotFoundException e) {
// Warns about the exception
throw new InvalidDataException("Supplied value represents a class not found: " + value);
}
}
@Override
public String convertToString(Class aClass) {
if (aClass != null) {
return aClass.getName();
} else {
return null;
}
}
}
/**
* Class defining how to convert String from/to Point
*
* @author sguerin
*/
private static class PointConverter extends Converter<Point> {
private PointConverter() {
super(Point.class);
}
@Override
public Point convertFromString(String value, ModelFactory factory) {
try {
Point returned = new Point();
StringTokenizer st = new StringTokenizer(value, ",");
if (st.hasMoreTokens()) {
returned.x = Integer.parseInt(st.nextToken());
}
if (st.hasMoreTokens()) {
returned.y = Integer.parseInt(st.nextToken());
}
return returned;
} catch (NumberFormatException e) {
// Warns about the exception
System.err.println("Supplied value is not parsable as a Point:" + value);
return null;
}
}
@Override
public String convertToString(Point aPoint) {
if (aPoint != null) {
return aPoint.x + "," + aPoint.y;
} else {
return null;
}
}
}
/**
* Class defining how to convert String from/to Color
*
* @author sguerin
*/
private static class ColorConverter extends Converter<Color> {
private ColorConverter() {
super(Color.class);
}
@Override
public Color convertFromString(String value, ModelFactory factory) {
return new Color(redFromString(value), greenFromString(value), blueFromString(value));
}
@Override
public String convertToString(Color aColor) {
return aColor.getRed() + "," + aColor.getGreen() + "," + aColor.getBlue();
}
private static int redFromString(String s) {
return Integer.parseInt(s.substring(0, s.indexOf(",")));
}
private static int greenFromString(String s) {
return Integer.parseInt(s.substring(s.indexOf(",") + 1, s.lastIndexOf(",")));
}
private static int blueFromString(String s) {
return Integer.parseInt(s.substring(s.lastIndexOf(",") + 1));
}
}
/**
* Class defining how to convert String from/to Font
*
* @author sguerin
*/
private static class FontConverter extends Converter<Font> {
private FontConverter() {
super(Font.class);
}
@Override
public Font convertFromString(String value, ModelFactory factory) {
return new Font(nameFromString(value), styleFromString(value), sizeFromString(value));
}
@Override
public String convertToString(Font aFont) {
return aFont.getName() + "," + aFont.getStyle() + "," + aFont.getSize();
}
private static String nameFromString(String s) {
return s.substring(0, s.indexOf(","));
}
private static int styleFromString(String s) {
return Integer.parseInt(s.substring(s.indexOf(",") + 1, s.lastIndexOf(",")));
}
private static int sizeFromString(String s) {
return Integer.parseInt(s.substring(s.lastIndexOf(",") + 1));
}
}
}