/**
 * URLSuspender
 * 探索を一時的に抑制しておきたいサイトを管理するクラス
 * あるサイトがこのクラスに登録されている場合，探索抑制対象となる
 */
package org.logical_paradox.rss.http;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

public class URLSuspender {
	private Hashtable sites = null;

	/**
	 * デフォルトコンストラクタ
	 */
	public URLSuspender() {
		sites = new Hashtable();
	}

	/**
	 * 指定サイトの探索を抑制する
	 */
	public void suspend( Site s, String url ) throws IllegalArgumentException {
		if( s == null || s.getSiteName() == null ) {
			throw new IllegalArgumentException();
		}

		URLSuspendedSite site = null;
		synchronized( sites ) {
			site = (URLSuspendedSite)sites.get( s.getSiteName() );
			if( site == null ) {
				site = new URLSuspendedSite( s );
			}
			site.add( url );
		}

		sites.put( s.getSiteName(), site );
	}

	/**
 	 * 指定サイトに対応するサイトオブジェクトを返す
	 */
	public Site get( String sn ) {
		URLSuspendedSite s = (URLSuspendedSite)sites.get( sn );
		if( s == null ) {
			return null;
		} else {
			return s.getSite();
		}
	}

	/**
	 * 指定サイトが探索を抑制されているかどうかを返す
	 */
	public boolean isSuspended( String s ) {
		if( s == null ) {
			throw new IllegalArgumentException();
		}

		boolean rc = false;
		synchronized( sites ) {
			if( sites.get( s ) == null ) {
				// 指定サイトが一覧に存在しない場合は抑制されていない
				rc = false;
			} else {
				// 指定サイトが一覧に存在した場合は抑制されている
				rc = true;
			}
		}

		return rc;
	}

	/**
	 * 指定サイトが探索を抑制されているかどうかを返す
	 */
	public boolean isSuspended( Site s ) throws IllegalArgumentException {
		if( s == null ) {
			throw new IllegalArgumentException();
		}

		return isSuspended( s.getSiteName() );
	}

	/**
	 * 指定サイトの探索抑制を解除する
	 * 解除する際，抑制状態に置かれていたURLを全て返す
	 */
	public String[] release( String s ) throws IllegalArgumentException {
		if( s == null ) {
			throw new IllegalArgumentException();
		}

		URLSuspendedSite us = (URLSuspendedSite)sites.get( s );
		if( us == null ) {
			return null;
		}

		// 指定サイトが抑制状態にあった場合は，URLを全て返す
		String[] urls = us.releaseAll();
		sites.remove( s );

		return urls;
	}

	/**
	 * 指定サイトの探索抑制を解除する
	 * 解除する際，抑制状態に置かれていたURLを全て返す
	 */
	public String[] release( Site s ) throws IllegalArgumentException {
		if( s == null ) {
			throw new IllegalArgumentException();
		}

		return release( s.getSiteName() );
	}

	/**
	 * 格納しているURLの数を返す
	 */
	public int size() {
		int urls = 0;
		synchronized( sites ) {
			Enumeration e = sites.elements();
			while( e.hasMoreElements() ) {
				urls += ((URLSuspendedSite)e.nextElement()).size();
			}
		}
		return urls;
	}

	/**
	 * 探索抑制されているサイトとそれに属するURLを格納するコンテナ
	 */
	class URLSuspendedSite {
		private Site site = null;
		private HashSet urls = null;

		// コンストラクタ
		private URLSuspendedSite( Site s ) {
			site = s;
			urls = new HashSet();
		}
		// URLを追加する
		private void add( String url ) {
			urls.add( url );
		}
		// URLを削除する
		private void remove( String url ) {
			urls.remove( url );
		}
		// 指定されたURLが抑制状態で格納されているかどうかを返す
		private boolean isContained( String url ) {
			return urls.contains( url );
		}
		// このサイトの探索抑制状態URLの総数を返す
		private int size() {
			return urls.size();
		}
		// サイトオブジェクトを返す
		private Site getSite() {
			return site;
		}
		// 全てのURLを解放する
		private String[] releaseAll() {
			Vector list = new Vector();
			synchronized( urls ) {
				Iterator i = urls.iterator();
				while( i.hasNext() ) {
					list.addElement( i.next() );
				}

				// 登録されている全てのURLを削除する
				urls.removeAll( urls );
			}

			return (String[])list.toArray( new String[1] );
		}
	}
}

// end of URLSuspender.java
