/FileExtraction/Java_unseen/IMS-MAXIMS_openMAXIMS/Source Library/openmaxims_workspace/Pathways/src/ims/pathways/domain/impl/PathwayConfigurationImpl.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 Daniel Laffan using IMS Development Environment (version 1.60 build 2838.16667)
// Copyright (C) 1995-2007 IMS MAXIMS plc. All rights reserved.

package ims.pathways.domain.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import ims.admin.helper.RecordStatusValidator;
import ims.core.configuration.domain.objects.AppUser;
import ims.core.configuration.vo.AppUserRefVo;
import ims.core.vo.lookups.PreActiveActiveInactiveStatus;
import ims.core.vo.lookups.Specialty;
import ims.domain.DomainFactory;
import ims.domain.exceptions.DomainInterfaceException;
import ims.domain.exceptions.StaleObjectException;
import ims.framework.exceptions.CodingRuntimeException;
import ims.pathways.configuration.domain.objects.Pathway;
import ims.pathways.configuration.domain.objects.PathwayTarget;
import ims.pathways.configuration.domain.objects.PathwayTargetExternalEventMapping;
import ims.pathways.configuration.domain.objects.PathwayTargetRTTEvent;
import ims.pathways.configuration.vo.ExternalEventMappingRefVoCollection;
import ims.pathways.configuration.vo.PathwayRefVo;
import ims.pathways.configuration.vo.PathwayTargetRefVo;
import ims.pathways.configuration.vo.PathwayTargetRefVoCollection;
import ims.pathways.configuration.vo.RTTEventRefVoCollection;
import ims.pathways.domain.PathwaySearchAndSelect;
import ims.pathways.domain.base.impl.BasePathwayConfigurationImpl;
import ims.pathways.vo.PathwayShortVoCollection;
import ims.pathways.vo.PathwayTargetExternalEventMappingVoCollection;
import ims.pathways.vo.PathwayTargetRTTEventVoCollection;
import ims.pathways.vo.PathwayTargetVoCollection;
import ims.pathways.vo.PathwayVo;
import ims.pathways.vo.domain.ExternalEventMappingVoAssembler;
import ims.pathways.vo.domain.PathwayTargetExternalEventMappingVoAssembler;
import ims.pathways.vo.domain.PathwayTargetRTTEventVoAssembler;
import ims.pathways.vo.domain.PathwayTargetVoAssembler;
import ims.pathways.vo.domain.PathwayVoAssembler;
import ims.pathways.vo.domain.RTTEventVoAssembler;

public class PathwayConfigurationImpl extends BasePathwayConfigurationImpl
{

	private static final long serialVersionUID = 1L;

	/**
	* getPathway
	*/
	public ims.pathways.vo.PathwayVo getPathway(ims.pathways.configuration.vo.PathwayRefVo pathway)
	{
		if(pathway.getID_Pathway() == null)
			throw new CodingRuntimeException("No id provided for Pathway in method getPathway");

		return PathwayVoAssembler.create((Pathway) getDomainFactory().getDomainObject(pathway));
	}

	/**
	* savePathway
	*/
	public ims.pathways.vo.PathwayVo savePathway(ims.pathways.vo.PathwayVo voPathway,ims.pathways.vo.PathwayTargetVoCollection voCollPathwayTargets, PathwayTargetExternalEventMappingVoCollection voCollExMappings, PathwayTargetRTTEventVoCollection voCollRttMappings) throws ims.domain.exceptions.StaleObjectException, DomainInterfaceException
	{
		if(!voPathway.isValidated())
			throw new CodingRuntimeException("Pathway not validated");
		
		if(voCollPathwayTargets != null)
		{
			if(!voCollPathwayTargets.isValidated())
				throw new CodingRuntimeException("PathwayTargets not validated");
		}
		
		DomainFactory factory = getDomainFactory();
		
		if(voCollPathwayTargets != null)
			voPathway.setPathwayTargets(voCollPathwayTargets.toIRecordStatusTreeArray());
		
		RecordStatusValidator helper = new RecordStatusValidator(factory, getLookupService());
		helper.validate(voPathway);
		
		if(!isUniquePathwayByName(voPathway, factory))
			throw new DomainInterfaceException("Duplicate Active or Pre Active Pathway with this name already exists");
		
		if(!isValidDefaultPathway(voPathway, factory))
			throw new DomainInterfaceException("Default Pathway is already set for this specialty");
			
		//create a hashmap here to store the (newly) created domain objects so that their reference to 
		//the new vo's will be held onto after each assembler call - ask dlaffan or bworwood
		HashMap objMap = new HashMap();
		
		Pathway doPathway = PathwayVoAssembler.extractPathway(factory, voPathway, objMap);		
		if(doPathway.getName() != null)
			doPathway.setUpperName(doPathway.getName().toUpperCase());
		
		factory.save(doPathway);

		//save pathway targets
		if(voCollPathwayTargets != null)		
			savePathwayTargets(factory, voCollPathwayTargets, objMap);
	
		// Save External
		if(voCollExMappings != null)	
			saveExternalMappings(factory, voCollExMappings, objMap);

		// Save RTT
		if(voCollRttMappings != null)
			saveRTTMappings(factory, voCollRttMappings, objMap);
		
		return PathwayVoAssembler.create(doPathway);
	}

	private void saveRTTMappings(DomainFactory factory, PathwayTargetRTTEventVoCollection rttMappings, HashMap objMap) throws StaleObjectException
	{
		for (int j = 0; j < rttMappings.size(); j++)
		{			
			PathwayTargetRTTEvent domainRTT = PathwayTargetRTTEventVoAssembler.extractPathwayTargetRTTEvent(factory, rttMappings.get(j), objMap);
			
			if(domainRTT.getId() == null)
			{
				domainRTT.setStatus(getDomLookup(PreActiveActiveInactiveStatus.ACTIVE));
				domainRTT.setActivatedBy(getUser());
				domainRTT.setActivatedDateTime(new Date());
			}
			else if(domainRTT.getStatus().equals(getDomLookup(PreActiveActiveInactiveStatus.INACTIVE)))
			{
				//if pathway target is made inactive - also inactivate the mappings
				if(domainRTT.getPathwayTarget().getStatus().equals(getDomLookup(PreActiveActiveInactiveStatus.INACTIVE)))
					domainRTT.setStatus(getDomLookup(PreActiveActiveInactiveStatus.INACTIVE));	
				
				if(domainRTT.getInactivatedDateTime() == null)
				{
					domainRTT.setInactivatedBy(getUser());
					domainRTT.setInactivatedDateTime(new Date());
				}
			}
			factory.save(domainRTT);
		}
	}

	private void saveExternalMappings(DomainFactory factory, PathwayTargetExternalEventMappingVoCollection exMappings, HashMap objMap) throws StaleObjectException
	{
		for (int i = 0; i < exMappings.size(); i++)
		{
			PathwayTargetExternalEventMapping domainExternal = PathwayTargetExternalEventMappingVoAssembler.extractPathwayTargetExternalEventMapping(factory, exMappings.get(i),objMap);
			if(domainExternal.getId() == null)
			{
				domainExternal.setStatus(getDomLookup(PreActiveActiveInactiveStatus.ACTIVE));
				domainExternal.setActivatedBy(getUser());
				domainExternal.setActivatedDateTime(new Date());
			}
			else 
			{
				//if pathway target is made inactive - also inactivate the mappings
				if(domainExternal.getPathwayTarget().getStatus().equals(getDomLookup(PreActiveActiveInactiveStatus.INACTIVE)))
					domainExternal.setStatus(getDomLookup(PreActiveActiveInactiveStatus.INACTIVE));	
				
				if(domainExternal.getStatus().equals(getDomLookup(PreActiveActiveInactiveStatus.INACTIVE)))
				{
					if(domainExternal.getInactivatedDateTime() == null)
					{
						domainExternal.setInactivatedBy(getUser());
						domainExternal.setInactivatedDateTime(new Date());
					}
				}
			}	
			
			factory.save(domainExternal);
		}
	}

	private AppUser getUser()
	{
		if(getMosUser() != null)
		{
			AppUserRefVo user = ((ims.core.vo.MemberOfStaffShortVo)getMosUser()).getAppUser();
			return (AppUser) getDomainFactory().getDomainObject(user);
		}
		return null;
	}

	/**
	 * check for other pathways that are active/preactive with the same name
	 * @param pathway
	 * @param factory
	 * @return
	 */
	private boolean isUniquePathwayByName(PathwayVo pathway, DomainFactory factory)
	{
		if (pathway == null || pathway.getName() == null)
			throw new CodingRuntimeException("Mandatory argument - Location Name");
		
		if(pathway.getStatusIsNotNull() && !(pathway.getStatus().equals(PreActiveActiveInactiveStatus.PREACTIVE) || pathway.getStatus().equals(PreActiveActiveInactiveStatus.ACTIVE)))
			return true;
				
		ArrayList<String> markers = new ArrayList<String>();
		ArrayList<Serializable> values = new ArrayList<Serializable>();
		StringBuffer condStr = new StringBuffer();
		String strHql = "";
		
		strHql = "from Pathway pw where pw.upperName = :name";
		markers.add("name");
		values.add(pathway.getName().toUpperCase());
		
		if (pathway.getID_PathwayIsNotNull())
		{
			condStr.append( " and pw.id <> :id");
			markers.add("id");
			values.add(pathway.getID_Pathway());
		}
		
		condStr.append(" and (pw.status = :activeStatus");
		markers.add("activeStatus");
		values.add(getDomLookup(PreActiveActiveInactiveStatus.ACTIVE));
		condStr.append(" or pw.status = :preActiveStatus )");
		markers.add("preActiveStatus");
		values.add(getDomLookup(PreActiveActiveInactiveStatus.PREACTIVE));
		
		strHql += condStr.toString();
		java.util.List pathways = factory.find(strHql, markers, values);

		if(pathways != null && pathways.size() > 0)
			return false;
		
		return true;	
	}

	private boolean isValidDefaultPathway(ims.pathways.vo.PathwayVo pathway, DomainFactory factory)
	{
		//validating for default pathway
		if(!pathway.getIsDefault())
			return true;
		
		String validatingHql = "from Pathway path where path.status = :activeStatus and path.specialty = :specialty and path.isDefault = true";
		ArrayList markers = new ArrayList();
		ArrayList values = new ArrayList();
		
		markers.add("activeStatus");
		values.add(getDomLookup(PreActiveActiveInactiveStatus.ACTIVE));
		markers.add("specialty");
		values.add(getDomLookup(pathway.getSpecialty()));
		
		if(pathway.getID_PathwayIsNotNull())
		{
			markers.add("idPathway");
			values.add(pathway.getID_Pathway());
			validatingHql += " and path.id <> :idPathway";
		}
		
		List items = factory.find(validatingHql, markers, values);
		if(items != null && items.size() > 0)
		{
			return false;
		}
		
		return true;
	}

	/**
	* savePathwayTargets
	 * @param objMap 
	*/
	private void savePathwayTargets(DomainFactory factory, ims.pathways.vo.PathwayTargetVoCollection collPathwayTarget, HashMap objMap) throws ims.domain.exceptions.StaleObjectException
	{
		if(collPathwayTarget == null)
			return;
		
		List<PathwayTarget> newPathwayTargets = PathwayTargetVoAssembler.extractPathwayTargetList(factory, collPathwayTarget, null, objMap);
		Iterator<PathwayTarget> it2 = newPathwayTargets.iterator();
		while(it2.hasNext())
		{
			PathwayTarget doPathwayTarget = it2.next();
			factory.save(doPathwayTarget);
		}
	}

	public PathwayTargetVoCollection listPathwayTargetsByPathway(PathwayRefVo pathway)
	{
		if(pathway.getID_Pathway() == null)
			throw new CodingRuntimeException("pathway id is null in method listPathwayTargetsByPathway ");
		DomainFactory factory = getDomainFactory();
		List pathwayTargets = factory.find("from PathwayTarget pt where pt.pathway.id = '" + pathway.getID_Pathway() + "'"); 
		if(pathwayTargets != null && pathwayTargets.size() > 0)
			return PathwayTargetVoAssembler.createPathwayTargetVoCollectionFromPathwayTarget(pathwayTargets);
		
		return null;
	}

	public ExternalEventMappingRefVoCollection listExternalMappingsForPathwayTarget(PathwayTargetRefVo pt)
	{
		if(pt.getID_PathwayTarget() == null)
			throw new CodingRuntimeException("pathwaytarget id is null in method listExternalMappingsForPathwayTarget");
		
		DomainFactory factory = getDomainFactory();
		List mappings =  factory.find("select ptem.externalEventMapping from PathwayTargetExternalEventMapping as ptem where ptem.pathwayTarget.id = :idPathwayTarget", new String[] {"idPathwayTarget"}, new Object[] { pt.getID_PathwayTarget()});
		
		return ExternalEventMappingVoAssembler.createExternalEventMappingVoCollectionFromExternalEventMapping(mappings).toRefVoCollection();
	}

	public RTTEventRefVoCollection listRTTMappingsForPathwayTarget(PathwayTargetRefVo pt)
	{
		if(pt.getID_PathwayTarget() == null)
			throw new CodingRuntimeException("pathwaytarget id is null in method listRTTMappingsForPathwayTarget");
		
		DomainFactory factory = getDomainFactory();
		List rttEvents =  factory.find("select ptre.rTTEvent from PathwayTargetRTTEvent as ptre where ptre.pathwayTarget.id = :idPathwayTarget", new String[] {"idPathwayTarget"}, new Object[] { pt.getID_PathwayTarget()});
		return RTTEventVoAssembler.createRTTEventVoCollectionFromRTTEvent(rttEvents).toRefVoCollection();
	}

	public PathwayTargetExternalEventMappingVoCollection listPathwayTargetsExMappingsByPathwayTargets(PathwayTargetRefVoCollection pathwayTargets)
	{
		if(pathwayTargets.size() == 0)
			throw new CodingRuntimeException("no pathwayTargets sent for method listPathwayTargetsExMappingsByPathwayTargets");
		
		DomainFactory factory = getDomainFactory();
		
		StringBuffer hql = new StringBuffer(" from PathwayTargetExternalEventMapping pteem where pteem.status = :status and pteem.pathwayTarget.id in ");
		hql.append( "( " + getIdString(pathwayTargets) + " )"); 
		
		List ptExternalMappings = factory.find(hql.toString(), new String[] {"status"}, new Object[] {getDomLookup(PreActiveActiveInactiveStatus.ACTIVE)},1000);		
		return PathwayTargetExternalEventMappingVoAssembler.createPathwayTargetExternalEventMappingVoCollectionFromPathwayTargetExternalEventMapping(ptExternalMappings);
	}

	public PathwayTargetRTTEventVoCollection listPathwayTargetsRTTEventsByPathwayTargets(PathwayTargetRefVoCollection pathwayTargets)
	{
		if(pathwayTargets.size() == 0)
			throw new CodingRuntimeException("no pathwayTargets sent for method listPathwayTargetsRTTEventsByPathwayTargets");
		
		DomainFactory factory = getDomainFactory();
		
		StringBuffer hql = new StringBuffer(" from PathwayTargetRTTEvent ptrtt where ptrtt.status = :status and ptrtt.pathwayTarget.id in ");
		hql.append( "( " + getIdString(pathwayTargets) + " )"); 
		
		List ptRTTMappings = factory.find(hql.toString(), new String[] {"status"}, new Object[] {getDomLookup(PreActiveActiveInactiveStatus.ACTIVE)});		
		return PathwayTargetRTTEventVoAssembler.createPathwayTargetRTTEventVoCollectionFromPathwayTargetRTTEvent(ptRTTMappings);
	}
	
	private String getIdString(PathwayTargetRefVoCollection pathwayTargets)
	{
		String idString = "";
		
		for(int i=0;i<pathwayTargets.size();i++)
		{
			idString += pathwayTargets.get(i).getID_PathwayTarget();
			idString += ((pathwayTargets.size() - (i+1)) > 0 ? "," : "");
		}
		
		return idString;
	}

	public PathwayShortVoCollection listPathway(Specialty specialty) {
		PathwaySearchAndSelect impl = (PathwaySearchAndSelect) getDomainImpl(PathwaySearchAndSelectImpl.class);
		return impl.listPathway(null,specialty,null,null);
	}

}
