/*
 * @(#)XHashtable.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>Hashtable</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 XHashtable extends Hashtable
    implements Stringable
{
    //////////////////
    // Constructors //
    //////////////////
    
    /**
     * Constructs a new, empty hashtable with a default capacity
     * and load factor, which is 0.75.
     *
     * @see XHashtable(int)
     * @see XHashtable(int, float)
     * @see XHashtable(Map)
     * @see XHashtable(String)
     */
    public XHashtable() { super(); }
    
    /**
     * Constructs a new, empty hashtable with the specified initial
     * capacity and default load factor, which is 0.75.
     *
     * @param initialCapacity the initial hashtable capacity
     * @see #XHashtable()
     * @see #XHashtable(int, float)
     * @see #XHashtable(Map)
     * @see #XHashtable(String)
     */
    public XHashtable(int initialCapacity)
        { super(initialCapacity); }
    
    /**
     * Constructs a new, empty hashtable with the specified initial
     * capacity and the specified load factor
     *
     * @param initialCapacity the initial hashtable capacity
     * @param loadFactor the hashtable load factor
     * @see #XHashtable()
     * @see #XHashtable(int)
     * @see #XHashtable(Map)
     * @see #XHashtable(String)
     */
    public XHashtable(int initialCapacity, float loadFactor)
        { super(initialCapacity, loadFactor); }
    
    /**
     * Constructs a new hashtable with the same mappings as the
     * given Map.
     *
     * @param t the map that supplies the initial hashtable data
     * @see #XHashtable()
     * @see #XHashtable(int)
     * @see #XHashtable(int, float)
     * @see #XHashtable(String)
     */
    public XHashtable(Map t) { super(t); }
    
    /**
     * Constructs a new hashtable initialized with the encapsulated
     * data.  The data should be supplied in the format created by
     * the function toStringData.
     *
     * @param data the encapsulated hashtable data
     * @see #XHashtable()
     * @see #XHashtable(int)
     * @see #XHashtable(int, float)
     * @see #XHashtable(Map)
     */
    public XHashtable(String data) {
        super();
        
        try {
            fromStringData(data);
        }
        catch (ParseException ex) {
            clear();
        }
    }
    
    ////////////////
    // 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 hashtableSize = (items == null) ? 0 : (items.length);
        
        for (int i = 0; i < hashtableSize; i++) {
            String[] pair = CodecUtilities.decode(items[i]);
        
            if (pair.length != 2)
                throw new ParseException
                    ("Item " + i + " is not a pair", -1);            
		
            Stringable key =
                StringableFactory.decodeTypeAndData(pair[0]);
        
            Stringable val =
                StringableFactory.decodeTypeAndData(pair[1]);
         
         	
            
            put(key, val);
       
        }       
       
    }

    /**
     * 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 hashtableSize = size();
        
        String[] items = new String[hashtableSize];
        
        Enumeration keys = keys();
        Enumeration vals = elements();
                
        String[] pair = new String[2];
        
        for (int i = 0; i < hashtableSize; i++) {
        	
            pair[0] =
                StringableFactory.encodeTypeAndData
                    ((Stringable) keys.nextElement());
                
            pair[1] =
                StringableFactory.encodeTypeAndData
                    ((Stringable) vals.nextElement());
                
            items[i] = CodecUtilities.encode(pair);
        }
        
        return CodecUtilities.encode(items);
    }
}
