/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id$
 */
package org.apache.xalan.lib.sql;

import java.util.Vector;

/**
 * Provide a simple Array storage mechinsim where  native Arrays will be use as
 * the basic storage mechinism but the Arrays will be stored as blocks.
 * The size of the Array blocks is determine during object construction.
 * This is intended to be a simple storage mechinsim where the storage only
 * can grow. Array elements can not be removed, only added to.
 */
public class ObjectArray
{
  /**
   */
  private int m_minArraySize = 10;
  /**
   * The container of all the sub arrays
   */
  private Vector m_Arrays = new Vector(200);

  /**
   * An index that porvides the Vector entry for the current Array that is
   * being appended to.
   */
  private _ObjectArray m_currentArray;


  /**
   * The next offset in the current Array to append a new object
   */
  private int m_nextSlot;


  /**
   */
  public ObjectArray( )
  {
    //
    // Default constructor will work with a minimal fixed size
    //
    init(10);
  }

  /**
   * @param minArraySize The size of the Arrays stored in the Vector
   */
  public ObjectArray( final int minArraySize )
  {
    init(minArraySize);
  }

  /**
   * @param size
   *
   */
  private void init( int size )
  {
    m_minArraySize = size;
    m_currentArray = new _ObjectArray(m_minArraySize);
  }

  /**
   * @param idx Index of the Object in the Array
   *
   */
  public Object getAt( final int idx )
  {
    int arrayIndx = idx / m_minArraySize;
    int arrayOffset = idx - (arrayIndx * m_minArraySize);

    //
    // If the array has been off loaded to the Vector Storage them
    // grab it from there.
    if (arrayIndx < m_Arrays.size())
    {
      _ObjectArray a = (_ObjectArray)m_Arrays.elementAt(arrayIndx);
      return a.objects[arrayOffset];
    }
    else
    {
      // We must be in the current array, so pull it from there

      // %REVIEW% We may want to check to see if arrayIndx is only
      // one freater that the m_Arrays.size(); This code is safe but
      // will repete if the index is greater than the array size.
      return m_currentArray.objects[arrayOffset];
    }
  }

  /**
   * @param idx Index of the Object in the Array
   * @param obj , The value to set in the Array
   *
   */
  public void setAt( final int idx, final Object obj )
  {
    int arrayIndx = idx / m_minArraySize;
    int arrayOffset = idx - (arrayIndx * m_minArraySize);

    //
    // If the array has been off loaded to the Vector Storage them
    // grab it from there.
    if (arrayIndx < m_Arrays.size())
    {
      _ObjectArray a = (_ObjectArray)m_Arrays.elementAt(arrayIndx);
      a.objects[arrayOffset] = obj;
    }
    else
    {
      // We must be in the current array, so pull it from there

      // %REVIEW% We may want to check to see if arrayIndx is only
      // one freater that the m_Arrays.size(); This code is safe but
      // will repete if the index is greater than the array size.
      m_currentArray.objects[arrayOffset] = obj;
    }
  }



  /**
   * @param o Object to be appended to the Array
   *
   */
  public int append( Object o )
  {
    if (m_nextSlot >= m_minArraySize)
    {
      m_Arrays.addElement(m_currentArray);
      m_nextSlot = 0;
      m_currentArray = new _ObjectArray(m_minArraySize);
    }

    m_currentArray.objects[m_nextSlot] = o;

    int pos = (m_Arrays.size() * m_minArraySize) + m_nextSlot;

    m_nextSlot++;

    return pos;
  }


  /**
   */
  class _ObjectArray
  {
    /**
     */
    public Object[] objects;
    /**
     * @param size
     */
    public _ObjectArray( int size )
    {
      objects = new Object[size];
    }
  }

  /**
   * @param args
   *
   */
  public static void main( String[] args )
  {
    String[] word={
      "Zero","One","Two","Three","Four","Five",
      "Six","Seven","Eight","Nine","Ten",
      "Eleven","Twelve","Thirteen","Fourteen","Fifteen",
      "Sixteen","Seventeen","Eighteen","Nineteen","Twenty",
      "Twenty-One","Twenty-Two","Twenty-Three","Twenty-Four",
      "Twenty-Five","Twenty-Six","Twenty-Seven","Twenty-Eight",
      "Twenty-Nine","Thirty","Thirty-One","Thirty-Two",
      "Thirty-Three","Thirty-Four","Thirty-Five","Thirty-Six",
      "Thirty-Seven","Thirty-Eight","Thirty-Nine"};

    ObjectArray m_ObjectArray = new ObjectArray();
    // Add them in, using the default block size
    for (int x =0; x< word.length; x++)
    {
      System.out.print(" - " + m_ObjectArray.append(word[x]));
    }

    System.out.println("\n");
    // Now let's read them out sequentally
    for (int x =0; x< word.length; x++)
    {
      String s = (String) m_ObjectArray.getAt(x);
      System.out.println(s);
    }

    // Some Random Access
    System.out.println((String) m_ObjectArray.getAt(5));
    System.out.println((String) m_ObjectArray.getAt(10));
    System.out.println((String) m_ObjectArray.getAt(20));
    System.out.println((String) m_ObjectArray.getAt(2));
    System.out.println((String) m_ObjectArray.getAt(15));
    System.out.println((String) m_ObjectArray.getAt(30));
    System.out.println((String) m_ObjectArray.getAt(6));
    System.out.println((String) m_ObjectArray.getAt(8));

    // Out of bounds
    System.out.println((String) m_ObjectArray.getAt(40));

  }
}
