package org.arefgard.flow.node;

import java.util.List;
import java.util.Map;

import org.arefgard.flow.exception.UsecaseFlowException;
import org.arefgard.flow.exception.UsecaseFlowExecuteException;
import org.arefgard.flow.integration.DIContainer;
import org.arefgard.flow.integration.DIContainerFactory;
import org.arefgard.flow.util.ReflectionUtil;

/**
 * 処理実行を表すノード。
 * 
 * @author Takashi Yamashina
 *
 */
public class InvokeNode extends Node {
	private String type;
	private String method;
	private String nextTo;
	
	private List<String> properties = new java.util.ArrayList<String>();
	private String returnValue;
	
	public String getMethod() {
		return method;
	}
	public void setMethod(String method) {
		this.method = method;
	}
	public String getNextTo() {
		return nextTo;
	}
	public void setNextTo(String nextTo) {
		this.nextTo = nextTo;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	
	public void addProperty(String name) {
		this.properties.add(name);
	}
	
	public String getProperty(int index) {
		return this.properties.get(index);
	}
	
	public String getReturn() {
		return this.returnValue;
	}
	
	public void setReturn(String returnValue) {
		this.returnValue = returnValue;
	}
	
	/**
	 * DIコンテナからオブジェクトを取り出して、指定した処理を実行する。
	 * 
	 * @param path DIコンテナのパス
	 * @param params パラメータ
	 * @throws UsecaseFlowException 処理の実行した場合
	 */
	public void invoke(String path, Map<String, Object> params) throws UsecaseFlowException {
		DIContainer container = DIContainerFactory.createContainer(path);
		Object obj = container.get(this.type);
		List<Object> paramList = new java.util.ArrayList<Object>();
		
		for(int i = 0, n = this.properties.size(); i < n; i++) {
			paramList.add(params.get(this.properties.get(i)));
		}
		try {
			Object ret = ReflectionUtil.execute(obj, this.method, paramList);
			if(this.returnValue != null) {
				params.put(returnValue, ret);
			}
		}catch(Exception e) {
			throw new UsecaseFlowExecuteException("", e);
		}
	}
	
}
