import java.util.*;

/**
 * This simple class is a quick-n-dirty implementation
 * of an invertible mapping.  It uses a pair of Hash
 * tables.
 */
public class DoubleHash implements DoubleMap, java.io.Serializable {
    private Hashtable xtab;
    private Hashtable ytab;

    public DoubleHash(int capacity) {
	xtab = new Hashtable(capacity);
	ytab = new Hashtable(capacity);
    }

    public DoubleHash() {
	this(17);
    }

    public synchronized void insertXY(Object x, Object y) {
	xtab.put(x,y);
	ytab.put(y,x);
    }

    public synchronized Object getY(Object x) {
	return xtab.get(x);
    }
    public synchronized Object getX(Object y) {
	return ytab.get(y);
    }

    public synchronized boolean deleteXY(Object x, Object y) {
	if (xtab.containsKey(x) &&
	    ytab.containsKey(y) &&
	    getY(x).equals(y) &&
	    getX(y).equals(x))
	    {
		xtab.remove(x);
		ytab.remove(y);
		return true;
	    }
	else return false;
    }

    public Enumeration xElements() {
	return xtab.keys();
    }

    public Enumeration yElements() {
	return ytab.keys();
    }

    public static void main(String args[]) {
	DoubleHash dh = new DoubleHash();

	dh.insertXY("Foo","Bar");
	dh.insertXY("Here","There");
	dh.insertXY("Hello","World");
	dh.insertXY("Not","Now");
	dh.insertXY("vi","Emacs");

	Enumeration e1 = dh.xElements();
	for( ; e1.hasMoreElements(); ) {
	    Object x = e1.nextElement();
	    System.out.println("Map: " + x + " <--> " + dh.getY(x));
	}
    }
}
