//1.1.2
package com.jxml.quick.recycle;
import com.jxml.quick.*;
import java.util.*;
import java.lang.ref.*;

/**
 * Maintains a table of all available external references
 */
public final class QRefHash
{
	private static QRefHash map=new QRefHash();

	private HashMap hash=new HashMap();
	private ReferenceQueue queue=new ReferenceQueue();

	private QRefHash(){}

	/**
	 * Define the document root as an external reference.
	 */
	public static void add(QDoc doc)
		throws QPE
	{
		map.put(doc.getRoot(),doc);
	}

	/**
	 * Define an external reference.
	 */
	public static void add(Object value, QDoc doc)
		throws QPE
	{
		map.put(value,doc);
	}

	private synchronized void put(Object value, QDoc doc)
		throws QPE
	{
		poll();
		String href=doc.getKey();
		if (href==null)
			return;
		if (doc.getSchema()==null)
			return;
		if (value==null)
			hash.remove(new I(value));
		else
		{
			I i=new I(value,queue);
			hash.put(i,new J(value,doc));
		}
	}

	/**
	 * Create an HRef.
	 */
	public static void createHRef(QDoc doc, Object value)
	{
		map.create(doc,value);
	}

	private synchronized void create(QDoc doc, Object value)
	{
		poll();
		I i=new I(value);
		J j=(J)hash.get(i);
		if (j==null)
		{
			return;
		}
		doc.createHRef(value,j.schema,j.href,"java.lang.Object");
	}

	/**
	 * Create an HRef.
	 */
	public static String getHRef(Object value)
	{
		return map.getRef(value);
	}

	private synchronized String getRef(Object value)
	{
		poll();
		I i=new I(value);
		J j=(J)hash.get(i);
		if (j==null)
		{
			return "";
		}
		return j.href;
	}

	private void poll()
	{
		I i=null;
		do
		{
			if (i!=null)
			{
				hash.remove(i);
			}
		} while (i!=null);
	}

	static class I extends SoftReference
	{
		private int hc;

		I(Object key, ReferenceQueue queue)
		{
			super(key,queue);
			hc=System.identityHashCode(key);
		}

		I(Object key)
		{
			super(key);
			hc=System.identityHashCode(key);
		}

		public boolean equals(Object x)
		{
			return this.get()==((I)x).get();
		}

		public int hashCode()
		{
			return hc;
		}
	}

	static class J
	{
		String schema;
		String href;

		J(Object value, QDoc doc)
			throws QPE
		{
			href=doc.getKey();
			if (value!=doc.getRoot())
			{
				String id=doc.getId(value);
				href+="#"+id;
			}
			schema=doc.getSchema().getKey();
		}
	}
}
