package org.arefgard.icerya.flow.core;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import org.arefgard.icerya.flow.exception.UsecaseFlowDefinitionParseException;
import org.arefgard.icerya.flow.exception.UsecaseFlowException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * XML文書で定義されたユースケースフロー定義ファイルをパースする。
 * 
 * @author Takashi Yamashina
 * @since 1.0.0
 */
public class UsecaseFlowDefinitionReader {
	
	/** パースした情報を格納するユースケースフロー */
	private UsecaseFlow flow;
	
	/**
	 * コンストラクタ。
	 * 
	 * @param flow
	 */
	public UsecaseFlowDefinitionReader(UsecaseFlow flow) {
		this.flow = flow;
	}
	
	/**
	 * ユースケースフロー定義ファイルをパースする。
	 * 
	 * @param path ユースケースフロー定義ファイルのパス
	 * @throws UsecaseFlowException ユースケースフロー定義ファイルのパースに失敗した場合
	 */
	public void parse(String path) throws UsecaseFlowException {
		
		// SAXパーサの取得
		XMLReader reader = null;
		try {
			reader = XMLReaderFactory.createXMLReader();
		} catch (SAXException e) {
			e.printStackTrace();
			throw new UsecaseFlowDefinitionParseException("Creation XMLReader failed.", e);
		}
		
		// ハンドラの設定
		reader.setContentHandler(new FlowHandler(flow));
		InputStream is = ClassLoader.getSystemResourceAsStream(path);
		if(is == null) {
			is = this.getClass().getClassLoader().getResourceAsStream(path);
		}

		try {
			reader.parse(new InputSource(is));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new UsecaseFlowDefinitionParseException("Usecase flow Definition File Parsing failed.", e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new UsecaseFlowDefinitionParseException("Usecase flow Definition File Parsing failed.", e);
		} catch (SAXException e) {
			e.printStackTrace();
			throw new UsecaseFlowDefinitionParseException("Usecase flow Definition File Parsing failed.", e);
		}finally {
			try {
				if(is != null) {
					is.close();
				}
			}catch(Exception ignored) {}
		}
	}
}
