001    package railo.transformer.bytecode.expression;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    
006    import org.objectweb.asm.Type;
007    import org.objectweb.asm.commons.GeneratorAdapter;
008    import org.objectweb.asm.commons.Method;
009    
010    import railo.transformer.bytecode.BytecodeContext;
011    import railo.transformer.bytecode.BytecodeException;
012    import railo.transformer.bytecode.expression.var.DataMember;
013    import railo.transformer.bytecode.expression.var.Member;
014    import railo.transformer.bytecode.expression.var.UDF;
015    import railo.transformer.bytecode.util.ExpressionUtil;
016    import railo.transformer.bytecode.util.Types;
017    
018    public final class ExpressionInvoker extends ExpressionBase implements Invoker {
019    
020        // Object getCollection (Object,String)
021        private final static Method GET_COLLECTION = new Method("getCollection",
022                            Types.OBJECT,
023                            new Type[]{Types.OBJECT,Types.STRING}
024                            );
025        
026        // Object get (Object,String)
027        private final static Method GET = new Method("get",
028                            Types.OBJECT,
029                            new Type[]{Types.OBJECT,Types.STRING}
030                            );
031    
032        // Object getFunction (Object,String,Object[])
033        private final static Method GET_FUNCTION = new Method("getFunction",
034                            Types.OBJECT,
035                            new Type[]{Types.OBJECT,Types.STRING,Types.OBJECT_ARRAY}
036                            );
037        
038        // Object getFunctionWithNamedValues (Object,String,Object[])
039        private final static Method GET_FUNCTION_WITH_NAMED_ARGS = new Method("getFunctionWithNamedValues",
040                            Types.OBJECT,
041                            new Type[]{Types.OBJECT,Types.STRING,Types.OBJECT_ARRAY}
042                            );
043            
044        
045            private Expression expr;
046            private List members=new ArrayList();
047    
048            public ExpressionInvoker(Expression expr) {
049                    super(expr.getStart(),expr.getEnd());
050                    this.expr=expr;
051            }
052    
053            public Type _writeOut(BytecodeContext bc, int mode)     throws BytecodeException {
054    
055            GeneratorAdapter adapter = bc.getAdapter();
056            
057                    Type rtn=Types.OBJECT;
058                    int count=members.size();
059                    
060                    for(int i=0;i<count;i++) {
061                    adapter.loadArg(0);
062                    }
063            
064                    expr.writeOut(bc, Expression.MODE_REF);
065                    
066                    for(int i=0;i<count;i++) {
067                            Member member=((Member)members.get(i));
068                    
069                            // Data Member
070                            if(member instanceof DataMember)        {
071                                    ((DataMember)member).getName().writeOut(bc, MODE_REF);
072                                    adapter.invokeVirtual(Types.PAGE_CONTEXT,((i+1)==count)?GET:GET_COLLECTION);
073                                    rtn=Types.OBJECT;
074                            }
075                            
076                            // UDF
077                            else if(member instanceof UDF) {
078                                    UDF udf=(UDF) member;
079                                    
080                                    udf.getName().writeOut(bc, MODE_REF);
081                                    ExpressionUtil.writeOutExpressionArray(bc, Types.OBJECT, udf.getArguments());
082                                    
083                                    adapter.invokeVirtual(Types.PAGE_CONTEXT,udf.hasNamedArgs()?GET_FUNCTION_WITH_NAMED_ARGS:GET_FUNCTION);
084                                    rtn=Types.OBJECT;
085                                    
086                            }
087                    }
088                    
089                    return rtn;
090            }
091    
092            /**
093             *
094             * @see railo.transformer.bytecode.expression.Invoker#addMember(railo.transformer.bytecode.expression.var.Member)
095             */
096            public void addMember(Member member) {
097                    members.add(member);
098            }
099    
100            /**
101             *
102             * @see railo.transformer.bytecode.expression.Invoker#getMembers()
103             */
104            public List getMembers() {
105                    return members;
106            }
107    
108    }