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}