001    package railo.transformer.bytecode.cast;
002    
003    import org.objectweb.asm.Type;
004    import org.objectweb.asm.commons.GeneratorAdapter;
005    import org.objectweb.asm.commons.Method;
006    
007    import railo.commons.lang.ClassException;
008    import railo.commons.lang.ClassUtil;
009    import railo.commons.lang.StringUtil;
010    import railo.transformer.bytecode.BytecodeContext;
011    import railo.transformer.bytecode.BytecodeException;
012    import railo.transformer.bytecode.expression.Expression;
013    import railo.transformer.bytecode.expression.ExpressionBase;
014    import railo.transformer.bytecode.expression.var.Variable;
015    import railo.transformer.bytecode.expression.var.VariableString;
016    import railo.transformer.bytecode.util.Methods_Caster;
017    import railo.transformer.bytecode.util.Types;
018    
019    /**
020     * cast a Expression to a Double
021     */
022    public final class CastOther extends ExpressionBase implements Cast { 
023        // TODO support short type
024        private Expression expr;
025        private String type;
026        private String lcType;
027        
028        private CastOther(Expression expr, String type, String lcType) {
029            super(expr.getStart(),expr.getEnd());
030            this.expr=expr;
031            this.type=type;
032            this.lcType=lcType;
033            
034        }
035    
036        public static Expression toExpression(Expression expr, String type) {
037            if(type==null) return expr;
038            
039            String lcType=StringUtil.toLowerCase(type);
040            switch(lcType.charAt(0)) {
041            case 'a':
042                if("any".equals(lcType))                                                    {
043                    return expr;
044                }
045            break;
046            case 'b':
047                if("boolean".equals(type) || "bool".equals(lcType)) return CastBoolean.toExprBoolean(expr);
048            break;
049            case 'd':
050                    if("double".equals(type))                                                       return CastDouble.toExprDouble(expr);
051            break;
052            case 'i':
053                    if("int".equals(lcType))                                                        return CastInt.toExprInt(expr);
054            case 'n':
055                    if("number".equals(lcType) || "numeric".equals(lcType))return CastDouble.toExprDouble(expr);
056            break;
057            case 'o':
058                    if("object".equals(lcType))                                                     {
059                            return expr;
060                    }
061            break;
062            case 's':
063                    if("string".equals(lcType))                                                     return CastString.toExprString(expr);
064                    //if("string_array".equals(lcType))                                     return StringArray.toExpr(expr);     
065            break;
066            case 'u':
067                    if("uuid".equals(lcType))                                                       return  CastString.toExprString(expr);
068            break;
069            case 'v':
070                    if("variablename".equals(lcType))                                       return VariableString.toExprString(expr);
071                    if("variable_name".equals(lcType))                                      return VariableString.toExprString(expr);
072                    if("variablestring".equals(lcType))                                     return VariableString.toExprString(expr);
073                    if("variable_string".equals(lcType))                            return VariableString.toExprString(expr);
074                    if("void".equals(lcType))                                                       return expr;
075            break;
076            
077            
078            
079            
080            }
081            return new CastOther(expr,type,lcType);
082        }
083    
084        // Array toArray(Object)
085        final public static Method TO_ARRAY = new Method("toArray",
086                    Types.ARRAY,
087                    new Type[]{Types.OBJECT});
088        
089        // String toBase64 (Object);
090        final public static Method TO_BASE64 = new Method("toBase64",
091                            Types.STRING,
092                            new Type[]{Types.OBJECT}); 
093        
094        // byte[] toBinary (Object)
095        final public static Method TO_BINARY = new Method("toBinary",
096                            Types.BYTE_VALUE_ARRAY,
097                            new Type[]{Types.OBJECT}); 
098        
099        // byte[] toCollection (Object)
100        final public static Method TO_COLLECTION = new Method("toCollection",
101                            Types.BYTE_VALUE_ARRAY,
102                            new Type[]{Types.OBJECT});
103        
104        // railo.runtime.Component toComponent (Object)
105        final public static Method TO_COMPONENT = new Method("toComponent",
106                            Types.COMPONENT,
107                            new Type[]{Types.OBJECT});
108            
109        
110        // String toDecimal (Object)
111        final public static Method TO_DECIMAL = new Method("toDecimal",
112                            Types.STRING,
113                            new Type[]{Types.OBJECT});
114        
115        // railo.runtime.config.Config getConfig ()
116        final public static Method GET_CONFIG = new Method("getConfig",
117                            Types.CONFIG_WEB,
118                            new Type[]{}); 
119        
120        //java.util.TimeZone getTimeZone ()
121        final public static Method GET_TIMEZONE = new Method("getTimeZone",
122                            Types.TIMEZONE,
123                            new Type[]{});
124    
125        // Excel toExcel (Object)
126        final public static Method TO_EXCEL = new Method("toExcel",
127                            Types.EXCEL,
128                            new Type[]{Types.OBJECT}); 
129        
130        /**
131         * @see railo.transformer.bytecode.expression.Expression#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int)
132         */
133        public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
134    //Caster.toDecimal(null);
135            GeneratorAdapter adapter = bc.getAdapter();
136            char first=lcType.charAt(0);
137            Type rtn;
138            
139            switch(first) {
140            case 'a':
141                if("array".equals(lcType)) {
142                    rtn=expr.writeOut(bc,MODE_REF);
143                    if(!rtn.equals(Types.ARRAY)) 
144                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_ARRAY);
145                    return Types.ARRAY;
146                }
147            break;
148            case 'b':
149                if("base64".equals(lcType)) {
150                    expr.writeOut(bc,MODE_REF);
151                    adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BASE64);
152                    return Types.STRING;
153                }
154                if("binary".equals(lcType)) {
155                    rtn=expr.writeOut(bc,MODE_REF);
156                    if(!rtn.equals(Types.BYTE_VALUE_ARRAY)) 
157                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BINARY);
158                    return Types.BYTE_VALUE_ARRAY;
159                }
160                if("byte".equals(type)) {
161                    rtn=expr.writeOut(bc,MODE_VALUE);
162                    if(!rtn.equals(Types.BYTE_VALUE)) 
163                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE_VALUE[Types.getType(rtn)]);
164                    return Types.BYTE_VALUE;
165                }
166                if("byte".equals(lcType)) {
167                    rtn=expr.writeOut(bc,MODE_REF);
168                    if(!rtn.equals(Types.BYTE)) 
169                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE[Types.getType(rtn)]);
170                    return Types.BYTE;
171                }
172                if("boolean".equals(lcType)) {
173                    return CastBoolean.toExprBoolean(expr).writeOut(bc, MODE_REF);
174                }
175            break;
176            case 'c':
177                if("char".equals(lcType)) {
178                    rtn=expr.writeOut(bc,MODE_VALUE);
179                    if(!rtn.equals(Types.CHAR)) 
180                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHAR_VALUE[Types.getType(rtn)]);
181                    return Types.CHAR;
182                }
183                if("character".equals(lcType)) {
184                    rtn=expr.writeOut(bc,MODE_REF);
185                    if(!rtn.equals(Types.CHARACTER)) 
186                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHARACTER[Types.getType(rtn)]);
187                    return Types.CHARACTER;
188                }
189                if("collection".equals(lcType)) {
190                    rtn=expr.writeOut(bc,MODE_REF);
191                    if(!rtn.equals(Types.COLLECTION)) 
192                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_COLLECTION);
193                    return Types.COLLECTION;
194                }
195                if("component".equals(lcType)) {
196                    rtn=expr.writeOut(bc,MODE_REF);
197                    if(!rtn.equals(Types.COMPONENT)) 
198                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_COMPONENT);
199                    return Types.COMPONENT;
200                }
201            break;
202            case 'd':
203                if("double".equals(lcType)) {
204                    return CastDouble.toExprDouble(expr).writeOut(bc, MODE_REF);
205                }
206                if("date".equals(lcType) || "datetime".equals(lcType)) {
207                    // First Arg
208                    rtn=expr.writeOut(bc,MODE_REF);
209                    if(rtn.equals(Types.DATE_TIME)) return Types.DATE_TIME;
210                    
211                    int type=Types.getType(rtn);
212                    
213                    // Second Arg
214                    adapter.loadArg(0);
215                    adapter.invokeVirtual(Types.PAGE_CONTEXT,GET_CONFIG);
216                    adapter.invokeInterface(Types.CONFIG_WEB,GET_TIMEZONE);
217                    adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DATE[type]);
218                    return Types.DATE_TIME;
219                }
220                if("decimal".equals(lcType)) {
221                    rtn=expr.writeOut(bc,MODE_REF);
222                    adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DECIMAL[Types.getType(rtn)]);
223                    return Types.STRING;
224                }
225            break;
226            case 'e':
227                    if("excel".equals(type)) {
228                    expr.writeOut(bc,MODE_REF);
229                    adapter.invokeStatic(Types.EXCEL_UTIL,TO_EXCEL);
230                    return Types.EXCEL;
231                }
232            break;
233            case 'f':
234                if("file".equals(lcType)) {
235                    rtn=expr.writeOut(bc,MODE_REF);
236                    if(!rtn.equals(Types.FILE))
237                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FILE);
238                    return Types.FILE;
239                }
240                if("float".equals(type)) {
241                    rtn=expr.writeOut(bc,MODE_VALUE);
242                    if(!rtn.equals(Types.FLOAT_VALUE))
243                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT_VALUE[Types.getType(rtn)]);
244                    return Types.FLOAT_VALUE;
245                }
246                if("float".equals(lcType)) {
247                    rtn=expr.writeOut(bc,MODE_REF);
248                    if(!rtn.equals(Types.FLOAT))
249                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT[Types.getType(rtn)]);
250                    return Types.FLOAT;
251                }
252            break;
253            case 'i':
254                if("int".equals(lcType)) {
255                    rtn=expr.writeOut(bc,MODE_VALUE);
256                    if(!rtn.equals(Types.INT_VALUE))
257                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INT_VALUE[Types.getType(rtn)]);
258                    return Types.INT_VALUE;
259                }
260                if("integer".equals(lcType)) {
261                    rtn=expr.writeOut(bc,MODE_REF);
262                    if(!rtn.equals(Types.INTEGER))
263                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INTEGER[Types.getType(rtn)]);
264                    return Types.INTEGER;
265                }
266            break;
267            case 'j':
268    
269                if("java.lang.boolean".equals(lcType))      {
270                    return CastBoolean.toExprBoolean(expr).writeOut(bc, MODE_REF);
271                }
272                if("java.lang.double".equals(lcType))       {
273                    return CastDouble.toExprDouble(expr).writeOut(bc, MODE_REF);
274                }
275                if("java.lang.string".equals(lcType))       {
276                    return CastString.toExprString(expr).writeOut(bc, MODE_REF);
277                }
278                if("java.lang.stringbuffer".equals(lcType)) {
279                    rtn=expr.writeOut(bc,MODE_REF);
280                    if(!rtn.equals(Types.STRING_BUFFER))
281                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRING_BUFFER);
282                    return Types.STRING_BUFFER;
283                }
284                if("java.lang.byte".equals(lcType)) {
285                    rtn=expr.writeOut(bc,MODE_REF);
286                    if(!rtn.equals(Types.BYTE))
287                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE[Types.getType(rtn)]);
288                    return Types.BYTE;
289                }
290                if("java.lang.character".equals(lcType)) {
291                    rtn=expr.writeOut(bc,MODE_REF);
292                    if(!rtn.equals(Types.CHARACTER))
293                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHARACTER[Types.getType(rtn)]);
294                    return Types.CHARACTER;
295                }
296                if("java.lang.short".equals(lcType)) {
297                    rtn=expr.writeOut(bc,MODE_REF);
298                    if(!rtn.equals(Types.SHORT))
299                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT[Types.getType(rtn)]);
300                    return Types.SHORT;
301                }
302                if("java.lang.integer".equals(lcType)) {
303                    rtn=expr.writeOut(bc,MODE_REF);
304                    if(!rtn.equals(Types.INTEGER))
305                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INTEGER[Types.getType(rtn)]);
306                    return Types.INTEGER;
307                }
308                if("java.lang.long".equals(lcType)) {
309                    rtn=expr.writeOut(bc,MODE_REF);
310                    if(!rtn.equals(Types.LONG))
311                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG[Types.getType(rtn)]);
312                    return Types.LONG;
313                }
314                if("java.lang.float".equals(lcType)) {
315                    rtn=expr.writeOut(bc,MODE_REF);
316                    if(!rtn.equals(Types.FLOAT))
317                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT[Types.getType(rtn)]);
318                    return Types.FLOAT;
319                }
320                if("java.io.file".equals(lcType)) {
321                    rtn=expr.writeOut(bc,MODE_REF);
322                    if(!rtn.equals(Types.FILE))
323                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FILE);
324                    return Types.FILE;
325                }
326                if("java.lang.object".equals(lcType)) {
327                    return expr.writeOut(bc,MODE_REF);
328                }
329                else if("java.util.date".equals(lcType)) {
330                    // First Arg
331                    rtn=expr.writeOut(bc,MODE_REF);
332                    if(rtn.equals(Types.DATE)) return Types.DATE;
333                    if(rtn.equals(Types.DATE_TIME)) return Types.DATE_TIME;
334    
335                    // Second Arg
336                    adapter.loadArg(0);
337                    adapter.invokeVirtual(Types.PAGE_CONTEXT,GET_CONFIG);
338                    adapter.invokeVirtual(Types.CONFIG_WEB,GET_TIMEZONE);
339                    adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DATE[Types.getType(rtn)]);
340                    return Types.DATE_TIME;
341                }
342            break;
343            case 'l':
344                if("long".equals(type)) {
345                    rtn=expr.writeOut(bc,MODE_VALUE);
346                    if(!rtn.equals(Types.LONG_VALUE))
347                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG_VALUE[Types.getType(rtn)]);
348                    return Types.LONG_VALUE;
349                }
350                else if("long".equals(lcType)) {
351                    rtn=expr.writeOut(bc,MODE_REF);
352                    if(!rtn.equals(Types.LONG))
353                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG[Types.getType(rtn)]);
354                    return Types.LONG;
355                }
356            break;
357            case 'n':
358                if("node".equals(lcType)) {
359                    rtn=expr.writeOut(bc,MODE_REF);
360                    if(!rtn.equals(Types.NODE))
361                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NODE);
362                    return Types.NODE;
363                }
364                else if("null".equals(lcType)) {
365                    expr.writeOut(bc,MODE_REF);
366                    adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NULL);
367                    // TODO gibt es einen null typ?
368                    return Types.OBJECT;
369                }
370            break;
371            case 'o':
372                if("object".equals(lcType) || "other".equals(lcType)) {
373                    expr.writeOut(bc,MODE_REF);
374                    return Types.OBJECT;
375                }
376            break;
377            case 's':
378                if("struct".equals(lcType)) {
379                    rtn=expr.writeOut(bc,MODE_REF);
380                    if(!rtn.equals(Types.STRUCT))
381                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRUCT);
382                    return Types.STRUCT;
383                }
384                if("short".equals(type)) {
385                    rtn=expr.writeOut(bc,MODE_VALUE);
386                    if(!rtn.equals(Types.SHORT_VALUE))
387                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT_VALUE[Types.getType(rtn)]);
388                    return Types.SHORT_VALUE;
389                }
390                if("short".equals(lcType)) {
391                    rtn=expr.writeOut(bc,MODE_REF);
392                    if(!rtn.equals(Types.SHORT))
393                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT[Types.getType(rtn)]);
394                    return Types.SHORT;
395                }
396                if("stringbuffer".equals(lcType)) {
397                    rtn=expr.writeOut(bc,MODE_REF);
398                    if(!rtn.equals(Types.STRING_BUFFER))
399                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRING_BUFFER);
400                    return Types.STRING_BUFFER;
401                }
402            break;
403    
404            case 'x':
405                if("xml".equals(lcType)) {
406                    rtn=expr.writeOut(bc,MODE_REF);
407                    if(!rtn.equals(Types.NODE))
408                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NODE);
409                    return Types.NODE;
410                }
411            break;
412            default:
413                if("query".equals(lcType)) {
414                    rtn=expr.writeOut(bc,MODE_REF);
415                    if(!rtn.equals(Types.QUERY))
416                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_QUERY);
417                    return Types.QUERY;
418                }
419                if("querycolumn".equals(lcType)) {
420                    rtn=(expr instanceof Variable)?((Variable)expr).writeOutCollection(bc, mode):expr.writeOut(bc,MODE_REF);
421                    if(!rtn.equals(Types.QUERY_COLUMN)) {
422    
423                        adapter.loadArg(0);
424                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_QUERY_COLUMN);
425                    }
426                    return Types.QUERY_COLUMN;
427                }
428                else if("timespan".equals(lcType)) {
429                    rtn=expr.writeOut(bc,MODE_REF);
430                    if(!rtn.equals(Types.TIMESPAN))
431                            adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_TIMESPAN);
432                    return Types.TIMESPAN;
433                }
434            }
435            Type t=getType(type);
436            
437            expr.writeOut(bc,MODE_REF);
438            adapter.checkCast(t);
439            return t;
440        }
441    
442        /*
443        private int writeExprx(BytecodeContext bc) throws TemplateException {
444            return Types.getType(expr.writeOut(bc,MODE_VALUE));
445            }*/
446    
447            
448    
449            public static Type getType(String type) throws BytecodeException {
450                    if(StringUtil.isEmpty(type)) return Types.OBJECT;
451            
452            
453            String lcType=StringUtil.toLowerCase(type);
454            switch(lcType.charAt(0)) {
455            case 'a':
456                    if("any".equals(lcType))                                                        return Types.OBJECT;
457                    if("array".equals(lcType))                                                      return Types.ARRAY;
458            break;
459            case 'b':
460                    if("bool".equals(lcType) || "boolean".equals(type))     return Types.BOOLEAN_VALUE;
461                if("boolean".equals(lcType))                                                return Types.BOOLEAN;
462                if("base64".equals(lcType))                                                 return Types.STRING;
463                
464                if("binary".equals(lcType))                                                 return Types.BYTE_VALUE_ARRAY;
465                if("byte".equals(type))                                                             return Types.BYTE_VALUE;
466                if("byte".equals(lcType))                                                   return Types.BYTE;
467                
468            break;
469            
470            case 'c':
471                if("char".equals(lcType))                                                   return Types.CHAR;
472                if("character".equals(lcType))                                              return Types.CHARACTER;
473                if("collection".equals(lcType))                                             return Types.COLLECTION;
474                if("component".equals(lcType))                                              return Types.COMPONENT;
475            break;
476            
477            case 'd':
478                if("double".equals(type))                                                   return Types.DOUBLE_VALUE;
479                if("double".equals(lcType))                                                 return Types.DOUBLE;
480                
481                if("date".equals(lcType) || "datetime".equals(lcType))return Types.DATE_TIME;
482                if("decimal".equals(lcType))                                                return Types.STRING;
483                
484            break;
485    
486            case 'e':
487                    if("excel".equals(lcType))                                                      return Types.EXCEL;
488            break;
489            case 'f':
490                    if("file".equals(lcType))                                                       return Types.FILE;
491                if("float".equals(type))                                                    return Types.FLOAT_VALUE;
492                if("float".equals(lcType))                                                  return Types.FLOAT;
493                if("function".equals(lcType))                                                       return Types.UDF;
494            break;
495    
496            case 'i':
497                if("int".equals(lcType))                                                    return Types.INT_VALUE;
498                if("integer".equals(lcType))                                                return Types.INTEGER;
499            break;
500    
501            case 'l':
502                if("long".equals(type))                                                             return Types.LONG_VALUE;
503                if("long".equals(lcType))                                                   return Types.LONG;
504            break;
505            case 'n':
506                if("node".equals(lcType))                                                   return Types.NODE;
507                if("null".equals(lcType))                                                   return Types.OBJECT;
508                if("number".equals(lcType))                                                 return Types.DOUBLE_VALUE;
509                if("numeric".equals(lcType))                                                return Types.DOUBLE_VALUE;
510            break;
511            case 's':
512                if("string".equals(lcType))                                                 return Types.STRING;
513                if("struct".equals(lcType))                                                 return Types.STRUCT;
514                if("short".equals(type))                                                    return Types.SHORT_VALUE;
515                if("short".equals(lcType))                                                  return Types.SHORT;
516            break;
517            case 'o':
518                    if("other".equals(lcType))                                                      return Types.OBJECT;
519                    if("object".equals(lcType))                                             return Types.OBJECT;
520            break;
521            case 'u':
522                    if("uuid".equals(lcType))                                                       return Types.STRING;
523                    if("udf".equals(lcType))                                                        return Types.UDF;
524            break;
525            case 'q':
526                    if("query".equals(lcType))                                                      return Types.QUERY;
527                    if("querycolumn".equals(lcType))                                                        return Types.QUERY_COLUMN;
528            break;
529            case 't':
530                    if("timespan".equals(lcType))                                           return Types.TIMESPAN;
531            break;
532            case 'v':
533                    if("variablename".equals(lcType))                                       return Types.STRING;
534                    if("variable_name".equals(lcType))                                      return Types.STRING;
535                    if("variablestring".equals(lcType))                                     return Types.STRING;
536                    if("variable_string".equals(lcType))                            return Types.STRING;
537                    if("void".equals(lcType))                                                       return Types.VOID;
538            break;
539            case 'x':
540                    if("xml".equals(lcType))                                                        return Types.NODE;
541            break;
542            }
543            try {
544                            return Type.getType(ClassUtil.loadClass(type));
545                    } 
546            catch (ClassException e) {
547                            throw new BytecodeException(e.getMessage(),null);
548                    }
549                    
550            }
551    
552            @Override
553            public Expression getExpr() {
554                    return expr;
555            }
556    
557            /**
558             * @return the type
559             */
560            public String getType() {
561                    return type;
562            }
563    
564    }
565    
566    
567    
568