    1   /*
    2    * Copyright 1999-2004 The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.jxpath.ri.model.beans;
    17
    18  import java.util.ArrayList;
    19  import java.util.List;
    20
    21  import org.apache.commons.jxpath.JXPathException;
    22  import org.apache.commons.jxpath.ri.model.NodeIterator;
    23  import org.apache.commons.jxpath.ri.model.NodePointer;
    24
    25  /***
    26   * Combines node iterators of all elements of a collection into one
    27   * aggregate node iterator.
    28   *
    29   * @author Dmitri Plotnikov
    30   * @version $Revision: 1.3 $ $Date: 2004/02/29 14:17:41 $
    31   */
    32  public abstract class CollectionNodeIterator implements NodeIterator {
    33      private CollectionPointer pointer;
    34      private boolean reverse;
    35      private NodePointer startWith;
    36      private int position;
    37      private List collection;
    38
    39      protected CollectionNodeIterator(
    40          CollectionPointer pointer,
    41          boolean reverse,
    42          NodePointer startWith)
    43      {
    44          this.pointer = pointer;
    45          this.reverse = reverse;
    46          this.startWith = startWith;
    47      }
    48
    49      /***
    50       * Implemened by subclasses to produce child/attribute node iterators.
    51       */
    52      protected abstract NodeIterator
    53              getElementNodeIterator(NodePointer elementPointer);
    54
    55      public int getPosition() {
    56          return position;
    57      }
    58
    59      public boolean setPosition(int position) {
    60          if (collection == null) {
    61              prepare();
    62          }
    63
    64          if (position < 1 || position > collection.size()) {
    65              return false;
    66          }
    67          this.position = position;
    68          return true;
    69      }
    70
    71      public NodePointer getNodePointer() {
    72          if (position == 0) {
    73              return null;
    74          }
    75          return (NodePointer) collection.get(position - 1);
    76      }
    77
    78      private void prepare() {
    79          collection = new ArrayList();
    80          NodePointer ptr = (NodePointer) pointer.clone();
    81          int length = ptr.getLength();
    82          for (int i = 0; i < length; i++) {
    83              ptr.setIndex(i);
    84              NodePointer elementPointer = ptr.getValuePointer();
    85              NodeIterator iter = getElementNodeIterator(elementPointer);
    86
    87              for (int j = 1; iter.setPosition(j); j++) {
    88                  NodePointer childPointer = iter.getNodePointer();
    89                  if (reverse) {
    90                      collection.add(0, childPointer);
    91                  }
    92                  else {
    93                      collection.add(childPointer);
    94                  }
    95              }
    96          }
    97          if (startWith != null) {
    98              int index = collection.indexOf(startWith);
    99              if (index == -1) {
    100                 throw new JXPathException(
    101                     "Invalid starting pointer for iterator: " + startWith);
    102             }
    103             while (collection.size() > index) {
    104                 if (!reverse) {
    105                     collection.remove(collection.size() - 1);
    106                 }
    107                 else {
    108                     collection.remove(0);
    109                 }
    110             }
    111         }
    112     }
    113 }