Package org.richfaces.component

Source Code of org.richfaces.component.SelectItemsIterator$GenericObjectSelectItemIterator$GenericObjectSelectItem

package org.richfaces.component;

import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;

import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UISelectItem;
import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

/**
* <p>Package private class for iterating over the set of {@link javax.faces.model.SelectItem}s
* for a parent {@link javax.faces.component.UISelectMany} or {@link javax.faces.component.UISelectOne}.</p>
* <p/>
*/
final class SelectItemsIterator implements Iterator<SelectItem> {
// ------------------------------ FIELDS ------------------------------

    /**
     * The {@link FacesContext} for the current request.
     */
    private FacesContext ctx;


    // ------------------------------------------------------ Instance Variables

    /**
     * <p>Iterator over the SelectItem elements pointed at by a
     * <code>UISelectItems</code> component, or <code>null</code>.</p>
     */
    private Iterator<SelectItem> items;

    /**
     * <p>Iterator over the children of the parent component.</p>
     */
    private ListIterator<UIComponent> kids;

    /**
     * Expose single SelectItems via an Iterator.  This iterator will be
     * reset/reused for each individual SelectItem instance encountered.
     */
    private SingleElementIterator singleItemIterator;

// --------------------------- CONSTRUCTORS ---------------------------


    // ------------------------------------------------------------ Constructors

    /**
     * <p>Construct an iterator instance for the specified parent component.</p>
     *
     * @param ctx    the {@link javax.faces.context.FacesContext} for the current request
     * @param parent The parent {@link javax.faces.component.UIComponent} whose children will be
     *               processed
     */
    public SelectItemsIterator(FacesContext ctx, UIComponent parent) {
        kids = parent.getChildren().listIterator();
        this.ctx = ctx;
    }

// ------------------------ INTERFACE METHODS ------------------------


// --------------------- Interface Iterator ---------------------


    // -------------------------------------------------------- Iterator Methods

    /**
     * <p>Return <code>true</code> if the iteration has more elements.</p>
     */
    public boolean hasNext() {
        if (items != null) {
            if (items.hasNext()) {
                return (true);
            } else {
                items = null;
            }
        }
        Object next = findNextValidChild();
        while (next != null) {
            initializeItems(next);
            if (items != null) {
                return true;
            } else {
                next = findNextValidChild();
            }
        }
        return false;
    }

    /**
     * <p>Return the next element in the iteration.</p>
     *
     * @throws java.util.NoSuchElementException
     *          if there are no more elements
     */
    @SuppressWarnings({"unchecked"})
    public SelectItem next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        if (items != null) {
            return (items.next());
        }
        return next();
    }

    /**
     * <p>Throw UnsupportedOperationException.</p>
     */
    public void remove() {
        throw new UnsupportedOperationException();
    }

    /**
     * @return the next valid child for processing
     */
    private Object findNextValidChild() {
        if (kids.hasNext()) {
            Object next = kids.next();
            while (kids.hasNext() && !(next instanceof UISelectItem || next instanceof UISelectItems)) {
                next = kids.next();
            }
            if (next instanceof UISelectItem || next instanceof UISelectItems) {
                return next;
            }
        }
        return null;
    }

    // --------------------------------------------------------- Private Methods

    /**
     * <p>
     * Initializes the <code>items</code> instance variable with an
     * <code>Iterator</code> appropriate to the UISelectItem(s) value.
     * </p>
     */
    private void initializeItems(Object kid) {
        if (kid instanceof UISelectItem) {
            UISelectItem ui = (UISelectItem) kid;
            SelectItem item = (SelectItem) ui.getValue();
            if (item == null) {
                item = new SelectItem(ui.getItemValue(), ui.getItemLabel(), ui.getItemDescription(), ui.isItemDisabled(), ui.isItemEscaped(),
                        ui.isNoSelectionOption());
            }
            updateSingeItemIterator(item);
            items = singleItemIterator;
        } else if (kid instanceof UISelectItems) {
            UISelectItems ui = (UISelectItems) kid;
            Object value = ui.getValue();
            if (value != null) {
                if (value instanceof SelectItem) {
                    updateSingeItemIterator((SelectItem) value);
                    items = singleItemIterator;
                } else if (value.getClass().isArray()) {
                    items = new ArrayIterator(ctx, (UISelectItems) kid, value);
                } else if (value instanceof Iterable) {
                    items = new IterableItemIterator(ctx, (UISelectItems) kid, (Iterable<?>) value);
                } else if (value instanceof Map) {
                    items = new MapIterator((Map) value);
                } else {
                    throw new IllegalArgumentException();
                }
            }
            if (items != null && !items.hasNext()) {
                items = null;
            }
        }
    }

    /**
     * Update the <code>singleItemIterator</code> with the provided
     * <code>item</code>
     *
     * @param item the {@link SelectItem} to expose as an Iterator
     */
    private void updateSingeItemIterator(SelectItem item) {
        if (singleItemIterator == null) {
            singleItemIterator = new SingleElementIterator();
        }
        singleItemIterator.updateItem(item);
    }

// -------------------------- INNER CLASSES --------------------------

    /**
     * Handles arrays of <code>SelectItem</code>s, generic Objects,
     * or combintations of both.
     * <p/>
     * A single <code>GenericObjectSelectItem</code> will be leverage for any
     * non-<code>SelectItem</code> objects encountered.
     */
    private static final class ArrayIterator extends GenericObjectSelectItemIterator {
// ------------------------------ FIELDS ------------------------------

        private Object array;

        private int count;

        private FacesContext ctx;

        private int index;

// --------------------------- CONSTRUCTORS ---------------------------

        // -------------------------------------------------------- Constructors
        private ArrayIterator(FacesContext ctx, UISelectItems sourceComponent, Object array) {
            super(sourceComponent);
            this.ctx = ctx;
            this.array = array;
            count = Array.getLength(array);
        }

// ------------------------ INTERFACE METHODS ------------------------


// --------------------- Interface Iterator ---------------------

        // ----------------------------------------------- Methods from Iterator
        public boolean hasNext() {
            return (index < count);
        }

        public SelectItem next() {
            if (index >= count) {
                throw new NoSuchElementException();
            }

            Object item = Array.get(array, index++);
            if (item instanceof SelectItem) {
                return (SelectItem) item;
            } else {
                return getSelectItemFor(ctx, item);
            }
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    } // END ArrayIterator

    /**
     * <p>
     * Base class to support iterating over Collections or Arrays that may
     * or may not contain <code>SelectItem</code> instances.
     * </p>
     */
    private static abstract class GenericObjectSelectItemIterator implements Iterator<SelectItem> {
// ------------------------------ FIELDS ------------------------------

        /**
         * The source <code>UISelectItems</code>.
         */
        protected UISelectItems sourceComponent;

        /**
         * SelectItem that is updated based on the current Object being
         * iterated over.
         */
        private GenericObjectSelectItem genericObjectSI;

// --------------------------- CONSTRUCTORS ---------------------------

        // -------------------------------------------------------- Constructors
        protected GenericObjectSelectItemIterator(UISelectItems sourceComponent) {
            this.sourceComponent = sourceComponent;
        }

        // --------------------------------------------------- Protected Methods

        protected SelectItem getSelectItemFor(FacesContext ctx, Object value) {
            if (genericObjectSI == null) {
                genericObjectSI = new GenericObjectSelectItem(sourceComponent);
            }

            genericObjectSI.updateItem(ctx, value);
            return genericObjectSI;
        }

// -------------------------- INNER CLASSES --------------------------


        // ------------------------------------------------------ Nested Classes

        /**
         * A <code>SelectItem</code> implementation to support generating
         * unique <code>SelectItem</code> values based on <code>ValueExpressions</code>
         * from the owning {@link UISelectItems} instance.
         */
        @SuppressWarnings({"serial"})
        private static final class GenericObjectSelectItem extends SelectItem {
// ------------------------------ FIELDS ------------------------------

            private static final String ITEM_DESCRIPTION = "itemDescription";

            private static final String ITEM_DISABLED = "itemDisabled";

            private static final String ITEM_ESCAPED = "itemLabelEscaped";

            private static final String ITEM_LABEL = "itemLabel";

            private static final String ITEM_VALUE = "itemValue";

            private static final String NO_SELECTION_OPTION = "noSelectionOption";

            private static final String VAR = "var";

            /**
             * Resolves to the description of the <code>SelectItem</code>.
             */
            private ValueExpression itemDescription;

            /**
             * Determines the value for the disabled property of the <code>SelectItem</code>/
             */
            private ValueExpression itemDisabled;

            /**
             * Determines the value for the escaped property of the <code>SelectItem</code>.
             */
            private ValueExpression itemEscaped;

            /**
             * Resolves to the label of the <code>SelectItem</code>.
             */
            private ValueExpression itemLabel;

            /**
             * Resolves to the value of the <code>SelectItem</code>.
             */
            private ValueExpression itemValue;

            /**
             * Determines the value for the noSelectionOption property of the <code>SelectItem</code>/
             */
            private ValueExpression noSelectionOption;

            private UISelectItems sourceComponent;

            /**
             * The request-scoped variable under which the current object
             * will be exposed.
             */
            private String var;

// --------------------------- CONSTRUCTORS ---------------------------

            // -------------------------------------------------------- Constructors
            private GenericObjectSelectItem(UISelectItems sourceComponent) {
                var = (String) sourceComponent.getAttributes().get(VAR);
                this.sourceComponent = sourceComponent;
                //itemValue = sourceComponent.getValueExpression(ITEM_VALUE);
                //itemLabel = sourceComponent.getValueExpression(ITEM_LABEL);
                //itemDescription = sourceComponent.getValueExpression(ITEM_DESCRIPTION);
                //itemEscaped = sourceComponent.getValueExpression(ITEM_ESCAPED);
                //itemDisabled = sourceComponent.getValueExpression(ITEM_DISABLED);
                //noSelectionOption = sourceComponent.getValueExpression(NO_SELECTION_OPTION);
            }

            private void readObject(ObjectInputStream in) throws IOException {
                throw new NotSerializableException();
            }

            // ----------------------------------------------------- Private Methods

            /**
             * Updates the <code>SelectItem</code> properties based on the
             * current value.
             *
             * @param ctx   the {@link FacesContext} for the current request
             * @param value the value to build the updated values from
             */
            private void updateItem(FacesContext ctx, Object value) {
                Map<String, Object> reqMap = ctx.getExternalContext().getRequestMap();
                Object oldVarValue = null;
                if (var != null) {
                    oldVarValue = reqMap.put(var, value);
                }
                try {
                    Map<String, Object> attrs = sourceComponent.getAttributes();
                    Object itemValueResult = attrs.get(ITEM_VALUE);
                    Object itemLabelResult = attrs.get(ITEM_LABEL);
                    Object itemDescriptionResult = attrs.get(ITEM_DESCRIPTION);
                    Object itemEscapedResult = attrs.get(ITEM_ESCAPED);
                    Object itemDisabledResult = attrs.get(ITEM_DISABLED);
                    Object noSelectionOptionResult = attrs.get(NO_SELECTION_OPTION);
                    setValue(((itemValueResult != null) ? itemValueResult : value));
                    setLabel(((itemLabelResult != null) ? itemLabelResult.toString() : value.toString()));
                    setDescription(((itemDescriptionResult != null) ? itemDescriptionResult.toString() : null));
                    setEscape(((itemEscapedResult != null) ? Boolean.valueOf(itemEscapedResult.toString()) : false));
                    setDisabled(((itemDisabledResult != null) ? Boolean.valueOf(itemDisabledResult.toString()) : false));
                    setNoSelectionOption(((noSelectionOptionResult != null) ? Boolean.valueOf(noSelectionOptionResult.toString()) : false));
                } finally {
                    if (var != null) {
                        if (oldVarValue != null) {
                            reqMap.put(var, oldVarValue);
                        } else {
                            reqMap.remove(var);
                        }
                    }
                }
            }

            // --------------------------------------- Methods from Serializable

            private void writeObject(ObjectOutputStream out) throws IOException {
                throw new NotSerializableException();
            }
        } // END GenericObjectSelectItem
    } // END GenericObjectSelectItemIterator

    /**
     * Handles Collections of <code>SelectItem</code>s, generic Objects,
     * or combintations of both.
     * <p/>
     * A single <code>GenericObjectSelectItem</code> will be leverage for any
     * non-<code>SelectItem</code> objects encountered.
     */
    private static final class IterableItemIterator extends GenericObjectSelectItemIterator {
// ------------------------------ FIELDS ------------------------------

        private FacesContext ctx;

        private Iterator<?> iterator;

// --------------------------- CONSTRUCTORS ---------------------------

        // -------------------------------------------------------- Constructors
        private IterableItemIterator(FacesContext ctx, UISelectItems sourceComponent, Iterable<?> iterable) {
            super(sourceComponent);
            this.ctx = ctx;
            this.iterator = iterable.iterator();
        }

// ------------------------ INTERFACE METHODS ------------------------


// --------------------- Interface Iterator ---------------------

        // ----------------------------------------------- Methods from Iterator
        public boolean hasNext() {
            return iterator.hasNext();
        }

        public SelectItem next() {
            Object item = iterator.next();
            if (item instanceof SelectItem) {
                return (SelectItem) item;
            } else {
                return getSelectItemFor(ctx, item);
            }
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    } // END CollectionItemIterator

    /**
     * Iterates over a <code>Map</code> of values exposing each entry as a SelectItem.
     * Note that this will do so re-using the same SelectItem but changing
     * the value and label as appropriate.
     */
    private static final class MapIterator implements Iterator<SelectItem> {
// ------------------------------ FIELDS ------------------------------

        private SelectItem item = new SelectItem();

        private Iterator iterator;

// --------------------------- CONSTRUCTORS ---------------------------

        // -------------------------------------------------------- Constructors
        private MapIterator(Map map) {
            this.iterator = map.entrySet().iterator();
        }

// ------------------------ INTERFACE METHODS ------------------------


// --------------------- Interface Iterator ---------------------

        // ----------------------------------------------- Methods from Iterator
        public boolean hasNext() {
            return iterator.hasNext();
        }

        public SelectItem next() {
            Map.Entry entry = (Map.Entry) iterator.next();
            Object key = entry.getKey();
            Object value = entry.getValue();
            item.setLabel(((key != null) ? key.toString() : value.toString()));
            item.setValue(((value != null) ? value : ""));
            return item;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    } // END MapIterator

    // ---------------------------------------------------------- Nested Classes

    /**
     * Exposes single {@link SelectItem} instances as an Iterator.
     */
    private static final class SingleElementIterator implements Iterator<SelectItem> {
// ------------------------------ FIELDS ------------------------------

        private SelectItem item;

        private boolean nextCalled;

// ------------------------ INTERFACE METHODS ------------------------


// --------------------- Interface Iterator ---------------------

        // ----------------------------------------------- Methods from Iterator
        public boolean hasNext() {
            return !nextCalled;
        }

        public SelectItem next() {
            if (nextCalled) {
                throw new NoSuchElementException();
            }
            nextCalled = true;
            return item;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }

        // ----------------------------------------------------- Private Methods

        private void updateItem(SelectItem item) {
            this.item = item;
            nextCalled = false;
        }
    } // END SingleElementIterator
}
TOP

Related Classes of org.richfaces.component.SelectItemsIterator$GenericObjectSelectItemIterator$GenericObjectSelectItem

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.