/********************************************************************
 * Copyright © 2006 VHA. All rights reserved
 ********************************************************************/


package gov.va.med.fw.batchprocess;

import java.util.Iterator;
import java.util.Set;

import org.apache.commons.lang.Validate;

import gov.va.med.fw.scheduling.AbstractScheduledProcess;
import gov.va.med.fw.scheduling.ScheduledProcess;
import gov.va.med.fw.scheduling.ScheduledProcessInvocationContext;
import gov.va.med.fw.scheduling.SpawnedScheduledProcess;
import gov.va.med.fw.security.LoginManager;
import gov.va.med.fw.service.support.SpawnedThreadInvoker;
import gov.va.med.fw.util.InvalidConfigurationException;

/**
 * Abstract implementation that allows for concurrent processing of "other"
 * instances of ScheduledProcess.  Useful for large volume processing.
 * 
 * Created Apr 28, 2006 12:19:57 PM
 * @author DNS   BOHMEG
 */
public class AbstractConcurrentProcess extends AbstractScheduledProcess {
	private LoginManager loginManager;
	private Set processes;
	
	/* (non-Javadoc)
	 * @see gov.va.med.fw.scheduling.AbstractScheduledProcess#executeProcess(java.lang.Object)
	 */
	protected void executeProcess(ScheduledProcessInvocationContext invContext) throws Exception {
		// iterate through processes and launch in threads
		Iterator itr = getProcesses().iterator();
		ScheduledProcess targetProcess = null;
		SpawnedThreadInvoker invoker;
		SpawnedScheduledProcess spawnedProcess;
		while(itr.hasNext()) {
			targetProcess = (ScheduledProcess) itr.next();
			
			spawnedProcess = new SpawnedScheduledProcess();
			spawnedProcess.setContext(invContext);
			spawnedProcess.setProcess(targetProcess);
			spawnedProcess.setAuditInfo(targetProcess.getAuditInfo(invContext));
			spawnedProcess.setLoginManager(loginManager);
			
			invoker = new SpawnedThreadInvoker(spawnedProcess, false);
			invoker.execute();
		}
	}
	
	public void interrupt() {
		super.interrupt();
		
		// interrupt all spawned processes
		Iterator itr = getProcesses().iterator();
		while(itr.hasNext()) {
			((ScheduledProcess) itr.next()).interrupt();
		}
	}	

	
	/**
	 * @return Returns the processes.
	 */
	public Set getProcesses() {
		return processes;
	}

	/**
	 * @param processes The processes to set.
	 */
	public void setProcesses(Set processes) {
		this.processes = processes;
	}

	public void afterPropertiesSet() {
		Validate.notNull(loginManager, "A LoginManager is needed for the spawned threads");
		if(processes == null || processes.isEmpty())
			throw new InvalidConfigurationException("Must configure at least one ScheduledProcess to launch");
	}

	/**
	 * @return Returns the loginManager.
	 */
	public LoginManager getLoginManager() {
		return loginManager;
	}

	/**
	 * @param loginManager The loginManager to set.
	 */
	public void setLoginManager(LoginManager loginManager) {
		this.loginManager = loginManager;
	}
}
