001 package railo.transformer.cfml.evaluator.impl; 002 003 import railo.commons.lang.StringUtil; 004 import railo.runtime.config.ConfigImpl; 005 import railo.runtime.engine.ThreadLocalPageContext; 006 import railo.transformer.bytecode.Statement; 007 import railo.transformer.bytecode.cast.CastBoolean; 008 import railo.transformer.bytecode.cast.CastString; 009 import railo.transformer.bytecode.expression.Expression; 010 import railo.transformer.bytecode.literal.LitString; 011 import railo.transformer.bytecode.statement.tag.Attribute; 012 import railo.transformer.bytecode.statement.tag.Tag; 013 import railo.transformer.bytecode.statement.tag.TagLoop; 014 import railo.transformer.bytecode.util.ASMUtil; 015 import railo.transformer.cfml.ExprTransformer; 016 import railo.transformer.cfml.TransfomerSettings; 017 import railo.transformer.cfml.evaluator.EvaluatorException; 018 import railo.transformer.cfml.evaluator.EvaluatorSupport; 019 import railo.transformer.library.function.FunctionLib; 020 import railo.transformer.library.tag.TagLib; 021 import railo.transformer.library.tag.TagLibTag; 022 import railo.transformer.util.CFMLString; 023 024 025 026 /** 027 * Prueft den Kontext des Tag loop. 028 * Die Anforderungen an das Tag unterscheiden sich je nach Definition der Attribute. 029 * Falls das Attribute list vorhanden ist, muss auch das Attribute index vorhanden sein. 030 * Falls das Attribute list nicht vorhanden ist, aber das Attribute index, muessen auch die Attribute from und to vorhanden sein. 031 * Wenn das Attribute condition vorhanden ist, muss dieses mithilfe des ExprTransformer noch transformiert werden. 032 * Falls das Attribute collection verwendet wird, muss auch das Attribute item verwendet werden. 033 **/ 034 public final class Loop extends EvaluatorSupport { 035 //� 036 /** 037 * 038 * @see railo.transformer.cfml.evaluator.EvaluatorSupport#evaluate(railo.transformer.bytecode.statement.tag.Tag, railo.transformer.library.tag.TagLibTag, railo.transformer.library.function.FunctionLib[]) 039 */ 040 public void evaluate(Tag tag,TagLibTag tagLibTag,FunctionLib[] flibs) throws EvaluatorException { 041 TagLoop loop=(TagLoop) tag; 042 043 // label 044 if(ASMUtil.isLiteralAttribute(tag, "label", ASMUtil.TYPE_STRING, false, true)) { 045 LitString ls=(LitString) CastString.toExprString(tag.getAttribute("label").getValue()); 046 String l = ls.getString(); 047 if(!StringUtil.isEmpty(l,true)) { 048 loop.setLabel(l.trim()); 049 tag.removeAttribute("label"); 050 } 051 } 052 053 // attribute maxrows and endrow not allowd at the same time 054 if(tag.containsAttribute("maxrows") && tag.containsAttribute("endrow")) 055 throw new EvaluatorException("Wrong Context, you cannot use attribute maxrows and endrow at the same time."); 056 057 // file loop 058 if(tag.containsAttribute("file")) { 059 if(!tag.containsAttribute("index")) 060 throw new EvaluatorException("Wrong Context, when you use attribute file you must also use attribute index"); 061 loop.setType(TagLoop.TYPE_FILE); 062 return; 063 } 064 // list loop 065 if(tag.containsAttribute("list")){ 066 if(!tag.containsAttribute("index") && !tag.containsAttribute("item")) 067 throw new EvaluatorException("Wrong Context, when you use attribute list,you must define attribute index and/or item"); 068 loop.setType(TagLoop.TYPE_LIST); 069 return; 070 } 071 // array loop 072 if(tag.containsAttribute("array")){ 073 if(!tag.containsAttribute("index") && !tag.containsAttribute("item")) 074 throw new EvaluatorException("Wrong Context, when you use attribute array, you must define attribute index and/or item"); 075 loop.setType(TagLoop.TYPE_ARRAY); 076 return; 077 } 078 // collection loop 079 if(tag.containsAttribute("collection")) { 080 if(!tag.containsAttribute("index") && !tag.containsAttribute("item")) 081 throw new EvaluatorException("Wrong Context, when you use attribute collection,you must define attribute index and/or item"); 082 loop.setType(TagLoop.TYPE_COLLECTION); 083 return; 084 } 085 // index loop 086 if(tag.containsAttribute("index")) { 087 if(!tag.containsAttribute("from") || !tag.containsAttribute("to")) 088 throw new EvaluatorException("Wrong Context, when you use attribute index you must also use attribute from and to or list or file"); 089 loop.setType(TagLoop.TYPE_INDEX); 090 return; 091 } 092 // condition loop 093 if(tag.containsAttribute("condition")){ 094 TagLib tagLib=tagLibTag.getTagLib(); 095 ExprTransformer transformer; 096 String text=ASMUtil.getAttributeString(tag, "condition"); 097 098 try { 099 ConfigImpl config=(ConfigImpl) ThreadLocalPageContext.getConfig(); 100 transformer = tagLib.getExprTransfomer(); 101 Expression expr=transformer.transform(ASMUtil.getAncestorPage(tag),null,flibs,config.getCoreTagLib().getScriptTags(),new CFMLString(text,"UTF-8"),TransfomerSettings.toSetting(ThreadLocalPageContext.getConfig())); 102 tag.addAttribute(new Attribute(false,"condition",CastBoolean.toExprBoolean(expr),"boolean")); 103 } 104 catch (Exception e) { 105 throw new EvaluatorException(e.getMessage()); 106 } 107 loop.setType(TagLoop.TYPE_CONDITION); 108 return; 109 } 110 // query loop 111 if(tag.containsAttribute("query")){ 112 loop.setType(TagLoop.TYPE_QUERY); 113 return; 114 } 115 Info info=getParentInfo(loop); 116 // query group 117 if(tag.containsAttribute("group") && info.hasParentWithQuery){ 118 loop.setType(TagLoop.TYPE_GROUP); 119 return; 120 } 121 122 if(info.hasParentWithQuery) { 123 if(info.hasParentWithGroup) loop.setType(TagLoop.TYPE_INNER_GROUP); 124 else loop.setType(TagLoop.TYPE_INNER_QUERY); 125 return; 126 } 127 /* 128 if(hasQuery) 129 output.setType(TagOutput.TYPE_QUERY); 130 131 else if(tag.containsAttribute("group") && hasParentWithQuery) 132 output.setType(TagOutput.TYPE_GROUP); 133 134 else if(hasParentWithQuery) { 135 if(hasParentWithGroup) output.setType(TagOutput.TYPE_INNER_GROUP); 136 else output.setType(TagOutput.TYPE_INNER_QUERY); 137 } 138 else 139 output.setType(TagOutput.TYPE_NORMAL); 140 141 142 */ 143 144 loop.setType(TagLoop.TYPE_NOTHING); 145 //throw new EvaluatorException("Wrong Context, invalid attributes in tag cfloop"); 146 147 } 148 149 private Info getParentInfo(TagLoop loop) { 150 151 // check if inside a query tag 152 TagLoop parent = loop; 153 Info info=new Info(); 154 info.hasParentWithGroup=false; 155 info.hasParentWithQuery=false; 156 //boolean hasQuery=loop.containsAttribute("query"); 157 158 while((parent=getParentTagLoop(parent))!=null) { 159 if(!info.hasParentWithQuery)info.hasParentWithQuery=parent.hasQuery(); 160 if(!info.hasParentWithGroup)info.hasParentWithGroup=parent.hasGroup(); 161 if(info.hasParentWithQuery && info.hasParentWithGroup)break; 162 } 163 return info; 164 } 165 166 167 168 private static TagLoop getParentTagLoop(TagLoop stat) { 169 Statement parent = stat; 170 while(true) { 171 parent=parent.getParent(); 172 if(parent==null)return null; 173 if(parent instanceof TagLoop) return (TagLoop) parent; 174 } 175 } 176 177 class Info { 178 private boolean hasParentWithGroup=false; 179 private boolean hasParentWithQuery=false; 180 } 181 }