gt:             if("double".equals(lcType))							return Types.DOUBLE;
context: package railo.transformer.bytecode.cast;
  
  import org.objectweb.asm.Type;
  import org.objectweb.asm.commons.GeneratorAdapter;
  import org.objectweb.asm.commons.Method;
  
  import railo.commons.lang.ClassException;
  import railo.commons.lang.ClassUtil;
  import railo.commons.lang.StringUtil;
  import railo.transformer.bytecode.BytecodeContext;
  import railo.transformer.bytecode.BytecodeException;
  import railo.transformer.bytecode.expression.Expression;
  import railo.transformer.bytecode.expression.ExpressionBase;
  import railo.transformer.bytecode.expression.var.Variable;
  import railo.transformer.bytecode.expression.var.VariableString;
  import railo.transformer.bytecode.util.Methods_Caster;
  import railo.transformer.bytecode.util.Types;
  
  /**
   * cast a Expression to a Double
   */
  public final class CastOther extends ExpressionBase implements Cast { 
      // TODO support short type
      private Expression expr;
      private String type;
      private String lcType;
      
      private CastOther(Expression expr, String type, String lcType) {
          super(expr.getStart(),expr.getEnd());
          this.expr=expr;
          this.type=type;
          this.lcType=lcType;
          
      }
  
      public static Expression toExpression(Expression expr, String type) {
      	if(type==null) return expr;
      	
      	String lcType=StringUtil.toLowerCase(type);
      	switch(lcType.charAt(0)) {
      	case 'a':
              if("any".equals(lcType)) 							{
              	return expr;
              }
      	break;
      	case 'b':
              if("boolean".equals(type) || "bool".equals(lcType)) return CastBoolean.toExprBoolean(expr);
          break;
      	case 'd':
      		if("double".equals(type))							return CastDouble.toExprDouble(expr);
      	break;
      	case 'i':
          	if("int".equals(lcType))							return CastInt.toExprInt(expr);
      	case 'n':
          	if("number".equals(lcType) || "numeric".equals(lcType))return CastDouble.toExprDouble(expr);
          break;
      	case 'o':
          	if("object".equals(lcType))							{
          		return expr;
          	}
          break;
          case 's':
          	if("string".equals(lcType))							return CastString.toExprString(expr);
          	//if("string_array".equals(lcType))					return StringArray.toExpr(expr);     
          break;
          case 'u':
          	if("uuid".equals(lcType)) 							return  CastString.toExprString(expr);
          break;
          case 'v':
          	if("variablename".equals(lcType))					return VariableString.toExprString(expr);
          	if("variable_name".equals(lcType))					return VariableString.toExprString(expr);
          	if("variablestring".equals(lcType))					return VariableString.toExprString(expr);
          	if("variable_string".equals(lcType))				return VariableString.toExprString(expr);
          	if("void".equals(lcType))							return expr;
          break;
          
          
          
          
      	}
          return new CastOther(expr,type,lcType);
      }
  
      // Array toArray(Object)
      final public static Method TO_ARRAY = new Method("toArray",
      		Types.ARRAY,
      		new Type[]{Types.OBJECT});
      
      // String toBase64 (Object);
      final public static Method TO_BASE64 = new Method("toBase64",
  			Types.STRING,
  			new Type[]{Types.OBJECT}); 
      
      // byte[] toBinary (Object)
      final public static Method TO_BINARY = new Method("toBinary",
  			Types.BYTE_VALUE_ARRAY,
  			new Type[]{Types.OBJECT}); 
      
      // byte[] toCollection (Object)
      final public static Method TO_COLLECTION = new Method("toCollection",
  			Types.BYTE_VALUE_ARRAY,
  			new Type[]{Types.OBJECT});
      
      // railo.runtime.Component toComponent (Object)
      final public static Method TO_COMPONENT = new Method("toComponent",
  			Types.COMPONENT,
  			new Type[]{Types.OBJECT});
  	
      
      // String toDecimal (Object)
      final public static Method TO_DECIMAL = new Method("toDecimal",
  			Types.STRING,
  			new Type[]{Types.OBJECT});
      
      // railo.runtime.config.Config getConfig ()
      final public static Method GET_CONFIG = new Method("getConfig",
  			Types.CONFIG_WEB,
  			new Type[]{}); 
      
      //java.util.TimeZone getTimeZone ()
      final public static Method GET_TIMEZONE = new Method("getTimeZone",
      			Types.TIMEZONE,
      			new Type[]{});
  
      // Excel toExcel (Object)
      final public static Method TO_EXCEL = new Method("toExcel",
  			Types.EXCEL,
  			new Type[]{Types.OBJECT}); 
      
      /**
       * @see railo.transformer.bytecode.expression.Expression#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int)
       */
      public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
  //Caster.toDecimal(null);
      	GeneratorAdapter adapter = bc.getAdapter();
          char first=lcType.charAt(0);
          Type rtn;
          
          switch(first) {
          case 'a':
              if("array".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.ARRAY)) 
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_ARRAY);
                  return Types.ARRAY;
              }
          break;
          case 'b':
              if("base64".equals(lcType)) {
                  expr.writeOut(bc,MODE_REF);
                  adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BASE64);
                  return Types.STRING;
              }
              if("binary".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.BYTE_VALUE_ARRAY)) 
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BINARY);
                  return Types.BYTE_VALUE_ARRAY;
              }
              if("byte".equals(type)) {
              	rtn=expr.writeOut(bc,MODE_VALUE);
              	if(!rtn.equals(Types.BYTE_VALUE)) 
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE_VALUE[Types.getType(rtn)]);
              	return Types.BYTE_VALUE;
              }
              if("byte".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.BYTE)) 
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE[Types.getType(rtn)]);
                  return Types.BYTE;
              }
              if("boolean".equals(lcType)) {
              	return CastBoolean.toExprBoolean(expr).writeOut(bc, MODE_REF);
              }
          break;
          case 'c':
              if("char".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_VALUE);
              	if(!rtn.equals(Types.CHAR)) 
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHAR_VALUE[Types.getType(rtn)]);
                  return Types.CHAR;
              }
              if("character".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.CHARACTER)) 
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHARACTER[Types.getType(rtn)]);
                  return Types.CHARACTER;
              }
              if("collection".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.COLLECTION)) 
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_COLLECTION);
                  return Types.COLLECTION;
              }
              if("component".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.COMPONENT)) 
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_COMPONENT);
                  return Types.COMPONENT;
              }
          break;
          case 'd':
              if("double".equals(lcType))	{
              	return CastDouble.toExprDouble(expr).writeOut(bc, MODE_REF);
              }
              if("date".equals(lcType) || "datetime".equals(lcType)) {
                  // First Arg
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(rtn.equals(Types.DATE_TIME)) return Types.DATE_TIME;
                  
              	int type=Types.getType(rtn);
                  
                  // Second Arg
                  adapter.loadArg(0);
                  adapter.invokeVirtual(Types.PAGE_CONTEXT,GET_CONFIG);
                  adapter.invokeInterface(Types.CONFIG_WEB,GET_TIMEZONE);
                  adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DATE[type]);
                  return Types.DATE_TIME;
              }
              if("decimal".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DECIMAL[Types.getType(rtn)]);
                  return Types.STRING;
              }
          break;
          case 'e':
          	if("excel".equals(type)) {
              	expr.writeOut(bc,MODE_REF);
                  adapter.invokeStatic(Types.EXCEL_UTIL,TO_EXCEL);
                  return Types.EXCEL;
              }
          break;
          case 'f':
              if("file".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.FILE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FILE);
                  return Types.FILE;
              }
              if("float".equals(type)) {
              	rtn=expr.writeOut(bc,MODE_VALUE);
              	if(!rtn.equals(Types.FLOAT_VALUE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT_VALUE[Types.getType(rtn)]);
                  return Types.FLOAT_VALUE;
              }
              if("float".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.FLOAT))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT[Types.getType(rtn)]);
                  return Types.FLOAT;
              }
          break;
          case 'i':
              if("int".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_VALUE);
              	if(!rtn.equals(Types.INT_VALUE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INT_VALUE[Types.getType(rtn)]);
                  return Types.INT_VALUE;
              }
              if("integer".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.INTEGER))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INTEGER[Types.getType(rtn)]);
                  return Types.INTEGER;
              }
          break;
          case 'j':
  
              if("java.lang.boolean".equals(lcType))	{
              	return CastBoolean.toExprBoolean(expr).writeOut(bc, MODE_REF);
              }
              if("java.lang.double".equals(lcType))	{
              	return CastDouble.toExprDouble(expr).writeOut(bc, MODE_REF);
              }
              if("java.lang.string".equals(lcType))	{
              	return CastString.toExprString(expr).writeOut(bc, MODE_REF);
              }
              if("java.lang.stringbuffer".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.STRING_BUFFER))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRING_BUFFER);
                  return Types.STRING_BUFFER;
              }
              if("java.lang.byte".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.BYTE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE[Types.getType(rtn)]);
                  return Types.BYTE;
              }
              if("java.lang.character".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.CHARACTER))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHARACTER[Types.getType(rtn)]);
                  return Types.CHARACTER;
              }
              if("java.lang.short".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.SHORT))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT[Types.getType(rtn)]);
                  return Types.SHORT;
              }
              if("java.lang.integer".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.INTEGER))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INTEGER[Types.getType(rtn)]);
                  return Types.INTEGER;
              }
              if("java.lang.long".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.LONG))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG[Types.getType(rtn)]);
                  return Types.LONG;
              }
              if("java.lang.float".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.FLOAT))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT[Types.getType(rtn)]);
                  return Types.FLOAT;
              }
              if("java.io.file".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.FILE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FILE);
                  return Types.FILE;
              }
              if("java.lang.object".equals(lcType)) {
              	return expr.writeOut(bc,MODE_REF);
              }
              else if("java.util.date".equals(lcType)) {
                  // First Arg
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(rtn.equals(Types.DATE)) return Types.DATE;
                  if(rtn.equals(Types.DATE_TIME)) return Types.DATE_TIME;
  
                  // Second Arg
                  adapter.loadArg(0);
                  adapter.invokeVirtual(Types.PAGE_CONTEXT,GET_CONFIG);
                  adapter.invokeVirtual(Types.CONFIG_WEB,GET_TIMEZONE);
                  adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DATE[Types.getType(rtn)]);
                  return Types.DATE_TIME;
              }
          break;
          case 'l':
              if("long".equals(type)) {
              	rtn=expr.writeOut(bc,MODE_VALUE);
                  if(!rtn.equals(Types.LONG_VALUE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG_VALUE[Types.getType(rtn)]);
                  return Types.LONG_VALUE;
              }
              else if("long".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.LONG))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG[Types.getType(rtn)]);
                  return Types.LONG;
              }
          break;
          case 'n':
              if("node".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.NODE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NODE);
                  return Types.NODE;
              }
              else if("null".equals(lcType)) {
                  expr.writeOut(bc,MODE_REF);
                  adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NULL);
                  // TODO gibt es einen null typ?
                  return Types.OBJECT;
              }
          break;
          case 'o':
              if("object".equals(lcType) || "other".equals(lcType)) {
                  expr.writeOut(bc,MODE_REF);
                  return Types.OBJECT;
              }
          break;
          case 's':
              if("struct".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.STRUCT))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRUCT);
                  return Types.STRUCT;
              }
              if("short".equals(type)) {
              	rtn=expr.writeOut(bc,MODE_VALUE);
                  if(!rtn.equals(Types.SHORT_VALUE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT_VALUE[Types.getType(rtn)]);
                  return Types.SHORT_VALUE;
              }
              if("short".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.SHORT))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT[Types.getType(rtn)]);
                  return Types.SHORT;
              }
              if("stringbuffer".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
              	if(!rtn.equals(Types.STRING_BUFFER))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRING_BUFFER);
                  return Types.STRING_BUFFER;
              }
          break;
  
          case 'x':
              if("xml".equals(lcType)) {
                  rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.NODE))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NODE);
                  return Types.NODE;
              }
          break;
          default:
              if("query".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.QUERY))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_QUERY);
                  return Types.QUERY;
              }
              if("querycolumn".equals(lcType)) {
              	rtn=(expr instanceof Variable)?((Variable)expr).writeOutCollection(bc, mode):expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.QUERY_COLUMN)) {
  
                      adapter.loadArg(0);
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_QUERY_COLUMN);
                  }
                  return Types.QUERY_COLUMN;
              }
              else if("timespan".equals(lcType)) {
              	rtn=expr.writeOut(bc,MODE_REF);
                  if(!rtn.equals(Types.TIMESPAN))
                  	adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_TIMESPAN);
                  return Types.TIMESPAN;
              }
          }
          Type t=getType(type);
          
          expr.writeOut(bc,MODE_REF);
          adapter.checkCast(t);
          return t;
      }
  
      /*
      private int writeExprx(BytecodeContext bc) throws TemplateException {
      	return Types.getType(expr.writeOut(bc,MODE_VALUE));
  	}*/
  
  	
  
  	public static Type getType(String type) throws BytecodeException {
  		if(StringUtil.isEmpty(type)) return Types.OBJECT;
      	
      	
      	String lcType=StringUtil.toLowerCase(type);
      	switch(lcType.charAt(0)) {
      	case 'a':
      		if("any".equals(lcType)) 							return Types.OBJECT;
      		if("array".equals(lcType)) 							return Types.ARRAY;
      	break;
      	case 'b':
      		if("bool".equals(lcType) || "boolean".equals(type))	return Types.BOOLEAN_VALUE;
              if("boolean".equals(lcType)) 						return Types.BOOLEAN;
              if("base64".equals(lcType)) 						return Types.STRING;
              
              if("binary".equals(lcType))							return Types.BYTE_VALUE_ARRAY;
              if("byte".equals(type))								return Types.BYTE_VALUE;
              if("byte".equals(lcType))							return Types.BYTE;
              
      	break;
      	
      	case 'c':
              if("char".equals(lcType)) 							return Types.CHAR;
              if("character".equals(lcType))						return Types.CHARACTER;
              if("collection".equals(lcType))						return Types.COLLECTION;
              if("component".equals(lcType))						return Types.COMPONENT;
      	break;
      	
          case 'd':
              if("double".equals(type))							return Types.DOUBLE_VALUE;
  