/**
 * 
 */


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


import gov.va.med.cds.filter.EntryFilterInterface;
import gov.va.med.cds.persistence.QueryAssociationInterface;
import gov.va.med.cds.persistence.ReadException;
import gov.va.med.cds.persistence.hibernate.interceptor.XmlTypeExtractQueryInterceptor;
import gov.va.med.cds.template.generated.JaxBMarshallerUnmarshallerInterface;

import java.util.List;
import java.util.Map;

import org.hibernate.Interceptor;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.internal.SessionImpl;


/**
 * @author DNS   egberb
 *
 * Query work implementation that sets up the Hibernate session with an Interceptor instance
 * if performing an extraction of data for an XMLType field.
 */
public class XmlTypeQueryWork
    extends
        PageableQueryWork
{

    public XmlTypeQueryWork( Session session, QueryAssociationInterface queryAssociation, EntryFilterInterface entryFilter,
                    QueryNameBuilderInterface queryNameBuilder, FilterParameterExtractorInterface filterParameterExtractor,
                    Map<String, QueryParameterTransformerInterface> parameterTransformerMap, QueryParameterBinderInterface queryParameterBinder,
                    List<String> personIdentifiers, Class<?> pointInTimeUserType, String applicationName, String siteId )
    {
        this( session, queryAssociation, entryFilter, queryNameBuilder, filterParameterExtractor, parameterTransformerMap, queryParameterBinder,
                        null, personIdentifiers, pointInTimeUserType, applicationName, siteId, null );
    }


    public XmlTypeQueryWork( Session session, QueryAssociationInterface queryAssociation, EntryFilterInterface entryFilter,
                    QueryNameBuilderInterface queryNameBuilder, FilterParameterExtractorInterface filterParameterExtractor,
                    Map<String, QueryParameterTransformerInterface> parameterTransformerMap, QueryParameterBinderInterface queryParameterBinder,
                    Map<String, String> templateTimeoutMap, List<String> personIdentifiers, Class<?> pointInTimeUserType, String applicationName,
                    String siteId, JaxBMarshallerUnmarshallerInterface marshallerUnmarshaller )
    {
        super( session, queryAssociation, entryFilter, queryNameBuilder, filterParameterExtractor, parameterTransformerMap, queryParameterBinder,
                        templateTimeoutMap, personIdentifiers, pointInTimeUserType, applicationName, siteId, marshallerUnmarshaller );
    }


    /*
     * (non-Javadoc)
     * @see gov.va.med.cds.persistence.hibernate.DefaultQueryWork#buildQuery(org.hibernate.Session, java.lang.String, gov.va.med.cds.filter.EntryFilterInterface, java.util.List)
     */
    @Override
    protected Query prepareQuery( Session session, String associationName, EntryFilterInterface entryFilter, List<String> personIdentifiers )
        throws ReadException
    {
        // Extend the existing query to support extraction of XMLType information if extraction 
        // expression is present in Entry Filter.
        
        // Start by preparing the query per the usual mechanisms.
        Query query = super.prepareQuery( session, associationName, entryFilter, personIdentifiers );

        // Configure the Hibernate Interceptor to use when performing an XML extraction of data if extraction is 
        // required by the filter.
        if ( entryFilter.getXpathExtractExpression() != null && entryFilter.getXpathExtractExpression().length() > 0 )
        {
            Interceptor interceptor = ( ( SessionImpl )session ).getInterceptor();
            if ( XmlTypeExtractQueryInterceptor.class.isInstance( interceptor ) )
            {
                ( ( XmlTypeExtractQueryInterceptor )interceptor ).setExtractExpression( entryFilter.getXpathExtractExpression() );
                ( ( XmlTypeExtractQueryInterceptor )interceptor ).setExtractExpressionNamespace( entryFilter.getXpathExtractExpressionNamespace() );
            }
        }

        return query;

    }

}
