1 52 53 package freemarker.core; 54 55 import java.io.IOException ; 56 import java.util.HashSet ; 57 import java.util.Set ; 58 import freemarker.template.*; 59 60 63 final class IteratorBlock extends TemplateElement { 64 65 private Expression listExpression; 66 private String indexName; 67 private boolean isForEach; 68 69 74 IteratorBlock(Expression listExpression, 75 String indexName, 76 TemplateElement nestedBlock, 77 boolean isForEach) 78 { 79 this.listExpression = listExpression; 80 this.indexName = indexName; 81 this.isForEach = isForEach; 82 this.nestedBlock = nestedBlock; 83 } 84 85 void accept(Environment env) throws TemplateException, IOException 86 { 87 TemplateModel baseModel = listExpression.getAsTemplateModel(env); 88 if (baseModel == null) { 89 if (env.isClassicCompatible()) { 90 return; 92 } 93 assertNonNull(baseModel, listExpression, env); 94 } 95 env.visit(new Context(baseModel)); 96 } 97 98 public String getCanonicalForm() { 99 if (isForEach) { 100 StringBuffer buf = new StringBuffer ("<#foreach "); 101 buf.append(indexName); 102 buf.append(" in "); 103 buf.append(listExpression.getCanonicalForm()); 104 buf.append(">"); 105 if (nestedBlock != null) { 106 buf.append(nestedBlock.getCanonicalForm()); 107 } 108 buf.append("</#foreach>"); 109 return buf.toString(); 110 } 111 else { 112 StringBuffer buf = new StringBuffer ("<#list "); 113 buf.append(listExpression.getCanonicalForm()); 114 buf.append(" as "); 115 buf.append(indexName); 116 buf.append(">"); 117 if (nestedBlock != null) { 118 buf.append(nestedBlock.getCanonicalForm()); 119 } 120 buf.append("</#list>"); 121 return buf.toString(); 122 } 123 } 124 125 public String getDescription() { 126 if (isForEach) { 127 return "foreach " + indexName + " in " + listExpression; 128 129 } 130 else { 131 return "list " + listExpression + " as " + indexName; 132 } 133 } 134 135 138 139 class Context implements LocalContext { 140 private boolean hasNext; 141 private TemplateModel loopVar; 142 private int index; 143 private Set variableNames = null; 144 private TemplateModel list; 145 146 Context(TemplateModel list) { 147 this.list = list; 148 } 149 150 151 void runLoop(Environment env) throws TemplateException, IOException { 152 if (list instanceof TemplateCollectionModel) { 153 TemplateCollectionModel baseListModel = (TemplateCollectionModel)list; 154 TemplateModelIterator it = baseListModel.iterator(); 155 hasNext = it.hasNext(); 156 while (hasNext) { 157 loopVar = it.next(); 158 hasNext = it.hasNext(); 159 if (nestedBlock != null) { 160 env.visit(nestedBlock); 161 } 162 index++; 163 } 164 } 165 else if (list instanceof TemplateSequenceModel) { 166 TemplateSequenceModel tsm = (TemplateSequenceModel) list; 167 int size = tsm.size(); 168 for (index =0; index <size; index++) { 169 loopVar = tsm.get(index); 170 hasNext = (size > index +1); 171 if (nestedBlock != null) { 172 env.visit(nestedBlock); 173 } 174 } 175 } 176 else if (env.isClassicCompatible()) { 177 loopVar = list; 178 if (nestedBlock != null) { 179 env.visit(nestedBlock); 180 } 181 } 182 else { 183 throw invalidTypeException(list, listExpression, env, "collection or sequence"); 184 } 185 } 186 187 public TemplateModel getLocalVariable(String name) { 188 if (name.startsWith(indexName)) { 189 switch(name.length() - indexName.length()) { 190 case 0: 191 return loopVar; 192 case 6: 193 if(name.endsWith("_index")) { 194 return new SimpleNumber(index); 195 } 196 break; 197 case 9: 198 if(name.endsWith("_has_next")) { 199 return hasNext ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; 200 } 201 break; 202 } 203 } 204 return null; 205 } 206 207 public Set getLocalVariableNames() { 208 if(variableNames == null) { 209 variableNames = new HashSet (); 210 variableNames.add(indexName); 211 variableNames.add(indexName + "_index"); 212 variableNames.add(indexName + "_has_next"); 213 } 214 return variableNames; 215 } 216 } 217 } 218 | Popular Tags |