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

package gov.va.med.fw.batchprocess;

import java.util.ArrayList;
import java.util.List;

/**
 * Abstract specialization for data files that contain Multiple Rows per Entity
 * (MRE). This involves a section header that indicates the start of the next
 * entity.  There is an assumption that the section header will always start the
 * entity data.
 * 
 * <p>For example, with B as the section header, in this sequence of rows
 * in the file: B, X, Y, Z, B, X, Y, B, Z, B - there are 4 entities in the file. 
 * 
 * <p>Statistics are captured at the entity level, not row level.
 * 
 * Created Mar 23, 2006 9:58:46 AM
 * 
 * @author DNS   BOHMEG
 */
public abstract class AbstractDataFileMREProcess extends
		AbstractDataFileListenerProcess {
	protected static final String NEW_ENTITY_ROW_RAW_DATA = "NEW_ENTITY_ROW_RAW_DATA";

	protected static final String ABORT_ENTIRE_ENTITY = "ABORT_ENTIRE_ENTITY";

	protected abstract boolean isNewEntityRow(String rowRawData);

	public final boolean beanCreationFailure(DataFileProcessExecutionContext context,
			String nextRowRawData, Exception e) {
		context.getExceptionData().add(context.getCurrentRowRawData());

		// ensure new entity row is listed in exception data for any problem
		// encountered in any of its rows
		if (!isNewEntityRow(context.getCurrentRowRawData())) {
			if (context.getContextData().containsKey(NEW_ENTITY_ROW_RAW_DATA)
					&& !context.getContextData().containsKey(
							ABORT_ENTIRE_ENTITY))
				context.getExceptionData().add(
						context.getContextData().get(NEW_ENTITY_ROW_RAW_DATA));
		}

		if (!context.getContextData().containsKey(ABORT_ENTIRE_ENTITY)) {
			context.getProcessStatistics().incrementNumberOfErrorRecords();
			context.getContextData().put(ABORT_ENTIRE_ENTITY, Boolean.TRUE);
		}

		boolean finishedWithEntity = isNewEntityRow(nextRowRawData) ? true
				: false;
		if (finishedWithEntity)
			removeTrackingKeys(context);

		return !finishedWithEntity;
	}

	public final void beanCreationSuccess(DataFileProcessExecutionContext context,
			String nextRowRawData) {
		if (isNewEntityRow(context.getCurrentRowRawData())) {
			removeTrackingKeys(context);			
			context.getContextData().put(NEW_ENTITY_ROW_RAW_DATA,
					context.getCurrentRowRawData());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see gov.va.med.fw.batchprocess.AbstractDataFileListenerProcess#acceptData(java.util.List,
	 *      java.lang.String, java.lang.String)
	 */
	public final boolean acceptData(DataFileProcessExecutionContext context,
			String nextRowRawData, List beans) {
		return (isNewEntityRow(nextRowRawData)) ? true : false;
	}
	
	public final void processDataRecords(DataFileProcessExecutionContext context, List acquiredData) {
		if(context.getContextData().containsKey(ABORT_ENTIRE_ENTITY)) {
			removeTrackingKeys(context);
			return;
		}
		
		processEntityData(context, new ArrayList(acquiredData)); // create new List in case of multiple threads processing
	}
	
	private void removeTrackingKeys(DataFileProcessExecutionContext context) {
		context.getContextData().remove(ABORT_ENTIRE_ENTITY);
		context.getContextData().remove(NEW_ENTITY_ROW_RAW_DATA);		
	}
	
	protected abstract void processEntityData(DataFileProcessExecutionContext context, List acquiredData);	
}
