/**
 * @(#)HTMLAnalyzer.java
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 * RID-3 : HTML Analizer
 * @author  Intelligent Technology Inc.
 * @version 1.00 2001/10/01-2001/12/28
 * @see 
 */
package	jp.co.nri.rid.analyzer;

import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import java.io.*;
import java.util.*;

import	jp.co.nri.rid.xml.*;

/**
 * HTMLからタグや属性を取り出すための解析クラス
 */

public class HTMLAnalyzer{
	private	HashMap	myFilter	= null;
	public	HashMap	list		= new HashMap();
	private boolean ese;
	
	private class AttrVec extends Vector{
		private HashMap myFilter;
		public AttrVec(HashMap filter){
			myFilter= (null==filter) ? null : (HashMap)filter.clone();
		}
		public boolean add(Object o){
			if(null!=myFilter){
				if(!myFilter.containsKey(((Attribute)o).name))	return false;
			}
			return super.add(o);
		}
	}
	
//--------[[ open method ]]----------------------------------------------------
	public boolean getEmptyStack(){ return ese; }
	public void addFilter(String[] filter){
		if(null==myFilter)	myFilter = new HashMap();
		for(int i=filter.length-1;0<=i;i--)	myFilter.put(filter[i] ,null);
	}
	
/*
	public void printFilter(){
		if(null!=myFilter){
			String[] keys = (String[])myFilter.keySet().toArray(new String[0]);
			for(int i=keys.length-1;0<=i;i--);
		}
	}
*/
	
	/**
	 * HTMLからattributeを抽出する。
	 * @param	filename	HTML
	 * @return	attribute配列
	 * @see		Attribute
	 * @exception	java.io.FileNotFoundException			HTMLが見つからなかった。
	 * @exception	java.io.IOException						HTMLを開けなかった。
	 * @exception	javax.swing.text.BadLocationException	
	 * @since	1.00
	 */
	public Attribute[] analyze(String filename, elementBooster xmlelem)
	throws java.io.FileNotFoundException ,java.io.IOException ,javax.swing.text.BadLocationException
	{
		ese = false;
		RHTMLDocument document	= new RHTMLDocument(list, xmlelem);
		document.putProperty("IgnoreCharsetDirective", new Boolean(true));
//		BufferedReader file = new BufferedReader(new FileReader(filename));
		BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream(filename),"JISAutoDetect"));
		try{
			RHTMLEditorKit kit = new RHTMLEditorKit();
			kit.read(file ,document ,0);
			ese = kit.isEmptyStack();
		}finally{ file.close(); }
		Vector	attributes	= new AttrVec(myFilter);
		
		AttributeSet[] attrsets = (AttributeSet[])document.areas.toArray(new AttributeSet[0]);
		if(null!=attrsets){
			int mx = attrsets.length;
			for(int i=0;i<mx;i++){
				jp.co.nri.rid.xml.Attribute attribute = new Attribute("area" ,null);
				attributes.add(attribute);
				attributeAnalyze(attribute ,"area" ,attrsets[i] ,attributes);
			}
		}
		
/*		
		// "-- Document propertys --"
		java.util.Dictionary ht = document.getDocumentProperties();
		Enumeration enum = ht.keys();
		while(enum.hasMoreElements()){
			Object key = enum.nextElement();
		}
		
		// "-- Styles --"
		Enumeration names = document.getStyleNames();
		while(names.hasMoreElements()){
			Object key =  names.nextElement();
		}
*/
		
		String	title	= (String)document.getProperty("title");
		if(null!=title)	attributes.add(new Attribute("titlestring" ,title));
		
		analyzeRobo(document.getDefaultRootElement() ,attributes);
		Attribute[] attrs = (Attribute[])attributes.toArray(new Attribute[0]);
		attributes = null;
		return attrs;
	}
	
//--------[[ close method ]]----------------------------------------------------
	private void analyzeRobo(Element element ,Vector attributes){
		String name = element.getName().toLowerCase();
//if( null != list.get(name) )	xmlelem = xmlelem.add(name);
		
		tagAnalyze(element ,attributes);
		if(element.isLeaf())	return;
		
		int mx = element.getElementCount();
		for(int i = 0;i<mx;i++)	analyzeRobo(element.getElement(i) ,attributes);
	}
	
	private void tagAnalyze(Element element ,Vector attributes){
		String name = element.getName().toLowerCase();
		jp.co.nri.rid.xml.Attribute attribute = new Attribute(name ,null);
		attributes.add(attribute);
		attributeAnalyze(attribute ,name ,element.getAttributes(), attributes);
	}
	
	private void attributeAnalyze(Attribute parent ,String name ,AttributeSet attributeset ,Vector attributes){
		StringBuffer strbuf;
		Enumeration enum = attributeset.getAttributeNames();
		while(enum.hasMoreElements()){
			Object key		= enum.nextElement();
			Object value	= attributeset.getAttribute(key);
			String keystr	=	key.toString().toLowerCase();
			
			strbuf = new StringBuffer(name);
			strbuf.append(".");
			strbuf.append(keystr);
			String keypath = strbuf.toString();
			jp.co.nri.rid.xml.Attribute attribute = new Attribute(keypath ,null);
			attributes.add(attribute);
			if(value instanceof String){
				parent.option(new Attribute(keystr ,(String)value));
//xmlelem.attribute(keystr, (String)value);
/*				
				strbuf = new StringBuffer(name);
				strbuf.append(".");
				strbuf.append(keystr);
*/
				attributes.add(new Attribute(/*strbuf.toString()*/keypath ,(String)value));
			}
//			else if(value instanceof AttributeSet)	attributeAnalyze(name+".attribute" ,(AttributeSet)value ,attributes);
			else if(value instanceof AttributeSet){
				attributeAnalyze(attribute ,"attribute" ,(AttributeSet)value ,attributes);
			}
			else if(value instanceof DefaultComboBoxModel){
				DefaultComboBoxModel combo = (DefaultComboBoxModel)value;
				int mx = combo.getSize();
				for(int i=0;i<mx;i++){
					Object obj = combo.getElementAt(i);
					if(obj instanceof Option){
						Option opt = (Option)obj;
//						attributes.add(new Attribute("xvalue" ,opt.getValue()));
						strbuf = new StringBuffer(name);
						strbuf.append(".option");
						attributeAnalyze(attribute ,strbuf.toString() ,opt.getAttributes() ,attributes);
					}
				}
			}
			else{
				String	keystring	= key.toString();
				if(!"name".equalsIgnoreCase(keystring)){
					StringBuffer namebuf = new StringBuffer(name);
					namebuf.append(".");
					namebuf.append(keystring.toLowerCase());
					String	valuestring	= value.toString();
					if(null == valuestring)	valuestring = "null";
					StringBuffer valuebuf = new StringBuffer(valuestring);
					valuebuf.append("@");
					valuebuf.append(value.getClass());
					attributes.add(new Attribute(namebuf.toString() ,valuebuf.toString()));
//xmlelem.add(keystr).text(valuebuf.toString());
				}
			}
		}
	}
}