1 28 29 package com.caucho.jstl.el; 30 31 import com.caucho.el.Expr; 32 import com.caucho.jsp.PageContextImpl; 33 import com.caucho.util.CharBuffer; 34 import com.caucho.util.EnumIterator; 35 import com.caucho.util.L10N; 36 import com.caucho.util.NullIterator; 37 38 import javax.el.ELContext; 39 import javax.servlet.jsp.JspException ; 40 import javax.servlet.jsp.JspTagException ; 41 import javax.servlet.jsp.jstl.core.LoopTag; 42 import javax.servlet.jsp.jstl.core.LoopTagStatus; 43 import javax.servlet.jsp.tagext.IterationTag ; 44 import javax.servlet.jsp.tagext.TagSupport ; 45 import java.lang.reflect.Array ; 46 import java.util.Collection ; 47 import java.util.Enumeration ; 48 import java.util.Iterator ; 49 import java.util.Map ; 50 51 public class ForEachTag extends TagSupport 52 implements IterationTag , LoopTag, LoopTagStatus { 53 private static L10N L = new L10N(ForEachTag.class); 54 55 protected Expr _itemsExpr; 56 57 protected Expr _beginExpr; 58 protected Expr _endExpr; 59 protected Expr _stepExpr; 60 61 protected String _var; 62 protected String _varStatus; 63 64 protected Iterator _iterator; 66 67 protected int _begin; 68 protected int _end; 69 protected int _step; 70 71 protected Object _initialVar; 72 protected Object _current; 73 protected int _index; 74 protected int _count; 75 76 79 public void setItems(Expr items) 80 { 81 _itemsExpr = items; 82 } 83 84 87 public void setBegin(Expr begin) 88 { 89 _beginExpr = begin; 90 } 91 92 95 public void setEnd(Expr end) 96 { 97 _endExpr = end; 98 } 99 100 103 public void setStep(Expr step) 104 { 105 _stepExpr = step; 106 } 107 108 111 public void setVar(String var) 112 { 113 _var = var; 114 } 115 116 119 public void setVarStatus(String var) 120 { 121 _varStatus = var; 122 } 123 124 127 public int doStartTag() 128 throws JspException 129 { 130 try { 131 _iterator = null; 132 _index = 0; 133 _count = 0; 134 135 PageContextImpl pageContext = (PageContextImpl) this.pageContext; 136 ELContext env = pageContext.getELContext(); 137 138 if (_beginExpr != null) 139 _begin = (int) _beginExpr.evalLong(env); 140 else 141 _begin = -1; 142 143 if (_endExpr != null) 144 _end = (int) _endExpr.evalLong(env); 145 else 146 _end = Integer.MAX_VALUE; 147 148 if (_stepExpr != null) 149 _step = (int) _stepExpr.evalLong(env); 150 else 151 _step = 0; 152 153 Object items = null; 154 155 if (_itemsExpr != null) { 156 items = _itemsExpr.evalObject(env); 157 158 _iterator = getIterator(items); 159 160 while (_index < _begin && _iterator.hasNext()) { 161 _index++; 162 _iterator.next(); 163 } 164 } 165 else if (_beginExpr == null) 166 throw new JspException (L.l("c:forEach must specify `items' or `begin'")); 167 else if (_endExpr == null) 168 throw new JspException (L.l("c:forEach must specify `items' or `begin'")); 169 else { 170 _iterator = new RangeIterator(_begin, _end); 171 _end = -1; 172 } 173 174 if (_varStatus != null) 175 pageContext.setAttribute(_varStatus, this); 176 177 if (_var != null) 178 _initialVar = pageContext.getAttribute(_var); 179 180 return doAfterBody(); 181 } catch (Exception e) { 182 throw new JspException (e); 183 } 184 } 185 186 public int doAfterBody() throws JspException 187 { 188 if (_iterator == null) { 189 if (_var != null) 190 pageContext.setAttribute(_var, _initialVar); 191 192 return SKIP_BODY; 193 } 194 else if (_iterator.hasNext()) { 195 int stepCount; 196 197 if (_step <= 0 || _count == 0) 198 stepCount = 1; 199 else 200 stepCount = _step; 201 202 for (; stepCount > 0; stepCount--) { 203 if (! _iterator.hasNext()) { 204 if (_var != null) 205 pageContext.setAttribute(_var, _initialVar); 206 207 return SKIP_BODY; 208 } 209 210 _index++; 211 _current = _iterator.next(); 212 } 213 214 _count++; 215 216 if (_var != null) 217 pageContext.setAttribute(_var, _current); 218 219 if (_index - 1 <= _end || _end < 0) 220 return EVAL_BODY_AGAIN; 221 else { 222 if (_var != null) 223 pageContext.setAttribute(_var, _initialVar); 224 225 return SKIP_BODY; 226 } 227 } 228 else { 229 if (_var != null) 230 pageContext.setAttribute(_var, _initialVar); 231 232 return SKIP_BODY; 233 } 234 } 235 236 238 241 public LoopTagStatus getLoopStatus() 242 { 243 return this; 244 } 245 246 247 249 252 public Object getCurrent() 253 { 254 return _current; 255 } 256 257 260 public int getIndex() 261 { 262 return _index - 1; 263 } 264 265 268 public int getCount() 269 { 270 return _count; 271 } 272 273 276 public boolean isFirst() 277 { 278 return _count == 1; 279 } 280 281 284 public boolean isLast() 285 { 286 if (_iterator == null || ! _iterator.hasNext()) 287 return true; 288 else if (_step > 0 && _step + _index > _end) 289 return true; 290 else 291 return false; 292 } 293 294 297 public Integer getBegin() 298 { 299 if (_beginExpr != null && _itemsExpr != null) 300 return new Integer (_begin); 301 else 302 return null; 303 } 304 305 308 public Integer getEnd() 309 { 310 if (_endExpr != null && _itemsExpr != null) 311 return new Integer (_end); 312 else 313 return null; 314 } 315 316 319 public Integer getStep() 320 { 321 if (_stepExpr != null) 322 return new Integer (_step); 323 else 324 return null; 325 } 326 327 public static Iterator getIterator(Object items) 328 throws JspTagException 329 { 330 if (items == null) 331 return NullIterator.create(); 332 else if (items instanceof Map ) 333 return ((Map ) items).entrySet().iterator(); 334 else if (items instanceof Collection ) 335 return ((Collection ) items).iterator(); 336 else if (items.getClass().isArray()) 337 return new ArrayIterator(items); 338 else if (items instanceof Iterator) 339 return (Iterator) items; 340 else if (items instanceof Enumeration ) 341 return new EnumIterator((Enumeration ) items); 342 else if (items instanceof String ) 343 return new StringIterator((String ) items); 344 else 345 throw new JspTagException (L.l("unknown items value `{0}'", items)); 346 } 347 348 public static class ArrayIterator implements Iterator { 349 private Object array; 350 private int index; 351 private int length; 352 353 ArrayIterator(Object array) 354 { 355 this.array = array; 356 this.length = Array.getLength(array); 357 } 358 359 public boolean hasNext() 360 { 361 return index < length; 362 } 363 364 public Object next() 365 { 366 if (index < length) 367 return Array.get(array, index++); 368 else 369 return null; 370 } 371 372 public void remove() 373 { 374 throw new UnsupportedOperationException (); 375 } 376 } 377 378 public static class StringIterator implements Iterator { 379 private String _value; 380 private int _length; 381 private int _i; 382 private CharBuffer _cb = new CharBuffer(); 383 384 StringIterator(String value) 385 { 386 _value = value; 387 _length = value.length(); 388 } 389 390 public boolean hasNext() 391 { 392 return _i < _length; 393 } 394 395 public Object next() 396 { 397 _cb.clear(); 398 399 char ch = 0; 400 for (; _i < _length && (ch = _value.charAt(_i)) != ','; _i++) 401 _cb.append(ch); 402 403 _i++; 404 405 return _cb.toString(); 406 } 407 408 public void remove() 409 { 410 throw new UnsupportedOperationException (); 411 } 412 } 413 414 public static class RangeIterator implements Iterator { 415 private int _end; 416 private int _i; 417 418 RangeIterator(int begin, int end) 419 { 420 _i = begin; 421 _end = end; 422 } 423 424 public boolean hasNext() 425 { 426 return _i <= _end; 427 } 428 429 public Object next() 430 { 431 if (_i <= _end) 432 return new Integer (_i++); 433 else 434 return null; 435 } 436 437 public void remove() 438 { 439 throw new UnsupportedOperationException (); 440 } 441 } 442 } 443 | Popular Tags |