Home » Mojarra-2.0.1 » javax » faces » component » [javadoc | source]

    1   /*
    2    * $Id: SelectItemsIterator.java,v 1.18 2008/01/08 22:29:24 rlubke Exp $
    3    */
    4   
    5   /*
    6    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    7    * 
    8    * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    9    * 
   10    * The contents of this file are subject to the terms of either the GNU
   11    * General Public License Version 2 only ("GPL") or the Common Development
   12    * and Distribution License("CDDL") (collectively, the "License").  You
   13    * may not use this file except in compliance with the License. You can obtain
   14    * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
   15    * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
   16    * language governing permissions and limitations under the License.
   17    * 
   18    * When distributing the software, include this License Header Notice in each
   19    * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
   20    * Sun designates this particular file as subject to the "Classpath" exception
   21    * as provided by Sun in the GPL Version 2 section of the License file that
   22    * accompanied this code.  If applicable, add the following below the License
   23    * Header, with the fields enclosed by brackets [] replaced by your own
   24    * identifying information: "Portions Copyrighted [year]
   25    * [name of copyright owner]"
   26    * 
   27    * Contributor(s):
   28    * 
   29    * If you wish your version of this file to be governed by only the CDDL or
   30    * only the GPL Version 2, indicate your decision by adding "[Contributor]
   31    * elects to include this software in this distribution under the [CDDL or GPL
   32    * Version 2] license."  If you don't indicate a single choice of license, a
   33    * recipient has the option to distribute your version of this file under
   34    * either the CDDL, the GPL Version 2 or to extend the choice of license to
   35    * its licensees as provided above.  However, if you add GPL Version 2 code
   36    * and therefore, elected the GPL Version 2 license, then the option applies
   37    * only if the new code is made subject to such option by the copyright
   38    * holder.
   39    */
   40   
   41   package javax.faces.component;
   42   
   43   import java.util.Iterator;
   44   import java.util.NoSuchElementException;
   45   import java.util.Map;
   46   import java.util.ListIterator;
   47   import java.io.ObjectOutputStream;
   48   import java.io.IOException;
   49   import java.io.NotSerializableException;
   50   import java.io.ObjectInputStream;
   51   import java.lang.reflect.Array;
   52   
   53   import javax.faces.model.SelectItem;
   54   import javax.faces.context.FacesContext;
   55   import javax.el.ValueExpression;
   56   
   57   
   58   /**
   59    * <p>Package private class for iterating over the set of {@link SelectItem}s
   60    * for a parent {@link UISelectMany} or {@link UISelectOne}.</p>
   61    *
   62    * // RELEASE_PENDING (rlubke,driscoll) performanc review
   63    */
   64   final class SelectItemsIterator implements Iterator<SelectItem> {
   65   
   66   
   67       // ------------------------------------------------------------ Constructors
   68   
   69   
   70       /**
   71        * <p>Construct an iterator instance for the specified parent component.</p>
   72        *
   73        * @param ctx the {@link FacesContext} for the current request
   74        * @param parent The parent {@link UIComponent} whose children will be
   75        *  processed
   76        */
   77       public SelectItemsIterator(FacesContext ctx, UIComponent parent) {
   78   
   79           kids = parent.getChildren().listIterator();
   80           this.ctx = ctx;
   81   
   82       }
   83   
   84   
   85       // ------------------------------------------------------ Instance Variables
   86   
   87   
   88       /**
   89        * <p>Iterator over the SelectItem elements pointed at by a
   90        * <code>UISelectItems</code> component, or <code>null</code>.</p>
   91        */
   92       private Iterator<SelectItem> items;
   93   
   94   
   95       /**
   96        * <p>Iterator over the children of the parent component.</p>
   97        */
   98       private ListIterator<UIComponent> kids;
   99   
  100   
  101       /**
  102        * Expose single SelectItems via an Iterator.  This iterator will be
  103        * reset/reused for each individual SelectItem instance encountered.
  104        */
  105       private SingleElementIterator singleItemIterator;
  106   
  107   
  108       /**
  109        * The {@link FacesContext} for the current request.
  110        */
  111       private FacesContext ctx;
  112   
  113   
  114       // -------------------------------------------------------- Iterator Methods
  115   
  116   
  117       /**
  118        * <p>Return <code>true</code> if the iteration has more elements.</p>
  119        */
  120       public boolean hasNext() {
  121   
  122           if (items != null) {
  123               if (items.hasNext()) {
  124                   return (true);
  125               } else {
  126                   items = null;
  127               }
  128           }
  129           Object next = findNextValidChild();
  130           while (next != null) {
  131               initializeItems(next);
  132               if (items != null) {
  133                   return true;
  134               } else {
  135                   next = findNextValidChild();
  136               }
  137           }
  138           return false;
  139   
  140       }
  141   
  142   
  143       /**
  144        * <p>Return the next element in the iteration.</p>
  145        *
  146        * @throws NoSuchElementException if there are no more elements
  147        */
  148       @SuppressWarnings({"unchecked"})
  149       public SelectItem next() {
  150   
  151           if (!hasNext()) {
  152               throw new NoSuchElementException();
  153           }
  154           if (items != null) {
  155               return (items.next());
  156           }
  157           return next();
  158   
  159       }
  160   
  161   
  162       /**
  163        * <p>Throw UnsupportedOperationException.</p>
  164        */
  165       public void remove() {
  166   
  167           throw new UnsupportedOperationException();
  168   
  169       }
  170   
  171   
  172       // --------------------------------------------------------- Private Methods
  173   
  174   
  175       /**
  176        * <p>
  177        * Initializes the <code>items</code> instance variable with an
  178        * <code>Iterator</code> appropriate to the UISelectItem(s) value.
  179        * </p>
  180        */
  181       private void initializeItems(Object kid) {
  182   
  183           if (kid instanceof UISelectItem) {
  184               UISelectItem ui = (UISelectItem) kid;
  185               SelectItem item = (SelectItem) ui.getValue();
  186               if (item == null) {
  187                   item = new SelectItem(ui.getItemValue(),
  188                                         ui.getItemLabel(),
  189                                         ui.getItemDescription(),
  190                                         ui.isItemDisabled(),
  191                                         ui.isItemEscaped(),
  192                                         ui.isNoSelectionOption());
  193               }
  194               updateSingeItemIterator(item);
  195               items = singleItemIterator;
  196           } else if (kid instanceof UISelectItems) {
  197               UISelectItems ui = (UISelectItems) kid;
  198               Object value = ui.getValue();
  199               if (value != null) {
  200                   if (value instanceof SelectItem) {
  201                       updateSingeItemIterator((SelectItem) value);
  202                       items = singleItemIterator;
  203                   } else if (value.getClass().isArray()) {
  204                       items = new ArrayIterator(ctx, (UISelectItems) kid, value);
  205                   } else if (value instanceof Iterable) {
  206                       items = new IterableItemIterator(ctx,
  207                                                        (UISelectItems) kid,
  208                                                        (Iterable<?>) value);
  209                   } else if (value instanceof Map) {
  210                       items = new MapIterator((Map) value);
  211                   } else {
  212                       throw new IllegalArgumentException();
  213                   }
  214               }
  215               if (items != null && !items.hasNext()) {
  216                   items = null;
  217               }
  218           } 
  219   
  220       }
  221   
  222   
  223       /**
  224        * @return the next valid child for processing
  225        */
  226       private Object findNextValidChild() {
  227   
  228           if (kids.hasNext()) {
  229               Object next = kids.next();
  230               while (kids.hasNext() && !(next instanceof UISelectItem || next instanceof UISelectItems)) {
  231                   next = kids.next();
  232               }
  233               if (next instanceof UISelectItem || next instanceof UISelectItems) {
  234                   return next;
  235               }
  236           }
  237           return null;
  238   
  239       }
  240   
  241   
  242       /**
  243        * Update the <code>singleItemIterator</code> with the provided
  244        * <code>item</code>
  245        * @param item the {@link SelectItem} to expose as an Iterator
  246        */
  247       private void updateSingeItemIterator(SelectItem item) {
  248   
  249           if (singleItemIterator == null) {
  250               singleItemIterator = new SingleElementIterator();
  251           }
  252           singleItemIterator.updateItem(item);
  253   
  254       }
  255   
  256   
  257       // ---------------------------------------------------------- Nested Classes
  258   
  259   
  260       /**
  261        * Exposes single {@link SelectItem} instances as an Iterator.
  262        */
  263       private static final class SingleElementIterator implements Iterator<SelectItem> {
  264   
  265           private SelectItem item;
  266           private boolean nextCalled;
  267   
  268   
  269           // ----------------------------------------------- Methods from Iterator
  270   
  271   
  272           public boolean hasNext() {
  273   
  274               return !nextCalled;
  275   
  276           }
  277   
  278   
  279           public SelectItem next() {
  280   
  281               if (nextCalled) {
  282                   throw new NoSuchElementException();
  283               }
  284               nextCalled = true;
  285               return item;
  286   
  287           }
  288   
  289   
  290           public void remove() {
  291   
  292               throw new UnsupportedOperationException();
  293   
  294           }
  295   
  296   
  297           // ----------------------------------------------------- Private Methods
  298   
  299   
  300           private void updateItem(SelectItem item) {
  301   
  302               this.item = item;
  303               nextCalled = false;
  304   
  305           }
  306   
  307       } // END SingleElementIterator
  308   
  309   
  310       /**
  311        * Iterates over a <code>Map</code> of values exposing each entry as a SelectItem.
  312        * Note that this will do so re-using the same SelectItem but changing
  313        * the value and label as appropriate.
  314        */
  315       private static final class MapIterator implements Iterator<SelectItem> {
  316   
  317           private SelectItem item = new SelectItem();
  318           private Iterator iterator;
  319   
  320   
  321           // -------------------------------------------------------- Constructors
  322   
  323   
  324           private MapIterator(Map map) {
  325   
  326               this.iterator = map.entrySet().iterator();
  327   
  328           }
  329   
  330   
  331           // ----------------------------------------------- Methods from Iterator
  332   
  333   
  334           public boolean hasNext() {
  335   
  336               return iterator.hasNext();
  337   
  338           }
  339   
  340   
  341           public SelectItem next() {
  342   
  343               Map.Entry entry = (Map.Entry) iterator.next();
  344               Object key = entry.getKey();
  345               Object value = entry.getValue();
  346               item.setLabel(((key != null) ? key.toString() : value.toString()));
  347               item.setValue(((value != null) ? value : ""));
  348               return item;
  349               
  350           }
  351   
  352   
  353           public void remove() {
  354   
  355               throw new UnsupportedOperationException();
  356   
  357           }
  358   
  359       } // END MapIterator
  360   
  361   
  362       /**
  363        * <p>
  364        * Base class to support iterating over Collections or Arrays that may
  365        * or may not contain <code>SelectItem</code> instances.
  366        * </p>
  367        */
  368       private static abstract class GenericObjectSelectItemIterator implements Iterator<SelectItem> {
  369   
  370           /**
  371            * SelectItem that is updated based on the current Object being
  372            * iterated over.
  373            */
  374           private GenericObjectSelectItem genericObjectSI;
  375   
  376           /**
  377            * The source <code>UISelectItems</code>.
  378            */
  379           protected UISelectItems sourceComponent;
  380   
  381   
  382           // -------------------------------------------------------- Constructors
  383   
  384   
  385           protected GenericObjectSelectItemIterator(UISelectItems sourceComponent) {
  386   
  387               this.sourceComponent = sourceComponent;
  388   
  389           }
  390   
  391   
  392           // --------------------------------------------------- Protected Methods
  393   
  394   
  395           protected SelectItem getSelectItemFor(FacesContext ctx, Object value) {
  396   
  397               if (genericObjectSI == null) {
  398                   genericObjectSI = new GenericObjectSelectItem(sourceComponent);
  399               }
  400   
  401               genericObjectSI.updateItem(ctx, value);
  402               return genericObjectSI;
  403               
  404           }
  405   
  406   
  407           // ------------------------------------------------------ Nested Classes
  408   
  409   
  410           /**
  411            * A <code>SelectItem</code> implementation to support generating
  412            * unique <code>SelectItem</code> values based on <code>ValueExpressions</code>
  413            * from the owning {@link UISelectItems} instance.
  414            */
  415           @SuppressWarnings({"serial"})
  416           private static final class GenericObjectSelectItem extends SelectItem {
  417   
  418   
  419               private static final String VAR = "var";
  420               private static final String ITEM_VALUE = "itemValue";
  421               private static final String ITEM_LABEL = "itemLabel";
  422               private static final String ITEM_DESCRIPTION = "itemDescription";
  423               private static final String ITEM_ESCAPED = "itemLabelEscaped";
  424               private static final String ITEM_DISABLED = "itemDisabled";
  425               private static final String NO_SELECTION_OPTION = "noSelectionOption";
  426   
  427               /**
  428                * Resolves to the value of the <code>SelectItem</code>.
  429                */
  430               private ValueExpression itemValue;
  431   
  432               /**
  433                * Resolves to the label of the <code>SelectItem</code>.
  434                */
  435               private ValueExpression itemLabel;
  436   
  437               /**
  438                * Resolves to the description of the <code>SelectItem</code>.
  439                */
  440               private ValueExpression itemDescription;
  441   
  442               /**
  443                * Determines the value for the escaped property of the <code>SelectItem</code>.
  444                */
  445               private ValueExpression itemEscaped;
  446   
  447               /**
  448                * Determines the value for the disabled property of the <code>SelectItem</code>/
  449                */
  450               private ValueExpression itemDisabled;
  451   
  452               /**
  453                * Determines the value for the noSelectionOption property of the <code>SelectItem</code>/
  454                */
  455               private ValueExpression noSelectionOption;
  456   
  457               /**
  458                * The request-scoped variable under which the current object
  459                * will be exposed.
  460                */
  461               private String var;
  462   
  463               private UISelectItems sourceComponent;
  464   
  465               // -------------------------------------------------------- Constructors
  466   
  467   
  468               private GenericObjectSelectItem(UISelectItems sourceComponent) {
  469   
  470                   var = (String) sourceComponent.getAttributes().get(VAR);
  471                   this.sourceComponent = sourceComponent;
  472                   //itemValue = sourceComponent.getValueExpression(ITEM_VALUE);
  473                   //itemLabel = sourceComponent.getValueExpression(ITEM_LABEL);
  474                   //itemDescription = sourceComponent.getValueExpression(ITEM_DESCRIPTION);
  475                   //itemEscaped = sourceComponent.getValueExpression(ITEM_ESCAPED);
  476                   //itemDisabled = sourceComponent.getValueExpression(ITEM_DISABLED);
  477                   //noSelectionOption = sourceComponent.getValueExpression(NO_SELECTION_OPTION);
  478   
  479               }
  480   
  481               // ----------------------------------------------------- Private Methods
  482   
  483   
  484               /**
  485                * Updates the <code>SelectItem</code> properties based on the
  486                * current value.
  487                *
  488                * @param ctx the {@link FacesContext} for the current request
  489                * @param value the value to build the updated values from
  490                */
  491               private void updateItem(FacesContext ctx, Object value) {
  492   
  493                   Map<String, Object> reqMap =
  494                         ctx.getExternalContext().getRequestMap();
  495                   Object oldVarValue = null;
  496                   if (var != null) {
  497                       oldVarValue = reqMap.put(var, value);
  498                   }
  499                   try {
  500                       Map<String,Object> attrs = sourceComponent.getAttributes();
  501                       Object itemValueResult = attrs.get(ITEM_VALUE);
  502                       Object itemLabelResult = attrs.get(ITEM_LABEL);
  503                       Object itemDescriptionResult = attrs.get(ITEM_DESCRIPTION);
  504                       Object itemEscapedResult = attrs.get(ITEM_ESCAPED);
  505                       Object itemDisabledResult = attrs.get(ITEM_DISABLED);
  506                       Object noSelectionOptionResult = attrs.get(NO_SELECTION_OPTION);
  507                       setValue(((itemValueResult != null) ? itemValueResult : value));
  508                       setLabel(((itemLabelResult != null)
  509                                     ? itemLabelResult.toString()
  510                                     : value.toString()));
  511                       setDescription(((itemDescriptionResult != null)
  512                                           ? itemDescriptionResult.toString()
  513                                           : null));
  514                       setEscape(((itemEscapedResult != null)
  515                                      ? Boolean.valueOf(itemEscapedResult.toString())
  516                                      : false));
  517                       setDisabled(((itemDisabledResult != null)
  518                                        ? Boolean.valueOf(itemDisabledResult.toString())
  519                                        : false));
  520                       setNoSelectionOption(((noSelectionOptionResult != null)
  521                                        ? Boolean.valueOf(noSelectionOptionResult.toString())
  522                                       : false));
  523                   } finally {
  524                       if (var != null) {
  525                           if (oldVarValue != null) {
  526                               reqMap.put(var, oldVarValue);
  527                           } else {
  528                               reqMap.remove(var);
  529                           }
  530                       }
  531                   }
  532   
  533               }
  534   
  535   
  536               // --------------------------------------- Methods from Serializable
  537   
  538   
  539               private void writeObject(ObjectOutputStream out) throws IOException {
  540   
  541                   throw new NotSerializableException();
  542   
  543               }
  544   
  545   
  546               private void readObject(ObjectInputStream in) throws IOException {
  547   
  548                   throw new NotSerializableException();
  549   
  550               }
  551   
  552           } // END GenericObjectSelectItem
  553   
  554       } // END GenericObjectSelectItemIterator
  555   
  556   
  557       /**
  558        * Handles arrays of <code>SelectItem</code>s, generic Objects,
  559        * or combintations of both.
  560        *
  561        * A single <code>GenericObjectSelectItem</code> will be leverage for any
  562        * non-<code>SelectItem</code> objects encountered.
  563        */
  564       private static final class ArrayIterator extends GenericObjectSelectItemIterator {
  565   
  566   
  567           private FacesContext ctx;
  568           private Object array;
  569           private int count;
  570           private int index;
  571   
  572   
  573           // -------------------------------------------------------- Constructors
  574   
  575   
  576           private ArrayIterator(FacesContext ctx,
  577                                 UISelectItems sourceComponent,
  578                                 Object array) {
  579   
  580               super(sourceComponent);
  581               this.ctx = ctx;
  582               this.array = array;
  583               count = Array.getLength(array);
  584   
  585           }
  586   
  587   
  588           // ----------------------------------------------- Methods from Iterator
  589   
  590   
  591           public boolean hasNext() {
  592   
  593               return (index < count);
  594   
  595           }
  596   
  597           public SelectItem next() {
  598   
  599               if (index >= count) {
  600                   throw new NoSuchElementException();
  601               }
  602   
  603               Object item = Array.get(array, index++);
  604               if (item instanceof SelectItem) {
  605                   return (SelectItem) item;
  606               } else {
  607                   return getSelectItemFor(ctx, item);
  608               }
  609   
  610           }
  611   
  612           public void remove() {
  613               throw new UnsupportedOperationException();
  614           }
  615   
  616   
  617       } // END ArrayIterator
  618   
  619   
  620       /**
  621        * Handles Collections of <code>SelectItem</code>s, generic Objects,
  622        * or combintations of both.
  623        *
  624        * A single <code>GenericObjectSelectItem</code> will be leverage for any
  625        * non-<code>SelectItem</code> objects encountered.
  626        */
  627       private static final class IterableItemIterator extends GenericObjectSelectItemIterator {
  628   
  629   
  630           private FacesContext ctx;
  631           private Iterator<?> iterator;
  632   
  633   
  634           // -------------------------------------------------------- Constructors
  635   
  636   
  637           private IterableItemIterator(FacesContext ctx,
  638                                        UISelectItems sourceComponent,
  639                                        Iterable<?> iterable) {
  640   
  641               super(sourceComponent);
  642               this.ctx = ctx;
  643               this.iterator = iterable.iterator();
  644   
  645           }
  646   
  647   
  648           // ----------------------------------------------- Methods from Iterator
  649   
  650   
  651           public boolean hasNext() {
  652   
  653               return iterator.hasNext();
  654   
  655           }
  656   
  657   
  658           public SelectItem next() {
  659   
  660               Object item = iterator.next();
  661               if (item instanceof SelectItem) {
  662                   return (SelectItem) item;
  663               } else {
  664                   return getSelectItemFor(ctx, item);
  665               }
  666   
  667           }
  668   
  669   
  670           public void remove() {
  671   
  672               throw new UnsupportedOperationException();
  673               
  674           }
  675   
  676       } // END CollectionItemIterator
  677   
  678   
  679   }

Home » Mojarra-2.0.1 » javax » faces » component » [javadoc | source]