Package org.richfaces.taglib

Source Code of org.richfaces.taglib.ColumnsHandler$IterationContext

/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
*/

/*
* ColumnsHandler.java    Date created: 07.12.2007
* Last modified by: $Author$
* $Revision$  $Date$
*/

package org.richfaces.taglib;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.el.ELException;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.servlet.jsp.JspTagException;

import org.richfaces.component.UIColumn;
import org.richfaces.el.ELBuilder;
import org.richfaces.iterator.ForEachIterator;
import org.richfaces.iterator.SimpleForEachIterator;

import com.sun.facelets.FaceletContext;
import com.sun.facelets.tag.MetaRule;
import com.sun.facelets.tag.MetaRuleset;
import com.sun.facelets.tag.MetaTagHandler;
import com.sun.facelets.tag.Metadata;
import com.sun.facelets.tag.MetadataTarget;
import com.sun.facelets.tag.TagAttribute;
import com.sun.facelets.tag.jsf.ComponentConfig;



/**
* TODO Class description goes here.
*
* @author "Andrey Markavtsov"
*
*/
public class ColumnsHandler extends MetaTagHandler {
   
    com.sun.facelets.tag.jsf.ComponentHandler handler;
   
    static final String DYNAMIC_COLUMN_MARKER = "_richfaces_columns";
  
    /** value attribute */
    private TagAttribute value;

    /** end attribute */
    private TagAttribute columns;

    /** begin attribute */
    private TagAttribute begin;

    /** var attribute */
    private TagAttribute var;

    /** index attribute */
    private TagAttribute index;

    /** end attribute */
    private TagAttribute end;
   
    /** rendered attribute */
    private boolean rendered = true;

    class IterationContext {
   
      /** Iterator for columns's tag value attribute */
      public ForEachIterator items; // our 'digested' items
 
      /** Value attribute value */
      public Object rawItems; // our 'raw' items
 
      /** Var attr - defines page variable for current item */
      public String _indexId;
 
      /** Integer value begin attr */
      public Integer _begin;
 
      /** Integer value end attr */
      public Integer _end;
 
      /** Integer value of end attr. */
      public Integer _columns;
 
      /** String value of var attr */
      public String _itemId = null;
 
      /** Current column counter */
      public Integer _index = 0;
 
      /** Expression for var item */
      public IteratedExpression iteratedExpression;
     
      public String valueExpr;
     
      public String getVarReplacement() {
        if (valueExpr == null) {
          return String.valueOf(index);
        }else if (items.getVarReplacement() != null) {
          return items.getVarReplacement();
        }
        return valueExpr + "[" + _index + "]";
      }
     
      public String getIndexReplacement() {
        return String.valueOf(_index);
      }
    };
   
    ThreadLocal<IterationContext> iterationContextLocal = new ThreadLocal<IterationContext>();
   
    public IterationContext getIterationContext() {
      return iterationContextLocal.get();
    }

    /**
     * TODO Description goes here.
     *
     * @param config
     */
    public ColumnsHandler(ComponentConfig config) {
  super(config);
  handler = new ColumnTagHandler(config) {
      @Override
      protected MetaRuleset createMetaRuleset(Class type) {
        MetaRuleset ruleset = super.createMetaRuleset(type);
        ruleset.addRule(new MetaRule() {

          @Override
          public Metadata applyRule(final String name,
              final TagAttribute attribute, MetadataTarget meta) {
            if (ColumnsAttributes.FILTER_ATTRIBUTES.indexOf(name) != -1) {
              return new Metadata() {

                @Override
                public void applyMetadata(FaceletContext ctx,
                    Object instance) {
                  if (!attribute.isLiteral()) {
                    String expr = attribute.getValue();
                    IterationContext itContext = iterationContextLocal.get();

                    ValueExpression ve = ELBuilder.createValueExpression(expr, Object.class, ctx.getExpressionFactory(), ctx.getFacesContext().getELContext(),
                      itContext._itemId, itContext._indexId,
                        itContext.getVarReplacement(), itContext.getIndexReplacement());
                    ((UIComponent)instance).setValueExpression(name, ve);
                  }else {
                    ((UIComponent)instance).getAttributes().put(name, attribute.getValue());
                  }
                }

              };
            }
            return null;
          }

        });
        return ruleset;
      }
     
      @Override
      protected void applyNextHandler(FaceletContext ctx, UIComponent c)
          throws IOException, FacesException, ELException {
        c.getAttributes().put(DYNAMIC_COLUMN_MARKER, Boolean.TRUE);
        super.applyNextHandler(ctx, c);
      }
    };
    }
 
 
    /**
     * Extracts tags attributes values
     */
    private void initVariables(FaceletContext ctx) {
  initColumnsCount(ctx);
  initIndex(ctx);
  initVar(ctx);
  initBegin(ctx);
  initEnd(ctx);
    }

    /**
     * Method prepares all we need for starting of tag rendering
     *
     * @throws JspTagException
     */
    private void prepare(FaceletContext ctx) {

  initVariables(ctx);
 
  IterationContext itContext = getIterationContext();

  try {

      this.value = getAttribute("value");
      itContext.valueExpr = ELBuilder.getVarReplacement(this.value.getValue());

      // produce the right sort of ForEachIterator
      if (value != null) {
    // If this is a deferred expression, make a note and get
    // the 'items' instance.

      itContext.rawItems = value.getObject(ctx);

    // extract an iterator over the 'items' we've got
      itContext.items = SimpleForEachIterator
      .supportedTypeForEachIterator(itContext.rawItems);
      } else {
    // no 'items', so use 'begin' and 'end'
        itContext.items = SimpleForEachIterator
      .beginEndForEachIterator(itContext._columns - 1);
      }
  } catch (Exception e) {
      // TODO: handle exception
  }

  correctFirst(ctx);
    }

    /**
     * Inits first iteration item
     */
    private void correctFirst(FaceletContext ctx) {
    IterationContext itContext = getIterationContext();
  if (itContext.items != null) {
      if (itContext._begin > 0 && (itContext._index < itContext._begin)) {
    while ((itContext._index < itContext._begin && hasNext())) {
        next(ctx);
    }
    if (!hasNext()) {
      itContext._index = 0;
    }
      }
  }
    }

    /**
     * Return true if we didn't complete column's count
     *
     * @return
     * @throws JspTagException
     */
    private boolean hasNext() {
    IterationContext itContext = getIterationContext();
  try {
      if (itContext._end != 0) {
    return (itContext._index < itContext._end) ? itContext.items.hasNext() : false;
      } else {
    return itContext.items.hasNext();
      }
  } catch (Exception e) {
      return false;
  }

    }

    /**
     * Iterate to next column
     *
     * @return
     * @throws JspTagException
     */
    private Object next(FaceletContext ctx) {
      IterationContext itContext = getIterationContext();
  try {
      Object o = itContext.items.next();
      itContext._index++;
      return o;
  } catch (Exception e) {
      return null;
  }
    }

    /**
     * Extracts integer value from end attr
     */
    private void initColumnsCount(FaceletContext ctx) {
    IterationContext itContext = getIterationContext();
  this.columns = getAttribute("columns");
  if (columns != null) {
      try {
        itContext._columns = Integer.parseInt((String) columns.getObject(ctx));
    if (itContext._columns < 0) {
      itContext._columns = 0; // If end is negative set up zero
    }
      } catch (Exception e) {
        itContext._columns = 0;
      }
  } else {
    itContext._columns = 0;
  }
    }

    /**
     * Extracts integer value from begin attr
     */
    private void initBegin(FaceletContext ctx) {
      IterationContext itContext = getIterationContext();
  this.begin = getAttribute("begin");
  if (begin != null) {
      try {
        Object o = begin.getObject(ctx);
        if (o instanceof Number) {
          itContext._begin = ((Number)o).intValue();
        }else if (o instanceof String) {
          itContext._begin = Integer.parseInt((String) o);
        }
        itContext._begin--;
    if (itContext._begin < 0) {
      itContext._begin = 0; // If end is negative set up zero
    }
      } catch (Exception e) {
        itContext._begin = 0;
      }
  } else {
    itContext._begin = 0;
  }
    }

    /**
     * Extracts integer value from end attr
     */
    private void initEnd(FaceletContext ctx) {
      IterationContext itContext = getIterationContext();
  this.end = getAttribute("end");
  if (end != null) {
      try {
        Object o = end.getObject(ctx);
        if (o instanceof Number) {
          itContext._end = ((Number)o).intValue();
        }else if ( o instanceof String) {
          itContext._end = Integer.parseInt((String) o);
        }
    if (itContext._end < 0) {
      itContext._end = 0; // If end is negative set up zero
    }
      } catch (Exception e) {
        itContext._end = 0;
      }
  } else {
    itContext._end = 0;
  }
    }

    /**
     * Extracts string value from var attr
     */
    private void initVar(FaceletContext ctx) {
      IterationContext itContext = getIterationContext();
  this.var = getAttribute("var");
  if (var != null) {
      try {
        itContext._itemId = (String) var.getObject(ctx);
      } catch (ClassCastException e) {
        itContext._itemId = null;
      }

  }
    }

    /**
     * Extracts string value from index attr
     */
    private void initIndex(FaceletContext ctx) {
      IterationContext itContext = getIterationContext();
  this.index = getAttribute("index");
  if (index != null) {
      try {
        itContext._indexId = (String) index.getObject(ctx);
      } catch (ClassCastException e) {
        itContext._indexId = null;
      }

  }
    }
   
    private void initRendered(FaceletContext ctx) {
    TagAttribute renderedAttribute = getAttribute("rendered");
    if (renderedAttribute != null) {
      try {
        this.rendered = (Boolean) renderedAttribute.getObject(ctx);
      } catch (ClassCastException e) {
        this.rendered = true;
      }
    }
  }
   
    /*
   * (non-Javadoc)
   *
   * @see org.richfaces.taglib.ComponentHandler#apply(com.sun.facelets.FaceletContext,
   *      javax.faces.component.UIComponent)
   */
    //@Override
    public void apply(FaceletContext ctx, UIComponent parent)
      throws IOException, FacesException, ELException {
   
    initRendered(ctx);
    if(!rendered){
      return;
    }
   
    IterationContext iterationContext = new IterationContext();
    iterationContextLocal.set(iterationContext);
     
    clearOldColumns(parent);
  prepare(ctx)// prepare data
   
  try {
      while (hasNext()) {  // for each
    exposeVariables(ctx);
    handler.apply(ctx, parent);
    next(ctx);
      }
  } catch (Exception e) {
      // TODO: handle exception
  } finally {
      release();
      unExposeVariables(ctx);
  }
 
    }

  
    private void clearOldColumns (UIComponent parent) {
      if (parent.getChildren() != null) {
        Iterator<UIComponent> childrenIt = parent.getChildren().iterator();
        List<UIComponent> forDelete = new ArrayList<UIComponent>();
          while (childrenIt.hasNext()) {
            UIComponent c = childrenIt.next();
            if (c instanceof UIColumn && c.getAttributes().get(DYNAMIC_COLUMN_MARKER) != null
                && (Boolean)c.getAttributes().get(DYNAMIC_COLUMN_MARKER)) {
              forDelete.add(c);
            }
          }
        if (forDelete.size() > 0) {
          Iterator<UIComponent> it = forDelete.iterator();
          while (it.hasNext()) {
            parent.getChildren().remove(it.next());
          }
        }
      }
  
    }
 
    /**
     * Sets page request variables
     *
     * @throws JspTagException
     */
    private void exposeVariables(FaceletContext ctx) {
    IterationContext itContext = getIterationContext();
  VariableMapper vm = ctx.getVariableMapper();
  int k = itContext._index;

  if (itContext._itemId != null) {
      if (vm != null) {
    if (value != null) {
        ValueExpression srcVE = value.getValueExpression(ctx,
          Object.class);
        ValueExpression ve = getVarExpression(ctx, srcVE);
        vm.setVariable(itContext._itemId, ve);
    }
      }

  }

  // Set up index variable

  if (itContext._indexId != null) {
      if (vm != null) {
    ValueExpression ve = new IteratedIndexExpression(k);
    vm.setVariable(itContext._indexId, ve);
      }

  }

    }

    /**
     * Removes page attributes that we have exposed and, if applicable, restores
     * them to their prior values (and scopes).
     */
    private void unExposeVariables(FaceletContext ctx) {
      IterationContext itContext = getIterationContext();
  VariableMapper vm = ctx.getVariableMapper();
  // "nested" variables are now simply removed
  if (itContext._itemId != null) {
      if (vm != null)
    vm.setVariable(itContext._itemId, null);
  }
  if (itContext._indexId != null) {
      if (vm != null)
    vm.setVariable(itContext._indexId, null);
  }
    }

    /**
     * Return expression for page variables
     *
     * @param expr
     * @return
     */
    private ValueExpression getVarExpression(FaceletContext ctx,
      ValueExpression expr/*, IterationContext itContext*/) {
      IterationContext itContext = getIterationContext();
  Object o = expr.getValue(ctx.getFacesContext().getELContext());
  int k = itContext._index;
  if (o.getClass().isArray() || o instanceof List) {
      return new IndexedValueExpression(expr, k);
  }

  if (o instanceof Collection || o instanceof Iterator
    || o instanceof Enumeration || o instanceof Map
    || o instanceof String) {

      if (itContext.iteratedExpression == null) {
        itContext.iteratedExpression = new IteratedExpression(expr, ",");
      }
      return new IteratedValueExpression(itContext.iteratedExpression, k);
  }

  throw new ELException("FOREACH_BAD_ITEMS");
    }

    /**
     * Release iteration variables
     */
    private void release() {
      IterationContext itContext = getIterationContext();
      itContext.items = null;
      itContext._index = 0;
    }
   
}
TOP

Related Classes of org.richfaces.taglib.ColumnsHandler$IterationContext

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.