/*
 * @(#)XVector.java    1.0  6 May 2001
 *
 * Copyright 2001
 * College of Computer Science
 * Northeastern University
 * Boston, MA  02115
 *
 * This software may be used for educational purposes as long as
 * this copyright notice is retained intact at the top of all files.
 *
 * To discuss commercial use of this software, contact 
 * Prof. Richard Rasala or Prof. Viera Proulx at the Northeastern 
 * University College of Computer Science: 617-373-2462.
 *
 * The principal software developer on this project is Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All publication rights are retained.  This software or its 
 * documentation may not be published in any media either in whole
 * or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */
package edu.neu.ccs;

import edu.neu.ccs.codec.*;
import edu.neu.ccs.util.*;
import java.awt.*;
import java.beans.*;
import java.text.ParseException;
import java.util.*;

/**
 * <P><CODE>Stringable</CODE> version of the Java
 * <CODE>Vector</CODE> class.
 * This class assumes that the objects stored are
 * <CODE>Stringable</CODE>.</P>
 * 
 * @author  Richard Rasala
 * @version 1.0
 * @since   1.0
 */
public class XVector extends Vector
    implements Stringable
{
    //////////////////
    // Constructors //
    //////////////////
    
    /**
     * Constructs an empty vector so that its internal data array
     * has size 10 and its standard capacity increment is zero.
     *
     * @see #Vector(int)
     * @see #Vector(int, int)
     * @see #Vector(Collection)
     * @see #Vector(String)
     */
    public XVector() { super(); }
    
    /**
     * Constructs an empty vector with the specified initial
     * capacity and with its capacity increment equal to zero.
     *
     * @see #Vector()
     * @see #Vector(int, int)
     * @see #Vector(Collection)
     * @see #Vector(String)
     */
    public XVector(int initialCapacity)
        { super(initialCapacity); }
    
    /**
     * Constructs an empty vector with the specified initial
     * capacity and capacity increment.
     *
     * @see #Vector()
     * @see #Vector(int)
     * @see #Vector(Collection)
     * @see #Vector(String)
     */
    public XVector(int initialCapacity, int capacityIncrement)
        { super(initialCapacity, capacityIncrement); }
    
    /**
     * Constructs a vector containing the elements of the
     * specified collection, in the order they are returned by
     * the collection's iterator.
     *
     * @see #Vector()
     * @see #Vector(int)
     * @see #Vector(int, int)
     * @see #Vector(String)
     */
    public XVector(Collection c) { super(c); }
    
    /**
     * Constructs a new vector initialized with the encapsulated
     * data.  The data should be supplied in the format created
     * by the function toStringData.
     *
     * @see #Vector()
     * @see #Vector(int)
     * @see #Vector(int, int)
     * @see #Vector(Collection)
     */
    public XVector(String data) {
        super();
        
        try {
            fromStringData(data);
        }
        catch (ParseException ex) {
            setSize(0);
        }
    }
    
    ////////////////
    // Stringable //
    ////////////////
    
    /**
     * Sets the state of this object 
     * using information contained in the given <CODE>String</CODE>.
     *
     * @param data the <CODE>String</CODE> containing state information
     * @exception ParseException if the data is malformed
     * @see #toStringData()
     */
    public void fromStringData(String data) throws ParseException {
        String[] items = CodecUtilities.decode(data);
        
        int vectorSize = (items == null) ? 0 : (items.length);
        
        setSize(vectorSize);
        
        for (int i = 0; i < vectorSize; i++)
            setElementAt
                (StringableFactory.decodeTypeAndData(items[i]), i);
    }

    /**
     * Returns a <CODE>String</CODE> encapsulation of this object 
     * that contains information needed 
     * to set the state of this object at a later time.
     *
     * @see #fromStringData(String)
     */
    public String toStringData() {
        int vectorSize = size();
        
        String[] items = new String[vectorSize];
        
        for (int i = 0; i < vectorSize; i++)
            items[i] =
                StringableFactory.encodeTypeAndData(stringableAt(i));
        
        return CodecUtilities.encode(items);
    }
    
    ////////////////
    // Public API //
    ////////////////
    
    /**
     * Returns elementAt(i) cast to Stringable.
     */
    public Stringable stringableAt(int i) {
        Object element = elementAt(i);
                
        if (StringableFactory.isStringable(element.getClass())) {
            return (Stringable) element;
        }
        else {
            throw new Error
                ("XVector elementAt(" + i + ") is not Stringable");
        }
    }
}
