package org.seasar.hibernate.dao.impl;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import net.sf.hibernate.Criteria;
import net.sf.hibernate.FetchMode;
import net.sf.hibernate.HibernateException;

import org.seasar.framework.util.StringUtil;
import org.seasar.hibernate.HibernateRuntimeException;
import org.seasar.hibernate.S2Session;
import org.seasar.hibernate.S2SessionFactory;
import org.seasar.hibernate.dao.QueryAutoHibernateCommand;
import org.seasar.hibernate.dao.criteria.EqCriteriaCommand;
import org.seasar.hibernate.dao.criteria.FirstResultCriteriaCommand;
import org.seasar.hibernate.dao.criteria.GeCriteriaCommand;
import org.seasar.hibernate.dao.criteria.GtCriteriaCommand;
import org.seasar.hibernate.dao.criteria.InCriteriaCommand;
import org.seasar.hibernate.dao.criteria.LeCriteriaCommand;
import org.seasar.hibernate.dao.criteria.LikeCriteriaCommand;
import org.seasar.hibernate.dao.criteria.LtCriteriaCommand;
import org.seasar.hibernate.dao.criteria.MaxResultsCriteriaCommand;
import org.seasar.hibernate.dao.criteria.OrderByCriteriaCommand;

/**
 * @author kenichi_okazaki 
 */
public abstract class AbstractAutoQueryCommand extends AbstractQueryHibernateCommand implements QueryAutoHibernateCommand {
	private String[] eagerFields_;
	protected List criteriaCommandList_ = new ArrayList();

	public AbstractAutoQueryCommand(S2SessionFactory s2sessionFactory,Class beanClass, Method method) {
		super(s2sessionFactory, beanClass,method);

	}

	/*
	 * (”ñ Javadoc)
	 * 
	 * @see org.srasar.hibernate.dao.HibernateCommand#execute(org.seasar.hibernate.S2Session,
	 *      java.lang.Object[])
	 */
	public Object execute( Object[] args) {
		List ret = null;
		
		try {
			Criteria criteria = getArgsCriteria(getS2Session(), args);
			
			
			criteria = setEagerFetch(criteria);
			ret = criteria.list();
		} catch (HibernateException ex) {
			throw new HibernateRuntimeException(ex);
		}
		
		return getReturnObject( getMethod() ,ret );
		
		
	}
	

	protected abstract Criteria getArgsCriteria(S2Session s2session, Object[] args) throws HibernateException ;


	private Criteria setEagerFetch(Criteria criteria) throws HibernateException{
		if(eagerFields_ != null){
			for(int i=0; i < eagerFields_.length ;i++){
					criteria.setFetchMode(eagerFields_[i], FetchMode.EAGER);
			}
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		}
		return criteria;
	}

	
	/**
	 * @param eager The eager to set.
	 */
	public void setEagerFields(String[] eagerFields) {
		eagerFields_ = eagerFields;
	}
	
	public void buildCriterionList(){
		String[] ArgNames = getArgNames();
		
		for (int i = 0; i < ArgNames.length; i++) {

			String[] expression = StringUtil.split(ArgNames[i], " ");
			String fieldName = expression[0];

			String dtoFieldName=fieldName;
			if(expression.length==3){
				dtoFieldName=expression[2];
			}
			
			if(expression.length == 1){
				if(fieldName.equals("orderBy")){
					criteriaCommandList_.add( new OrderByCriteriaCommand(fieldName,dtoFieldName));
					
				}else if(fieldName.equals("firstResult" )){
					criteriaCommandList_.add( new FirstResultCriteriaCommand(fieldName,dtoFieldName));

				}else if(fieldName.equals("maxResults" )){
					criteriaCommandList_.add( new MaxResultsCriteriaCommand(fieldName,dtoFieldName));
					
				}else{
					criteriaCommandList_.add( new EqCriteriaCommand(fieldName,dtoFieldName));	
				}

			}else if(expression[1].equals(">" )){
				criteriaCommandList_.add( new GtCriteriaCommand(fieldName,dtoFieldName));
			
			}else if(expression[1].equals(">=" )){
				criteriaCommandList_.add( new GeCriteriaCommand(fieldName,dtoFieldName));

			}else if(expression[1].equals("<" )){
				criteriaCommandList_.add( new LtCriteriaCommand(fieldName,dtoFieldName));

			}else if(expression[1].equals("<=" )){
				criteriaCommandList_.add( new LeCriteriaCommand(fieldName,dtoFieldName));
			
			}else if(expression[1].equals("like" )){
				criteriaCommandList_.add( new LikeCriteriaCommand(fieldName,dtoFieldName));

			}else if(expression[1].equals("in" )){
				criteriaCommandList_.add( new InCriteriaCommand(fieldName,dtoFieldName));

			}
		}
	}
	

}