// 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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.phoenixctms.ctsms.compare.FieldComparator;
import org.phoenixctms.ctsms.query.CategoryCriterion;
import org.phoenixctms.ctsms.query.CriteriaUtil;
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.IcdSystCategoryVO;
import org.phoenixctms.ctsms.vo.IcdSystModifierVO;

/**
 * @see IcdSystCategory
 */
public class IcdSystCategoryDaoImpl
extends IcdSystCategoryDaoBase
{

	@Override
	protected Collection<String> handleFindCategoryPreferredRubricLabels(
			String preferredRubricLabelInfix, Integer limit) throws Exception {
		org.hibernate.Criteria icdSystCategoryCriteria = this.getSession().createCriteria(IcdSystCategory.class);
		icdSystCategoryCriteria.setCacheable(true);
		CategoryCriterion.apply(icdSystCategoryCriteria, new CategoryCriterion(preferredRubricLabelInfix, "preferredRubricLabel", MatchMode.ANYWHERE));
		icdSystCategoryCriteria.add(Restrictions.not(Restrictions.or(Restrictions.eq("preferredRubricLabel", ""), Restrictions.isNull("preferredRubricLabel"))));
		// icdSystCategoryCriteria.add(Restrictions.eq("revision",
		// Settings.getString(SettingCodes.ICD_SYSTEMATICS_REVISION, Bundle.SETTINGS, DefaultSettings.ICD_SYSTEMATICS_REVISION)));
		icdSystCategoryCriteria.addOrder(Order.asc("preferredRubricLabel"));
		icdSystCategoryCriteria.setProjection(Projections.distinct(Projections.property("preferredRubricLabel")));
		CriteriaUtil.applyLimit(limit, Settings.getIntNullable(SettingCodes.ICD_SYST_CATEGORY_PREFERRED_RUBRIC_LABEL_AUTOCOMPLETE_DEFAULT_RESULT_LIMIT, Bundle.SETTINGS,
				DefaultSettings.ICD_SYST_CATEGORY_PREFERRED_RUBRIC_LABEL_AUTOCOMPLETE_DEFAULT_RESULT_LIMIT), icdSystCategoryCriteria);
		return icdSystCategoryCriteria.list();
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public IcdSystCategory icdSystCategoryVOToEntity(IcdSystCategoryVO icdSystCategoryVO)
	{
		IcdSystCategory entity = this.loadIcdSystCategoryFromIcdSystCategoryVO(icdSystCategoryVO);
		this.icdSystCategoryVOToEntity(icdSystCategoryVO, entity, true);
		return entity;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void icdSystCategoryVOToEntity(
			IcdSystCategoryVO source,
			IcdSystCategory target,
			boolean copyIfNull)
	{
		super.icdSystCategoryVOToEntity(source, target, copyIfNull);
		Collection modifiers = source.getModifiers();
		if (modifiers.size() > 0) {
			this.getIcdSystModifierDao().icdSystModifierVOToEntityCollection(modifiers);
			target.setModifiers(modifiers);
		} else if (copyIfNull) {
			target.getModifiers().clear();
		}
	}

	/**
	 * 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 IcdSystCategory loadIcdSystCategoryFromIcdSystCategoryVO(IcdSystCategoryVO icdSystCategoryVO)
	{
		// TODO implement loadIcdSystCategoryFromIcdSystCategoryVO
		// throw new UnsupportedOperationException("org.phoenixctms.ctsms.domain.loadIcdSystCategoryFromIcdSystCategoryVO(IcdSystCategoryVO) not yet implemented.");
		Long id = icdSystCategoryVO.getId();
		IcdSystCategory icdSystCategory = null;
		if (id != null) {
			icdSystCategory = this.load(id);
		}
		if (icdSystCategory == null)
		{
			icdSystCategory = IcdSystCategory.Factory.newInstance();
		}
		return icdSystCategory;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public IcdSystCategoryVO toIcdSystCategoryVO(final IcdSystCategory entity)
	{
		return super.toIcdSystCategoryVO(entity);
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void toIcdSystCategoryVO(
			IcdSystCategory source,
			IcdSystCategoryVO target)
	{
		super.toIcdSystCategoryVO(source, target);
		target.setModifiers(toIcdSystModifierVOCollection(source.getModifiers()));
	}

	private ArrayList<IcdSystModifierVO> toIcdSystModifierVOCollection(Collection<IcdSystModifier> modifiers) {
		// related to http://forum.andromda.org/viewtopic.php?t=4288
		IcdSystModifierDao icdSystModifierDao = this.getIcdSystModifierDao();
		ArrayList<IcdSystModifierVO> result = new ArrayList<IcdSystModifierVO>(modifiers.size());
		Iterator<IcdSystModifier> it = modifiers.iterator();
		while (it.hasNext()) {
			result.add(icdSystModifierDao.toIcdSystModifierVO(it.next()));
		}
		Collections.sort(result, new FieldComparator(false, "getLevel"));
		return result;
	}
}