/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
// Package
package gov.va.med.fw.report.data;

// Java classes
import java.util.Map;

// Library classes
import org.apache.commons.lang.Validate;

// Framework classes
import gov.va.med.fw.report.ReportConfiguration;
import gov.va.med.fw.report.ReportException;
import gov.va.med.fw.report.ReportNameResolver;
import gov.va.med.fw.report.SimpleReportNameResolver;
import gov.va.med.fw.service.AbstractComponent;

/**
 * 
 *
 * Project: Framework</br>
 * Created on: 11:20:00 AM </br>
 *
 * @author DNS   LEV
 */
public abstract class AbstractReportDataService extends AbstractComponent implements ReportDataService {

	/**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = -2827771775513302070L;

	/**
	 * A map containing all report data daos
	 */
	private Map reportDataDAOs = null;
	
	/**
	 * An instance of nameResolver
	 */
	private ReportNameResolver nameResolver = null;
	
	/**
	 * A default constructor
	 */
	public AbstractReportDataService() {
		super();
	}

	/**
	 * @return Returns the nameResolver.
	 */
	public ReportNameResolver getNameResolver() {
		return nameResolver;
	}

	/**
	 * @param nameResolver The nameResolver to set.
	 */
	public void setNameResolver(ReportNameResolver nameResolver) {
		this.nameResolver = nameResolver;
	}
	
	/**
	 * @param reportDataDAOs The reportDataDAOs to set.
	 */
	public void setReportDataDAOs(Map reportDataDAOs) {
		this.reportDataDAOs = reportDataDAOs;
	}

	/**
	 * @see gov.va.med.fw.service.AbstractComponent#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		Validate.notEmpty( this.reportDataDAOs, "A report DAO map must be configured" );
		if( this.nameResolver == null ) {
			this.nameResolver = new SimpleReportNameResolver();
		}
	}

	/**
	 * @see gov.va.med.fw.report.data.ReportDataService#requestReportData(gov.va.med.fw.report.ReportConfiguration)
	 */
	public ReportData requestReportData( ReportConfiguration config ) throws ReportException {
		
		Validate.notNull( config, "A report configuration must not be NULL" );
		Validate.notNull( config.getQueryCriteria(), "A report query criteria must not be NULL" );
		
		// Perform any pre-processing operation in a DAO first 
		ReportDataDAO dao = this.getReportDataDAO( config );
		dao.preDataRetrieval( config );
		
		return this.doRequestData( config );
	}

	/** Returns a dao that is used to retrieve report data
	 * @param config A report configuration
	 * @return A report data dap
	 * @throws ReportException In case of errors getting a report data dao
	 */
	protected ReportDataDAO getReportDataDAO( ReportConfiguration config ) throws ReportException {
		String name = this.nameResolver.getReportName( config );
		if( !this.reportDataDAOs.containsKey( name ) ) {
			throw new ReportException("A report data DAO is missing for report: " + name );
		}
		Object componentName = reportDataDAOs.get( name );
		try {
			Object dao = this.getComponent( (String)componentName );
			return (ReportDataDAO)dao;
		}
		catch( Exception e ) {
			throw new ReportException("A report data dao " + componentName + " is not defined", e ); 
		}
	}
	
	/** Performs the actual tast of request for report data 
	 * 
	 * @param configuration A report configuration
	 * @return A report data
	 * @throws ReportException In case of errors request report data
	 */
	protected abstract ReportData doRequestData( ReportConfiguration configuration ) throws ReportException;

}