001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.transformer.cfml.evaluator.impl;
020
021import lucee.runtime.op.Caster;
022import lucee.transformer.bytecode.cast.CastBoolean;
023import lucee.transformer.bytecode.cast.CastString;
024import lucee.transformer.bytecode.expression.ExprString;
025import lucee.transformer.bytecode.expression.Expression;
026import lucee.transformer.bytecode.literal.LitBoolean;
027import lucee.transformer.bytecode.literal.LitDouble;
028import lucee.transformer.bytecode.literal.LitString;
029import lucee.transformer.bytecode.statement.tag.Attribute;
030import lucee.transformer.bytecode.statement.tag.Tag;
031import lucee.transformer.bytecode.util.ASMUtil;
032import lucee.transformer.cfml.evaluator.EvaluatorException;
033import lucee.transformer.cfml.evaluator.EvaluatorSupport;
034import lucee.transformer.library.tag.TagLibTag;
035
036
037
038/**
039 *
040 * Prueft den Kontext des Tag argument.
041 * Das Tag <code>argument</code> darf nur direkt innerhalb des Tag <code>function</code> liegen.
042 * Dem Tag <code>argument</code> muss als erstes im tag function vorkommen
043 */
044public final class Argument extends EvaluatorSupport {
045        /**
046         * @see lucee.transformer.cfml.evaluator.EvaluatorSupport#evaluate(org.w3c.dom.Element, lucee.transformer.library.tag.TagLibTag)
047         */
048        public void evaluate(Tag tag, TagLibTag libTag) throws EvaluatorException  {
049                        String ns=libTag.getTagLib().getNameSpaceAndSeparator();
050                        String functionName=ns+"function";
051                    
052                        ASMUtil.isLiteralAttribute(tag,"type",ASMUtil.TYPE_STRING,false,true);
053                        ASMUtil.isLiteralAttribute(tag,"name",ASMUtil.TYPE_STRING,false,true);
054                        //ASMUtil.isLiteralAttribute(tag,"hint",ASMUtil.TYPE_STRING,false,true);
055                        //ASMUtil.isLiteralAttribute(tag,"displayname",ASMUtil.TYPE_STRING,false,true);
056                        
057                        // check if default can be converted to a literal value that match the type declration.
058                        checkDefaultValue(tag);
059                                
060                        // check attribute passby
061                        Attribute attrPassBy = tag.getAttribute("passby");
062                        if(attrPassBy!=null) {
063                                ExprString expr = CastString.toExprString(attrPassBy.getValue());
064                                if(!(expr instanceof LitString))
065                                        throw new EvaluatorException("Attribute passby of the Tag Argument, must be a literal string");
066                                LitString lit = (LitString)expr;
067                                String passBy = lit.getString().toLowerCase().trim();
068                                if(!"value".equals(passBy) && !"ref".equals(passBy) && !"reference".equals(passBy))
069                                        throw new EvaluatorException("Attribute passby of the Tag Argument has an invalid value ["+passBy+"], valid values are [reference,value]");
070                        }
071                                
072                        // check if tag is direct inside function
073                        if(!ASMUtil.isParentTag(tag,functionName)) {
074                            Tag parent=ASMUtil.getParentTag(tag);
075                            
076                            String addText=(parent!=null)?
077                                    "but tag "+libTag.getFullName()+" is inside tag "+parent.getFullname()+"":
078                                    "but tag "+libTag.getFullName()+" has no parent";
079                            
080                                throw new EvaluatorException("Wrong Context, tag "+libTag.getFullName()
081                                        +" must be direct inside a "+functionName+" tag, "+addText);
082                        }
083                        // TODO check if there is a tag other than argument and text before     
084                        
085                }
086
087        public static void checkDefaultValue(Tag tag) {
088                // required (patch)
089                Attribute req = tag.getAttribute("required");
090                if(req!=null) {
091                        Expression value = req.getValue();
092                        if(value instanceof CastBoolean) {
093                                Expression expr = ((CastBoolean)value).getExpr();
094                                if(expr instanceof LitString) {
095                                        LitString ls=(LitString) expr;
096                                        if(ls.getString()==null || ls.getString().isEmpty())
097                                                tag.addAttribute(new Attribute(req.isDynamicType(),req.getName(), LitBoolean.TRUE, req.getType()));
098                                }
099                        }
100                }
101                                
102                // type
103                Attribute _type = tag.getAttribute("type");
104                if(_type!=null) {
105                        ExprString typeValue = CastString.toExprString(_type.getValue());
106                        if(typeValue instanceof LitString) {
107                                String strType=((LitString)typeValue).getString();
108                                Attribute _default = tag.getAttribute("default");
109                                if(_default!=null) {
110                                        Expression defaultValue = _default.getValue();
111                                        if(defaultValue instanceof LitString) {
112                                                String strDefault=((LitString)defaultValue).getString();
113                                                
114                                                
115                                                
116                                                // check for boolean
117                                                if("boolean".equalsIgnoreCase(strType)) {
118                                                        if("true".equalsIgnoreCase(strDefault) || "yes".equalsIgnoreCase(strDefault))
119                                                                tag.addAttribute(new Attribute(_default.isDynamicType(),_default.getName(), LitBoolean.TRUE, _default.getType()));
120                                                        if("false".equalsIgnoreCase(strDefault) || "no".equalsIgnoreCase(strDefault))
121                                                                tag.addAttribute(new Attribute(_default.isDynamicType(),_default.getName(), LitBoolean.FALSE, _default.getType()));
122                                                }
123
124                                                // check for numbers
125                                                if("number".equalsIgnoreCase(strType) || "numeric".equalsIgnoreCase(strType)) {
126                                                        Double dbl = Caster.toDouble(strDefault,null);
127                                                        if(dbl!=null) {
128                                                                tag.addAttribute(new Attribute(_default.isDynamicType(),_default.getName(), LitDouble.toExprDouble(dbl.doubleValue()), _default.getType()));
129                                                        }
130                                                }
131                                        }
132                                }
133                        }
134                }
135        }
136
137}