/*
 * This file is part of Nuts Framework.
 * Copyright (C) 2009 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 * 
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.gae.dao;

import nuts.core.dao.AbstractModelDAO;
import nuts.core.dao.DaoException;
import nuts.core.dao.DaoSession;
import nuts.core.dao.DataHandler;

import java.util.List;

/**
 * @param <T> model type
 * @param <E> model example type
 */
@SuppressWarnings("unchecked")
public abstract class GaeModelDAO<T, E extends GaeQueryParameter> extends AbstractModelDAO<T, E> {
	/**
	 * Constructor
	 */
	public GaeModelDAO() {
		super();
	}

	/**
	 * Constructor
	 *
	 * @param dataAccessSession the dataAccessSession to set
	 */
	public GaeModelDAO(DaoSession dataAccessSession) {
		super(dataAccessSession);
	}

	/**
	 * @return the GaeDataAccessClient
	 */
	public GaeDataAccessClient getGaeDataAccessClient() {
		return ((GaeDataAccessClient)getDataAccessClient());
	}

	/**
	 * @return the GaeDataAccessSession
	 */
	public GaeDataAccessSession getGaeDataAccessSession() {
		return ((GaeDataAccessSession)getDataAccessSession());
	}

	/**
	 * @return model id
	 */
	protected abstract String getModelId();
	
	/**
	 * exists
	 * 
	 * @param key T
	 * @return T
	 * @throws DaoException if a data access error occurs
	 */ 
	public boolean exists(T key) throws DaoException {
		return getGaeDataAccessSession().exists(getModelId(), key);
	}
	
	/**
	 * countByExample
	 * 
	 * @param example E
	 * @return count
	 * @throws DaoException if a data access error occurs
	 */ 
	public int count(E example) throws DaoException {
		return getGaeDataAccessSession().countByExample(getModelId(), example);
	}

	/**
	 * selectByPrimaryKey
	 * 
	 * @param key T
	 * @return T
	 * @throws DaoException if a data access error occurs
	 */ 
	public T fetch(T key) throws DaoException {
		return (T)(getGaeDataAccessSession().selectByPrimaryKey(getModelId(), key));
	}

	/**
	 * selectByExampleWithDataHandler
	 * 
	 * @param example E
	 * @param dataHandler data handler
	 * @return data count
	 * @throws DaoException if a data access error occurs
	 */ 
	public int selectWithDataHandler(E example, DataHandler<T> dataHandler) throws DaoException {
		return getGaeDataAccessSession().selectByExampleWithDataHandler(getModelId(), example, dataHandler);
	}

	/**
	 * selectByExample
	 * 
	 * @param example E
	 * @return list of T 
	 * @throws DaoException if a data access error occurs
	 */ 
	public List<T> selectList(E example) throws DaoException {
		return getGaeDataAccessSession().selectByExample(getModelId(), example);
	}

	/**
	 * if (exists(data)) { updateByPrimaryKey(data); } else { insert(data}; }
	 * 
	 * @param data T
	 * @throws DaoException if a data access error occurs
	 */ 
	public void save(T data) throws DaoException {
		getGaeDataAccessSession().save(getModelId(), data);
	}
	
	/**
	 * insert
	 * 
	 * @param data T
	 * @throws DaoException if a data access error occurs
	 */ 
	public void insert(T data) throws DaoException {
		getGaeDataAccessSession().insert(getModelId(), data);
	}

	/**
	 * deleteByPrimaryKey
	 * 
	 * @param key T
	 * @return count of deleted records
	 * @throws DaoException if a data access error occurs
	 */ 
	public int delete(T key) throws DaoException {
		return getGaeDataAccessSession().deleteByPrimaryKey(getModelId(), key);
	}

	/**
	 * deleteByExample
	 * 
	 * @param example E
	 * @return count of deleted records
	 * @throws DaoException if a data access error occurs
	 */ 
	public int deleteByExample(E example) throws DaoException {
		return getGaeDataAccessSession().deleteByExample(getModelId(), example);
	}

	/**
	 * updateByPrimaryKey
	 * 
	 * @param data T
	 * @return count of updated records
	 * @throws DaoException if a data access error occurs
	 */ 
	public int update(T data) throws DaoException {
		return getGaeDataAccessSession().updateByPrimaryKey(getModelId(), data);
	}

	/**
	 * updateByPrimaryKeySelective (ignore null properties)
	 * 
	 * @param data T
	 * @return count of updated records
	 * @throws DaoException if a data access error occurs
	 */ 
	public int updateIgnoreNull(T data) throws DaoException {
		return getGaeDataAccessSession().updateByPrimaryKeySelective(getModelId(), data);
	}

	/**
	 * updateByExample
	 * 
	 * @param data T
	 * @param example E
	 * @return count of updated records
	 * @throws DaoException if a data access error occurs
	 */ 
	public int update(T data, E example) throws DaoException {
		return getGaeDataAccessSession().updateByExample(getModelId(), data, example);
	}

	/**
	 * updateByExampleSelective (ignore null properties)
	 * 
	 * @param data T
	 * @param example E
	 * @return count of updated records
	 * @throws DaoException if a data access error occurs
	 */ 
	public int updateIgnoreNull(T data, E example) throws DaoException {
		return getGaeDataAccessSession().updateByExampleSelective(getModelId(), data, example);
	}
}
