Package org.zkoss.selector

Source Code of org.zkoss.selector.ComponentIterator

/**
*
*/
package org.zkoss.selector;

import java.util.HashMap;
import java.util.Map;

import org.zkoss.selector.lang.Parser;
import org.zkoss.selector.lang.Tokenizer;
import org.zkoss.selector.model.Selector;
import org.zkoss.selector.model.Selector.Combinator;
import org.zkoss.selector.util.CachedIterator;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Page;

/**
*
* @author simonpai
*/
public class ComponentIterator extends CachedIterator<Component> {
 
  private Page _page;
  private Component _root;
  // TODO: support seeking on multiple selectors
  private Selector _selector;
  private Map<String, PseudoClassDef> _localDefs;
 
  private ComponentMatchCtx _currCtx;
  private int _index;
 
  /**
   * Create an iterator which selects from all the components in the page.
   * @param page
   * @param selector
   */
  public ComponentIterator(Page page, String selector){
    this(page, null, selector);
  }
 
  /**
   * Create an iterator which selects from all the descendants of a given
   * component, including itself.
   * @param root
   * @param selector
   */
  public ComponentIterator(Component root, String selector){
    this(root.getPage(), root, selector);
  }
 
  private ComponentIterator(Page page, Component root, String selector){
    if(page == null || selector == null || selector.isEmpty())
      throw new IllegalArgumentException();
   
    _localDefs = new HashMap<String, PseudoClassDef>();
    _selector =
      new Parser().parse(new Tokenizer().tokenize(selector), selector);
    _root = root;
    _page = page;
    _index = -1;
  }
 
  /**
   * Returns the index of next Component.
   */
  public int getIndex(){
    return _ready? _index : _index + 1;
  }
 
 
 
  // custom pseudo class definition //
  /**
   * Add or set pseudo class definition.
   * @param name
   * @param def
   */
  public void setPseudoClassDef(String name, PseudoClassDef def){
    _localDefs.put(name, def);
  }
 
  /**
   * Remove a pseudo class definition.
   * @param name
   * @return the original definition
   */
  public PseudoClassDef removePseudoClassDef(String name){
    return _localDefs.remove(name);
  }
 
  /**
   * Clear all custom pseudo class definitions.
   */
  public void clearPseudoClassDefs(){
    _localDefs.clear();
  }
 
 
 
  // cached iterator //
  @Override
  protected Component seekNext() {
    _currCtx = _index < 0 ? buildRootCtx() : buildNextCtx();
    while(_currCtx != null && !_currCtx.isTheOne()) _currCtx = buildNextCtx();
    if(_currCtx != null) {
      _index++;
      return _currCtx.getComponent();
    }
    return null;
  }
 
 
 
  // helper //
  private ComponentMatchCtx buildRootCtx(){
    Component rt = _root == null? _page.getFirstRoot(): _root;
    ComponentMatchCtx ctx = new ComponentMatchCtx(rt, _selector.size());
   
    matchLevel0(ctx);
    return ctx;
  }
 
  private ComponentMatchCtx buildNextCtx(){
   
    if(_currCtx.getComponent().getFirstChild() != null)
      return buildFirstChildCtx(_currCtx);
   
    while(_currCtx.getComponent().getNextSibling() == null) {
      _currCtx = _currCtx.getParent();
      if(_currCtx == null || _currCtx.getComponent() == _root)
        return null; // reached root
    }
   
    return buildNextSiblingCtx(_currCtx);
  }
 
  private ComponentMatchCtx buildFirstChildCtx(ComponentMatchCtx parent){
   
    ComponentMatchCtx ctx = new ComponentMatchCtx(
        parent.getComponent().getFirstChild(), parent);
   
    matchLevel0(ctx);
   
    for(int i=0; i<_selector.size()-1; i++){
      Combinator cb = _selector.getCombinator(i);
     
      if((parent.isQualified(i) && cb == Combinator.DESCENDANT) ||
          parent.isDescendantOf(i))
        ctx.setDescendant(i);
     
      if(((parent.isQualified(i) && cb == Combinator.CHILD) ||
          ctx.isDescendantOf(i)) && match(ctx, i+1))
        ctx.setQualified(i+1);
    }
    return ctx;
  }
 
  private ComponentMatchCtx buildNextSiblingCtx(ComponentMatchCtx ctx){
   
    ctx.moveToNextSibling();
   
    for(int i=0; i<_selector.size()-1; i++)
      if(ctx.isQualified(i) && _selector.getCombinator(i) ==
        Combinator.GENERAL_SIBLING)
          ctx.setYoungerBrother(i);
   
    for(int i = _selector.size() - 2; i > -1; i--){
      Combinator cb = _selector.getCombinator(i);
      ComponentMatchCtx parent = ctx.getParent();
      boolean relationMatched =
        ctx.isDescendantOf(i) || ctx.isYoungerBrotherOf(i) ||
        (parent != null && parent.isQualified(i) && cb == Combinator.CHILD) ||
        (ctx.isQualified(i) && cb == Combinator.ADJACENT_SIBLING);
      ctx.setQualified(i+1, relationMatched && match(ctx, i+1));
    }
   
    matchLevel0(ctx);
   
    return ctx;
  }
 
 
 
  private void matchLevel0(ComponentMatchCtx ctx){
    ctx.setQualified(0, match(ctx, 0));
  }
 
  private boolean match(ComponentMatchCtx ctx, int index){
    return ctx.match(_selector.get(index), _localDefs);
  }
 
  @Override
  public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append("ComponentIterator: \n* index: ").append(_index);
    for(ComponentMatchCtx c = _currCtx; c != null; c = c.getParent())
      sb.append("\n").append(c);
    return sb.append("\n\n").toString();
  }
 
}
TOP

Related Classes of org.zkoss.selector.ComponentIterator

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.