Coverage Report - org.apache.myfaces.view.facelets.tag.jstl.core.ForEachHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
ForEachHandler
0%
0/280
0%
0/178
5.857
ForEachHandler$ArrayIterator
0%
0/8
0%
0/2
5.857
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.view.facelets.tag.jstl.core;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.io.Serializable;
 23  
 import java.lang.reflect.Array;
 24  
 import java.util.Collection;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 import java.util.Map;
 28  
 
 29  
 import javax.el.ELException;
 30  
 import javax.el.ValueExpression;
 31  
 import javax.faces.FacesException;
 32  
 import javax.faces.application.StateManager;
 33  
 import javax.faces.component.UIComponent;
 34  
 import javax.faces.event.PhaseId;
 35  
 import javax.faces.view.facelets.FaceletContext;
 36  
 import javax.faces.view.facelets.FaceletException;
 37  
 import javax.faces.view.facelets.TagAttribute;
 38  
 import javax.faces.view.facelets.TagAttributeException;
 39  
 import javax.faces.view.facelets.TagConfig;
 40  
 import javax.faces.view.facelets.TagHandler;
 41  
 
 42  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
 43  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
 44  
 import org.apache.myfaces.util.ExternalSpecifications;
 45  
 import org.apache.myfaces.view.facelets.AbstractFaceletContext;
 46  
 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
 47  
 import org.apache.myfaces.view.facelets.PageContext;
 48  
 import org.apache.myfaces.view.facelets.el.FaceletStateValueExpression;
 49  
 import org.apache.myfaces.view.facelets.el.FaceletStateValueExpressionUEL;
 50  
 import org.apache.myfaces.view.facelets.tag.ComponentContainerHandler;
 51  
 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 52  
 import org.apache.myfaces.view.facelets.tag.jsf.FaceletState;
 53  
 
 54  
 /**
 55  
  * The basic iteration tag, accepting many different
 56  
  * collection types and supporting subsetting and other
 57  
  * functionality
 58  
  * 
 59  
  * @author Jacob Hookom
 60  
  * @author Andrew Robinson
 61  
  * @version $Id$
 62  
  */
 63  
 @JSFFaceletTag(name="c:forEach")
 64  
 public final class ForEachHandler extends TagHandler implements ComponentContainerHandler
 65  
 {
 66  
 
 67  
     private static class ArrayIterator implements Iterator<Object>
 68  
     {
 69  
 
 70  
         protected final Object array;
 71  
 
 72  
         protected int i;
 73  
 
 74  
         protected final int len;
 75  
 
 76  
         public ArrayIterator(Object src)
 77  0
         {
 78  0
             this.i = 0;
 79  0
             this.array = src;
 80  0
             this.len = Array.getLength(src);
 81  0
         }
 82  
 
 83  
         public boolean hasNext()
 84  
         {
 85  0
             return this.i < this.len;
 86  
         }
 87  
 
 88  
         public Object next()
 89  
         {
 90  0
             return Array.get(this.array, this.i++);
 91  
         }
 92  
 
 93  
         public void remove()
 94  
         {
 95  0
             throw new UnsupportedOperationException();
 96  
         }
 97  
     }
 98  
 
 99  
     /**
 100  
      * If items specified:
 101  
      * Iteration begins at the item located at the
 102  
      * specified index. First item of the collection has
 103  
      * index 0.
 104  
      * If items not specified:
 105  
      * Iteration begins with index set at the value
 106  
      * specified.
 107  
      */
 108  
     @JSFFaceletAttribute(className="int")
 109  
     private final TagAttribute begin;
 110  
 
 111  
     /**
 112  
      * If items specified:
 113  
      * Iteration ends at the item located at the
 114  
      * specified index (inclusive).
 115  
      * If items not specified:
 116  
      * Iteration ends when index reaches the value
 117  
      * specified.
 118  
      */
 119  
     @JSFFaceletAttribute(className="int")
 120  
     private final TagAttribute end;
 121  
 
 122  
     /**
 123  
      * Collection of items to iterate over.
 124  
      */
 125  
     @JSFFaceletAttribute(className="javax.el.ValueExpression")
 126  
     private final TagAttribute items;
 127  
 
 128  
     /**
 129  
      * Iteration will only process every step items of
 130  
      * the collection, starting with the first one.
 131  
      */
 132  
     @JSFFaceletAttribute(className="int")
 133  
     private final TagAttribute step;
 134  
 
 135  
     private final TagAttribute tranzient;
 136  
 
 137  
     /**
 138  
      * Name of the exported scoped variable for the
 139  
      * current item of the iteration. This scoped
 140  
      * variable has nested visibility. Its type depends
 141  
      * on the object of the underlying collection.
 142  
      */
 143  
     @JSFFaceletAttribute(className="java.lang.String")
 144  
     private final TagAttribute var;
 145  
 
 146  
     /**
 147  
      * Name of the exported scoped variable for the
 148  
      * status of the iteration. 
 149  
      */
 150  
     @JSFFaceletAttribute(className="java.lang.String")
 151  
     private final TagAttribute varStatus;
 152  
 
 153  
     /**
 154  
      * @param config
 155  
      */
 156  
     public ForEachHandler(TagConfig config)
 157  
     {
 158  0
         super(config);
 159  0
         this.items = this.getAttribute("items");
 160  0
         this.var = this.getAttribute("var");
 161  0
         this.begin = this.getAttribute("begin");
 162  0
         this.end = this.getAttribute("end");
 163  0
         this.step = this.getAttribute("step");
 164  0
         this.varStatus = this.getAttribute("varStatus");
 165  0
         this.tranzient = this.getAttribute("transient");
 166  
 
 167  0
         if (this.items == null && this.begin != null && this.end == null)
 168  
         {
 169  0
             throw new TagAttributeException(this.tag, this.begin,
 170  
                                             "If the 'items' attribute is not specified, but the 'begin' attribute is, "
 171  
                                             + "then the 'end' attribute is required");
 172  
         }
 173  0
     }
 174  
 
 175  
     public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
 176  
             ELException
 177  
     {
 178  0
         int e = this.getEnd(ctx);
 179  0
         Object src = null;
 180  0
         ValueExpression srcVE = null;
 181  0
         if (this.items != null)
 182  
         {
 183  0
             srcVE = this.items.getValueExpression(ctx, Object.class);
 184  0
             src = srcVE.getValue(ctx);
 185  
         }
 186  
         else
 187  
         {
 188  0
             byte[] b = new byte[e + 1];
 189  0
             for (int i = 0; i < b.length; i++)
 190  
             {
 191  0
                 b[i] = (byte) i;
 192  
             }
 193  0
             src = b;
 194  
         }
 195  0
         FaceletCompositionContext fcc = FaceletCompositionContext.getCurrentInstance(ctx);
 196  0
         AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
 197  
         // Just increment one number to ensure the prefix doesn't conflict later if two
 198  
         // c:forEach are close between each other. Note c:forEach is different from
 199  
         // c:if tag and doesn't require a section because c:forEach requires to provide
 200  
         // multiple sections starting with a specified "base" related to the element
 201  
         // position and value in the collection.
 202  0
         fcc.incrementUniqueComponentId();
 203  0
         String uniqueId = actx.generateUniqueFaceletTagId(fcc.generateUniqueId(), tagId);
 204  0
         if (src != null)
 205  
         {
 206  0
             PageContext pctx = actx.getPageContext();
 207  
             // c:forEach is special because it requires FaceletState even if no pss is used.
 208  0
             FaceletState restoredFaceletState = ComponentSupport.getFaceletState(ctx, parent, false);
 209  0
             IterationState restoredSavedOption = (restoredFaceletState == null) ? null : 
 210  
                 (IterationState) restoredFaceletState.getState(uniqueId);
 211  
 
 212  0
             if (restoredSavedOption != null)
 213  
             {            
 214  0
                 if (!PhaseId.RESTORE_VIEW.equals(ctx.getFacesContext().getCurrentPhaseId()))
 215  
                 {
 216  
                     // Refresh, evaluate and synchronize state
 217  0
                     applyOnRefresh(ctx, fcc, pctx, parent, uniqueId, src, srcVE, restoredSavedOption);
 218  
                 }
 219  
                 else
 220  
                 {
 221  
                     // restore view, don't record iteration, use the saved value
 222  0
                     applyOnRestore(ctx, fcc, pctx, parent, uniqueId, src, srcVE, restoredSavedOption);
 223  
                 }
 224  
             }
 225  
             else
 226  
             {
 227  
                 // First time         
 228  0
                 applyFirstTime(ctx, fcc, pctx, parent, uniqueId, src, srcVE);
 229  
             }
 230  
         }
 231  
 
 232  0
         if (fcc.isUsingPSSOnThisView() && fcc.isRefreshTransientBuildOnPSS() && !fcc.isRefreshingTransientBuild())
 233  
         {
 234  
             //Mark the parent component to be saved and restored fully.
 235  0
             ComponentSupport.markComponentToRestoreFully(ctx.getFacesContext(), parent);
 236  
         }
 237  0
         if (fcc.isDynamicComponentSection())
 238  
         {
 239  0
             ComponentSupport.markComponentToRefreshDynamically(ctx.getFacesContext(), parent);
 240  
         }
 241  0
     }
 242  
     
 243  
     private void setVar(FaceletContext ctx, UIComponent parent,
 244  
         String uniqueId, String base, boolean t, Object src, 
 245  
         ValueExpression srcVE, Object value, String v, int i)
 246  
     {
 247  
         // set the var
 248  0
         if (v != null)
 249  
         {
 250  
             ValueExpression ve;
 251  0
             if (t || srcVE == null)
 252  
             {
 253  0
                 if (value == null)
 254  
                 {
 255  0
                     ve = null;
 256  
                 }
 257  
                 else
 258  
                 {
 259  0
                     ve = ctx.getExpressionFactory().createValueExpression(
 260  
                                 value, Object.class);
 261  
                 }
 262  
             }
 263  
             else
 264  
             {
 265  0
                 ve = this.getVarExpr(srcVE, src, value, i);
 266  
             }
 267  0
             setVar(ctx, parent, uniqueId, base, v, ve, srcVE);
 268  
         }
 269  0
     }
 270  
     
 271  
     private void setVar(FaceletContext ctx, UIComponent parent,
 272  
         String uniqueId, String base, String v, ValueExpression ve, ValueExpression srcVE)
 273  
     {
 274  0
         AbstractFaceletContext actx = ((AbstractFaceletContext) ctx);
 275  0
         PageContext pctx = actx.getPageContext();
 276  
         //if (ELExpressionCacheMode.alwaysRecompile.equals(actx.getELExpressionCacheMode()))
 277  
         //{
 278  0
         if (srcVE != null)
 279  
         {
 280  0
             FaceletState faceletState = ComponentSupport.getFaceletState(ctx, parent, true);
 281  0
             faceletState.putBinding(uniqueId, base, ve);
 282  
 
 283  
             //Put the indirect EL into context
 284  
             ValueExpression fve;
 285  0
             if (ExternalSpecifications.isUnifiedELAvailable())
 286  
             {
 287  0
                 fve = new FaceletStateValueExpressionUEL(uniqueId, base);
 288  
             }
 289  
             else
 290  
             {
 291  0
                 fve = new FaceletStateValueExpression(uniqueId, base);
 292  
             }
 293  0
             pctx.getAttributes().put(v, fve);
 294  0
         }
 295  
         else
 296  
         {
 297  0
             pctx.getAttributes().put(v, ve);
 298  
         }
 299  0
     }
 300  
     
 301  
     private void applyFirstTime(FaceletContext ctx, FaceletCompositionContext fcc, PageContext pctx, 
 302  
         UIComponent parent, String uniqueId, Object src, ValueExpression srcVE) throws IOException
 303  
     {
 304  0
         int s = this.getBegin(ctx);
 305  0
         int e = this.getEnd(ctx);
 306  0
         int m = this.getStep(ctx);
 307  0
         Integer sO = this.begin != null ? Integer.valueOf(s) : null;
 308  0
         Integer eO = this.end != null ? Integer.valueOf(e) : null;
 309  0
         Integer mO = this.step != null ? Integer.valueOf(m) : null;
 310  0
         boolean t = this.getTransient(ctx);
 311  0
         IterationState iterationState = new IterationState();
 312  
 
 313  0
         boolean serializableValues = true;
 314  0
         Iterator<?> itr = this.toIterator(src);
 315  0
         if (itr != null)
 316  
         {
 317  0
             int i = 0;
 318  
 
 319  
             // move to start
 320  0
             while (i < s && itr.hasNext())
 321  
             {
 322  0
                 itr.next();
 323  0
                 i++;
 324  
             }
 325  
 
 326  0
             String v = this.getVarName(ctx);
 327  0
             String vs = this.getVarStatusName(ctx);
 328  0
             ValueExpression vO = this.capture(v, pctx);
 329  0
             ValueExpression vsO = this.capture(vs, pctx);
 330  0
             int mi = 0;
 331  0
             Object value = null;
 332  
             try
 333  
             {
 334  0
                 boolean first = true;
 335  0
                 while (i <= e && itr.hasNext())
 336  
                 {
 337  0
                     value = itr.next();
 338  
 
 339  
                     // first time, use the counter
 340  0
                     Integer count = iterationState.getCounter();
 341  0
                     String base = count.toString();
 342  0
                     iterationState.setCounter(count+1);
 343  
 
 344  0
                     if (value instanceof Serializable)
 345  
                     {
 346  0
                         iterationState.getValueList().add(
 347  
                             new Object[]{base, value, i});
 348  
                     }
 349  
                     else
 350  
                     {
 351  0
                         serializableValues = false;
 352  
                     }
 353  
 
 354  
                     try
 355  
                     {
 356  0
                         fcc.startComponentUniqueIdSection(base);
 357  
 
 358  0
                         setVar(ctx, parent, uniqueId, base, t, src, srcVE, value, v, i);
 359  0
                         boolean last = !itr.hasNext();
 360  
                         // set the varStatus
 361  0
                         if (vs != null)
 362  
                         {
 363  0
                             IterationStatus itrS = new IterationStatus(first, last, i, sO, eO, mO, value);
 364  
                             ValueExpression ve;
 365  0
                             if (t || srcVE == null)
 366  
                             {
 367  0
                                 if (srcVE == null)
 368  
                                 {
 369  0
                                     ve = null;
 370  
                                 }
 371  
                                 else
 372  
                                 {
 373  0
                                     ve = ctx.getExpressionFactory().createValueExpression(
 374  
                                                 itrS, Object.class);
 375  
                                 }
 376  
                             }
 377  
                             else
 378  
                             {
 379  0
                                 ve = new IterationStatusExpression(itrS);
 380  
                             }
 381  0
                             setVar(ctx, parent, uniqueId, base+"_vs", vs, ve, srcVE);
 382  
                         }
 383  
 
 384  
                         // execute body
 385  0
                         this.nextHandler.apply(ctx, parent);
 386  
                     }
 387  
                     finally
 388  
                     {
 389  0
                         fcc.endComponentUniqueIdSection(base);
 390  0
                     }
 391  
 
 392  
                     // increment steps
 393  0
                     mi = 1;
 394  0
                     while (mi < m && itr.hasNext())
 395  
                     {
 396  0
                         itr.next();
 397  0
                         mi++;
 398  0
                         i++;
 399  
                     }
 400  0
                     i++;
 401  
 
 402  0
                     first = false;
 403  0
                 }
 404  
             }
 405  
             finally
 406  
             {
 407  0
                 removeVarAndVarStatus(pctx, v, vO, vs, vsO);
 408  0
             }
 409  
         }
 410  0
         if (serializableValues)
 411  
         {
 412  0
             FaceletState faceletState = ComponentSupport.getFaceletState(ctx, parent, true);
 413  0
             faceletState.putState(uniqueId, iterationState);
 414  
         }
 415  0
     }
 416  
     
 417  
     private void applyOnRestore(FaceletContext ctx, FaceletCompositionContext fcc, PageContext pctx, 
 418  
         UIComponent parent, String uniqueId, Object src, ValueExpression srcVE, IterationState restoredSavedOption)
 419  
         throws IOException
 420  
     {
 421  0
         int s = this.getBegin(ctx);
 422  0
         int e = this.getEnd(ctx);
 423  0
         int m = this.getStep(ctx);
 424  0
         Integer sO = this.begin != null ? Integer.valueOf(s) : null;
 425  0
         Integer eO = this.end != null ? Integer.valueOf(e) : null;
 426  0
         Integer mO = this.step != null ? Integer.valueOf(m) : null;
 427  0
         boolean t = this.getTransient(ctx);
 428  
 
 429  
         // restore view, don't record iteration, use the saved value
 430  0
         String v = this.getVarName(ctx);
 431  0
         String vs = this.getVarStatusName(ctx);
 432  0
         ValueExpression vO = this.capture(v, pctx);
 433  0
         ValueExpression vsO = this.capture(vs, pctx);
 434  0
         Object value = null;
 435  
         try
 436  
         {
 437  0
             int size = restoredSavedOption.getValueList().size();
 438  0
             for (int si = 0; si < size; si++)
 439  
             {
 440  0
                 Object[] stateValue = restoredSavedOption.getValueList().get(si);
 441  0
                 value = stateValue[1];
 442  0
                 String base = (String) stateValue[0];
 443  
 
 444  
                 try
 445  
                 {
 446  0
                     fcc.startComponentUniqueIdSection(base);
 447  
 
 448  0
                     setVar(ctx, parent, uniqueId, base, t, src, srcVE, value, v, (Integer) stateValue[2]);
 449  
 
 450  0
                     boolean first = (si == 0);
 451  0
                     boolean last = (si == size-1);
 452  0
                     int i = (Integer)stateValue[2];
 453  
                     // set the varStatus
 454  0
                     if (vs != null)
 455  
                     {
 456  0
                         IterationStatus itrS = new IterationStatus(first, last, i, sO, eO, mO, value);
 457  
                         ValueExpression ve;
 458  0
                         if (t || srcVE == null)
 459  
                         {
 460  0
                             if (srcVE == null)
 461  
                             {
 462  0
                                 ve = null;
 463  
                             }
 464  
                             else
 465  
                             {
 466  0
                                 ve = ctx.getExpressionFactory().createValueExpression(
 467  
                                             itrS, Object.class);
 468  
                             }
 469  
                         }
 470  
                         else
 471  
                         {
 472  0
                             ve = new IterationStatusExpression(itrS);
 473  
                         }
 474  0
                         setVar(ctx, parent, uniqueId, base+"_vs", vs, ve, srcVE);
 475  
                     }
 476  
 
 477  
                     // execute body
 478  0
                     this.nextHandler.apply(ctx, parent);
 479  
                 }
 480  
                 finally
 481  
                 {
 482  0
                     fcc.endComponentUniqueIdSection(base);
 483  0
                 }
 484  
             }
 485  
         }
 486  
         finally
 487  
         {
 488  0
             removeVarAndVarStatus(pctx, v, vO, vs, vsO);
 489  0
         }
 490  0
     }
 491  
     
 492  
     private void applyOnRefresh(FaceletContext ctx, FaceletCompositionContext fcc, PageContext pctx, 
 493  
         UIComponent parent, String uniqueId, Object src, ValueExpression srcVE, IterationState restoredSavedOption)
 494  
         throws IOException
 495  
     {
 496  0
         int s = this.getBegin(ctx);
 497  0
         int e = this.getEnd(ctx);
 498  0
         int m = this.getStep(ctx);
 499  0
         Integer sO = this.begin != null ? Integer.valueOf(s) : null;
 500  0
         Integer eO = this.end != null ? Integer.valueOf(e) : null;
 501  0
         Integer mO = this.step != null ? Integer.valueOf(m) : null;
 502  0
         boolean t = this.getTransient(ctx);
 503  
 
 504  
         // Refresh, evaluate and synchronize state
 505  0
         Iterator<?> itr = this.toIterator(src);
 506  0
         IterationState iterationState = new IterationState();
 507  0
         iterationState.setCounter(restoredSavedOption.getCounter());
 508  0
         if (itr != null)
 509  
         {
 510  0
             int i = 0;
 511  
 
 512  
             // move to start
 513  0
             while (i < s && itr.hasNext())
 514  
             {
 515  0
                 itr.next();
 516  0
                 i++;
 517  
             }
 518  
 
 519  0
             String v = this.getVarName(ctx);
 520  0
             String vs = this.getVarStatusName(ctx);
 521  0
             ValueExpression vO = this.capture(v, pctx);
 522  0
             ValueExpression vsO = this.capture(vs, pctx);
 523  0
             int mi = 0;
 524  0
             Object value = null;
 525  0
             int stateIndex = 0;
 526  
             try
 527  
             {
 528  0
                 boolean first = true;
 529  0
                 while (i <= e && itr.hasNext())
 530  
                 {
 531  0
                     value = itr.next();
 532  0
                     Object[] stateValue = null; /*restoredSavedOption.getValueList().get(stateIndex);*/
 533  0
                     String base = null;
 534  0
                     boolean found = false;
 535  
 
 536  
                     // The important thing here is use the same base for the generated component ids
 537  
                     // for each element in the iteration that was used on the restore. To do that
 538  
                     // 
 539  0
                     int stateIndexCheck = stateIndex;
 540  0
                     for (; stateIndexCheck < restoredSavedOption.getValueList().size(); stateIndexCheck++)
 541  
                     {
 542  0
                         stateValue = restoredSavedOption.getValueList().get(stateIndexCheck);
 543  0
                         if (value.equals(stateValue[1]))
 544  
                         {
 545  0
                             found = true;
 546  0
                             break;
 547  
                         }
 548  
                     }
 549  0
                     if (found)
 550  
                     {
 551  0
                         stateIndex = stateIndexCheck;
 552  0
                         base = (String) stateValue[0];
 553  0
                         stateIndex++;
 554  
                     }
 555  
                     else
 556  
                     {
 557  
                         // No state, added item, create new count
 558  0
                         Integer count = iterationState.getCounter();
 559  0
                         base = count.toString();
 560  0
                         iterationState.setCounter(count+1);
 561  0
                         stateValue = null;
 562  
                     }
 563  
 
 564  0
                     if (value instanceof Serializable)
 565  
                     {
 566  0
                         iterationState.getValueList().add(
 567  
                             new Object[]{base, value, i});
 568  
                     }
 569  
 
 570  
                     try
 571  
                     {
 572  0
                         fcc.startComponentUniqueIdSection(base);
 573  
 
 574  0
                         setVar(ctx, parent, uniqueId, base, t, src, srcVE, value, v, i);
 575  
 
 576  0
                         boolean last = !itr.hasNext();
 577  
                         // set the varStatus
 578  0
                         if (vs != null)
 579  
                         {
 580  0
                             IterationStatus itrS = new IterationStatus(first, last, i, sO, eO, mO, value);
 581  
                             ValueExpression ve;
 582  0
                             if (t || srcVE == null)
 583  
                             {
 584  0
                                 if (srcVE == null)
 585  
                                 {
 586  0
                                     ve = null;
 587  
                                 }
 588  
                                 else
 589  
                                 {
 590  0
                                     ve = ctx.getExpressionFactory().createValueExpression(
 591  
                                                 itrS, Object.class);
 592  
                                 }
 593  
                             }
 594  
                             else
 595  
                             {
 596  0
                                 ve = new IterationStatusExpression(itrS);
 597  
                             }
 598  0
                             setVar(ctx, parent, uniqueId, base+"_vs", vs, ve, srcVE);
 599  
                         }
 600  
                         //setVarStatus(ctx, pctx, t, sO, eO, mO, srcVE, value, vs, first, !itr.hasNext(), i);
 601  
 
 602  
                         // execute body
 603  0
                         boolean markInitialState = (stateValue == null);// !restoredSavedOption.equals(i)
 604  0
                         boolean oldMarkInitialState = false;
 605  0
                         Boolean isBuildingInitialState = null;
 606  
                         try
 607  
                         {
 608  0
                             if (markInitialState && fcc.isUsingPSSOnThisView())
 609  
                             {
 610  
                                 //set markInitialState flag
 611  0
                                 oldMarkInitialState = fcc.isMarkInitialState();
 612  0
                                 fcc.setMarkInitialState(true);
 613  0
                                 isBuildingInitialState = (Boolean) ctx.getFacesContext().getAttributes().put(
 614  
                                         StateManager.IS_BUILDING_INITIAL_STATE, Boolean.TRUE);
 615  
                             }                                
 616  0
                             this.nextHandler.apply(ctx, parent);
 617  
                         }
 618  
                         finally
 619  
                         {
 620  0
                             if (markInitialState && fcc.isUsingPSSOnThisView())
 621  
                             {
 622  
                                 //unset markInitialState flag
 623  0
                                 if (isBuildingInitialState == null)
 624  
                                 {
 625  0
                                     ctx.getFacesContext().getAttributes().remove(
 626  
                                             StateManager.IS_BUILDING_INITIAL_STATE);
 627  
                                 }
 628  
                                 else
 629  
                                 {
 630  0
                                     ctx.getFacesContext().getAttributes().put(
 631  
                                             StateManager.IS_BUILDING_INITIAL_STATE, isBuildingInitialState);
 632  
                                 }
 633  0
                                 fcc.setMarkInitialState(oldMarkInitialState);
 634  
                             }
 635  
                         }
 636  
                     }
 637  
                     finally
 638  
                     {
 639  0
                         fcc.endComponentUniqueIdSection(base);
 640  0
                     }
 641  
 
 642  
                     // increment steps
 643  0
                     mi = 1;
 644  0
                     while (mi < m && itr.hasNext())
 645  
                     {
 646  0
                         itr.next();
 647  0
                         mi++;
 648  0
                         i++;
 649  
                     }
 650  0
                     i++;
 651  
 
 652  0
                     first = false;
 653  0
                 }
 654  
             }
 655  
             finally
 656  
             {
 657  0
                 removeVarAndVarStatus(pctx, v, vO, vs, vsO);
 658  0
             }
 659  
         }
 660  0
         FaceletState faceletState = ComponentSupport.getFaceletState(ctx, parent, true);
 661  0
         faceletState.putState(uniqueId, iterationState);
 662  0
     }
 663  
     
 664  
     private void removeVarAndVarStatus(PageContext pctx, String v, ValueExpression vO, String vs, ValueExpression vsO)
 665  
     {
 666  
         //Remove them from PageContext
 667  0
         if (v != null)
 668  
         {
 669  0
             pctx.getAttributes().put(v, vO);
 670  
         }
 671  
         else
 672  
         {
 673  0
             pctx.getAttributes().remove(v);
 674  
         }
 675  0
         if (vs != null)
 676  
         {
 677  0
             pctx.getAttributes().put(vs, vsO);
 678  
         }
 679  
         else
 680  
         {
 681  0
             pctx.getAttributes().remove(vs);
 682  
         }
 683  0
     }
 684  
 
 685  
     private ValueExpression capture(String name, PageContext pctx)
 686  
     {
 687  0
         if (name != null)
 688  
         {
 689  0
             return pctx.getAttributes().put(name, null);
 690  
         }
 691  0
         return null;
 692  
     }
 693  
 
 694  
     private int getBegin(FaceletContext ctx)
 695  
     {
 696  0
         if (this.begin != null)
 697  
         {
 698  0
             return this.begin.getInt(ctx);
 699  
         }
 700  0
         return 0;
 701  
     }
 702  
 
 703  
     private int getEnd(FaceletContext ctx)
 704  
     {
 705  0
         if (this.end != null)
 706  
         {
 707  0
             return this.end.getInt(ctx);
 708  
         }
 709  0
         return Integer.MAX_VALUE - 1; // hotspot bug in the JVM
 710  
     }
 711  
 
 712  
     private int getStep(FaceletContext ctx)
 713  
     {
 714  0
         if (this.step != null)
 715  
         {
 716  0
             return this.step.getInt(ctx);
 717  
         }
 718  0
         return 1;
 719  
     }
 720  
 
 721  
     private boolean getTransient(FaceletContext ctx)
 722  
     {
 723  0
         if (this.tranzient != null)
 724  
         {
 725  0
             return this.tranzient.getBoolean(ctx);
 726  
         }
 727  0
         return false;
 728  
     }
 729  
 
 730  
     private ValueExpression getVarExpr(ValueExpression ve, Object src, Object value, int i)
 731  
     {
 732  0
         if (src instanceof List || src.getClass().isArray())
 733  
         {
 734  
             //return new IndexedValueExpression(ve, i);
 735  0
             return new IteratedValueExpression(ve, value);
 736  
         }
 737  0
         else if (src instanceof Map && value instanceof Map.Entry)
 738  
         {
 739  0
             return new MappedValueExpression(ve, (Map.Entry) value);
 740  
         }
 741  0
         else if (src instanceof Collection)
 742  
         {
 743  0
             return new IteratedValueExpression(ve, value);
 744  
         }
 745  0
         throw new IllegalStateException("Cannot create VE for: " + src);
 746  
     }
 747  
 
 748  
     private String getVarName(FaceletContext ctx)
 749  
     {
 750  0
         if (this.var != null)
 751  
         {
 752  0
             return this.var.getValue(ctx);
 753  
         }
 754  0
         return null;
 755  
     }
 756  
 
 757  
     private String getVarStatusName(FaceletContext ctx)
 758  
     {
 759  0
         if (this.varStatus != null)
 760  
         {
 761  0
             return this.varStatus.getValue(ctx);
 762  
         }
 763  0
         return null;
 764  
     }
 765  
 
 766  
     private Iterator<?> toIterator(Object src)
 767  
     {
 768  0
         if (src == null)
 769  
         {
 770  0
             return null;
 771  
         }
 772  0
         else if (src instanceof Collection)
 773  
         {
 774  0
             return ((Collection<?>) src).iterator();
 775  
         }
 776  0
         else if (src instanceof Map)
 777  
         {
 778  0
             return ((Map<?, ?>) src).entrySet().iterator();
 779  
         }
 780  0
         else if (src.getClass().isArray())
 781  
         {
 782  0
             return new ArrayIterator(src);
 783  
         }
 784  
         else
 785  
         {
 786  0
             throw new TagAttributeException(this.tag, this.items,
 787  
                     "Must evaluate to a Collection, Map, Array, or null.");
 788  
         }
 789  
     }
 790  
 
 791  
 }