001    package railo.transformer.bytecode.statement.tag;
002    
003    import java.util.HashMap;
004    import java.util.Iterator;
005    import java.util.List;
006    import java.util.Map;
007    
008    import railo.runtime.type.util.ComponentUtil;
009    import railo.transformer.bytecode.Body;
010    import railo.transformer.bytecode.BodyBase;
011    import railo.transformer.bytecode.BytecodeContext;
012    import railo.transformer.bytecode.BytecodeException;
013    import railo.transformer.bytecode.Statement;
014    import railo.transformer.bytecode.expression.ExprString;
015    import railo.transformer.bytecode.expression.Expression;
016    import railo.transformer.bytecode.literal.LitBoolean;
017    import railo.transformer.bytecode.literal.LitString;
018    import railo.transformer.bytecode.statement.Function;
019    import railo.transformer.bytecode.statement.IFunction;
020     
021    public final class TagFunction extends TagBase implements IFunction {
022    
023            private static final ExprString ANY = LitString.toExprString("any", -1);
024    
025            private static final Expression PUBLIC = LitString.toExprString("public",-1);
026    
027            private static final Expression EMPTY = LitString.toExprString("", -1);
028    
029            public TagFunction(int startline) {
030                    this(startline,-1);
031            }
032            
033            public TagFunction(int startline,int endline) {
034                    super(startline,endline);
035                    
036            }
037            
038            /**
039             * @see railo.transformer.bytecode.statement.IFunction#writeOut(railo.transformer.bytecode.BytecodeContext, int)
040             */
041            public void writeOut(BytecodeContext bc, int type) throws BytecodeException {
042            //ExpressionUtil.visitLine(bc, getStartLine());
043            _writeOut(bc,type);
044            //ExpressionUtil.visitLine(bc, getEndLine());
045            }
046            
047            /**
048             * @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(railo.transformer.bytecode.BytecodeContext)
049             */
050            public void _writeOut(BytecodeContext bc) throws BytecodeException {
051                    _writeOut(bc,Function.PAGE_TYPE_REGULAR);
052            }
053    
054            public void _writeOut(BytecodeContext bc, int type) throws BytecodeException {
055                    Body functionBody = new BodyBase();
056                    Function func = createFunction(functionBody);
057                    func.setParent(getParent());
058    
059                    List statements = getBody().getStatements();
060                    Statement stat;
061                    Tag tag;
062                    Iterator it = statements.iterator();
063                    while (it.hasNext()) {
064                            stat = (Statement) it.next();
065                            if (stat instanceof Tag) {
066                                    tag = (Tag) stat;
067                                    if (tag.getTagLibTag().getTagClassName().equals(
068                                                    "railo.runtime.tag.Argument")) {
069                                            addArgument(func, tag);
070                                            continue;
071                                    }
072                            }
073                            functionBody.addStatement(stat);
074                    }
075                    ;
076                    func._writeOut(bc,type);
077    
078            }
079    
080            private void addArgument(Function func, Tag tag) {
081                    Attribute attr;
082                    // name
083                    Expression name = tag.removeAttribute("name").getValue();
084                    
085                    // type
086                    attr = tag.removeAttribute("type");
087                    Expression type = (attr == null) ? ANY : attr.getValue();
088    
089                    // required
090                    attr = tag.removeAttribute("required");
091                    Expression required = (attr == null) ? LitBoolean.FALSE : attr
092                                    .getValue();
093    
094                    // default
095                    attr = tag.removeAttribute("default");
096                    Expression defaultValue = (attr == null) ? null : attr.getValue();
097                    
098                    // passby
099                    attr = tag.removeAttribute("passby");
100                    LitBoolean passByReference = LitBoolean.TRUE;
101                    if(attr!=null) {
102                            // i can cast irt to LitString because he evulator check this before
103                             String str = ((LitString)attr.getValue()).getString();
104                             if(str.trim().equalsIgnoreCase("value"))
105                                     passByReference=LitBoolean.FALSE;
106                    }
107                    
108                    
109                    // displayname
110                    attr = tag.removeAttribute("displayname");
111                    Expression displayName = (attr == null) ? EMPTY : attr.getValue();
112    
113                    // hint
114                    attr = tag.removeAttribute("hint");
115                    if (attr == null)
116                            attr = tag.removeAttribute("description");
117                    
118                    Expression hint;
119                    if(attr == null)hint=EMPTY;
120                    else hint=attr.getValue();
121                    
122                    func.addArgument(name, type, required, defaultValue, passByReference,displayName, hint,tag.getAttributes());
123    
124            }
125    
126            private Function createFunction(Body body) throws BytecodeException {
127                    Attribute attr;
128    
129                    // name
130                    Expression name = removeAttribute("name").getValue();
131                    /*if(name instanceof LitString) {
132                            ((LitString)name).upperCase();
133                    }*/
134                    // return
135                    attr = removeAttribute("returntype");
136                    // if(attr==null) attr = getAttribute("return");
137                    // if(attr==null) attr = getAttribute("type");
138                    Expression returnType = (attr == null) ? ANY : attr.getValue();
139    
140                    // output
141                    attr = removeAttribute("output");
142                    Expression output = (attr == null) ? LitBoolean.TRUE : attr.getValue();
143    
144                    // abstract
145                    attr = removeAttribute("abstract");
146                    Expression abstr = (attr == null) ? LitBoolean.FALSE : attr.getValue();
147    
148                    // access
149                    attr = removeAttribute("access");
150                    Expression access = (attr == null) ? PUBLIC : attr.getValue();
151    
152                    // dspLabel
153                    attr = removeAttribute("displayname");
154                    Expression displayname = (attr == null) ? EMPTY : attr.getValue();
155    
156                    // hint
157                    attr = removeAttribute("hint");
158                    Expression hint = (attr == null) ? EMPTY : attr.getValue();
159    
160                    // description
161                    attr = removeAttribute("description");
162                    Expression description = (attr == null) ? EMPTY : attr.getValue();
163    
164                    // returnformat
165                    attr = removeAttribute("returnformat");
166                    Expression returnFormat = (attr == null) ? null : attr.getValue();
167    
168                    // secureJson
169                    attr = removeAttribute("securejson");
170                    Expression secureJson = (attr == null) ? null : attr.getValue();
171    
172                    // verifyClient
173                    attr = removeAttribute("verifyclient");
174                    Expression verifyClient = (attr == null) ? null : attr.getValue();
175                    
176                    String strAccess = ((LitString)access).getString();
177                    int acc = ComponentUtil.toIntAccess(strAccess,-1);
178                    if(acc==-1)
179                            throw new BytecodeException("invalid access type ["+strAccess+"], access types are remote, public, package, private",getLine());
180            
181                    Function func = new Function(name, returnType,returnFormat, output,abstr, acc, displayname,description,
182                                    hint,secureJson,verifyClient, body, getStartLine(),getEndLine());
183                    
184    //               %**%
185                    Map attrs = getAttributes();
186                    Iterator it = attrs.entrySet().iterator();
187                    HashMap<String,Attribute> metadatas=new HashMap<String,Attribute>();
188                    while(it.hasNext()){
189                            attr=(Attribute) ((Map.Entry)it.next()).getValue();
190                            metadatas.put(attr.getName(),attr);
191                    }
192                    func.setMetaData(metadatas);
193                    return func;
194            }
195    
196    }