<?php
/**
* モジュールグラフを実装するクラス
*
* PHP version 5
*
* @package    core
* @author     stk2k <stk2k@sazysoft.com>
* @copyright  2008 stk2k, sazysoft
*/

class charcoal_ModuleGraph 
{
	var $_module_graph;
	var $_current_node;

	/*
	 *    コンストラクタ
	 */
	public function __construct()
	{
		$this->_current_node = NULL;
		$this->_module_graph = array();
	}

	/*
	 * グラフ中の全ノード名を取得
	 */
	public function getNodeNames()
	{
		return array_keys( $this->_module_graph );
	}

	/*
	 * ノード名に対応するノードを取得
	 */
	public function getNode( $node_name )
	{
		return $this->_module_graph[ $node_name ];
	}

	/*
	 * startノードから実行を開始する
	 */
	public function start()
	{
		$start_node = "start";

		log_info( "system",  "モジュールグラフの現在ノードを[$start_node]に設定します。", __FILE__, __LINE__ );

		$this->_current_node = $this->_module_graph[ $start_node ];
	}

	/*
	 * 現在のノードがあるか
	 */
	public function hasCurrentNode()
	{
		return ($this->_current_node != NULL);
	}

	/*
	 * 現在のノード
	 */
	public function getCurrentNode()
	{
		return $this->_current_node;
	}

	/*
	 * ノードを遷移する
	 */
	public function moveNext( $transition_key )
	{
		// 遷移先のノード名を取得
		$next_node_name = $this->_current_node->getNextNode( $transition_key );

		log_info( "system",  "遷移先のノード名は[$next_node_name]です。", __FILE__, __LINE__ );

		// 遷移先が未定義なら例外
		if ( $next_node_name == NULL ){
			throw new charcoal_ModuleGraphTransitionException( $this->_current_node->getNodeName(), $transition_key );
		}

		// 現在のノードを更新
		$next_node = isset($this->_module_graph[ $next_node_name ]) ? $this->_module_graph[ $next_node_name ] : NULL;
		$this->_current_node = $next_node;

		// ノードを返却
		return $next_node;
	}

	/*
	 * モジュールグラフを構成する
	 */
	public function build( charcoal_Config $config, charcoal_ProcedureContext $context )
	{
		log_info( "system",  "モジュールグラフの構築を開始します。", __FILE__, __LINE__ );

		$this->_current_node = NULL;
		$this->_module_graph = array();

		// ノード名一覧を取得
		$node_name_list= $config->getArray( "graph_nodes" );

		if ( !$node_name_list ) {
			throw new charcoal_ModuleGraphConfigException( "graph_nodes", "mandatory" );
		}

		// 各ノードのモジュールを読み込む
		foreach( $node_name_list as $node_name => $node_data )
		{
			log_info( "system",  "ノード[$node_name]の設定を読み込みます。", __FILE__, __LINE__ );
			if ( !$node_data ) {
				throw new charcoal_ModuleGraphConfigException( "graph_nodes/$node_name", "mandatory" );
			}

			// グラフノードを作成
			$graph_node = new charcoal_ModuleGraphNode();
			$graph_node->create( $node_name, $node_data );

			// モジュールグラフにグラフノードを追加
			$this->_module_graph[ $node_name ] = $graph_node;
		}

		log_info( "system",  "モジュールグラフの構築が完了しました。", __FILE__, __LINE__ );
	}
}
