//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010 huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/willow
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : willow@lists.sourceforge.net 
 */
//----------------------------END  LICENSE-----------------------------
package org.huihoo.workflow.xpdl.util;

import org.apache.commons.collections.FastHashMap;

public final class TypeDefinition
{
	public static Class XPDLToJava(String value)
	{
		BasicTypeMapper mapper = (BasicTypeMapper) mappers.get(value.getClass());
		if (mapper == null)
		{
			mapper = (BasicTypeMapper) mappers.get(String.class);
		}

		return (mapper.map(value));
	}

	public static String javaToXPDL(Class clazz)
	{
		if (clazz==null || java.lang.String.class.getName().equals(clazz.getName()))
		{
			return "STRING";
		}
		if (boolean.class.getName().equals(clazz.getName()))
		{
			return "BOOLEAN";
		}
		else if (byte.class.getName().equals(clazz.getName()))
		{
			return "BYTE";
		}
		else if (short.class.getName().equals(clazz.getName()))
		{
			return "SHORT";
		}
		else if (char.class.getName().equals(clazz.getName()))
		{
			return "CHAR";
		}
		else if (int.class.getName().equals(clazz.getName()))
		{
			return "INTEGER";
		}
		else if (long.class.getName().equals(clazz.getName()))
		{
			return "LONG";
		}
		else if (float.class.getName().equals(clazz.getName()))
		{
			return "FLOAT";
		}
		else if (double.class.getName().equals(clazz.getName()))
		{
			return "DOUBLE";
		}
		else
		{
			return clazz.getName();
		}
}

/**
 * The set of {@link TypeDefinition}s that can be used to convert Strings
 * into  a specified class instance (instance of class ,not an object), keyed by the destination Class.
 */
private static FastHashMap mappers = new FastHashMap();
static {
	mappers.setFast(false);
	deregister();
	mappers.setFast(true);
}
/**
 * Remove all registered {@link Converter}s, and re-establish the
 * standard Converters.
 */
public static void deregister()
{
	mappers.clear();
	mappers.put(java.lang.String.class, new StringMapper());
}
/**
 * Remove any registered {@link Converter} for the specified destination
 * <code>Class</code>.
 *
 * @param clazz Class for which to remove a registered Converter
 */
public static void deregister(Class clazz)
{
	mappers.remove(clazz);
}
/**
 * Look up and return any registered {@link BasicTypeMapper} for the specified
 * destination class; if there is no registered BasicTypeMapper, return
 * <code>null</code>.
 *
 * @param clazz Class for which to return a registered Converter
 */
public static BasicTypeMapper lookup(Class clazz)
{
	return ((BasicTypeMapper) mappers.get(clazz));
}
/**
 * Register a custom {@link BasicTypeMapper} for the specified destination
 * <code>Class</code>, replacing any previously registered BasicTypeMapper.
 *
 * @param mapper BasicTypeMapper to be registered
 * @param clazz Destination class for conversions performed by this
 *  BasicTypeMapper
 */
public static void register(BasicTypeMapper mapper, Class clazz)
{
	mappers.put(clazz, mapper);
}
}

interface BasicTypeMapper
{
	public Class map(Object clazzObject);
}

class StringMapper implements BasicTypeMapper
{
	//----------------------------------------------------------- Constructors
	/**
	 * Create a {@link BasicTypeMapper} that will throw a {@link ConversionException}
	 * if a conversion error occurs.
	 */
	public StringMapper()
	{
		this.defaultValue = null;
		this.useDefault = false;
	}
	/**
	 * Create a {@link BasicTypeMapper} that will return the specified default value
	 * if a conversion error occurs.
	 *
	 * @param defaultValue The default value to be returned
	 */
	public StringMapper(Class defaultValue)
	{
		this.defaultValue = defaultValue;
		this.useDefault = true;
	}
	// ----------------------------------------------------- Instance Variables
	/**
	 * The default value specified to our Constructor, if any.
	 */
	private Class defaultValue = null;
	/**
	 * Should we return the default value on conversion errors?
	 */
	private boolean useDefault = true;

	// --------------------------------------------------------- Public Methods
	public Class map(Object clazzObject)
	{
		if (clazzObject == null)
		{
			if (useDefault)
			{
				return (defaultValue);
			}
			else
			{
				throw new RuntimeException("No value specified");
			}
		}

		if (clazzObject instanceof String)
		{
			if ("STRING".equalsIgnoreCase((String) clazzObject))
			{
				return java.lang.String.class;
			}
			else if ("FLOAT".equalsIgnoreCase((String) clazzObject))
			{
				return float.class;
			}
			else if ("DOUBLE".equalsIgnoreCase((String) clazzObject))
			{
				return double.class;
			}
			else if ("BYTE".equalsIgnoreCase((String) clazzObject))
			{
				return byte.class;
			}
			else if ("SHORT".equalsIgnoreCase((String) clazzObject))
			{
				return short.class;
			}
			else if ("CHAR".equalsIgnoreCase((String) clazzObject))
			{
				return char.class;
			}
			else if ("INTEGER".equalsIgnoreCase((String) clazzObject))
			{
				return int.class;
			}
			else if ("LONG".equalsIgnoreCase((String) clazzObject))
			{
				return long.class;
			}
			else if ("BOOLEAN".equalsIgnoreCase((String) clazzObject))
			{
				return boolean.class;
			}
		}

		return clazzObject.getClass();
	}

}
