package com.dbxml.xml.dtsm;

/*
 * dbXML - Native XML Database
 * Copyright (C) 1999-2004  The dbXML Group, L.L.C.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Id: PullProcessor.java,v 1.3 2004/02/12 00:17:58 bradford Exp $
 */

/**
 * PullProcessor is a simple pull processor for DocumentTable streams.  It
 * can be constructed to either traverse an entire stream or a stream
 * fragment if constructed with an initial index.
 */

public final class PullProcessor {
   private DocumentTable table;
   private int nesting = -1;
   private int idx;
   private int origIdx;

   public PullProcessor(DocumentTable table) {
      this.table = table;
   }

   public PullProcessor(DocumentTable table, int idx) {
      this.table = table;
      if ( idx > 0 ) {
         this.idx = idx;
         origIdx = idx;
         nesting = 0;
      }
   }

   /**
    * next returns the next DocumentTableEntry in the PullProcessor, or it
    * returns null if no more entries are available.
    *
    * @return The next DocumentTableEntry
    */
   public DocumentTableEntry next() {
      if ( idx != -1 && idx < table.getEntryCount() ) {
         DocumentTableEntry dte = table.getEntry(idx++);
         if ( nesting != -1 ) {
            byte typeID = dte.getTypeID();
            if ( Constants.isTypePaired(typeID) ) {
               if ( typeID > 0 )
                  nesting++;
               else {
                  nesting--;
                  if ( nesting == 0 )
                     idx = -1;
               }
            }
         }
         return dte;
      }
      else
         return null;
   }

   /**
    * getPos returns the DocumentTable position of the most recently pulled
    * DocumentTableEntry.  The initial result of this method is -1 (no entries
    * have been returned).
    *
    * @return The DocumentTable position
    */
   public int getPos() {
      return idx-1;
   }

   /**
    * peek retrieves the next DocumentTableEntry without actually incrementing
    * the PullProcessor's position.
    *
    * @return The DocumentTableEntry
    */
   public DocumentTableEntry peek() {
      if ( idx != -1 && idx < table.getEntryCount() )
         return table.getEntry(idx);
      else
         return null;
   }

   /**
    * hasNext returns whether or not there are any more DocumentTableEntry
    * objects available in the PullProcessor.
    *
    * @return True if more can be pulled
    */
   public boolean hasNext() {
      return idx != -1 && idx < table.getEntryCount();
   }

   /**
    * reset will reset the PullProcessor position to its original location.
    */
   public void reset() {
      idx = origIdx;
   }

   /**
    * pushBack pushes the most recently retrieved DocumentTableEntry back
    * into the PullProcessor.  After this operation, the next
    * DocumentTableEntry retrieved will be the most recent one pushed
    * back onto the stack.
    */
   public void pushBack() {
      if ( idx > origIdx )
         idx--;
   }
}
