
package com.exedio.cope.instrument;

import java.util.HashMap;
import java.util.List;

import com.exedio.cope.lib.BooleanAttribute;
import com.exedio.cope.lib.DoubleAttribute;
import com.exedio.cope.lib.IntegerFunction;
import com.exedio.cope.lib.LongAttribute;
import com.exedio.cope.lib.StringFunction;

public class PersistentNativeAttribute extends PersistentAttribute
{
	private final String boxedType;
	private final boolean boxed;
	private final String boxingPrefix, boxingPostfix, unboxingPrefix, unboxingPostfix;

	public PersistentNativeAttribute(
			final JavaAttribute javaAttribute,
			Class typeClass,
			final List initializerArguments,
			final List qualifiers)
		throws InjectorParseException
	{
		super(javaAttribute, typeClass, getPersistentType(typeClass), initializerArguments, qualifiers);

		// TODO do this a bit more intelligent
		if(StringFunction.class.isAssignableFrom(typeClass))
			typeClass = StringFunction.class;
		else if(IntegerFunction.class.isAssignableFrom(typeClass))
			typeClass = IntegerFunction.class;

		final String nativeType = (String)toNativeTypeMapping.get(typeClass);
		if(notNull && nativeType!=null)
		{
			boxedType = nativeType;
			boxed = true;
			boxingPrefix = (String)toBoxingPrefixMapping.get(typeClass);
			boxingPostfix = (String)toBoxingPostfixMapping.get(typeClass);
			unboxingPrefix = (String)toUnboxingPrefixMapping.get(typeClass);
			unboxingPostfix = (String)toUnboxingPostfixMapping.get(typeClass);
		}
		else
		{
			boxedType = getPersistentType();
			boxed = false;
			boxingPrefix = boxingPostfix = unboxingPrefix = unboxingPostfix = null;
		}
	}

	private static final String getPersistentType(Class typeClass)
	{
		// TODO do this a bit more intelligent
		if(StringFunction.class.isAssignableFrom(typeClass))
			typeClass = StringFunction.class;
		else if(IntegerFunction.class.isAssignableFrom(typeClass))
			typeClass = IntegerFunction.class;

		final String result = (String)toPersistentTypeMapping.get(typeClass);

		if(result==null)
			throw new RuntimeException(typeClass.toString());

		return result;
	}

	private static final HashMap toPersistentTypeMapping = new HashMap(3);
	private static final HashMap toNativeTypeMapping = new HashMap(3);
	private static final HashMap toBoxingPrefixMapping = new HashMap(3);
	private static final HashMap toBoxingPostfixMapping = new HashMap(3);
	private static final HashMap toUnboxingPrefixMapping = new HashMap(3);
	private static final HashMap toUnboxingPostfixMapping = new HashMap(3);
	
	private static final void fillNativeTypeMap(final Class typeClass, final String persistentType, final String nativeType,
															  final String boxingPrefix, final String boxingPostfix,
															  final String unboxingPrefix, final String unboxingPostfix)
	{
		toPersistentTypeMapping.put(typeClass, persistentType);
		toNativeTypeMapping.put(typeClass, nativeType);
		toBoxingPrefixMapping.put(typeClass, boxingPrefix);
		toBoxingPostfixMapping.put(typeClass, boxingPostfix);
		toUnboxingPrefixMapping.put(typeClass, unboxingPrefix);
		toUnboxingPostfixMapping.put(typeClass, unboxingPostfix);
	}
	
	static
	{
		fillNativeTypeMap(BooleanAttribute.class, "Boolean", "boolean", "(", "?Boolean.TRUE:Boolean.FALSE)", "(", ").booleanValue()");
		fillNativeTypeMap(LongAttribute.class, "Long", "long", "new Long(", ")", "(", ").longValue()");
		fillNativeTypeMap(IntegerFunction.class, "Integer", "int", "new Integer(", ")", "(", ").intValue()");
		fillNativeTypeMap(DoubleAttribute.class, "Double", "double", "new Double(", ")", "(", ").doubleValue()");
		fillNativeTypeMap(StringFunction.class, "String", null, null, null, null, null);
	}

	public final String getBoxedType()
	{
		return boxedType;
	}
	
	public final boolean isBoxed()
	{
		return boxed;
	}
	
	public final String getBoxingPrefix()
	{
		if(!boxed)
			throw new RuntimeException();

		return boxingPrefix;
	}
	
	public final String getBoxingPostfix()
	{
		if(!boxed)
			throw new RuntimeException();

		return boxingPostfix;
	}
	
	public final String getUnBoxingPrefix()
	{
		if(!boxed)
			throw new RuntimeException();

		return unboxingPrefix;
	}
	
	public final String getUnBoxingPostfix()
	{
		if(!boxed)
			throw new RuntimeException();

		return unboxingPostfix;
	}
	
}

@@ -813,197 +813,38 @@
 %0A%0A%09%09
-// TODO do this a bit more intelligent%0A%09%09if(StringFunction.class.isAssignableFrom(typeClass))%0A%09%09%09typeClass = StringFunction.class;%0A%09%09else if(IntegerFunction.class.isAssignableFrom(t
+typeClass = normalizeT
 ypeClass
 ))%0A%09
@@ -831,38 +831,33 @@
 rmalizeTypeClass
-))%0A%09%09%09
+(
 typeClass = Inte
@@ -853,34 +853,10 @@
 lass
- = IntegerFunction.class;%0A
+);
 %0A%09%09f
@@ -1421,24 +1421,25 @@
 ull;%0A%09%09%7D%0A%09%7D%0A
+%09
 %0A%09private st
@@ -1453,93 +1453,58 @@
 nal 
-String getPersistentType(Class typeClass)%0A%09%7B%0A%09%09// TODO do this a bit more intelligent
+Class normalizeTypeClass(final Class typeClass)%0A%09%7B
 %0A%09%09i
@@ -1558,27 +1558,22 @@
 ss))%0A%09%09%09
-typeClass =
+return
  StringF
@@ -1655,43 +1655,142 @@
 %0A%09%09%09
-typeClass = IntegerFunction.class;%0A
+return IntegerFunction.class;%0A%09%09else%0A%09%09%09return typeClass;%0A%09%7D%0A%0A%09private static final String getPersistentType(final Class typeClass)%0A%09%7B
 %0A%09%09f
@@ -1838,32 +1838,51 @@
 TypeMapping.get(
+normalizeTypeClass(
 typeClass);%0A%0A%09%09i
@@ -1875,16 +1875,17 @@
 peClass)
+)
 ;%0A%0A%09%09if(

introduce normalizeTypeClass