001    package railo.transformer.cfml.evaluator.impl;
002    
003    
004    import java.util.Iterator;
005    import java.util.List;
006    import java.util.Map;
007    
008    import railo.runtime.functions.system.CFFunction;
009    import railo.transformer.bytecode.Body;
010    import railo.transformer.bytecode.BytecodeException;
011    import railo.transformer.bytecode.Literal;
012    import railo.transformer.bytecode.Statement;
013    import railo.transformer.bytecode.cast.CastBoolean;
014    import railo.transformer.bytecode.expression.Expression;
015    import railo.transformer.bytecode.literal.LitBoolean;
016    import railo.transformer.bytecode.literal.LitString;
017    import railo.transformer.bytecode.statement.PrintOut;
018    import railo.transformer.bytecode.statement.tag.Attribute;
019    import railo.transformer.bytecode.statement.tag.Tag;
020    import railo.transformer.bytecode.util.ASMUtil;
021    import railo.transformer.cfml.evaluator.EvaluatorException;
022    import railo.transformer.cfml.evaluator.EvaluatorSupport;
023    import railo.transformer.library.function.FunctionLib;
024    import railo.transformer.library.function.FunctionLibFunction;
025    import railo.transformer.library.tag.TagLibTag;
026    
027    /**
028     * Pr�ft den Kontext des Tag function.
029     * Das Attribute <code>argument</code> darf nur direkt innerhalb des Tag <code>function</code> liegen.
030     * Dem Tag <code>argument</code> muss als erstes im tag function vorkommen
031     */
032    public final class Function extends EvaluatorSupport {
033    
034            //�
035            /**
036             * @see railo.transformer.cfml.evaluator.EvaluatorSupport#evaluate(org.w3c.dom.Element, railo.transformer.library.tag.TagLibTag)
037             */
038            public void evaluate(Tag tag, TagLibTag libTag, FunctionLib[] flibs) throws EvaluatorException {
039                    Body p=(Body) tag.getParent();
040                    Statement pp = p.getParent();
041                    
042                    boolean isCFC=true;
043            try {
044                            isCFC = ASMUtil.getAncestorPage(tag).isComponent();
045                    } catch (BytecodeException e) {}
046    
047                    Attribute attrName = tag.getAttribute("name");
048                    if(attrName!=null) {
049                            Expression expr = attrName.getValue();
050                            if(expr instanceof LitString && !isCFC){
051                                    checkFunctionName(((LitString)expr).getString(),flibs);
052                            }
053                                    
054                    }
055                    // attribute abstract
056                    Attribute attrAbstract = tag.getAttribute("abstract");
057                    if(attrAbstract!=null) {
058                            Expression expr = CastBoolean.toExprBoolean(attrAbstract.getValue());
059                            if(!(expr instanceof LitBoolean))
060                                    throw new EvaluatorException("Attribute abstract of the Tag Function, must be a literal boolean value (true or false, yes or no)");
061                            boolean abstr = ((LitBoolean)expr).getBooleanValue();
062                            if(abstr)throwIfNotEmpty(tag);
063                    }
064                    
065                    // Attribute Output
066                    // "output=true" wird in "railo.transformer.cfml.attributes.impl.Function" geh�ndelt
067                    Attribute attrOutput = tag.getAttribute("output");
068                    if(attrOutput!=null) {
069                            Expression expr = CastBoolean.toExprBoolean(attrOutput.getValue());
070                            if(!(expr instanceof LitBoolean))
071                                    throw new EvaluatorException("Attribute output of the Tag Function, must be a literal boolean value (true or false, yes or no)");
072                            boolean output = ((LitBoolean)expr).getBooleanValue();
073                            //if(!output) ASMUtil.removeLiterlChildren(tag, true);
074                    }
075                    
076                    
077            //if(ASMUtil.isRoot(pp)) {
078                    Map attrs = tag.getAttributes();
079                    Iterator it = attrs.keySet().iterator();
080                    Attribute attr;
081                    while(it.hasNext()) {
082                            attr=(Attribute) attrs.get(it.next());
083                            checkAttributeValue(tag,attr);
084                    }
085            //}
086            
087            }
088    
089    
090            public static void checkFunctionName(String name, FunctionLib[] flibs) throws EvaluatorException {
091                    FunctionLibFunction flf;
092                    for (int i = 0; i < flibs.length; i++) {
093                            flf = flibs[i].getFunction(name);
094                            if(flf!=null && flf.getCazz()!=CFFunction.class) {
095                                    throw new EvaluatorException("The name ["+name+"] is already used by a built in Function");
096                            }
097                    }
098            }
099    
100    
101            public static void throwIfNotEmpty(Tag tag) throws EvaluatorException {
102                    Body body = tag.getBody();
103                    List statments = body.getStatements();
104                    Statement stat;
105                    Iterator it = statments.iterator();
106                    TagLibTag tlt;
107                    
108                    while(it.hasNext()) {
109                            stat=(Statement) it.next();
110                            if(stat instanceof PrintOut) {
111                                    //body.remove(stat);
112                            }
113                            else if(stat instanceof Tag) {
114                                    tlt = ((Tag)stat).getTagLibTag();
115                                    if(!tlt.getTagClassName().equals("railo.runtime.tag.Argument"))
116                                            throw new EvaluatorException("tag "+tlt.getFullName()+" is not allowed inside a function declaration");
117                            }
118                    }
119            }
120    
121            private void checkAttributeValue(Tag tag, Attribute attr) throws EvaluatorException {
122                    if(!(attr.getValue() instanceof Literal))
123                            throw new EvaluatorException("Attribute ["+attr.getName()+"] of the Tag ["+tag.getFullname()+"] must be a literal/constant value");
124            
125        }
126    }