// Generated by: hibernate/SpringHibernateDaoImpl.vsl in andromda-spring-cartridge.
// license-header java merge-point
/**
 * This is only generated once! It will never be overwritten.
 * You can (and have to!) safely modify it by hand.
 */
package org.phoenixctms.ctsms.domain;

import java.awt.Dimension;
import java.util.Collection;
import java.util.HashMap;

import org.hibernate.Query;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.phoenixctms.ctsms.enumeration.DBModule;
import org.phoenixctms.ctsms.enumeration.FileModule;
import org.phoenixctms.ctsms.enumeration.InputFieldType;
import org.phoenixctms.ctsms.query.CategoryCriterion;
import org.phoenixctms.ctsms.query.CriteriaUtil;
import org.phoenixctms.ctsms.query.QueryUtil;
import org.phoenixctms.ctsms.query.SubCriteriaMap;
import org.phoenixctms.ctsms.util.CommonUtil;
import org.phoenixctms.ctsms.util.CoreUtil;
import org.phoenixctms.ctsms.util.DefaultSettings;
import org.phoenixctms.ctsms.util.SettingCodes;
import org.phoenixctms.ctsms.util.Settings;
import org.phoenixctms.ctsms.util.Settings.Bundle;
import org.phoenixctms.ctsms.vo.CriteriaInstantVO;
import org.phoenixctms.ctsms.vo.InputFieldImageVO;
import org.phoenixctms.ctsms.vo.InputFieldInVO;
import org.phoenixctms.ctsms.vo.InputFieldOutVO;
import org.phoenixctms.ctsms.vo.MimeTypeVO;
import org.phoenixctms.ctsms.vo.PSFVO;
import org.phoenixctms.ctsms.vo.UserOutVO;
import org.phoenixctms.ctsms.vocycle.InputFieldGraph;

/**
 * @see InputField
 */
public class InputFieldDaoImpl
extends InputFieldDaoBase
{

	private final static Object[] SELECT_FIELD_TYPES = new Object[] {
		InputFieldType.SELECT_MANY_H,
		InputFieldType.SELECT_MANY_V,
		InputFieldType.SELECT_ONE_RADIO_H,
		InputFieldType.SELECT_ONE_RADIO_V,
		InputFieldType.SELECT_ONE_DROPDOWN,
		InputFieldType.SKETCH
	};

	private static void applySortOrders(org.hibernate.Criteria inputFieldCriteria) {
		if (inputFieldCriteria != null) {
			inputFieldCriteria.addOrder(Order.asc("localized"));
			inputFieldCriteria.addOrder(Order.asc("nameL10nKey"));
		}
	}

	private  static void applyUsedByCriterions(org.hibernate.Criteria inputFieldCriteria, String fieldNameInfix, String inputFieldProperty) {
		if (inputFieldCriteria != null) {
			if (!CommonUtil.isEmptyString(inputFieldProperty)) {
				inputFieldCriteria.add(Restrictions.not(Restrictions.isEmpty(inputFieldProperty)));
			}
			//fieldCriteria.add(Restrictions.eq("localized", false));
			if (!CommonUtil.isEmptyString(fieldNameInfix)) {
				CategoryCriterion.apply(inputFieldCriteria, new CategoryCriterion(fieldNameInfix, "nameL10nKey", MatchMode.ANYWHERE));
			}

		}
	}

	private org.hibernate.Criteria createInputFieldCriteria() {
		org.hibernate.Criteria inputFieldCriteria = this.getSession().createCriteria(InputField.class);
		return inputFieldCriteria;
	}

	@Override
	protected Collection<InputField> handleFindByCriteria(CriteriaInstantVO criteria, PSFVO psf) throws Exception
	{
		Query query = QueryUtil.createSearchQuery(
				criteria,
				DBModule.INPUT_FIELD_DB,
				psf,
				this.getSessionFactory(),
				this.getCriterionTieDao(),
				this.getCriterionPropertyDao(),
				this.getCriterionRestrictionDao());
		return query.list();
	}

	@Override
	protected Collection<InputField> handleFindById(Long fieldId, PSFVO psf) throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		SubCriteriaMap criteriaMap = new SubCriteriaMap(InputField.class, inputFieldCriteria);
		CriteriaUtil.applyIdDepartmentCriterion(inputFieldCriteria, fieldId, null);
		CriteriaUtil.applyPSFVO(criteriaMap, psf);
		return inputFieldCriteria.list();
	}

	@Override
	protected Collection<InputField> handleFindByNameL10nKeyLocalized(
			String nameL10nKey, Boolean localized) throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		if (nameL10nKey != null) {
			inputFieldCriteria.add(Restrictions.eq("nameL10nKey", nameL10nKey));
		}
		if (localized != null) {
			inputFieldCriteria.add(Restrictions.eq("localized", localized.booleanValue()));
		}
		return inputFieldCriteria.list();
	}

	@Override
	protected Collection<String> handleFindCategories(InputFieldType fieldType,
			String categoryPrefix, Integer limit) throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		if (fieldType != null) {
			inputFieldCriteria.add(Restrictions.eq("fieldType", fieldType));
		}
		CategoryCriterion.apply(inputFieldCriteria, new CategoryCriterion(categoryPrefix, "category", MatchMode.START));
		inputFieldCriteria.addOrder(Order.asc("category"));
		inputFieldCriteria.setProjection(Projections.distinct(Projections.property("category")));
		CriteriaUtil.applyLimit(limit, Settings.getIntNullable(SettingCodes.INPUT_FIELD_CATEGORY_AUTOCOMPLETE_DEFAULT_RESULT_LIMIT, Bundle.SETTINGS,
				DefaultSettings.INPUT_FIELD_CATEGORY_AUTOCOMPLETE_DEFAULT_RESULT_LIMIT), inputFieldCriteria);
		return inputFieldCriteria.list();
	}

	@Override
	protected Collection<InputField> handleFindUsedByEcrfFieldsSorted() throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		applyUsedByCriterions(inputFieldCriteria, null, "ecrfFields");
		applySortOrders(inputFieldCriteria);
		return inputFieldCriteria.list();
	}

	@Override
	protected Collection<InputField> handleFindUsedByEcrfFieldsSorted(String fieldNameInfix, Integer limit) throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		applyUsedByCriterions(inputFieldCriteria, fieldNameInfix, "ecrfFields");
		applySortOrders(inputFieldCriteria);
		return inputFieldCriteria.list();
	}

	@Override
	protected Collection<InputField> handleFindUsedByInquiriesSorted() throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		applyUsedByCriterions(inputFieldCriteria, null, "inquiries");
		applySortOrders(inputFieldCriteria);
		return inputFieldCriteria.list();
	}

	@Override
	protected Collection<InputField> handleFindUsedByInquiriesSorted(String fieldNameInfix, Integer limit) throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		applyUsedByCriterions(inputFieldCriteria,fieldNameInfix,"inquiries");
		applySortOrders(inputFieldCriteria);
		return inputFieldCriteria.list();
	}

	@Override
	protected Collection<InputField> handleFindUsedByListEntryTagsSorted() throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		applyUsedByCriterions(inputFieldCriteria, null, "listEntryTags");
		applySortOrders(inputFieldCriteria);
		return inputFieldCriteria.list();
	}

	@Override
	protected Collection<InputField> handleFindUsedByListEntryTagsSorted(String fieldNameInfix, Integer limit) throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		applyUsedByCriterions(inputFieldCriteria, fieldNameInfix, "listEntryTags");
		applySortOrders(inputFieldCriteria);
		return inputFieldCriteria.list();
	}

	@Override
	protected long handleGetCountByCriteria(CriteriaInstantVO criteria, PSFVO psf) throws Exception {
		return QueryUtil.getSearchQueryResultCount(
				criteria,
				DBModule.INPUT_FIELD_DB,
				psf,
				this.getSessionFactory(),
				this.getCriterionTieDao(),
				this.getCriterionPropertyDao(),
				this.getCriterionRestrictionDao());
	}

	@Override
	protected long handleGetEcrfFieldMaxSelectionSetValueCount(Long trialId) throws Exception {
		org.hibernate.Criteria inputFieldCriteria = createInputFieldCriteria();
		inputFieldCriteria.add(
				Restrictions.in("fieldType", SELECT_FIELD_TYPES)); // no AUTOCOMPLETE!
		org.hibernate.Criteria ecrfFieldCriteria = inputFieldCriteria.createCriteria("ecrfFields", "ecrfFields0", CriteriaSpecification.INNER_JOIN);
		ecrfFieldCriteria.add(Restrictions.eq("trial.id", trialId.longValue()));

		org.hibernate.Criteria selectionSetValueCriteria = inputFieldCriteria.createCriteria("selectionSetValues","inputFieldSelectionSetValues", CriteriaSpecification.INNER_JOIN);

		inputFieldCriteria.setProjection(Projections.projectionList()
				.add(Projections.groupProperty("ecrfFields0.id"))
				.add(Projections.alias(Projections.count("inputFieldSelectionSetValues.id"),"selectionSetValuesCount")));

		inputFieldCriteria.addOrder(Order.desc("selectionSetValuesCount"));
		inputFieldCriteria.setMaxResults(1);
		long maxSelectionSetValues = 0l;
		try {
			maxSelectionSetValues = (Long) ((Object[]) inputFieldCriteria.list().iterator().next())[1];
		} catch (Exception e) {

		}
		return maxSelectionSetValues;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public InputField inputFieldImageVOToEntity(InputFieldImageVO inputFieldImageVO)
	{
		InputField entity = this.loadInputFieldFromInputFieldImageVO(inputFieldImageVO);
		this.inputFieldImageVOToEntity(inputFieldImageVO, entity, true);
		return entity;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void inputFieldImageVOToEntity(
			InputFieldImageVO source,
			InputField target,
			boolean copyIfNull)
	{
		super.inputFieldImageVOToEntity(source, target, copyIfNull);
		MimeTypeVO contentTypeVO = source.getContentType();
		UserOutVO modifiedUserVO = source.getModifiedUser();
		if (contentTypeVO != null) {
			target.setContentType(this.getMimeTypeDao().mimeTypeVOToEntity(contentTypeVO));
		} else if (copyIfNull) {
			target.setContentType(null);
		}
		if (modifiedUserVO != null) {
			target.setModifiedUser(this.getUserDao().userOutVOToEntity(modifiedUserVO));
		} else if (copyIfNull) {
			target.setModifiedUser(null);
		}
		if (copyIfNull || source.getDatas() != null)
		{
			target.setData(source.getDatas());
		}
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public InputField inputFieldInVOToEntity(InputFieldInVO inputFieldInVO)
	{
		InputField entity = this.loadInputFieldFromInputFieldInVO(inputFieldInVO);
		this.inputFieldInVOToEntity(inputFieldInVO, entity, true);
		return entity;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void inputFieldInVOToEntity(
			InputFieldInVO source,
			InputField target,
			boolean copyIfNull)
	{
		super.inputFieldInVOToEntity(source, target, copyIfNull);
		target.setLocalized(false);
		target.setTextPresetL10nKey(source.getTextPreset());
		target.setNameL10nKey(source.getName());
		target.setTitleL10nKey(source.getTitle());
		target.setCommentL10nKey(source.getComment());
		target.setValidationErrorMsgL10nKey(source.getValidationErrorMsg());
		if (source.getDatas() != null && source.getDatas().length > 0) {
			target.setData(source.getDatas());
			target.setFileSize((long) source.getDatas().length);
			target.setContentType(this.getMimeTypeDao().findByMimeTypeModule(source.getMimeType(), FileModule.INPUT_FIELD_IMAGE).iterator().next());
			if (source.getWidth() == null || source.getHeight() == null) {
				Dimension imageDimension = CoreUtil.getImageDimension(source.getDatas());
				if (imageDimension != null) {
					if (source.getWidth() == null) {
						target.setWidth((long) imageDimension.width);
					}
					if (source.getHeight() == null) {
						target.setHeight((long) imageDimension.height);
					}
				}
			}
		} else if (copyIfNull) {
			target.setData(null);
			target.setFileSize(0l);
			target.setContentType(null);
		}
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public InputField inputFieldOutVOToEntity(InputFieldOutVO inputFieldOutVO)
	{
		// TODO verify behavior of inputFieldOutVOToEntity
		InputField entity = this.loadInputFieldFromInputFieldOutVO(inputFieldOutVO);
		this.inputFieldOutVOToEntity(inputFieldOutVO, entity, true);
		return entity;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void inputFieldOutVOToEntity(
			InputFieldOutVO source,
			InputField target,
			boolean copyIfNull)
	{
		// TODO verify behavior of inputFieldOutVOToEntity
		super.inputFieldOutVOToEntity(source, target, copyIfNull);
		// No conversion for target.fieldType (can't convert source.getFieldType():org.phoenixctms.ctsms.vo.InputFieldTypeVO to InputFieldType
	}

	/**
	 * Retrieves the entity object that is associated with the specified value object
	 * from the object store. If no such entity object exists in the object store,
	 * a new, blank entity is created
	 */
	private InputField loadInputFieldFromInputFieldImageVO(InputFieldImageVO inputFieldImageVO)
	{
		InputField inputField = this.load(inputFieldImageVO.getId());
		if (inputField == null)
		{
			inputField = InputField.Factory.newInstance();
		}
		return inputField;
	}

	/**
	 * Retrieves the entity object that is associated with the specified value object
	 * from the object store. If no such entity object exists in the object store,
	 * a new, blank entity is created
	 */
	private InputField loadInputFieldFromInputFieldInVO(InputFieldInVO inputFieldInVO)
	{
		// TODO implement loadInputFieldFromInputFieldInVO
		// throw new UnsupportedOperationException("org.phoenixctms.ctsms.domain.loadInputFieldFromInputFieldInVO(InputFieldInVO) not yet implemented.");
		InputField inputField = null;
		Long id = inputFieldInVO.getId();
		if (id != null) {
			inputField = this.load(id);
		}
		if (inputField == null)
		{
			inputField = InputField.Factory.newInstance();
		}
		return inputField;
	}

	/**
	 * Retrieves the entity object that is associated with the specified value object
	 * from the object store. If no such entity object exists in the object store,
	 * a new, blank entity is created
	 */
	private InputField loadInputFieldFromInputFieldOutVO(InputFieldOutVO inputFieldOutVO)
	{
		// TODO implement loadInputFieldFromInputFieldOutVO
		throw new UnsupportedOperationException("org.phoenixctms.ctsms.domain.loadInputFieldFromInputFieldOutVO(InputFieldOutVO) not yet implemented.");
		/* A typical implementation looks like this: InputField inputField = this.load(inputFieldOutVO.getId()); if (inputField == null) { inputField =
		 * InputField.Factory.newInstance(); } return inputField; */
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public InputFieldImageVO toInputFieldImageVO(final InputField entity)
	{
		// TODO verify behavior of toInputFieldImageVO
		return super.toInputFieldImageVO(entity);
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void toInputFieldImageVO(
			InputField source,
			InputFieldImageVO target)
	{
		// TODO verify behavior of toInputFieldImageVO
		super.toInputFieldImageVO(source, target);
		// WARNING! No conversion for target.modifiedUser (can't convert source.getModifiedUser():org.phoenixctms.ctsms.domain.User to org.phoenixctms.ctsms.vo.UserOutVO
		// WARNING! No conversion for target.contentType (can't convert source.getContentType():org.phoenixctms.ctsms.domain.MimeType to org.phoenixctms.ctsms.vo.MimeTypeVO
		MimeType contentType = source.getContentType();
		User modifiedUser = source.getModifiedUser();
		target.setHasImage(source.getFileSize() != null && source.getFileSize() > 0l);
		if (contentType != null) {
			target.setContentType(this.getMimeTypeDao().toMimeTypeVO(contentType));
		}
		if (modifiedUser != null) {
			target.setModifiedUser(this.getUserDao().toUserOutVO(modifiedUser));
		}
		target.setDatas(source.getData());

	}

	/**
	 * @inheritDoc
	 */
	@Override
	public InputFieldInVO toInputFieldInVO(final InputField entity)
	{
		return super.toInputFieldInVO(entity);
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void toInputFieldInVO(
			InputField source,
			InputFieldInVO target)
	{
		super.toInputFieldInVO(source, target);
		MimeType contentType = source.getContentType();
		// if (source.isLocalized()) {
		// target.setTextPreset(L10nUtil.getInputFieldTextPreset(Locales.USER, source.getTextPresetL10nKey()));
		// target.setName(L10nUtil.getInputFieldName(Locales.USER, source.getNameL10nKey()));
		// target.setTitle(L10nUtil.getInputFieldTitle(Locales.USER, source.getTitleL10nKey()));
		// target.setComment(L10nUtil.getInputFieldComment(Locales.USER, source.getCommentL10nKey()));
		// target.setValidationErrorMsg(L10nUtil.getInputFieldValidationErrorMsg(Locales.USER, source.getValidationErrorMsgL10nKey()));
		// } else {
		target.setTextPreset(source.getTextPresetL10nKey());
		target.setName(source.getNameL10nKey());
		target.setTitle(source.getTitleL10nKey());
		target.setComment(source.getCommentL10nKey());
		target.setValidationErrorMsg(source.getValidationErrorMsgL10nKey());
		// }
		target.setDatas(source.getData());
		if (contentType != null) {
			target.setMimeType(contentType.getMimeType());
		}
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public InputFieldOutVO toInputFieldOutVO(final InputField entity)
	{
		// TODO verify behavior of toInputFieldOutVO
		return super.toInputFieldOutVO(entity);
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void toInputFieldOutVO(
			InputField source,
			InputFieldOutVO target)
	{
		(new InputFieldGraph(this, this.getInputFieldSelectionSetValueDao(), this.getUserDao())).toVOHelper(source, target, new HashMap<Class, HashMap<Long, Object>>());
	}

	@Override
	public void toInputFieldOutVO(
			InputField source,
			InputFieldOutVO target, HashMap<Class, HashMap<Long, Object>> voMap)
	{
		(new InputFieldGraph(this, this.getInputFieldSelectionSetValueDao(), this.getUserDao())).toVOHelper(source, target, voMap);
	}
}