/*
 * $Id: URLSuspender.java,v 1.3 2006/01/27 14:20:44 rampil Exp $
 * Copyright (c) 2006 LOGICAL-PARADOX.ORG
 */
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;

/**
 * URLSuspender
 * 探索を一時的に抑制しておきたいサイトを管理するクラス
 * あるサイトがこのクラスに登録されている場合，探索抑制対象となる
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.3 $
 */
public class URLSuspender {
	/** 探索抑制マップ */
	private Hashtable<String, URLSuspendedSite> sites = null;

	/**
	 * コンストラクタ．
	 */
	public URLSuspender() {
		sites = new Hashtable<String, URLSuspendedSite>();
	}

	/**
	 * 指定サイトの探索を抑制する．
	 * @param s サイト
	 * @param url URL
	 * @throws IllegalArgumentException サイト情報が不正
	 */
	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);
	}

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

	/**
	 * 指定サイトが探索を抑制されているかどうかを返す．
	 * @param s ドメイン名(サイト名)
	 * @return true: 抑制されている / false: 抑制されていない
	 */
	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;
	}

	/**
	 * 指定サイトが探索を抑制されているかどうかを返す．
	 * @param s サイト情報
	 * @return true: 抑制されている / false: 抑制されていない
	 * @throws IllegalArgumentException サイト情報が不正
	 */
	public boolean isSuspended(Site s) throws IllegalArgumentException {
		if(s == null) {
			throw new IllegalArgumentException();
		}

		return isSuspended(s.getSiteName());
	}

	/**
	 * 指定サイトの探索抑制を解除する．
	 * 解除する際，抑制状態に置かれていたURLを全て返す
	 * @param s ドメイン名(サイト名)
	 * @return 抑制状態だったURLの配列
	 * @throws IllegalArgumentException サイト名が不正
	 */
	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を全て返す
	 * @param s サイト情報
	 * @return 抑制状態だったURLの配列
	 * @throws IllegalArgumentException サイト情報が不正
	 */
	public String[] release(Site s) throws IllegalArgumentException {
		if(s == null) {
			throw new IllegalArgumentException();
		}

		return release(s.getSiteName());
	}

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

	/**
	 * 探索抑制されているサイトとそれに属するURLを格納するコンテナ．
	 * @author satoshi akabane@logical-paradox.org
	 * @version $Revision: 1.3 $
	 */
	class URLSuspendedSite {
		private Site site = null;
		private HashSet<String> urls = null;

		// コンストラクタ
		private URLSuspendedSite(Site s) {
			site = s;
			urls = new HashSet<String>();
		}
		// 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<String> list = new Vector<String>();
			synchronized(urls) {
				Iterator i = urls.iterator();
				while(i.hasNext()) {
					list.addElement(i.next().toString());
				}

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

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

// end of URLSuspender.java
