

package gov.va.med.tfs.persistence.hibernate;

import gov.va.med.tfs.persistence.CreateFilterPersistenceManagerInterface;
import gov.va.med.tfs.tfdm.EntryFilter;
import gov.va.med.tfs.tfdm.FilterMetaData;
import gov.va.med.tfs.tfdm.FilterMetaDataInterface;

import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;


public class CreatableHibernateFilterPersistenceManager
    extends
        AbstractTfsHibernatePersistenceManager
    implements
        CreateFilterPersistenceManagerInterface
{
    public CreatableHibernateFilterPersistenceManager( )
    {
    }

    private String PERSIST_SUCCESSFUL = "Sucessfully Persisted Filter - Thank You";
    private String RECORD_EXISTS = "Record already exists -- Filter Not Persisted";
    private String PERSISTING_RECORD = "Persisting Record";

    /**
     * This method persists a single Filter Schema to the FILTER_SCHEMA table.
     * 
     * @param FilterMetaDataInterface filterMetaData - contains all of the Filter Schema information.
     * @param Session aSession - is a database reference to be used with the persistence request.
     * @throws FilterCacheException - thrown if the exception occurs while the database is storing the filter schema.
     */
    private String persistFilterSchema( FilterMetaDataInterface filterMetaData, Session aSession )
        throws Exception
    {

    	String persistReturn = PERSISTING_RECORD;
    	
    	persistifyVhimVersions( aSession, filterMetaData.getVhimVersionWrappers() );
            
        persistifyEntryFilters( aSession, filterMetaData.getEntryFilters() );
            
    	persistReturn = persistifyFilter( aSession, filterMetaData );
        
        if ( persistReturn.equals(PERSIST_SUCCESSFUL) )
        {
        	aSession.flush();
        }
    	
        aSession.close();
        return persistReturn;
        
    }
    
    
    /**
     * Entry Filters are many-to-many to FilterMetaData.  Each EntryFilter has a DomainEntryPoint and an Xpath.
     * I assume the combination of both makes a unique EntryFilter. 
     * @param aSession hibernate session to persist with
     * @param entryFilters set of entry filters to persist
     */
    private void persistifyEntryFilters( Session aSession, Set<EntryFilter> entryFilters )
    {
        EntryFilter[] entryFiltersArray = entryFilters.toArray( new EntryFilter[]{} );
        EntryFilter queryResult = null;
        
        Query query;
        
        for ( EntryFilter entryFilter : entryFiltersArray )
        {
            entryFilter.setDomainEntryPoint( persistifyDomainEntryPoint( aSession, entryFilter.getDomainEntryPoint() ) );

            if ( entryFilter.getXpath() != null )
            {
                query = aSession.getNamedQuery( "EntryFilterDomainXpath" ).setParameter( "xpath", entryFilter.getXpath() )
                                  .setParameter( "depw", entryFilter.getDomainEntryPoint() );
            }
            else
            {
                query = aSession.getNamedQuery( "EntryFilterDomainNullXpath" )
                                  .setParameter( "depw", entryFilter.getDomainEntryPoint() );
            }
                
            queryResult = (EntryFilter)query.uniqueResult();
            
            if ( queryResult != null )
            {
                entryFilters.remove( entryFilter ); 
                entryFilters.add( queryResult );
            }
        }
    }
    
    
    private String persistifyFilter( Session aSession, FilterMetaDataInterface aFilterMetaData )
    {
        FilterMetaData queryResult = null;
        String persistifyFilterReturn = RECORD_EXISTS;
        
        // check to see if that filter already exists in the database
        // if it does, replace the one in the FMD collection with the persistent version.
        Query query = aSession.getNamedQuery( "FilterSchemaId" ).setParameter( "filterId", aFilterMetaData.getFilterId() );
        queryResult = (FilterMetaData)query.uniqueResult();
            
        if ( queryResult == null )
        {
            aSession.save( aFilterMetaData );
            persistifyFilterReturn = PERSIST_SUCCESSFUL;
        }
        
        return persistifyFilterReturn;

    }

    
    /**
     * This method persists a single Filter Schema to the FILTER_SCHEMA table.
     * 
     * @param FilterMetaDataInterface filterMetaData - contains all of the Filter Schema information.
     * @throws FilterCacheException - thrown if the exception occurs while the database is storing the filter schema.
     */
    public String createFilterData( FilterMetaDataInterface aFilterMetaData )
        throws Exception
    {
        //Session session = this.sessionFactory.getCurrentSession();
        Session session = sessionFactory.openSession();
        return persistFilterSchema( aFilterMetaData, session );
    }

}
