/FileExtraction/Java_unseen/IMS-MAXIMS_openMAXIMS/Source Library/openmaxims_workspace/ValueObjects/src/ims/pci/vo/ClientImmunisationScheduleVo.java
//#############################################################################
//#                                                                           #
//#  Copyright (C) <2015>  <IMS MAXIMS>                                       #
//#                                                                           #
//#  This program is free software: you can redistribute it and/or modify     #
//#  it under the terms of the GNU Affero General Public License as           #
//#  published by the Free Software Foundation, either version 3 of the       #
//#  License, or (at your option) any later version.                          # 
//#                                                                           #
//#  This program 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 Affero General Public License for more details.                      #
//#                                                                           #
//#  You should have received a copy of the GNU Affero General Public License #
//#  along with this program.  If not, see <http://www.gnu.org/licenses/>.    #
//#                                                                           #
//#  IMS MAXIMS provides absolutely NO GUARANTEE OF THE CLINICAL SAFTEY of    #
//#  this program.  Users of this software do so entirely at their own risk.  #
//#  IMS MAXIMS only ensures the Clinical Safety of unaltered run-time        #
//#  software that it builds, deploys and maintains.                          #
//#                                                                           #
//#############################################################################
//#EOH
// This code was generated by Barbara Worwood using IMS Development Environment (version 1.80 build 5589.25814)
// Copyright (C) 1995-2015 IMS MAXIMS. All rights reserved.
// WARNING: DO NOT MODIFY the content of this file

package ims.pci.vo;

/**
 * Linked to PCI.ClientImmunisationSchedule business object (ID: 1091100006).
 */
public class ClientImmunisationScheduleVo extends ims.pci.vo.ClientImmunisationScheduleRefVo implements ims.vo.ImsCloneable, Comparable
{
	private static final long serialVersionUID = 1L;

	public ClientImmunisationScheduleVo()
	{
	}
	public ClientImmunisationScheduleVo(Integer id, int version)
	{
		super(id, version);
	}
	public ClientImmunisationScheduleVo(ims.pci.vo.beans.ClientImmunisationScheduleVoBean bean)
	{
		this.id = bean.getId();
		this.version = bean.getVersion();
		this.client = bean.getClient() == null ? null : bean.getClient().buildVo();
		this.scheduleprofiles = ims.pci.vo.ClientPCIScheduleProfileVoCollection.buildFromBeanCollection(bean.getScheduleProfiles());
		this.stages = ims.pci.vo.ClientScheduleStageVoCollection.buildFromBeanCollection(bean.getStages());
		this.vaccinesummarystatus = ims.pci.vo.ClientVaccineSummaryVoCollection.buildFromBeanCollection(bean.getVaccineSummaryStatus());
	}
	public void populate(ims.vo.ValueObjectBeanMap map, ims.pci.vo.beans.ClientImmunisationScheduleVoBean bean)
	{
		this.id = bean.getId();
		this.version = bean.getVersion();
		this.client = bean.getClient() == null ? null : bean.getClient().buildVo(map);
		this.scheduleprofiles = ims.pci.vo.ClientPCIScheduleProfileVoCollection.buildFromBeanCollection(bean.getScheduleProfiles());
		this.stages = ims.pci.vo.ClientScheduleStageVoCollection.buildFromBeanCollection(bean.getStages());
		this.vaccinesummarystatus = ims.pci.vo.ClientVaccineSummaryVoCollection.buildFromBeanCollection(bean.getVaccineSummaryStatus());
	}
	public ims.vo.ValueObjectBean getBean()
	{
		return this.getBean(new ims.vo.ValueObjectBeanMap());
	}
	public ims.vo.ValueObjectBean getBean(ims.vo.ValueObjectBeanMap map)
	{
		ims.pci.vo.beans.ClientImmunisationScheduleVoBean bean = null;
		if(map != null)
			bean = (ims.pci.vo.beans.ClientImmunisationScheduleVoBean)map.getValueObjectBean(this);
		if (bean == null)
		{
			bean = new ims.pci.vo.beans.ClientImmunisationScheduleVoBean();
			map.addValueObjectBean(this, bean);
			bean.populate(map, this);
		}
		return bean;
	}
	public Object getFieldValueByFieldName(String fieldName)
	{
		if(fieldName == null)
			throw new ims.framework.exceptions.CodingRuntimeException("Invalid field name");
		fieldName = fieldName.toUpperCase();
		if(fieldName.equals("CLIENT"))
			return getClient();
		if(fieldName.equals("SCHEDULEPROFILES"))
			return getScheduleProfiles();
		if(fieldName.equals("STAGES"))
			return getStages();
		if(fieldName.equals("VACCINESUMMARYSTATUS"))
			return getVaccineSummaryStatus();
		return super.getFieldValueByFieldName(fieldName);
	}
	public boolean getClientIsNotNull()
	{
		return this.client != null;
	}
	public ims.pci.vo.ClientLiteVo getClient()
	{
		return this.client;
	}
	public void setClient(ims.pci.vo.ClientLiteVo value)
	{
		this.isValidated = false;
		this.client = value;
	}
	public boolean getScheduleProfilesIsNotNull()
	{
		return this.scheduleprofiles != null;
	}
	public ims.pci.vo.ClientPCIScheduleProfileVoCollection getScheduleProfiles()
	{
		return this.scheduleprofiles;
	}
	public void setScheduleProfiles(ims.pci.vo.ClientPCIScheduleProfileVoCollection value)
	{
		this.isValidated = false;
		this.scheduleprofiles = value;
	}
	public boolean getStagesIsNotNull()
	{
		return this.stages != null;
	}
	public ims.pci.vo.ClientScheduleStageVoCollection getStages()
	{
		return this.stages;
	}
	public void setStages(ims.pci.vo.ClientScheduleStageVoCollection value)
	{
		this.isValidated = false;
		this.stages = value;
	}
	public boolean getVaccineSummaryStatusIsNotNull()
	{
		return this.vaccinesummarystatus != null;
	}
	public ims.pci.vo.ClientVaccineSummaryVoCollection getVaccineSummaryStatus()
	{
		return this.vaccinesummarystatus;
	}
	public void setVaccineSummaryStatus(ims.pci.vo.ClientVaccineSummaryVoCollection value)
	{
		this.isValidated = false;
		this.vaccinesummarystatus = value;
	}
	/**
	* getVaccineDetails(ClientScheduleStageVo stage, VaccineLiteVo vaccine)
	*/
	public ims.pci.vo.ClientScheduleStageVaccineVo getVaccineDetails(ims.pci.vo.ClientScheduleStageVo stage, ims.core.vo.VaccineLiteVo vaccine)
	{
		if (stage == null || vaccine == null)
			return null;
	
		if (this.stages == null)
			return null;
	
		int stageIndex = this.stages.indexOf(stage);
	
		if (stageIndex == -1 || this.stages.get(stageIndex).getVaccines() == null)
			return null;
	
		for (int i = 0; i < this.stages.get(stageIndex).getVaccines().size(); i++)
		{
			if (this.stages.get(stageIndex).getVaccines().get(i) == null)
				continue;
	
			if (vaccine.equals(this.stages.get(stageIndex).getVaccines().get(i).getVaccine()))
				return this.stages.get(stageIndex).getVaccines().get(i);
		}
	
			return null;
	}
	
	/**
	* addStageConfiguration(StageConfigurationVo stageConfiguration)
	*/
	private ClientImmunisationScheduleVo addStageConfiguration(StageConfigurationVo stageConfiguration)
	{
		if (stageConfiguration == null || stageConfiguration.stage == null || stageConfiguration.stagevaccines == null || stageConfiguration.ageinmonths == null)
			return this;
	
		if (this.stages == null)
		{
			this.stages = new ClientScheduleStageVoCollection();
		}
	
		for (int i = 0; i < this.stages.size(); i++)
		{
			if (this.stages.get(i) == null || this.stages.get(i).stage == null)
				continue;
	
			if (stageConfiguration.stage.equals(this.stages.get(i).stage.stage))
			{
				StageVaccineVoCollection stagevaccines = stageConfiguration.stagevaccines;
	
				if (Boolean.TRUE.equals(this.stages.get(i).isdeleted))
					this.stages.get(i).isdeleted = false;
	
				for (int k = 0; k < stagevaccines.size(); k++)
				{
					if (stagevaccines.get(k) == null || stagevaccines.get(k).getVaccine() == null)
						continue;
	
					boolean exists = false;
	
					for (int m = 0; m < this.stages.get(i).vaccines.size(); m++)
					{
						ClientScheduleStageVaccineVo vaccineVo = this.stages.get(i).vaccines.get(m);
						if (vaccineVo == null)
							continue;
	
						if (stagevaccines.get(k).getVaccine().equals(vaccineVo.getVaccine()))
						{
							exists = true;
	
							// Clear the vaccine (no sure if we need to do it - could cause innapropriate actions)
	//						clearVaccine(vaccineVo);
	
							vaccineVo.isdeleted = Boolean.FALSE;
	
							if (Boolean.TRUE.equals(vaccineVo.isextracted))
								vaccineVo.isextracted = Boolean.FALSE;
	
							// Update the status
							VaccineStatusLiteVo newStatus = new VaccineStatusLiteVo();
							newStatus.status = ims.pci.vo.lookups.VaccineStatus.SCHEDULED;
							newStatus.terminatedby = null;
							newStatus.terminationreason = null;
	
							ClientVaccineSummaryVo vaccineSummary = this.getVaccineSummary(stagevaccines.get(k).getVaccine());
							if (vaccineSummary == null)
							{
								vaccineSummary = new ClientVaccineSummaryVo();
								vaccineSummary.vaccine = stagevaccines.get(k).getVaccine();
								vaccineSummary.setNewStatusTo(newStatus);
	
								if (this.vaccinesummarystatus == null)
									this.vaccinesummarystatus = new ClientVaccineSummaryVoCollection();
	
								this.vaccinesummarystatus.add(vaccineSummary);
							}
							else
							{
								vaccineSummary.setNewStatusTo(newStatus);
							}
						}
					}
	
					if (exists)
						continue;
	
					// Build a new ClientScheduleStageVaccineVo
					ClientScheduleStageVaccineVo vaccine = new ClientScheduleStageVaccineVo();
					vaccine.stagevaccine = stagevaccines.get(k);
					vaccine.scheduleddate = calculateScheduleDate(this.client == null? new ims.framework.utils.PartialDate() : this.client.dob, stageConfiguration.ageinmonths);
					vaccine.batchnumber = null;
					vaccine.deliveredbygp = null;
					vaccine.deliveredbymedic = null;
					vaccine.delivereddate = null;
					vaccine.expirydate = null;
					vaccine.paymentgp = null;
					vaccine.paymenttype = null;
					vaccine.terminatedby = null;
					vaccine.terminateddate = null;
					vaccine.terminationreason = null;
					vaccine.vaccinemanufacturer = null;
	
					if (Boolean.TRUE.equals(vaccine.isextracted))
						vaccine.isextracted = Boolean.FALSE;
	
					// Add vaccine to ClientStage
					if (this.stages.get(i).vaccines == null)
						this.stages.get(i).vaccines = new ClientScheduleStageVaccineVoCollection();
	
					this.stages.get(i).vaccines.add(vaccine);
					this.stages.get(i).vaccines.sort();
	
					// Update the status
					setVaccineStatusOnAdd(vaccine.getVaccine());
				}
	
				return this;
			}
		}
	
		ClientScheduleStageVo stage = new ClientScheduleStageVo();
		stage.stage = stageConfiguration;
	
		if (stage.vaccines == null)
			stage.vaccines = new ClientScheduleStageVaccineVoCollection();
	
		for (int i = 0; i < stageConfiguration.stagevaccines.size(); i++)
		{
			if (stageConfiguration.stagevaccines.get(i) == null)
				continue;
	
			// Build a new ClientScheduleStageVaccineVo
			ClientScheduleStageVaccineVo vaccine = new ClientScheduleStageVaccineVo();
			vaccine.stagevaccine = stageConfiguration.stagevaccines.get(i);
			vaccine.scheduleddate = calculateScheduleDate(this.client == null? new ims.framework.utils.PartialDate() : this.client.dob, stageConfiguration.ageinmonths);
			vaccine.batchnumber = null;
			vaccine.deliveredbygp = null;
			vaccine.deliveredbymedic = null;
			vaccine.delivereddate = null;
			vaccine.expirydate = null;
			vaccine.paymentgp = null;
			vaccine.paymenttype = null;
			vaccine.terminatedby = null;
			vaccine.terminateddate = null;
			vaccine.terminationreason = null;
			vaccine.vaccinemanufacturer = null;
	
			vaccine.isextracted = Boolean.FALSE;
	
			// Add vaccines to ClientStage
			stage.vaccines.add(vaccine);
			stage.vaccines.sort();
	
			// Update the status
			setVaccineStatusOnAdd(vaccine.getVaccine());
		}
	
		this.stages.add(stage);
		this.stages.sort();
	
		return this;
	}
	
	/**
	* calculateScheduleDate(PartialDate date, Integer ageInMonths)
	*/
		    private ims.framework.utils.Date calculateScheduleDate(ims.framework.utils.PartialDate date, Integer ageInMonths)
		    {
			if (ageInMonths == null)
			    ageInMonths = new Integer(0);
			
			ims.framework.utils.Date scheduleDate = new ims.framework.utils.Date();
			scheduleDate.setDay(date == null ? new Integer(1) : date.getDay() == null ? new Integer(1) : date.getDay());
			scheduleDate.setMonth(date == null ? new Integer(1) : date.getMonth() == null ? new Integer(1) : date.getMonth());
			scheduleDate.setYear(date == null ? new Integer(1) : date.getYear() == null ? new Integer(1) : date.getYear());
			
			scheduleDate.addMonth(ageInMonths);
			return scheduleDate;
		    }
	
	/**
	* clearVaccine(ClientScheduleStageVaccineVo vaccine)
	*/
	private ClientScheduleStageVaccineVo clearVaccine(ClientScheduleStageVaccineVo vaccine)
	{
		if (vaccine == null)
			vaccine = new ClientScheduleStageVaccineVo();
	
		// Erase the previous data
		vaccine.isdeleted = false;
		vaccine.batchnumber = null;
		vaccine.vaccinemanufacturer = null;
		vaccine.expirydate = null;
		vaccine.delivereddate = null;
		vaccine.paymenttype = null;
		vaccine.deliveredbygp = null;
		vaccine.deliveredbymedic = null;
		vaccine.paymentgp = null;
		vaccine.scheduleddate = null;
		vaccine.terminateddate = null;
		vaccine.terminatedby = null;
		vaccine.terminationreason = null;
	
		return vaccine;
	}
	
	/**
	* addSchedule(ScheduleConfigurationVo schedule, MemberOfStaffLiteVo mos, DateTime dateTime) throws IllegalArgumentException
	*/
	public ims.pci.vo.ClientImmunisationScheduleVo addSchedule(ims.pci.vo.ScheduleConfigurationVo schedule, ims.core.vo.MemberOfStaffLiteVo mos, ims.framework.utils.DateTime dateTime) throws java.lang.IllegalArgumentException
	{
		if (schedule == null)
			return this;
	
		if (mos == null)
			return this;
	
		// Build the ClientPCISchedule 
		ims.pci.vo.ClientPCIScheduleProfileVo scheduleProfile = new ClientPCIScheduleProfileVo();
		scheduleProfile.schedule = schedule;
		scheduleProfile.selectedby = mos;
		scheduleProfile.datecreated = dateTime;
	
		addSchedule(scheduleProfile);
	
		return this;
	}
	
	/**
	* addSchedule(ClientPCIScheduleProfileVo schedule) throws IllegalArgumentException
	*/
	public ims.pci.vo.ClientImmunisationScheduleVo addSchedule(ims.pci.vo.ClientPCIScheduleProfileVo schedule) throws java.lang.IllegalArgumentException
	{
		if (schedule == null)
			return this;
	
		if (schedule.schedule == null)
			return this;
	
		if (ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(schedule.schedule.scheduletype))
		{
			String[] conflictErrors = getConflictErrors(schedule.schedule);
	
			if (conflictErrors != null && conflictErrors.length > 0)
			{
				throw new java.lang.IllegalArgumentException("The Schedule can not be added to current schedule. Please check if the stages or the vaccines are not in conflict with current schedule");
			}
		}
	
		// Add to client schedule
		if (this.scheduleprofiles == null)
			this.scheduleprofiles = new ClientPCIScheduleProfileVoCollection();
	
		if (ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(schedule.schedule.scheduletype))
		{
			boolean exists = false;
			for (int i = 0; i < this.scheduleprofiles.size(); i++)
			{
				ClientPCIScheduleProfileVo clientScheduleProfile = this.scheduleprofiles.get(i);
	
				if (clientScheduleProfile == null)
					continue;
	
				if (schedule.schedule.equals(clientScheduleProfile.schedule))
				{
					exists = true;
	
					clientScheduleProfile.isdeleted = Boolean.FALSE;
					clientScheduleProfile.selectedby = schedule.selectedby;
					clientScheduleProfile.datecreated = schedule.datecreated;
	
					break;
				}
			}
			if (exists == false)
			{
				this.scheduleprofiles.add(schedule);
			}
		}
		else
		{
			this.scheduleprofiles.add(schedule);
		}
	
		// Add schedule configuration
		ScheduleConfigurationVo scheduleConfiguration = schedule.schedule;
	
		if (scheduleConfiguration == null || scheduleConfiguration.stages == null)
			return this;
	
		for (int i = 0; i < scheduleConfiguration.stages.size(); i++)
		{
			if (scheduleConfiguration.stages.get(i) == null)
				continue;
	
			if (ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(scheduleConfiguration.scheduletype))
			{
				if (this.stages == null)
					this.stages = new ClientScheduleStageVoCollection();
	
				addStageConfigurationPCI(this.stages, scheduleConfiguration.stages.get(i));
			}
			if (ims.pci.vo.lookups.ScheduleType.OUTBREAKSCHEDULE.equals(scheduleConfiguration.scheduletype))
			{
				if (this.stages == null)
					this.stages = new ClientScheduleStageVoCollection();
	
				addStageConfigurationOutbreak(this.stages, scheduleConfiguration.stages.get(i), scheduleConfiguration.campaignstartdate);
			}
			else if (ims.pci.vo.lookups.ScheduleType.INVALIDVACCINESCHEDULE.equals(scheduleConfiguration.scheduletype))
			{
				if (this.stages == null)
					this.stages = new ClientScheduleStageVoCollection();
	
				addStageConfigurationInvalid(this.stages, scheduleConfiguration.stages.get(i));
			}
		}
	
		return this;
	}
	
	/**
	* addStageConfigurationPCI(ClientScheduleStageVoCollection stages, StageConfigurationVo stageConfiguration)
	*/
	private ClientScheduleStageVoCollection addStageConfigurationPCI(ClientScheduleStageVoCollection stages, StageConfigurationVo stageConfiguration)
	{
		// OBSERVATION: DO NOT code a line like stages = new ClientScheduleStageVoCollection() in this function
		// 'stages' - must always point to the 'this.stages' (using 'new' will point 'stage' to an object outside the schedule)
		if (stages == null)
			throw new ims.framework.exceptions.CodingRuntimeException("Major Logical Error - Can not add a stage configuration to a null stage collection");
	
		// Check for a valid stage configuration to be added
		if (stageConfiguration == null || stageConfiguration.stage == null || stageConfiguration.stagevaccines == null || stageConfiguration.ageinmonths == null)
			return stages;
	
		// Look in the stages collection for an existing stage configuration
		for (int i = 0; i < stages.size(); i++)
		{
			ClientScheduleStageVo stageVo = stages.get(i);
	
			if (stageVo == null || stageVo.stage == null)
				continue;
	
			// If the stage is different from the stage configuration to add move to the next
			if (!stageConfiguration.stage.equals(stageVo.stage.stage))
				continue;
	
			// Add the stage to the schedule configuration
			stageVo.isdeleted = Boolean.FALSE;
			stageVo.campaignstartdate = null;
			stageVo.stage = stageConfiguration;
	
			addVaccinesToStagePCI(stageVo, stageConfiguration.stagevaccines, stageConfiguration.ageinmonths);
	
			// Stage has been added - return the result
			return stages;
		}
	
		// Stage was not found - create a new stage
		ClientScheduleStageVo stageVo = new ClientScheduleStageVo();
		stageVo.stage = stageConfiguration;
		stageVo.isdeleted = Boolean.FALSE;
	
		// Add the stage to the schedule configuration
		stages.add(addVaccinesToStagePCI(stageVo, stageConfiguration.stagevaccines, stageConfiguration.ageinmonths));
		stages.sort();
	
		return stages;
	}
	
	/**
	* addVaccinesToStagePCI(ClientScheduleStageVo stage, StageVaccineVoCollection vaccines, Integer ageInMonths)
	*/
	private ClientScheduleStageVo addVaccinesToStagePCI(ClientScheduleStageVo stage, StageVaccineVoCollection vaccines, Integer ageInMonths)
	{
		// OBSERVATION: DO NOT code a line like stage = new ClientScheduleStageVo()
		// 'stage' - must always point to 'this.stages.get(i)' (using 'new' will point 'stage' to an object outside the schedule)
		// In addition, the 'stage.stage' and 'stage.stage.ageinmonths' can not be null as they are needed to calculate the scheduled date
		if (stage == null)
			throw new ims.framework.exceptions.CodingRuntimeException("Major Logical Error - Can not add the vaccines to a null stage");
	
		if (ageInMonths == null)
			throw new ims.framework.exceptions.CodingRuntimeException("Data Error - The provided data does not match the required data format. Missing stage of age in months");
	
		// Check for a valid vaccine collection to be added
		if (vaccines == null || vaccines.size() == 0)
			return stage;
	
	
		for (int i = 0; i < vaccines.size(); i++)
		{
			StageVaccineVo vaccine = vaccines.get(i);
	
			if (vaccine == null || vaccine.vaccine == null)
				continue;
	
			// OBESERVATION: KEEP THIS CODE ALWAYS
			// stage.vaccines == null is true when adding a schedule the first time
			// There is also no point to check for an existing vaccine (deleted - as this is an PCI schedule)
			if (stage.vaccines == null)
			{
				stage.vaccines = new ClientScheduleStageVaccineVoCollection();
			}
	
			boolean exists = false;
	
			for (int j = 0; j < stage.vaccines.size(); j++)
			{
				ClientScheduleStageVaccineVo existingVaccine = stage.vaccines.get(j);
				if (existingVaccine == null)
					continue;
	
				// If the vaccine is different from the stage vaccine to add move to the next 
				if (!vaccine.vaccine.equals(existingVaccine.getVaccine()))
					continue;
	
				if (!(existingVaccine.scheduletype == null || ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(existingVaccine.scheduletype)))
					continue;
	
				exists = true;
	
				// Reset the existing vaccine, calculate the schedule date, and update the isExtracted property
				existingVaccine.resetVaccine();
				existingVaccine.scheduletype = ims.pci.vo.lookups.ScheduleType.PCISCHEDULE;
				existingVaccine.scheduleddate = calculateScheduleDate(this.client == null ? new ims.framework.utils.PartialDate() : this.client.dob, ageInMonths);
				existingVaccine.stagevaccine.canberescheduled = vaccine.canberescheduled;
	
				if (Boolean.TRUE.equals(existingVaccine.isextracted))
					existingVaccine.isextracted = Boolean.FALSE;
	
				// Set the vaccine summary status
				setVaccineStatusOnAdd(existingVaccine.getVaccine());
			}
	
			if (exists)
				continue;
	
			// Vaccine was not found - create a new vaccine
			ClientScheduleStageVaccineVo newVaccine = new ClientScheduleStageVaccineVo();
			newVaccine.stagevaccine = vaccine;
			newVaccine.scheduletype = ims.pci.vo.lookups.ScheduleType.PCISCHEDULE;
			newVaccine.scheduleddate = calculateScheduleDate(this.client == null ? new ims.framework.utils.PartialDate() : this.client.dob, ageInMonths);
	
			// Add the vaccine to the schedule configuration
			stage.vaccines.add(newVaccine);
			stage.vaccines.sort();
	
			// Set the vaccine summary status
			setVaccineStatusOnAdd(vaccine.getVaccine());
		}
	
		return stage;
	}
	
	/**
	* addStageConfigurationOutbreak(ClientScheduleStageVoCollection stages, StageConfigurationVo stageConfiguration, Date campaignStartDate) 
	*/
	private ClientScheduleStageVoCollection addStageConfigurationOutbreak(ClientScheduleStageVoCollection stages, StageConfigurationVo stageConfiguration, ims.framework.utils.Date campaignStartDate)
	{
		// OBSERVATION: DO NOT code a line like stages = new ClientScheduleStageVoCollection() in this function
		// 'stages' - must always point to 'this.stages' (using 'new' will point 'stage' to an object outside the schedule)
		if (stages == null)
			throw new ims.framework.exceptions.CodingRuntimeException("Major logical error - can not add stage configuration to a null stage collection");
	
		// Check for a valid stage configuration to be added
		if (stageConfiguration == null || stageConfiguration.stage == null || stageConfiguration.stagevaccines == null)
			return stages;
	
		if (campaignStartDate == null)
			return stages;
	
		// Look in the stages collection for an existing stage configuration
		for (int i = 0; i < stages.size(); i++)
		{
			ClientScheduleStageVo stageVo = stages.get(i);
	
			if (stageVo == null || stageVo.stage == null)
				continue;
	
			// If the stage is different than the one we require then move to the next stage
			if (!stageConfiguration.stage.equals(stageVo.stage.stage))
				continue;
	
			if (stageVo.stage.ageinmonths != null)
				continue;
	
			if (!campaignStartDate.equals(stageVo.campaignstartdate))
				continue;
	
			// Add the stage to the schedule configuration
			stageVo.isdeleted = Boolean.FALSE;
			stageVo.stage = stageConfiguration;
			stageVo.campaignstartdate = campaignStartDate;
	
			addVaccinesToStageOutbreak(stageVo, stageConfiguration.stagevaccines, campaignStartDate);
	
			// Stage has been added - return the result
			return stages;
		}
	
		// Stage was not found - create a new stage
		ClientScheduleStageVo stageVo = new ClientScheduleStageVo();
		stageVo.stage = stageConfiguration;
		stageVo.isdeleted = Boolean.FALSE;
		stageVo.campaignstartdate = campaignStartDate;
	
	
		// Add the stage to the schedule configuration
		stages.add(addVaccinesToStageOutbreak(stageVo, stageConfiguration.stagevaccines, campaignStartDate));
		stages.sort();
	
		return stages;
	}
	
	/**
	* addVaccinesToStageOutbreak(ClientScheduleStageVo stage, StageVaccineVoCollection stageVaccines, Date campaignStartDate)
	*/
	private ClientScheduleStageVo addVaccinesToStageOutbreak(ClientScheduleStageVo stage, StageVaccineVoCollection stageVaccines, ims.framework.utils.Date campaignStartDate)
	{
		// OBSERVATION: DO NOT code a line like stage = new ClientScheduleStageVo()
		// 'stage' - must always point to 'this.stages.get(i)' (using 'new' will point 'stage' to an object outside the schedule)
		// In addition, the 'stage.stage' and 'stage.stage.ageinmonths' can not be null as they are needed to calculate the scheduled date
		if (stage == null)
			throw new ims.framework.exceptions.CodingRuntimeException("Major Logical Error - Can not add vaccines to a null stage");
	
		if (stage.stage == null)
			throw new ims.framework.exceptions.CodingRuntimeException("Data Error - The provided data does not match the required data format. Missing stage.");
	
		// Check for a valid vaccine collection to be added
		if (stageVaccines == null || stageVaccines.size() == 0)
			return stage;
	
		if (campaignStartDate == null)
			return stage;
	
	
		for (int i = 0; i < stageVaccines.size(); i++)
		{
			StageVaccineVo vaccine = stageVaccines.get(i);
	
			if (vaccine == null || vaccine.vaccine == null)
				continue;
	
			// OBESERVATION: KEEP THIS CODE ALWAYS
			// stage.vaccines == null is true when adding a schedule the first time
			// There is also no point to check for an existing vaccine (deleted - as this is an PCI add
			if (stage.vaccines == null)
			{
				stage.vaccines = new ClientScheduleStageVaccineVoCollection();
			}
	
			// TODO For now - always create a new vaccine record
	//		boolean exists = false;
	
	//		for (int j = 0; j < stage.vaccines.size(); j++)
	//		{
	//		ClientScheduleStageVaccineVo existingVaccine = stage.vaccines.get(j);
	//		if (existingVaccine == null)
	//		continue;
	
	//		// If the vaccine is different from the stage vaccine to add move to the next 
	//		if (!vaccine.vaccine.equals(existingVaccine.getVaccine()))
	//		continue;
	
	//		if (!(ims.pci.vo.lookups.ScheduleType.OUTBREAKSCHEDULE.equals(existingVaccine.scheduletype) || ims.pci.vo.lookups.ScheduleType.INVALIDVACCINESCHEDULE.equals(existingVaccine.scheduletype)))
	//		continue;
	
	//		exists = true;
	
	//		// Reset the existing vaccine, calculate the schedule date, and update the isExtracted property
	//		existingVaccine.resetVaccine();
	//		existingVaccine.scheduletype = ims.pci.vo.lookups.ScheduleType.OUTBREAKSCHEDULE;
	//		existingVaccine.scheduleddate = calculateScheduleDate(campaignStartDate.toPartialDate(), new Integer(0));
	
	//		if (Boolean.TRUE.equals(existingVaccine.isextracted))
	//		existingVaccine.isextracted = Boolean.FALSE;
	
	//		// Set the vaccine summary status
	//		setVaccineStatusOnAdd(existingVaccine.getVaccine());
	//		}
	
	//		if (exists)
	//		continue;
	
			// Vaccine was not found - create a new vaccine
			ClientScheduleStageVaccineVo newVaccine = new ClientScheduleStageVaccineVo();
			newVaccine.stagevaccine = vaccine;
			newVaccine.scheduletype = ims.pci.vo.lookups.ScheduleType.OUTBREAKSCHEDULE;
			newVaccine.scheduleddate = calculateScheduleDate(campaignStartDate.toPartialDate(), new Integer(0));
	
			// Add the vaccine to the schedule configuration
			stage.vaccines.add(newVaccine);
			stage.vaccines.sort();
	
			// Set the vaccine summary status
			setVaccineStatusOnAdd(vaccine.getVaccine());
		}
	
		return stage;
	}
	
	/**
	* addStageConfigurationInvalid(ClientScheduleStageVoCollection stages, StageConfigurationVo stageConfiguration)
	*/
	private ClientScheduleStageVoCollection addStageConfigurationInvalid(ClientScheduleStageVoCollection stages, StageConfigurationVo stageConfiguration)
	{
		// OBSERVATION: DO NOT code a line like stages = new ClientScheduleStageVoCollection() in this function
		// 'stages' - must always point to 'this.stages' (using 'new' will point 'stage' to an object outside the schedule)
		if (stages == null)
			throw new ims.framework.exceptions.CodingRuntimeException("Major Logical Error - Can not add a stage configuration to a null stage collection");
	
		// Check for a valid stage configuration to be added
		if (stageConfiguration == null || stageConfiguration.stage == null || stageConfiguration.stagevaccines == null || stageConfiguration.ageinmonths == null)
			return stages;
	
		// Look in the stages collection for an existing stage configuration
		for (int i = 0; i < stages.size(); i++)
		{
			ClientScheduleStageVo stageVo = stages.get(i);
	
			if (stageVo == null || stageVo.stage == null)
				continue;
	
			// If the stage is different from the stage configuration to add move to the next 
			if (!(stageConfiguration.stage.equals(stageVo.stage.stage) && stageConfiguration.ageinmonths.equals(stageVo.stage.ageinmonths)))
				continue;
	
			// Add the stage to the schedule configuration
			stageVo.isdeleted = Boolean.FALSE;
			stageVo.campaignstartdate = null;
			stageVo.stage = stageConfiguration;
	
			addVaccinesToStageInvalid(stageVo, stageConfiguration.stagevaccines, stageConfiguration.ageinmonths);
	
			// Stage has been added - return the result
			return stages;
		}
	
		// Stage was not found - create a new stage
		ClientScheduleStageVo stageVo = new ClientScheduleStageVo();
		stageVo.stage = stageConfiguration;
		stageVo.isdeleted = Boolean.FALSE;
	
		// Add the stage to the schedule configuration
		stages.add(addVaccinesToStageInvalid(stageVo, stageConfiguration.stagevaccines, stageConfiguration.ageinmonths));
	
		return stages;
	}
	
	/**
	* addVaccinesToStageInvalid(ClientScheduleStageVo stage, StageVaccineVoCollection vaccines, Integer ageInMonths)
	*/
		private ClientScheduleStageVo addVaccinesToStageInvalid(ClientScheduleStageVo stage, StageVaccineVoCollection vaccines, Integer ageInMonths)
		{
			// OBSERVATION: DO NOT code a line like stage = new ClientScheduleStageVo()
			// 'stage' - must always point to 'this.stages.get(i)' (using 'new' will point 'stage' to an object outside the schedule)
			// In addition, the 'stage.stage' and 'stage.stage.ageinmonths' can not be null as they are needed to calculate the scheduled date
			if (stage == null)
				throw new ims.framework.exceptions.CodingRuntimeException("Major Logical Error - Can not add the vaccines to a null stage");
	
			if (ageInMonths == null)
				throw new ims.framework.exceptions.CodingRuntimeException("Data Error - The provided data does not match the required data format. Missing stage of age in months");
	
			// Check for a valid vaccine collection to be added
			if (vaccines == null || vaccines.size() == 0)
				return stage;
	
	
			for (int i = 0; i < vaccines.size(); i++)
			{
				StageVaccineVo vaccine = vaccines.get(i);
	
				if (vaccine == null || vaccine.vaccine == null)
					continue;
	
				// OBESERVATION: KEEP THIS CODE ALWAYS
				// stage.vaccines == null is true when adding a schedule the first time
				// There is also no point to check for an existing vaccine (deleted - as this is an PCI schedule)
				if (stage.vaccines == null)
				{
					stage.vaccines = new ClientScheduleStageVaccineVoCollection();
				}
	
				// TODO For now - always create a new vaccine record in the schedule
	//			boolean exists = false;
	
	//			for (int j = 0; j < stage.vaccines.size(); j++)
	//			{
	//			ClientScheduleStageVaccineVo existingVaccine = stage.vaccines.get(j);
	//			if (existingVaccine == null)
	//			continue;
	
	//			// If the vaccine is different from the stage vaccine to add move to the next 
	//			if (!vaccine.vaccine.equals(existingVaccine.getVaccine()))
	//			continue;
	
	//			if (!(ims.pci.vo.lookups.ScheduleType.OUTBREAKSCHEDULE.equals(existingVaccine.scheduletype) || ims.pci.vo.lookups.ScheduleType.INVALIDVACCINESCHEDULE.equals(existingVaccine.scheduletype)))
	//			continue;
	
	//			exists = true;
	
	//			// Reset the existing vaccine, calculate the schedule date, and update the isExtracted property
	//			existingVaccine.resetVaccine();
	//			existingVaccine.scheduletype = ims.pci.vo.lookups.ScheduleType.INVALIDVACCINESCHEDULE;
	//			existingVaccine.scheduleddate = calculateScheduleDate(this.client == null ? new ims.framework.utils.PartialDate() : this.client.dob, ageInMonths);		// TODO Cross your fingers and hope to work (a client should be added to the VO)
	
	//			if (Boolean.TRUE.equals(existingVaccine.isextracted))
	//			existingVaccine.isextracted = Boolean.FALSE;
	
	//			// Set the vaccine summary status
	//			setVaccineStatusOnAdd(existingVaccine.getVaccine());
	//			}
	
	//			if (exists)
	//			continue;
	
				// Vaccine was not found - create a new vaccine
				ClientScheduleStageVaccineVo newVaccine = new ClientScheduleStageVaccineVo();
				newVaccine.stagevaccine = vaccine;
				newVaccine.scheduletype = ims.pci.vo.lookups.ScheduleType.INVALIDVACCINESCHEDULE;
				newVaccine.scheduleddate = calculateScheduleDate(this.client == null ? new ims.framework.utils.PartialDate() : this.client.dob, ageInMonths);
	
				// Add the vaccine to the schedule configuration
				stage.vaccines.add(newVaccine);
				stage.vaccines.sort();
	
				// Set the vaccine summary status
				setVaccineStatusOnAdd(vaccine.getVaccine());
			}
	
			return stage;
		}
	
	/**
	* getConflictErrors()
	*/
	public String[] getConflictErrors(ScheduleConfigurationVo schedule)
	{
		java.util.ArrayList<String> errorList = new java.util.ArrayList<String>();
	
		if (schedule == null)
		{
			errorList.add("Invalid schedule.");
			return errorList.toArray(new String[errorList.size()]);
		}
	
		if (schedule.stages == null)
		{
			errorList.add(schedule.getScheduleName() + " has no stages.");
			return errorList.toArray(new String[errorList.size()]);
		}
	
		if (ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(schedule.getScheduleType()))
		{
			if (this.scheduleprofiles != null)
			{
				for (int i = 0; i < this.scheduleprofiles.size(); i++)
				{
					ClientPCIScheduleProfileVo clientScheduleProfile = this.scheduleprofiles.get(i);
	
					if (clientScheduleProfile == null)
						continue;
	
					if (schedule.equals(clientScheduleProfile.schedule) && !Boolean.TRUE.equals(clientScheduleProfile.isdeleted))
					{
						errorList.add(schedule.getScheduleName() + " is already present and active.");
					}
				}
			}
		}
	
		for (StageConfigurationVo stageConfiguration : schedule.stages)
		{
			getConflictStageErrors(stageConfiguration, errorList, schedule.getScheduleType());
		}
	
		return errorList.toArray(new String[errorList.size()]);
	}
	
	/**
	* getConflictStageErrors() - Function used to check if a stage configuration is in conflict with current ClientImmunisationSchedule
	*/
	private String[] getConflictStageErrors(StageConfigurationVo stageConfiguration, java.util.ArrayList<String> errorList, ims.pci.vo.lookups.ScheduleType scheduleType)
	{
		if (errorList == null)
		{
			errorList = new java.util.ArrayList<String>();
		}
		
		// Check minimum requirements for the StageConfiguration to be added
		if (stageConfiguration == null || stageConfiguration.stage == null)
		{
			errorList.add("Invalid stage present in schedule.");
			return errorList.toArray(new String[errorList.size()]);
		}
		
		if (stageConfiguration.stagevaccines == null)
		{
			errorList.add(stageConfiguration.stage.getText() + " has no vaccines.");
			return errorList.toArray(new String[errorList.size()]);
		}
		
		if (ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(scheduleType) || ims.pci.vo.lookups.ScheduleType.INVALIDVACCINESCHEDULE.equals(scheduleType))
		{
			if (stageConfiguration.ageinmonths == null)
			{
				errorList.add(stageConfiguration.stage.getText() + " has no age completed.");
				return errorList.toArray(new String[errorList.size()]);
			}
		}
	
		// If the ClientImmunisationSchedule doesn't have any stages - NO CONFLICTS
		if (this.stages == null)
		{
			return errorList.toArray(new String[errorList.size()]);
		}
	
		// Iterate all stages in the ClientImmunisationSchedule
		for (ClientScheduleStageVo clientScheduleStageVo : this.stages)
		{
			if (ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(scheduleType))
			{
				// Skip stages from Client Immunisation Schedule that don't have a StageConfiguration
				if (clientScheduleStageVo == null || clientScheduleStageVo.stage == null)
					continue;
	
				// Skip stages from Client Immunisation Schedule marked as deleted
				if (Boolean.TRUE.equals(clientScheduleStageVo.isdeleted))
					continue;
	
				// If the StageConfiguration is found in the Client Immunisation Schedule
				if (stageConfiguration.stage.equals(clientScheduleStageVo.stage.stage))
				{
					// If the StageConfiguration has different "Age in Months" value - consider this StageConfiguration to be in conflict
					if (!(stageConfiguration.ageinmonths.equals(clientScheduleStageVo.stage.ageinmonths)))
					{
						errorList.add(stageConfiguration.stage.getText() + " is already present with a different age value.");
					}
				}
			}
		
			// If the vaccines from StageConfiguration are in conflict with ClientImmunisationSchedule then the stage is in conflict
			getConflictVaccineErrors(stageConfiguration.stagevaccines, clientScheduleStageVo.vaccines, stageConfiguration, clientScheduleStageVo.getStage(), errorList, scheduleType);
		}
	
		// At this point the stage is assumed not to be in conflict
		return errorList.toArray(new String[errorList.size()]);
	}
	
	/**
	* getConflictVaccineErrors(...) - Function used to check if a vaccine conflicts with the vaccines already present in ClientImmunisationSchedule
	*/
	private String[] getConflictVaccineErrors(StageVaccineVoCollection stagevaccines, ClientScheduleStageVaccineVoCollection vaccines, StageConfigurationVo sourceStage, StageConfigurationVo targetStage, java.util.ArrayList<String> errorList, ims.pci.vo.lookups.ScheduleType scheduleType)
	{
		if (errorList == null)
		{
			errorList = new java.util.ArrayList<String>();
		}
		
		// Check vaccines to add
		if (stagevaccines == null)
		{
			errorList.add(sourceStage.stage.getText() + " stage has no vaccines.");
			return errorList.toArray(new String[errorList.size()]);
		}
	
		if (ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(scheduleType))
		{
			// Check vaccines in stage
			if (vaccines == null)
				return errorList.toArray(new String[errorList.size()]);
	
			// Iterate vaccines to be added
			for (StageVaccineVo stageVaccine : stagevaccines)
			{
				// If any vaccine is invalid - consider a conflict and do not add the schedule
				if (stageVaccine == null || stageVaccine.getVaccine() == null)
				{
					errorList.add(sourceStage.stage.getText() + " has invalid vaccines.");
					return errorList.toArray(new String[errorList.size()]);
				}
	
				// Iterate client vaccines in stage from Client Immunisation Schedule
				for (ClientScheduleStageVaccineVo clientVaccine : vaccines)
				{
					// Skip client Vaccines not valid - this condition should never be true
					if (clientVaccine == null || clientVaccine.getVaccine() == null)
						continue;
	
					// If the client vaccine is marked as deleted - then move to next client vaccine
					if (Boolean.TRUE.equals(clientVaccine.getIsDeleted()))
						continue;
	
					// If the client vaccine is from an INVALID or OUTBREAK schedule - then move to next client vaccine
					if (ims.pci.vo.lookups.ScheduleType.INVALIDVACCINESCHEDULE.equals(clientVaccine.scheduletype)
						|| ims.pci.vo.lookups.ScheduleType.OUTBREAKSCHEDULE.equals(clientVaccine.scheduletype))
						continue;
	
					// Check client vaccine to be a match for vaccine to be added
					if (clientVaccine.getVaccine().equals(stageVaccine.getVaccine()))
					{
						// If client vaccine shot is not the same as the shot in vaccine to be added
						if (clientVaccine.getStageVaccineIsNotNull() && clientVaccine.getStageVaccine().getShotNoIsNotNull()
								&& stageVaccine.getShotNoIsNotNull()
								&& !clientVaccine.getStageVaccine().getShotNo().equals(stageVaccine.getShotNo()))
						{
							// Check not to be in the same stage
							if (sourceStage != null && targetStage != null && sourceStage.stage != null && sourceStage.stage.equals(targetStage.stage))
							{
								errorList.add(stageVaccine.getVaccine().getVaccineName() + " from stage " + sourceStage.getStage().getText() + " is already in the client immunisation schedule in the stage " + targetStage.getStage().getText() + ".");
							}
						
							// Allow a vaccine of the existing type to be added if it is added with a different shot number
							// and in a stage where this vaccine is not present
							continue;
						}
					
	
						// In this point the vaccine is in conflict with current Client Immunisation Schedule
						errorList.add(stageVaccine.getVaccine().getVaccineName() + " / shot " + stageVaccine.getShotNo().toString() + " combination already exists in client immunisation schedule.");
					}
				}
			}
		}
	
		// In this point of the algorithm the vaccine can be added to Client Immunisation Schedule
		// as it is not in conflict with the schedule
		return errorList.toArray(new String[errorList.size()]);
	}
	
	/**
	* setVaccineStatusOnAdd(VaccineLiteVo vaccine)
	*/
	private void setVaccineStatusOnAdd(ims.core.vo.VaccineLiteVo vaccine)
	{
		ClientVaccineSummaryVo vaccineSummary = this.getVaccineSummary(vaccine);
	
		if (vaccineSummary != null)
		{
			if (ims.pci.vo.lookups.VaccineStatus.TERMINATEDBYGP.equals(vaccineSummary.currentstatus.status))
			{
				ims.pci.vo.TerminationDetailsVo terminationDetails = new ims.pci.vo.TerminationDetailsVo();
				terminationDetails.terminatedby = ims.pci.vo.lookups.TerminatedBy.GP;
	
				// Get termination details
				for (int i = 0; i < this.stages.size(); i++)
				{
					ClientScheduleStageVo stage = this.stages.get(i);
					if (stage == null)
						continue;
	
					for (int j = 0; j < stage.vaccines.size(); j++)
					{
						ClientScheduleStageVaccineVo vaccineVo = stage.vaccines.get(j);
						if (vaccineVo == null || vaccineVo.stagevaccine == null || vaccineVo.stagevaccine.vaccine == null)
							continue;
	
						if (vaccineVo.terminateddate == null || vaccineVo.terminationreason == null)
							continue;
	
						if (vaccineVo.stagevaccine.vaccine.equals(vaccine))
						{
							terminationDetails.terminationdate = vaccineVo.terminateddate;
							terminationDetails.terminationreason = vaccineVo.terminationreason;
	
							terminateVaccine(vaccine, terminationDetails);
							return;
						}
					}
				}
	
				return;
			}
			if (ims.pci.vo.lookups.VaccineStatus.TERMINATEDBYPARENTGUARDIAN.equals(vaccineSummary.currentstatus.status))
			{
				ims.pci.vo.TerminationDetailsVo terminationDetails = new ims.pci.vo.TerminationDetailsVo();
				terminationDetails.terminatedby = ims.pci.vo.lookups.TerminatedBy.PARENT;
	
				// Get termination details
				for (int i = 0; i < this.stages.size(); i++)
				{
					ClientScheduleStageVo stage = this.stages.get(i);
					if (stage == null)
						continue;
	
					for (int j = 0; j < stage.vaccines.size(); j++)
					{
						ClientScheduleStageVaccineVo vaccineVo = stage.vaccines.get(j);
						if (vaccineVo == null || vaccineVo.stagevaccine == null || vaccineVo.stagevaccine.vaccine == null)
							continue;
	
						if (vaccineVo.terminateddate == null || vaccineVo.terminationreason == null)
							continue;
	
						if (vaccineVo.stagevaccine.vaccine.equals(vaccine))
						{
							terminationDetails.terminationdate = vaccineVo.terminateddate;
							terminationDetails.terminationreason = vaccineVo.terminationreason;
	
							terminateVaccine(vaccine, terminationDetails);
							return;
						}
					}
				}
	
				return;
			}
		}
	
		VaccineStatusLiteVo newStatus = new VaccineStatusLiteVo();
		newStatus.terminatedby = null;
		newStatus.terminationreason = null;
	
		if (vaccineSummary == null)
		{
			newStatus.status = ims.pci.vo.lookups.VaccineStatus.SCHEDULED;
	
			vaccineSummary = new ClientVaccineSummaryVo();
			vaccineSummary.vaccine = vaccine;
			vaccineSummary.setNewStatusTo(newStatus);
	
			if (this.vaccinesummarystatus == null)
				this.vaccinesummarystatus = new ClientVaccineSummaryVoCollection();
	
			this.vaccinesummarystatus.add(vaccineSummary);
		}
		else
		{
			if (vaccineSummary.currentstatus == null)
			{
				newStatus.status = ims.pci.vo.lookups.VaccineStatus.SCHEDULED;
				vaccineSummary.setNewStatusTo(newStatus);
			}
			else if (ims.pci.vo.lookups.VaccineStatus.SCHEDULED.equals(vaccineSummary.currentstatus.status) || ims.pci.vo.lookups.VaccineStatus.DELETEDVACCINESCHEDULE.equals(vaccineSummary.currentstatus.status))
			{
				newStatus.status = ims.pci.vo.lookups.VaccineStatus.SCHEDULED;
				vaccineSummary.setNewStatusTo(newStatus);
			}
			else
			{
				newStatus.status = ims.pci.vo.lookups.VaccineStatus.STARTED;
				vaccineSummary.setNewStatusTo(newStatus);
			}
		}
	}
	
	/**
	* getVaccineSummary(VaccineLiteVo vaccine)
	*/
	public ims.pci.vo.ClientVaccineSummaryVo getVaccineSummary(ims.core.vo.VaccineLiteVo vaccine)
	{
		if (vaccine == null)
			return null;
	
		if (this.vaccinesummarystatus == null)
			return null;
	
		for (int i = 0; i < vaccinesummarystatus.size(); i++)
		{
			if (vaccinesummarystatus.get(i) == null)
				continue;
	
			if (vaccine.equals(vaccinesummarystatus.get(i).getVaccine()))
				return vaccinesummarystatus.get(i);
		}
	
		return null;
	}
	
	/**
	* deliverVaccineShot(MemberOfStaffLiteVo mos, ClientScheduleStageVo stage, ClientScheduleStageVaccineVo vaccine, DeliverShotDetailsVo deliveryDetails)
	*/
	public ims.pci.vo.ClientImmunisationScheduleVo deliverVaccineShot(ims.core.vo.MemberOfStaffLiteVo mos, ims.pci.vo.ClientScheduleStageVo stage, ims.pci.vo.ClientScheduleStageVaccineVo vaccine, ims.pci.vo.DeliverShotDetailsVo deliveryDetails)
	{
		if (stage == null || vaccine == null || vaccine.getVaccine() == null)
				return this;
		
			if (this.stages == null)
				return this;
		
			this.stages.sort();
		
			int indexStage = this.stages.indexOf(stage);
			if (indexStage == -1 || this.stages.get(indexStage).getVaccines() == null)
				return this;
		
			int indexVaccine = this.stages.get(indexStage).getVaccines().indexOf(vaccine);
			if (indexVaccine == -1)
				return this;
		
			ClientScheduleStageVaccineVo vaccineDetails = this.stages.get(indexStage).vaccines.get(indexVaccine);
		
			vaccineDetails.batchnumber = deliveryDetails == null ? null : deliveryDetails.getBatchNumber();
			vaccineDetails.deliveredbygp = deliveryDetails == null ? null : deliveryDetails.getDeliveredByGp();
			vaccineDetails.deliveredbymedic = deliveryDetails == null ? null : deliveryDetails.getDeliveredBy();
			vaccineDetails.delivereddate = deliveryDetails == null ? null : deliveryDetails.getDeliveredDate();
			vaccineDetails.expirydate = deliveryDetails == null ? null : deliveryDetails.getExpiryDate();
			vaccineDetails.paymentgp = deliveryDetails == null ? null : deliveryDetails.getPaymentGp();
			vaccineDetails.paymenttype = deliveryDetails == null ? null : deliveryDetails.getPaymentType();
			vaccineDetails.vaccinemanufacturer = deliveryDetails == null ? null : deliveryDetails.getVaccineManufacturer();
			vaccineDetails.personrecordingdelivery = mos;
		
			if (Boolean.TRUE.equals(vaccineDetails.isextracted))
				vaccineDetails.isextracted = Boolean.FALSE;
		
			// Calculate number of Days the delivery was late
			if (!(vaccineDetails.delivereddate == null || vaccineDetails.scheduleddate == null))
			{
		
				if (vaccineDetails.delivereddate.isGreaterOrEqualThan(vaccineDetails.scheduleddate))
				{
					//delivery date is later then the schedule date for the driver
					if(vaccineDetails.stagevaccine != null && vaccineDetails.stagevaccine.driver != null && vaccineDetails.stagevaccine.driver)
					{
						Integer minimumInterval = vaccineDetails.stagevaccine.intervalmonths;
						ims.framework.utils.Date compareDate = (ims.framework.utils.Date) vaccineDetails.delivereddate.clone();
						
						for (int i = indexStage + 1; i < this.stages.size(); i++)
						{
							ClientScheduleStageVo stageVo = this.stages.get(i);
							if (stageVo.getVaccines() == null)
								continue;
						
							if(minimumInterval != null)
							{
								ims.framework.utils.Date newScheduleDate = compareDate.addMonth(minimumInterval);	
										
								for (int k = 0; k < stageVo.getVaccines().size(); k++)
								{
									ClientScheduleStageVaccineVo vaccineVo = stageVo.getVaccines().get(k);
									if (vaccineVo == null)
										continue;
										
									if (Boolean.TRUE.equals(vaccineVo.isdeleted))
										continue;
									
									vaccineVo.scheduleddate = calculateScheduleDate(this.client == null? new ims.framework.utils.PartialDate() : this.client.dob, stageVo.stage.ageinmonths);
										
									if(newScheduleDate.isGreaterThan(vaccineVo.scheduleddate))
									{
										vaccineVo.scheduleddate = newScheduleDate;
									}
										
									compareDate = (ims.framework.utils.Date) vaccineVo.scheduleddate.clone();
										
									/*	WDEV-13489
									if (Boolean.TRUE.equals(vaccineVo.isextracted))
										vaccineVo.isextracted = false;
									*/
								}
							}
								
							minimumInterval = stageVo.getInterval();
						}
					}
				}
			}
		
			// Set the status
			ClientVaccineSummaryVo vaccineSummary = this.getVaccineSummary(vaccine.getVaccine());
			if (vaccineSummary != null && vaccineSummary.getCurrentStatusIsNotNull())
			{
				if (ims.pci.vo.lookups.VaccineStatus.TERMINATEDBYGP.equals(vaccineSummary.getCurrentStatus().status) || ims.pci.vo.lookups.VaccineStatus.TERMINATEDBYPARENTGUARDIAN.equals(vaccineSummary.getCurrentStatus().status))
					return this;
			}
		
			//isLastShot
			for (int i = 0; i < this.stages.size(); i++)
			{
				ClientScheduleStageVo stageVo = this.stages.get(i);
				if (stageVo.getVaccines() == null)
					continue;
			
				for (int k = 0; k < stageVo.getVaccines().size(); k++)
				{
					ClientScheduleStageVaccineVo vaccineVo = stageVo.getVaccines().get(k);
					if (vaccineVo == null)
						continue;
						
					if(vaccine.getVaccine().equals(vaccineVo.getVaccine()) && vaccineVo.delivereddate != null && vaccineVo.stagevaccine.getIsLastShotForVaccineIsNotNull() && vaccineVo.stagevaccine.getIsLastShotForVaccine())
					{
						VaccineStatusLiteVo status = new VaccineStatusLiteVo();
						status.status = ims.pci.vo.lookups.VaccineStatus.COMPLETED;
						status.terminatedby = null;
						status.terminationreason = null;
						vaccineSummary.setNewStatusTo(status);
							
						return this;
					}
				}
			}	
				
			for (int i = 0; i < this.stages.size(); i++)
			{
				ClientScheduleStageVo stageVo = this.stages.get(i);
				if (stageVo.getVaccines() == null)
					continue;
						
				for (int k = 0; k < stageVo.getVaccines().size(); k++)
				{
					ClientScheduleStageVaccineVo vaccineVo = stageVo.getVaccines().get(k);
					if (vaccineVo == null)
						continue;
		
					if (vaccine.getVaccine().equals(vaccineVo.getVaccine()) && vaccineVo.delivereddate == null && vaccineVo.terminateddate == null)
					{
						if (Boolean.TRUE.equals(vaccineVo.isdeleted))
							continue;
			
						VaccineStatusLiteVo status = new VaccineStatusLiteVo();
						status.status = ims.pci.vo.lookups.VaccineStatus.STARTED;
						status.terminatedby = null;
						status.terminationreason = null;
						vaccineSummary.setNewStatusTo(status);
						return this;
					}
				}
			}
				
			VaccineStatusLiteVo status = new VaccineStatusLiteVo();
			status.status = ims.pci.vo.lookups.VaccineStatus.COMPLETED;
			status.terminatedby = null;
			status.terminationreason = null;
			vaccineSummary.setNewStatusTo(status);
		
			return this;
	}
	
	/**
	* terminateVaccine(VaccineLiteVo vaccine, TerminationDetailsVo terminationDetails)
	*/
		public ims.pci.vo.ClientImmunisationScheduleVo terminateVaccine(ims.core.vo.VaccineLiteVo vaccine, ims.pci.vo.TerminationDetailsVo terminationDetails)
		{
			if (vaccine == null || terminationDetails == null)
				return this;
	
			if (this.stages == null)
				return this;
	
			for (int i = 0; i < this.stages.size(); i++)
			{
				ims.pci.vo.ClientScheduleStageVo stage = this.stages.get(i);
	
				if (stage == null || stage.getVaccines() == null)
					continue;
	
				for (int k = 0; k < stage.getVaccines().size(); k++)
				{
					ClientScheduleStageVaccineVo vaccineVo = stage.getVaccines().get(k);
					if (vaccineVo == null)
						continue;
	
					if (vaccine.equals(vaccineVo.getVaccine()) && !vaccineVo.getDeliveredDateIsNotNull())
					{
						vaccineVo.terminatedby = terminationDetails.getTerminatedBy();
						vaccineVo.terminateddate = terminationDetails.getTerminationDate();
						vaccineVo.terminationreason = terminationDetails.getTerminationReason();
							
						vaccineVo.setIsExtracted(Boolean.FALSE);
					}
				}
			}
	
			// Create a new status
			ims.pci.vo.VaccineStatusLiteVo status = new ims.pci.vo.VaccineStatusLiteVo();
	
			if (ims.pci.vo.lookups.TerminatedBy.GP.equals(terminationDetails.getTerminatedBy()))
				status.status = ims.pci.vo.lookups.VaccineStatus.TERMINATEDBYGP;
			else if (ims.pci.vo.lookups.TerminatedBy.PARENT.equals(terminationDetails.getTerminatedBy()))
				status.status = ims.pci.vo.lookups.VaccineStatus.TERMINATEDBYPARENTGUARDIAN;
	
			status.terminatedby = terminationDetails.getTerminatedBy();
			status.terminationreason = terminationDetails.getTerminationReason();
	
			this.getVaccineSummary(vaccine).setNewStatusTo(status);
	
			return this;
		}
	
	/**
	* deleteVaccine(VaccineLiteVo vaccine)
	*/
		public ims.pci.vo.ClientImmunisationScheduleVo deleteVaccine(ims.core.vo.VaccineLiteVo vaccine)
		{
			if (vaccine == null)
				return this;
	
			// Create the new status
			ims.pci.vo.VaccineStatusLiteVo status = new ims.pci.vo.VaccineStatusLiteVo();
			status.status = ims.pci.vo.lookups.VaccineStatus.DELETEDVACCINESCHEDULE;
	
			// Set status to deleted
			this.getVaccineSummary(vaccine).setNewStatusTo(status);
	
			// Set the isDeleted marker to true
			if (this.stages != null)
			{
				for (int i = 0; i < this.stages.size(); i++)
				{
					ClientScheduleStageVo stage = this.stages.get(i);
	
					if (stage == null)
						continue;
	
					ClientScheduleStageVaccineVoCollection vaccines = stage.vaccines;
					if (vaccines == null)
						continue;
	
					for (int j = 0; j < vaccines.size(); j++)
					{
						ClientScheduleStageVaccineVo vaccineVo = vaccines.get(j);
						if (vaccineVo == null)
							continue;
	
						if (vaccine.equals(vaccineVo.getVaccine()))
						{
							if (Boolean.TRUE.equals(vaccineVo.isextracted))
								vaccineVo.isextracted = Boolean.FALSE;
	
							vaccineVo.isdeleted = true;
						}
					}
	
					stage.updateStageDeleteStatus();
				}
			}
	
			updateSchedulesCollectionDeletedStatus();
			return this;
		}
	
	/**
	* restartVaccine(VaccineLiteVo vaccine)
	*/
	public ims.pci.vo.ClientImmunisationScheduleVo restartVaccine(ims.core.vo.VaccineLiteVo vaccine)
	{
		if (vaccine == null)
			return this;
	
		if (this.stages == null)
			return this;
	
		for (int i = 0; i < this.stages.size(); i++)
		{
			ClientScheduleStageVo stageVo = this.stages.get(i);
			if (stageVo == null || stageVo.getVaccines() == null)
				continue;
	
			for (int k = 0; k < stageVo.getVaccines().size(); k++)
			{
				ClientScheduleStageVaccineVo vaccineVo = stageVo.getVaccines().get(k);
				if (vaccineVo == null)
					continue;
	
				if (vaccine.equals(vaccineVo.getVaccine()))
				{
					// Clear terminated fields
					vaccineVo.terminatedby = null;
					vaccineVo.terminateddate = null;
					vaccineVo.terminationreason = null;
	
					// Removed in the issue WDEV-7017
					// Restart the extracted part from vaccine
					//if (Boolean.TRUE.equals(vaccineVo.isextracted))
					//	vaccineVo.isextracted = Boolean.FALSE;
				}
			}
		}
	
		// Create the new status
		ims.pci.vo.VaccineStatusLiteVo status = new ims.pci.vo.VaccineStatusLiteVo();
		status.status = ims.pci.vo.lookups.VaccineStatus.STARTED;
	
		this.getVaccineSummary(vaccine).setNewStatusTo(status);
	
		return this;
	}
	
	/**
	* updateSchedulesCollectionDeletedStatus()
	*/
	private void updateSchedulesCollectionDeletedStatus()
	{
		if (this.scheduleprofiles == null)
			return;
	
		for (int i = 0; i < this.scheduleprofiles.size(); i++)
		{
			ClientPCIScheduleProfileVo scheduleProfile = this.scheduleprofiles.get(i);
	
			// TODO Add 'isdeleted' field to the BO - boolean (can be null)
			if (scheduleProfile == null)
				continue;
	
			if (scheduleProfile.schedule == null)
				scheduleProfile.isdeleted = Boolean.TRUE;
	
			if (!ims.pci.vo.lookups.ScheduleType.PCISCHEDULE.equals(scheduleProfile.schedule.scheduletype))
				continue;
	
			if (scheduleProfile == null || Boolean.TRUE.equals(scheduleProfile.isdeleted))
				continue;
	
			updateScheduleDeletedStatus(scheduleProfile);
		}
	}
	
	/**
	* updateScheduleDeletedStatus(ClientPCIScheduleProfileVo scheduleProfile)
	*/
	private void updateScheduleDeletedStatus(ClientPCIScheduleProfileVo scheduleProfile)
	{
		// TODO Uncomment code when 'isdeleted' boolean field in the BO
		if (scheduleProfile == null || Boolean.TRUE.equals(scheduleProfile.isdeleted))
			return;
	
		if (scheduleProfile.schedule == null || scheduleProfile.schedule.stages == null)
			scheduleProfile.isdeleted = Boolean.TRUE;
	
		for (int i = 0; i < scheduleProfile.schedule.stages.size(); i++)
		{
			StageConfigurationVo stage = scheduleProfile.schedule.stages.get(i);
			if (stage == null)
				continue;
	
			if (isStageDeleted(stage) == false)
				return;
		}
	
		// TODO Uncomment code when 'isdeleted' boolean field is added to the BO
		scheduleProfile.isdeleted = Boolean.TRUE;
	
		return;
	}
	
	/**
	* isStageDeleted(StageConfigurationVo stage)
	*/
	private boolean isStageDeleted(StageConfigurationVo stage)
	{
		if (stage == null || stage.stagevaccines == null)
			return true;
	
		for (int i = 0; i < stage.stagevaccines.size(); i++)
		{
			StageVaccineVo vaccine = stage.stagevaccines.get(i);
			if (vaccine == null || vaccine.vaccine == null)
				continue;
	
			if (isVaccineDeleted(vaccine.vaccine, stage) == false)
				return false;
		}
	
		return true;
	}
	
	/**
	* isVaccineDeleted(VaccineLiteVo vaccine, StageConfigurationVo stage)
	*/
	private boolean isVaccineDeleted(ims.core.vo.VaccineLiteVo vaccine, StageConfigurationVo stage)
	{
		if (this.stages == null)
			return true;
		
		ClientScheduleStageVaccineVo vaccineVo = getVaccineDetails(stage, vaccine, ims.pci.vo.lookups.ScheduleType.PCISCHEDULE);
		
		if (vaccineVo == null || Boolean.TRUE.equals(vaccineVo.isdeleted))
			return true;
		
		return false;
	}
	
	/**
	* getVaccineDetails(ClientScheduleStageVo stage, ClientScheduleStageVaccineVo vaccine)
	*/
	public ims.pci.vo.ClientScheduleStageVaccineVo getVaccineDetails(ims.pci.vo.ClientScheduleStageVo stage, ims.pci.vo.ClientScheduleStageVaccineVo vaccine)
	{
		if (stage == null || vaccine == null)
			return null;
	
		if (this.stages == null)
			return null;
	
		int stageIndex = this.stages.indexOf(stage);
	
		if (stageIndex == -1 || this.stages.get(stageIndex).getVaccines() == null)
			return null;
	
		int vaccineIndex = this.stages.get(stageIndex).getVaccines().indexOf(vaccine);
	
		if (vaccineIndex == -1)
			return null;
	
		return this.stages.get(stageIndex).getVaccines().get(vaccineIndex);
	}
	
	/**
	* getVaccineDetails(StageConfigurationVo stage, VaccineLiteVo vaccine, ScheduleType scheduleType)
	*/
	private ClientScheduleStageVaccineVo getVaccineDetails(StageConfigurationVo stage, ims.core.vo.VaccineLiteVo vaccine, ims.pci.vo.lookups.ScheduleType scheduleType)
	{
		if (stage == null || vaccine == null)
			return null;
	
		if (scheduleType == null)
			scheduleType = ims.pci.vo.lookups.ScheduleType.PCISCHEDULE;
	
		if (stage.stage == null || stage.ageinmonths == null)
			return null;
	
		if (this.stages == null)
			return null;
	
	
		for (int i = 0; i < this.stages.size(); i++)
		{
			ClientScheduleStageVo clientStage = this.stages.get(i);
	
			if (clientStage == null || clientStage.vaccines == null || clientStage.stage == null)
				continue;
	
			if (!(stage.stage.equals(clientStage.stage.stage) && stage.ageinmonths.equals(clientStage.stage.ageinmonths)))
				continue;
	
			for (int j = 0; j < clientStage.vaccines.size(); j++)
			{
				ClientScheduleStageVaccineVo vaccineVo = clientStage.vaccines.get(j);
	
				if (vaccineVo == null)
					continue;
	
				if (!scheduleType.equals(vaccineVo.scheduletype))
					continue;
	
				if (vaccine.equals(vaccineVo.getVaccine()))
					return vaccineVo;
			}
		}
	
		return null;
	}
	
	/**
	* areAllTerminated()
	*/
	public boolean areAllTerminated()
	{
		if (this.vaccinesummarystatus == null)
			return false;
		
		for (int i = 0; i < vaccinesummarystatus.size(); i++)
		{
			if (vaccinesummarystatus.get(i) == null)
				continue;
		
			if (vaccinesummarystatus.get(i).currentstatus == null)
				return false;
				
			if (!(vaccinesummarystatus.get(i).currentstatus.status.equals(ims.pci.vo.lookups.VaccineStatus.TERMINATEDBYGP) || vaccinesummarystatus.get(i).currentstatus.status.equals(ims.pci.vo.lookups.VaccineStatus.TERMINATEDBYPARENTGUARDIAN)))
				return false;
		}
		
		return true;
	}
	/**
	* deleteVaccine (ims.core.vo.VaccineLiteVo vaccine, ims.pci.vo.ClientScheduleStageVo vaccineStage)
	*/
	public ims.pci.vo.ClientImmunisationScheduleVo deleteVaccine(ims.core.vo.VaccineLiteVo vaccine, ims.pci.vo.ClientScheduleStageVo vaccineStage)
	{
		if (vaccine == null)
			return this;
	
		// Set the isDeleted marker to true
		if (this.stages != null)
		{
			for (int i = 0; i < this.stages.size(); i++)
			{
				ClientScheduleStageVo stage = this.stages.get(i);
	
				if (stage == null)
					continue;
	
				ClientScheduleStageVaccineVoCollection vaccines = stage.vaccines;
				if (vaccines == null)
					continue;
	
				for (int j = 0; j < vaccines.size(); j++)
				{
					ClientScheduleStageVaccineVo vaccineVo = vaccines.get(j);
					if (vaccineVo == null)
						continue;
	
					if (vaccine.equals(vaccineVo.getVaccine()) && isSameScheduleConfiguration(vaccineStage, this.stages.get(i)))
					{
						if (Boolean.TRUE.equals(vaccineVo.isextracted))
							vaccineVo.isextracted = Boolean.FALSE;
	
						vaccineVo.isdeleted = true;
					}
				}
	
				stage.updateStageDeleteStatus();
			}
		}
			
		if (areAllVaccinesOfTheSameTypeDeleted(vaccine))
		{
			// Create the new status
			ims.pci.vo.VaccineStatusLiteVo status = new ims.pci.vo.VaccineStatusLiteVo();
			status.status = ims.pci.vo.lookups.VaccineStatus.DELETEDVACCINESCHEDULE;
	
			// Set status to deleted
			this.getVaccineSummary(vaccine).setNewStatusTo(status);
		}
	
		updateSchedulesCollectionDeletedStatus();
		return this;
	}
	/**
	* getScheduleConfiguration(ims.pci.vo.ClientScheduleStageVo stage)
	*/
		public ims.pci.vo.ScheduleConfigurationVo getScheduleConfiguration(ims.pci.vo.ClientScheduleStageVo stage)
		{
			if (stage == null || stage.getStage() == null)
				return null;
	
			if (this.scheduleprofiles == null || this.scheduleprofiles.size() == 0)
				return null;
	
			for (int i = 0; i < this.scheduleprofiles.size(); i++)
			{
				ClientPCIScheduleProfileVo scheduleProfile = this.scheduleprofiles.get(i);
				if (scheduleProfile == null || 
				    scheduleProfile.schedule == null ||
				    scheduleProfile.schedule.stages == null)
					continue;
				
				int stageIndex = scheduleProfile.schedule.stages.indexOf(stage.getStage());
	
				if (stageIndex != -1)
					return scheduleProfile.schedule;
			}
	
			return null;
		}
	/**
	* isSameScheduleConfiguration(ims.pci.vo.ClientScheduleStageVo stage, ims.pci.vo.ClientScheduleStageVo newStage)
	*/
		public boolean isSameScheduleConfiguration(ims.pci.vo.ClientScheduleStageVo stage, ims.pci.vo.ClientScheduleStageVo newStage)
		{
			if (stage == null || newStage == null)
				return false;
	
			ScheduleConfigurationVo stageScheduleConfig = getScheduleConfiguration(stage);
			ScheduleConfigurationVo newStageScheduleConfig = getScheduleConfiguration(newStage);
			
			if (stageScheduleConfig == null || newStageScheduleConfig  == null ||
		          !stageScheduleConfig.getBoId().equals(newStageScheduleConfig.getBoId()))
				return false;	
	
			return true;
		}
	/**
	* areAllVaccinesOfTheSameTypeDeleted(ims.core.vo.VaccineLiteVo vaccine)
	*/
		public boolean areAllVaccinesOfTheSameTypeDeleted(ims.core.vo.VaccineLiteVo vaccine)
		{
			if (vaccine == null)
				return true;
	
			if (this.stages == null || this.stages.size() == 0)
				return true;
	
			for (int i = 0; i < this.stages.size(); i++)
			{
				ClientScheduleStageVo clientScheduleStage = this.stages.get(i);
				if (clientScheduleStage == null || 
					clientScheduleStage.vaccines == null)
					continue;
				
				for (int j = 0; j < clientScheduleStage.vaccines.size(); j ++ )
				{
					ClientScheduleStageVaccineVo clientVaccine = clientScheduleStage.vaccines.get(j);
					
					if (clientVaccine.getStageVaccine() == null || clientVaccine.getStageVaccine().getVaccine() == null)
						continue;
					
					if (vaccine.getID_Vaccine().equals(clientVaccine.getStageVaccine().getVaccine().getID_Vaccine()) &&
						(Boolean.FALSE.equals(clientVaccine.getIsDeleted()) || clientVaccine.getIsDeleted() == null))
					{
						return false;
					}
					
				}
			}
	
			return true;
		}
	/**
	* doesOneVaccineFromTheScheduleHasDeliveryDate(ims.core.vo.VaccineLiteVo vaccine, ims.pci.vo.ClientScheduleStageVo vaccineStage)
	*/
		public boolean doesOneVaccineFromTheScheduleHasDeliveryDate(ims.core.vo.VaccineLiteVo vaccine, ims.pci.vo.ClientScheduleStageVo vaccineStage)
		{
			if (vaccine == null)
				return false;
	
			if (this.stages == null || this.stages.size() == 0)
				return false;
	
			for (int i = 0; i < this.stages.size(); i++)
			{
				ClientScheduleStageVo clientScheduleStage = this.stages.get(i);
				if (clientScheduleStage == null || 
					clientScheduleStage.vaccines == null)
					continue;
				
				for (int j = 0; j < clientScheduleStage.vaccines.size(); j ++ )
				{
					ClientScheduleStageVaccineVo clientVaccine = clientScheduleStage.vaccines.get(j);
					
					if (clientVaccine.getStageVaccine() == null || clientVaccine.getStageVaccine().getVaccine() == null)
						continue;
					
					if (vaccine.getID_Vaccine().equals(clientVaccine.getStageVaccine().getVaccine().getID_Vaccine()) &&
						clientVaccine.getDeliveredDate() != null && isSameScheduleConfiguration(clientScheduleStage, vaccineStage))
					{
						return true;
					}
					
				}
			}
	
			return false;
		}
	public boolean isValidated()
	{
		if(this.isBusy)
			return true;
		this.isBusy = true;
	
		if(!this.isValidated)
		{
			this.isBusy = false;
			return false;
		}
		if(this.client != null)
		{
			if(!this.client.isValidated())
			{
				this.isBusy = false;
				return false;
			}
		}
		if(this.scheduleprofiles != null)
		{
			if(!this.scheduleprofiles.isValidated())
			{
				this.isBusy = false;
				return false;
			}
		}
		if(this.stages != null)
		{
			if(!this.stages.isValidated())
			{
				this.isBusy = false;
				return false;
			}
		}
		if(this.vaccinesummarystatus != null)
		{
			if(!this.vaccinesummarystatus.isValidated())
			{
				this.isBusy = false;
				return false;
			}
		}
		this.isBusy = false;
		return true;
	}
	public String[] validate()
	{
		return validate(null);
	}
	public String[] validate(String[] existingErrors)
	{
		if(this.isBusy)
			return null;
		this.isBusy = true;
	
		java.util.ArrayList<String> listOfErrors = new java.util.ArrayList<String>();
		if(existingErrors != null)
		{
			for(int x = 0; x < existingErrors.length; x++)
			{
				listOfErrors.add(existingErrors[x]);
			}
		}
		if(this.client == null)
			listOfErrors.add("Client is mandatory");
		if(this.client != null)
		{
			String[] listOfOtherErrors = this.client.validate();
			if(listOfOtherErrors != null)
			{
				for(int x = 0; x < listOfOtherErrors.length; x++)
				{
					listOfErrors.add(listOfOtherErrors[x]);
				}
			}
		}
		if(this.scheduleprofiles == null || this.scheduleprofiles.size() == 0)
			listOfErrors.add("ScheduleProfiles are mandatory");
		if(this.scheduleprofiles != null)
		{
			String[] listOfOtherErrors = this.scheduleprofiles.validate();
			if(listOfOtherErrors != null)
			{
				for(int x = 0; x < listOfOtherErrors.length; x++)
				{
					listOfErrors.add(listOfOtherErrors[x]);
				}
			}
		}
		if(this.stages == null || this.stages.size() == 0)
			listOfErrors.add("Stages are mandatory");
		if(this.stages != null)
		{
			String[] listOfOtherErrors = this.stages.validate();
			if(listOfOtherErrors != null)
			{
				for(int x = 0; x < listOfOtherErrors.length; x++)
				{
					listOfErrors.add(listOfOtherErrors[x]);
				}
			}
		}
		if(this.vaccinesummarystatus == null || this.vaccinesummarystatus.size() == 0)
			listOfErrors.add("VaccineSummaryStatus are mandatory");
		if(this.vaccinesummarystatus != null)
		{
			String[] listOfOtherErrors = this.vaccinesummarystatus.validate();
			if(listOfOtherErrors != null)
			{
				for(int x = 0; x < listOfOtherErrors.length; x++)
				{
					listOfErrors.add(listOfOtherErrors[x]);
				}
			}
		}
		int errorCount = listOfErrors.size();
		if(errorCount == 0)
		{
			this.isBusy = false;
			this.isValidated = true;
			return null;
		}
		String[] result = new String[errorCount];
		for(int x = 0; x < errorCount; x++)
			result[x] = (String)listOfErrors.get(x);
		this.isBusy = false;
		this.isValidated = false;
		return result;
	}
	public void clearIDAndVersion()
	{
		this.id = null;
		this.version = 0;
	}
	public Object clone()
	{
		if(this.isBusy)
			return this;
		this.isBusy = true;
	
		ClientImmunisationScheduleVo clone = new ClientImmunisationScheduleVo(this.id, this.version);
		
		if(this.client == null)
			clone.client = null;
		else
			clone.client = (ims.pci.vo.ClientLiteVo)this.client.clone();
		if(this.scheduleprofiles == null)
			clone.scheduleprofiles = null;
		else
			clone.scheduleprofiles = (ims.pci.vo.ClientPCIScheduleProfileVoCollection)this.scheduleprofiles.clone();
		if(this.stages == null)
			clone.stages = null;
		else
			clone.stages = (ims.pci.vo.ClientScheduleStageVoCollection)this.stages.clone();
		if(this.vaccinesummarystatus == null)
			clone.vaccinesummarystatus = null;
		else
			clone.vaccinesummarystatus = (ims.pci.vo.ClientVaccineSummaryVoCollection)this.vaccinesummarystatus.clone();
		clone.isValidated = this.isValidated;
		
		this.isBusy = false;
		return clone;
	}
	public int compareTo(Object obj)
	{
		return compareTo(obj, true);
	}
	public int compareTo(Object obj, boolean caseInsensitive)
	{
		if (obj == null)
		{
			return -1;
		}
		if(caseInsensitive); // this is to avoid eclipse warning only.
		if (!(ClientImmunisationScheduleVo.class.isAssignableFrom(obj.getClass())))
		{
			throw new ClassCastException("A ClientImmunisationScheduleVo object cannot be compared an Object of type " + obj.getClass().getName());
		}
		if (this.id == null)
			return 1;
		if (((ClientImmunisationScheduleVo)obj).getBoId() == null)
			return -1;
		return this.id.compareTo(((ClientImmunisationScheduleVo)obj).getBoId());
	}
	public synchronized static int generateValueObjectUniqueID()
	{
		return ims.vo.ValueObject.generateUniqueID();
	}
	public int countFieldsWithValue()
	{
		int count = 0;
		if(this.client != null)
			count++;
		if(this.scheduleprofiles != null)
			count++;
		if(this.stages != null)
			count++;
		if(this.vaccinesummarystatus != null)
			count++;
		return count;
	}
	public int countValueObjectFields()
	{
		return 4;
	}
	protected ims.pci.vo.ClientLiteVo client;
	protected ims.pci.vo.ClientPCIScheduleProfileVoCollection scheduleprofiles;
	protected ims.pci.vo.ClientScheduleStageVoCollection stages;
	protected ims.pci.vo.ClientVaccineSummaryVoCollection vaccinesummarystatus;
	private boolean isValidated = false;
	private boolean isBusy = false;
}
