// 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.sql.Timestamp;
import java.util.Collection;

import org.hibernate.Criteria;
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.query.CategoryCriterion;
import org.phoenixctms.ctsms.query.CategoryCriterion.EmptyPrefixModes;
import org.phoenixctms.ctsms.query.CriteriaUtil;
import org.phoenixctms.ctsms.query.SubCriteriaMap;
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.util.date.ShiftDuration;
import org.phoenixctms.ctsms.vo.DutyRosterTurnInVO;
import org.phoenixctms.ctsms.vo.DutyRosterTurnOutVO;
import org.phoenixctms.ctsms.vo.PSFVO;
import org.phoenixctms.ctsms.vo.StaffOutVO;
import org.phoenixctms.ctsms.vo.TrialOutVO;
import org.phoenixctms.ctsms.vo.UserOutVO;
import org.phoenixctms.ctsms.vo.VisitScheduleItemOutVO;

/**
 * @see DutyRosterTurn
 */
public class DutyRosterTurnDaoImpl
		extends DutyRosterTurnDaoBase {

	private org.hibernate.Criteria createDutyRosterTurnCriteria(String alias) {
		org.hibernate.Criteria dutyRosterCriteria;
		if (alias != null && alias.length() > 0) {
			dutyRosterCriteria = this.getSession().createCriteria(DutyRosterTurn.class, alias);
		} else {
			dutyRosterCriteria = this.getSession().createCriteria(DutyRosterTurn.class);
		}
		return dutyRosterCriteria;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public DutyRosterTurn dutyRosterTurnInVOToEntity(DutyRosterTurnInVO dutyRosterTurnInVO) {
		DutyRosterTurn entity = this.loadDutyRosterTurnFromDutyRosterTurnInVO(dutyRosterTurnInVO);
		this.dutyRosterTurnInVOToEntity(dutyRosterTurnInVO, entity, true);
		return entity;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void dutyRosterTurnInVOToEntity(
			DutyRosterTurnInVO source,
			DutyRosterTurn target,
			boolean copyIfNull) {
		super.dutyRosterTurnInVOToEntity(source, target, copyIfNull);
		Long staffId = source.getStaffId();
		Long trialId = source.getTrialId();
		Long visitScheduleItemId = source.getVisitScheduleItemId();
		if (staffId != null) {
			Staff staff = this.getStaffDao().load(staffId);
			target.setStaff(staff);
			staff.addDutyRosterTurns(target);
		} else if (copyIfNull) {
			Staff staff = target.getStaff();
			target.setStaff(null);
			if (staff != null) {
				staff.removeDutyRosterTurns(target);
			}
		}
		if (trialId != null) {
			Trial trial = this.getTrialDao().load(trialId);
			target.setTrial(trial);
			trial.addDutyRosterTurns(target);
		} else if (copyIfNull) {
			Trial trial = target.getTrial();
			target.setTrial(null);
			if (trial != null) {
				trial.removeDutyRosterTurns(target);
			}
		}
		if (visitScheduleItemId != null) {
			VisitScheduleItem visitScheduleItem = this.getVisitScheduleItemDao().load(visitScheduleItemId);
			target.setVisitScheduleItem(visitScheduleItem);
			visitScheduleItem.addDutyRosterTurns(target);
		} else if (copyIfNull) {
			VisitScheduleItem visitScheduleItem = target.getVisitScheduleItem();
			target.setVisitScheduleItem(null);
			if (visitScheduleItem != null) {
				visitScheduleItem.removeDutyRosterTurns(target);
			}
		}
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public DutyRosterTurn dutyRosterTurnOutVOToEntity(DutyRosterTurnOutVO dutyRosterTurnOutVO) {
		DutyRosterTurn entity = this.loadDutyRosterTurnFromDutyRosterTurnOutVO(dutyRosterTurnOutVO);
		this.dutyRosterTurnOutVOToEntity(dutyRosterTurnOutVO, entity, true);
		return entity;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void dutyRosterTurnOutVOToEntity(
			DutyRosterTurnOutVO source,
			DutyRosterTurn target,
			boolean copyIfNull) {
		super.dutyRosterTurnOutVOToEntity(source, target, copyIfNull);
		StaffOutVO staffVO = source.getStaff();
		TrialOutVO trialVO = source.getTrial();
		VisitScheduleItemOutVO visitScheduleItemVO = source.getVisitScheduleItem();
		UserOutVO modifiedUserVO = source.getModifiedUser();
		if (staffVO != null) {
			Staff staff = this.getStaffDao().staffOutVOToEntity(staffVO);
			target.setStaff(staff);
			staff.addDutyRosterTurns(target);
		} else if (copyIfNull) {
			Staff staff = target.getStaff();
			target.setStaff(null);
			if (staff != null) {
				staff.removeDutyRosterTurns(target);
			}
		}
		if (trialVO != null) {
			Trial trial = this.getTrialDao().trialOutVOToEntity(trialVO);
			target.setTrial(trial);
			trial.addDutyRosterTurns(target);
		} else if (copyIfNull) {
			Trial trial = target.getTrial();
			target.setTrial(null);
			if (trial != null) {
				trial.removeDutyRosterTurns(target);
			}
		}
		if (visitScheduleItemVO != null) {
			VisitScheduleItem visitScheduleItem = this.getVisitScheduleItemDao().visitScheduleItemOutVOToEntity(visitScheduleItemVO);
			target.setVisitScheduleItem(visitScheduleItem);
			visitScheduleItem.addDutyRosterTurns(target);
		} else if (copyIfNull) {
			VisitScheduleItem visitScheduleItem = target.getVisitScheduleItem();
			target.setVisitScheduleItem(null);
			if (visitScheduleItem != null) {
				visitScheduleItem.removeDutyRosterTurns(target);
			}
		}
		if (modifiedUserVO != null) {
			target.setModifiedUser(this.getUserDao().userOutVOToEntity(modifiedUserVO));
		} else if (copyIfNull) {
			target.setModifiedUser(null);
		}
	}

	/**
	 * @inheritDoc
	 */
	@Override
	protected Collection<DutyRosterTurn> handleFindByDepartmentCategoryCalendarInterval(Long staffDepartmentId, Long staffCategoryId, Boolean allocatable, String calendar,
			Timestamp from, Timestamp to) {
		Criteria dutyRosterCriteria = createDutyRosterTurnCriteria("dutyRosterTurn");
		CriteriaUtil.applyClosedIntervalCriterion(dutyRosterCriteria, from, to, null);
		Criteria staffCriteria = null;
		if (staffDepartmentId != null) {
			staffCriteria = dutyRosterCriteria.createCriteria("staff", CriteriaSpecification.LEFT_JOIN);
		} else if (staffCategoryId != null || allocatable != null) {
			staffCriteria = dutyRosterCriteria.createCriteria("staff", CriteriaSpecification.INNER_JOIN);
		}
		if (staffDepartmentId != null || staffCategoryId != null || allocatable != null) {
			if (staffDepartmentId != null) {
				staffCriteria.add(Restrictions.or(Restrictions.isNull("dutyRosterTurn.staff"), Restrictions.eq("department.id", staffDepartmentId.longValue())));
			}
			if (staffCategoryId != null) {
				staffCriteria.add(Restrictions.eq("category.id", staffCategoryId.longValue()));
			}
			if (allocatable != null) {
				staffCriteria.add(Restrictions.eq("allocatable", allocatable.booleanValue()));
			}
		}
		CategoryCriterion.apply(dutyRosterCriteria, new CategoryCriterion(calendar, "calendar", MatchMode.EXACT, EmptyPrefixModes.ALL_ROWS));
		return dutyRosterCriteria.list();
	}

	@Override
	protected Collection<DutyRosterTurn> handleFindByDepartmentStatusStaffTrialCalendarInterval(
			Long trialDepartmentId, Long statusId, Long staffId, boolean unassigned, Long trialId, String calendar, Timestamp from, Timestamp to)
			throws Exception {
		Criteria dutyRosterCriteria = createDutyRosterTurnCriteria("dutyRosterTurn");
		CriteriaUtil.applyClosedIntervalCriterion(dutyRosterCriteria, from, to, null);
		Criteria trialCriteria = null;
		if (trialDepartmentId != null) {
			trialCriteria = dutyRosterCriteria.createCriteria("trial", CriteriaSpecification.LEFT_JOIN);
		} else if (statusId != null || trialId != null) {
			trialCriteria = dutyRosterCriteria.createCriteria("trial", CriteriaSpecification.INNER_JOIN);
		}
		if (trialDepartmentId != null || statusId != null || trialId != null) {
			if (trialDepartmentId != null) {
				trialCriteria.add(Restrictions.or(Restrictions.isNull("dutyRosterTurn.trial"), Restrictions.eq("department.id", trialDepartmentId.longValue())));
			}
			if (statusId != null) {
				trialCriteria.add(Restrictions.eq("status.id", statusId.longValue()));
			}
			if (trialId != null) {
				trialCriteria.add(Restrictions.idEq(trialId.longValue()));
			}
		}
		if (staffId != null) {
			if (unassigned) {
				dutyRosterCriteria.add(Restrictions.or(Restrictions.eq("staff.id", staffId.longValue()), Restrictions.isNull("staff")));
			} else {
				dutyRosterCriteria.add(Restrictions.eq("staff.id", staffId.longValue()));
			}
		}
		CategoryCriterion.apply(dutyRosterCriteria, new CategoryCriterion(calendar, "calendar", MatchMode.EXACT, EmptyPrefixModes.ALL_ROWS));
		return dutyRosterCriteria.list();
	}

	/**
	 * @throws Exception
	 * @inheritDoc
	 */
	@Override
	protected Collection<DutyRosterTurn> handleFindByStaff(Long staffId, PSFVO psf) throws Exception {
		Criteria dutyRosterCriteria = createDutyRosterTurnCriteria(null);
		SubCriteriaMap criteriaMap = new SubCriteriaMap(DutyRosterTurn.class, dutyRosterCriteria);
		if (staffId != null) {
			dutyRosterCriteria.add(Restrictions.eq("staff.id", staffId.longValue()));
		}
		CriteriaUtil.applyPSFVO(criteriaMap, psf);
		return dutyRosterCriteria.list();
	}

	/**
	 * @inheritDoc
	 */
	@Override
	protected Collection<DutyRosterTurn> handleFindByStaffTrialCalendarInterval(Long staffId, Long trialId, String calendar, Timestamp from, Timestamp to) {
		Criteria dutyRosterCriteria = createDutyRosterTurnCriteria(null);
		CriteriaUtil.applyClosedIntervalCriterion(dutyRosterCriteria, from, to, null);
		if (staffId != null) {
			dutyRosterCriteria.add(Restrictions.eq("staff.id", staffId.longValue()));
		}
		if (trialId != null) {
			dutyRosterCriteria.add(Restrictions.eq("trial.id", trialId.longValue()));
		}
		CategoryCriterion.apply(dutyRosterCriteria, new CategoryCriterion(calendar, "calendar", MatchMode.EXACT, EmptyPrefixModes.ALL_ROWS));
		return dutyRosterCriteria.list();
	}

	@Override
	protected Collection<DutyRosterTurn> handleFindByTrial(Long trialId,
			PSFVO psf) throws Exception {
		Criteria dutyRosterCriteria = createDutyRosterTurnCriteria(null);
		SubCriteriaMap criteriaMap = new SubCriteriaMap(DutyRosterTurn.class, dutyRosterCriteria);
		if (trialId != null) {
			dutyRosterCriteria.add(Restrictions.eq("trial.id", trialId.longValue()));
		}
		CriteriaUtil.applyPSFVO(criteriaMap, psf);
		return dutyRosterCriteria.list();
	}

	@Override
	protected Collection<String> handleFindCalendars(Long trialDepartmentId,
			Long staffId, Long trialId, String calendarPrefix, Integer limit)
			throws Exception {
		Criteria dutyRosterCriteria = createDutyRosterTurnCriteria("dutyRosterTurn");
		Criteria trialCriteria = null;
		if (trialDepartmentId != null) {
			trialCriteria = dutyRosterCriteria.createCriteria("trial", CriteriaSpecification.LEFT_JOIN);
		} else if (trialId != null) {
			trialCriteria = dutyRosterCriteria.createCriteria("trial", CriteriaSpecification.INNER_JOIN);
		}
		if (trialDepartmentId != null || trialId != null) {
			if (trialDepartmentId != null) {
				trialCriteria.add(Restrictions.or(Restrictions.isNull("dutyRosterTurn.trial"), Restrictions.eq("department.id", trialDepartmentId.longValue())));
			}
			if (trialId != null) {
				trialCriteria.add(Restrictions.idEq(trialId.longValue()));
			}
		}
		if (staffId != null) {
			dutyRosterCriteria.add(Restrictions.eq("staff.id", staffId.longValue()));
		}
		CategoryCriterion.apply(dutyRosterCriteria, new CategoryCriterion(calendarPrefix, "calendar", MatchMode.START));
		dutyRosterCriteria.addOrder(Order.asc("calendar"));
		dutyRosterCriteria.setProjection(Projections.distinct(Projections.property("calendar")));
		CriteriaUtil.applyLimit(limit, Settings.getIntNullable(SettingCodes.DUTY_ROSTER_TURN_CALENDAR_AUTOCOMPLETE_DEFAULT_RESULT_LIMIT, Bundle.SETTINGS,
				DefaultSettings.DUTY_ROSTER_TURN_CALENDAR_AUTOCOMPLETE_DEFAULT_RESULT_LIMIT), dutyRosterCriteria);
		return dutyRosterCriteria.list();
	}

	@Override
	protected Collection<String> handleFindTitles(Long trialDepartmentId,
			Long staffId, Long trialId, String titleInfix, Integer limit)
			throws Exception {
		Criteria dutyRosterCriteria = createDutyRosterTurnCriteria("dutyRosterTurn");
		Criteria trialCriteria = null;
		if (trialDepartmentId != null) {
			trialCriteria = dutyRosterCriteria.createCriteria("trial", CriteriaSpecification.LEFT_JOIN);
		} else if (trialId != null) {
			trialCriteria = dutyRosterCriteria.createCriteria("trial", CriteriaSpecification.INNER_JOIN);
		}
		if (trialDepartmentId != null || trialId != null) {
			if (trialDepartmentId != null) {
				trialCriteria.add(Restrictions.or(Restrictions.isNull("dutyRosterTurn.trial"), Restrictions.eq("department.id", trialDepartmentId.longValue())));
			}
			if (trialId != null) {
				trialCriteria.add(Restrictions.idEq(trialId.longValue()));
			}
		}
		if (staffId != null) {
			dutyRosterCriteria.add(Restrictions.eq("staff.id", staffId.longValue()));
		}
		CategoryCriterion.apply(dutyRosterCriteria, new CategoryCriterion(titleInfix, "title", MatchMode.ANYWHERE));
		dutyRosterCriteria.addOrder(Order.asc("title"));
		dutyRosterCriteria.setProjection(Projections.distinct(Projections.property("title")));
		CriteriaUtil.applyLimit(limit, Settings.getIntNullable(SettingCodes.DUTY_ROSTER_TURN_TITLE_AUTOCOMPLETE_DEFAULT_RESULT_LIMIT, Bundle.SETTINGS,
				DefaultSettings.DUTY_ROSTER_TURN_TITLE_AUTOCOMPLETE_DEFAULT_RESULT_LIMIT), dutyRosterCriteria);
		return dutyRosterCriteria.list();
	}

	@Override
	protected long handleGetCount(Long staffId, Long trialId) throws Exception {
		Criteria dutyRosterCriteria = createDutyRosterTurnCriteria(null);
		if (staffId != null) {
			dutyRosterCriteria.add(Restrictions.eq("staff.id", staffId.longValue()));
		}
		if (trialId != null) {
			dutyRosterCriteria.add(Restrictions.eq("trial.id", trialId.longValue()));
		}
		return (Long) dutyRosterCriteria.setProjection(Projections.rowCount()).uniqueResult();
	}

	/**
	 * 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 DutyRosterTurn loadDutyRosterTurnFromDutyRosterTurnInVO(DutyRosterTurnInVO dutyRosterTurnInVO) {
		DutyRosterTurn dutyRosterTurn = null;
		Long id = dutyRosterTurnInVO.getId();
		if (id != null) {
			dutyRosterTurn = this.load(id);
		}
		if (dutyRosterTurn == null) {
			dutyRosterTurn = DutyRosterTurn.Factory.newInstance();
		}
		return dutyRosterTurn;
	}

	/**
	 * 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 DutyRosterTurn loadDutyRosterTurnFromDutyRosterTurnOutVO(DutyRosterTurnOutVO dutyRosterTurnOutVO) {
		DutyRosterTurn dutyRosterTurn = this.load(dutyRosterTurnOutVO.getId());
		if (dutyRosterTurn == null) {
			dutyRosterTurn = DutyRosterTurn.Factory.newInstance();
		}
		return dutyRosterTurn;
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public DutyRosterTurnInVO toDutyRosterTurnInVO(final DutyRosterTurn entity) {
		return super.toDutyRosterTurnInVO(entity);
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void toDutyRosterTurnInVO(
			DutyRosterTurn source,
			DutyRosterTurnInVO target) {
		super.toDutyRosterTurnInVO(source, target);
		Staff staff = source.getStaff();
		Trial trial = source.getTrial();
		VisitScheduleItem visitScheduleItem = source.getVisitScheduleItem();
		if (staff != null) {
			target.setStaffId(staff.getId());
		}
		if (trial != null) {
			target.setTrialId(trial.getId());
		}
		if (visitScheduleItem != null) {
			target.setVisitScheduleItemId(visitScheduleItem.getId());
		}
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public DutyRosterTurnOutVO toDutyRosterTurnOutVO(final DutyRosterTurn entity) {
		return super.toDutyRosterTurnOutVO(entity);
	}

	/**
	 * @inheritDoc
	 */
	@Override
	public void toDutyRosterTurnOutVO(
			DutyRosterTurn source,
			DutyRosterTurnOutVO target) {
		super.toDutyRosterTurnOutVO(source, target);
		Staff staff = source.getStaff();
		Trial trial = source.getTrial();
		VisitScheduleItem visitScheduleItem = source.getVisitScheduleItem();
		User modifiedUser = source.getModifiedUser();
		if (staff != null) {
			target.setStaff(this.getStaffDao().toStaffOutVO(staff));
		}
		if (trial != null) {
			target.setTrial(this.getTrialDao().toTrialOutVO(trial));
		}
		if (visitScheduleItem != null) {
			target.setVisitScheduleItem(this.getVisitScheduleItemDao().toVisitScheduleItemOutVO(visitScheduleItem));
		}
		if (modifiedUser != null) {
			target.setModifiedUser(this.getUserDao().toUserOutVO(modifiedUser));
		}
		ShiftDuration shiftDuration = new ShiftDuration();
		try {
			shiftDuration.add(target.getStart(), target.getStop(), this.getHolidayDao());
			shiftDuration.updateDutyRosterTurn(target);
		} catch (Exception e) {
		}
	}
}