/**
 * @(#)WebPage.java
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 * RIDUAL : Web Page
 * @author  Intelligent Technology Inc.
 * @version 1.00 2002/08/23
 */
package jp.co.nri.rid.web;

import	java.net.URL;
import	java.io.*;
import	java.util.*;
import	javax.swing.DefaultComboBoxModel;
import	javax.swing.text.*;
import	javax.swing.text.html.*;

/**
 * WebPageから任意のHTMLタグ、属性情報を取得できる。
 */
public class WebPage{
	private	Hashtable2D	myKeytable	= null;
	private	Reader		myReader	= null;
	private	HashVector	myList;
	
	/**
	 * コンストラクタ
	 * @since	1.00
	 */
	public WebPage(){}
	public WebPage(Reader reader){ setPage(reader); }
	
	public void setPage(Reader reader){	myReader = reader; }
	public void setPage(URL url) throws IOException ,UnsupportedEncodingException {
		setPage(url.openStream());
	}
	public void setPage(File file) throws FileNotFoundException ,UnsupportedEncodingException {
		setPage(new FileInputStream(file));
	}
	public void setPage(InputStream in) throws UnsupportedEncodingException {
		myReader = new BufferedReader(new InputStreamReader(in,"JISAutoDetect"));
	}
	
	/**
	 * キーマップを設定する。
	 * @since	1.00
	 */
	public void setKeytable(Hashtable2D keytable){ myKeytable = keytable; }
	
	/**
	 * @since	1.00
	 */
	public HashVector get() throws IOException ,BadLocationException{
		myList = new HashVector();
		
		HTMLDocumentEx document	= new HTMLDocumentEx();
		document.putProperty("IgnoreCharsetDirective", new Boolean(true));
		HTMLEditorKitEx kit = new HTMLEditorKitEx();
		kit.read(myReader ,document ,0);
		
		AttributeSet[] attrsets = (AttributeSet[])document.areas.toArray(new AttributeSet[0]);
		if(null!=attrsets){
			for(int i=attrsets.length-1;0<=i;i--)	scanAttribute("area" ,attrsets[i]);
		}
		
		String	title	= (String)document.getProperty("title");
		if(null!=title)	myList.add(WebKeyMap.TITLE ,title);
		
		scanTag(document.getDefaultRootElement());
		
		return myList;
	}
	
	private void scanTag(Element element){
		scanAttribute(element.getName().toLowerCase() ,element.getAttributes());	// このelementのattributeをスキャン
		
		// 子elementのattributeをスキャン
		if(element.isLeaf())	return;
		for(int i = element.getElementCount()-1;0<=i;i--)	scanTag(element.getElement(i));
	}
	
	private void scanAttribute(String name ,AttributeSet attributeset){
		boolean	isWildCard	= false;
		Hashtable	map		= null;
		
		if(null==myKeytable)	isWildCard	= true;
		else					map			= myKeytable.get(name);
		
		Enumeration enum = attributeset.getAttributeNames();
		while(enum.hasMoreElements()){
			Object key		= enum.nextElement();
			Object value	= attributeset.getAttribute(key);
			
			// AttributeSetの場合は無条件にスキャン
			if(value instanceof AttributeSet){
//				scanAttribute("a" ,(AttributeSet)value);
				scanAttribute(key.toString().toLowerCase() ,(AttributeSet)value);
			}
			
			// コンボボックス
			else if(value instanceof DefaultComboBoxModel){
				DefaultComboBoxModel combo = (DefaultComboBoxModel)value;
				for(int i=combo.getSize()-1;0<=i;i--){
					Object obj = combo.getElementAt(i);
					if(obj instanceof Option){
//						scanAttribute("option" ,(AttributeSet)value);
						scanAttribute(key.toString().toLowerCase() ,((Option)obj).getAttributes());
					}
				}
			}
			
			// AttributeSetとコンボボックス以外
			else{
				if(null!=map){
					Object listkey = map.get(key.toString().toLowerCase());
					if(null!=listkey){
						myList.add(listkey ,value.toString());
					}
				}
				else if(isWildCard){
					myList.add(name+" "+key.toString().toLowerCase() ,value.toString());
				}
			}
		}
	}
}
