<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xsp="http://apache.org/xsp"
	xmlns:sdx="http://www.culture.gouv.fr/ns/sdx/sdx"
	exclude-result-prefixes="xsl">

	<!--
		Added at the beginning of each query.
	-->
	<xsl:template name="sdx:query-before">
		<xsp:logic>
        sdx_query=null; <!-- a query is requested, so delete all currents -->
			<xsl:call-template name="sdx:build-locations"/>
		</xsp:logic>
	</xsl:template>


	<!--
		Added at the end of each query.
	-->
	<xsl:template name="sdx:query-after">
		<xsp:logic>
            <!--setting the runtime encoding-->
            if (sdx_query != null) sdx_query.setEncoding(sdx_encoding);
			<xsl:call-template name="sdx:filter"/>
    if (sdx_filter != null &amp;&amp; sdx_query != null) sdx_query.addFilter(sdx_filter);

			<xsl:call-template name="sdx:baseQuery"/>
			<xsl:call-template name="sdx:boostQuery"/>
			<xsl:apply-templates select="sdx:expandQuery"/>

			<xsl:if test="ancestor::sdx:debug">
				<sdx:debug title="QUERY" element="{name()}">
					<xsp:attribute name="class">
						<xsp:expr>sdx_query</xsp:expr>
					</xsp:attribute>
					<xsp:expr>sdx_query</xsp:expr>
				</sdx:debug>
			</xsl:if>

			<!--
				This is used for nested conditional tags in a not executed query.
			-->
			<xsl:if test="sdx:success and not(starts-with(local-name(), 'execute'))">
    if (sdx_query != null )
    {
            		<xsl:apply-templates select="sdx:success"/>
    }
        		</xsl:if>

			<xsl:if test="sdx:fallback and not(starts-with(local-name(), 'execute'))">
    if (sdx_query == null)
    {
            		<xsl:apply-templates select="sdx:fallback"/>
				<!-- should do better (store and retrieve results) -->
        sdx_results=null;
    }
        		</xsl:if>

		</xsp:logic>

	</xsl:template>

	<!--
		Build a Results object (sdx_results) ;
		set page, hpp, sort specification with in order :
			1) a session cached Results (sdx_qid)
			2) the current Query (sdx_query)
	-->
	<xsl:template name="sdx:results" match="sdx:results">
		<xsp:logic>

			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'RESULTS - '"/>
			</xsl:call-template>

    sdx_results=null; sdx_page=-1; /* in case of dynamic hpp, pass it to a show */
            	<xsl:call-template name="sdx:sorts"/>
			<xsl:call-template name="sdx:hpp"/>

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'qid'"/>
			</xsl:call-template>

    sdx_qid=sdx_parameter;
            	<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'force'"/>
			</xsl:call-template>
    sdx_object=null;
    if (sdx_check(sdx_qid)) sdx_object=getSessionObject(session, sdx_qid);
    if (sdx_query == null) sdx_bool=false; // don't try to force query execute if there's no query
    if (sdx_object != null &amp;&amp; sdx_object instanceof Results
    &amp;&amp; !sdx_bool) /* get cached results if there are and not force execute query */
    {
            	<xsl:if test="ancestor::sdx:debug">
    if (sdx_results != null ) sdx_i=sdx_results.count(); else sdx_i=-1;
               	<sdx:debug title="RESULTS cached" element="{name()}">
					<xsp:attribute name="qid">
						<xsp:expr>sdx_qid</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="count">
						<xsp:expr>sdx_i</xsp:expr>
					</xsp:attribute>
				</sdx:debug>
			</xsl:if>

        sdx_results=(Results)sdx_object;

        <!--
        		Dynamic changes of hitsPerPage (HPP) try to give best page from requested
        		not useful for base query.
        -->
        sdx_results.setEncoding(sdx_encoding);
        sdx_j=sdx_results.getHitsPerPage();
        if (!(sdx_hpp == sdx_j)) /* if new hpp */
        { /* recalculate requested page on dynamic change of hpp */
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'page'"/>
				<xsl:with-param name="abbr" select="'p'"/>
			</xsl:call-template>
            sdx_page=(int)java.lang.Math.floor(  (((sdx_i-1)*sdx_j)+1)/sdx_hpp )+1;
            sdx_results.setHitsPerPage(sdx_hpp);

			<xsl:if test="ancestor::sdx:debug">
				<sdx:debug title="HPP dynamic">
					<xsp:attribute name="hppOld">
						<xsp:expr>sdx_j</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="hppNew">
						<xsp:expr>sdx_hpp</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="pageOld">
						<xsp:expr>sdx_i</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="pageNew">
						<xsp:expr>sdx_page</xsp:expr>
					</xsp:attribute>
				</sdx:debug>
			</xsl:if>
        }
        if (sdx_sorts != null) sdx_results.reSort(sdx_sorts);
    }
    if (sdx_results==null &amp;&amp; sdx_query != null) /* new results */
    {
        sdx_results=sdx_query.execute();
        sdx_results.service(cocoon_serviceManager);
        sdx_results.reSort(sdx_sorts);
        sdx_results.setHitsPerPage(sdx_hpp);
            /* cache results */
            <!-- THINK, TEST problem of a "static" query, repeated for each user -->
         sdx_string = setShowSessionObject(session, sdx_qid, sdx_results, sdx_qmax);//allowing called method to calculate key
        sdx_results.setId(sdx_string); /* to inform the method Results.toSAX() */
        sdx_qid=sdx_string;

			<xsl:if test="ancestor::sdx:debug">
    if (sdx_results != null ) sdx_i=sdx_results.count(); else sdx_i=-1;
               	<sdx:debug title="RESULTS" element="{name()}">
					<xsp:attribute name="count">
						<xsp:expr>sdx_i</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="query">
						<xsp:expr>sdx_query</xsp:expr>
					</xsp:attribute>
				</sdx:debug>
			</xsl:if>
    }
            <!--
            		This is used for nested conditional tags in a <sdx:results>.
            	-->
			<xsl:if test="sdx:success">
    if (sdx_results != null &amp;&amp; sdx_results.count() &gt; 0)
    {
	            <xsl:apply-templates select="sdx:success/node()"/>
    }
      		</xsl:if>

			<xsl:if test="sdx:fallback">
    if (sdx_results == null || sdx_results.count() == 0) /* <xsl:value-of select="name()"/>/sdx:fallback */
    {
            		<xsl:apply-templates select="sdx:fallback"/>
				<!-- should do better (store and retrieve results) -->
        sdx_results=null;
    }
        		</xsl:if>
    sdx_query=null; // clean current variables

        </xsp:logic>

	</xsl:template>


	<!--
		Output (.toSax()) current sdx object (sdx_results, sdx_terms, included document)
		with pipes
	-->
	<xsl:template match="sdx:show" name="sdx:show">
		<xsp:logic>

			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'show'"/>
			</xsl:call-template>

    if (sdx_pipeline != null) sdx_consumer=sdx_pipeline;
    else {sdx_consumer=(XMLConsumer)contentHandler; }
    if (sdx_results != null)
    {
        		<xsl:call-template name="sdx:hilite"/>
        if (sdx_pipeline != null) sdx_consumer=(XMLConsumer)sdx_pipeline;
            	<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'docs'"/>
			</xsl:call-template>
        if (sdx_bool)
        {
            sdx_pipeline = new GetDocumentsPipeline();
            sdx_pipeline.enableLogging(sdx_log);
            sdx_pipeline.service(cocoon_serviceManager);
            Parameters params = new Parameters();
            params.setParameter(GetDocumentsTransformation.SEND_INTERNAL_FIELDS, "true");
            sdx_pipeline.setParameters(params);
            /* change consumer */
            sdx_pipeline.setConsumer(sdx_consumer);
            	<xsl:if test="ancestor::sdx:debug">
				<sdx:debug title="PIPELINE docs">
					<xsp:attribute name="pipeline">
						<xsp:expr>sdx_pipeline</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="consumer">
						<xsp:expr>sdx_consumer</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="element">
						<xsl:value-of select="name()"/>
					</xsp:attribute>
				</sdx:debug>
			</xsl:if>
            sdx_consumer=(XMLConsumer)sdx_pipeline;
        }

        <!--
        		The sdx_show logic is :

			One string is common to all document, define in
			sdx_show by <sdx:page show="..." showParam="show" .../>
			a local show could be defined by <sdx:* show="..." showParam="?" .../>

			sdx_show2 store general or local show if one then, define params
         -->
        sdx_show2=sdx_show;
            <xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'show'"/>
				<xsl:with-param name="http" select="''"/>
			</xsl:call-template> if (sdx_parameter != null) sdx_show2=sdx_parameter;
        if (sdx_show2 != null &amp;&amp; sdx_show2.indexOf("documents") != -1)
        {
            sdx_pipeline = new GetDocumentsPipeline();
            sdx_pipeline.enableLogging(sdx_log);
            sdx_pipeline.service(cocoon_serviceManager);
            Parameters params =
                new Parameters();
            if (sdx_show2.indexOf("results") == -1) params.setParameter(GetDocumentsTransformation.SEND_SDX_ELEMENTS, "false");
            else params.setParameter(GetDocumentsTransformation.SEND_SDX_ELEMENTS, "true");
            if (sdx_show2.indexOf("fields") == -1)
            {
                params.setParameter(GetDocumentsTransformation.SEND_INTERNAL_FIELDS, "false");
                params.setParameter(GetDocumentsTransformation.SEND_USER_FIELDS, "false");
            }
            else
            {
                params.setParameter(GetDocumentsTransformation.SEND_INTERNAL_FIELDS, "true");
                params.setParameter(GetDocumentsTransformation.SEND_USER_FIELDS, "true");
            }
            sdx_pipeline.setParameters(params);

            /* change consumer */
            sdx_pipeline.setConsumer(sdx_consumer);
            sdx_consumer=(XMLConsumer)sdx_pipeline;
        }
            	<xsl:if test="ancestor::sdx:debug">
				<sdx:debug title="CONSUMER">
					<xsp:attribute name="consumer">
						<xsp:expr>sdx_consumer</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="element">
						<xsl:value-of select="name()"/>
					</xsp:attribute>
				</sdx:debug>
			</xsl:if>

        /* test if a numbered result requested */
            	<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'no'"/>
				<xsl:with-param name="abbr" select="'n'"/>
			</xsl:call-template>
        if (sdx_i &gt; 0)
        {
            sdx_j=sdx_results.getHitsPerPage();
            sdx_results.setHitsPerPage(1);
            sdx_results.toSAX(sdx_consumer, sdx_i);
            sdx_results.setHitsPerPage(sdx_j);
        }
        else if (sdx_page &gt; 0) {sdx_results.toSAX(sdx_consumer, sdx_page); } /* page setted by dynamic hpp */
        else  /* get a requested page */
        { <xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'page'"/>
				<xsl:with-param name="abbr" select="'p'"/>
			</xsl:call-template>
            sdx_results.toSAX(sdx_consumer, sdx_i);
        }
    }
    sdx_pipeline=null; sdx_consumer=null; sdx_results=null; // drop pipelines after one usage
        </xsp:logic>

	</xsl:template>


	<!-- ========================= SORT SPECIFICATION ======================== -->
	<xsl:template name="sdx:sorts">
		<xsp:logic>

			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'SORT'"/>
			</xsl:call-template>

			if(sdx_application != null) sdx_app=sdx_application;

			sdx_sorts=new SortSpecification();

			/*search the default value of maxsort in this documentbase*/
			if( (sdx_baseIds != null) &amp;&amp; (sdx_baseIds.length &gt; 0))
				if(sdx_baseId != null)
					sdx_sorts.setMaxSort(sdx_app.getDocumentBase(sdx_baseId).getDefaultMaxSort());
				else
					sdx_sorts.setMaxSort(sdx_app.getDocumentBase(sdx_baseIds[0]).getDefaultMaxSort());
			else
				sdx_sorts.setMaxSort(sdx_app.getDefaultDocumentBase().getDefaultMaxSort());

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'maxsort'"/>
			</xsl:call-template> sdx_sorts.setMaxSort(sdx_parameter);


            	<xsl:choose>

				<xsl:when test="sdx:sort">
					<xsl:apply-templates select="sdx:sort"/>
				</xsl:when>

				<xsl:otherwise>

					<xsl:call-template name="sdx:parameters">
						<xsl:with-param name="name" select="'sf'"/>
					</xsl:call-template> sdx_fields=sdx_parameters;

					<xsl:call-template name="sdx:parameters">
						<xsl:with-param name="name" select="'so'"/>
					</xsl:call-template>

    if (sdx_fields != null &amp;&amp; sdx_fields.length != 0 &amp;&amp; sdx_fields[0] != null)
        for (sdx_i=0; sdx_i &lt; sdx_fields.length; sdx_i++)
        {
            sdx_j=SortSpecification.SORT_ORDER_ASCENDANT;
            if (sdx_parameters == null || sdx_parameters.length &lt;= sdx_i) {}
            else if ("descendant".equalsIgnoreCase(sdx_parameters[sdx_i]) || "desc".equalsIgnoreCase(sdx_parameters[sdx_i]) || "1".equals(sdx_parameters[sdx_i]))
                sdx_j=SortSpecification.SORT_ORDER_DESCENDANT;

            sdx_sorts.addSortKey(sdx_fields[sdx_i], sdx_j, sdx_locations);
        }
				</xsl:otherwise>

			</xsl:choose>

		</xsp:logic>

	</xsl:template>

	<xsl:template name="sdx:sort" match="sdx:sort">
		<xsp:logic>

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'field'"/>
				<xsl:with-param name="http" select="''"/>
			</xsl:call-template>

			<xsp:logic>sdx_field=sdx_parameter;</xsp:logic>

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'order'"/>
				<xsl:with-param name="http" select="''"/>
			</xsl:call-template>

    if (sdx_field != null)
    {
        sdx_j=SortSpecification.SORT_ORDER_ASCENDANT;
        if (sdx_parameter == null) {}
        else if ("descendant".equals(sdx_parameter) || "desc".equals(sdx_parameter) || "1".equals(sdx_parameter) )
            sdx_j=SortSpecification.SORT_ORDER_DESCENDANT;
        sdx_sorts.addSortKey(sdx_field, sdx_j, sdx_locations);
    }
		</xsp:logic>

	</xsl:template>

	<!-- ========================= THE QUERIES ======================== -->
	<!--
		SimpleQuery : search a lucene query string
	-->
	<xsl:template match="sdx:executeSimpleQuery">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:simpleQuery"/>
			<xsl:call-template name="sdx:results"/>
			<xsl:call-template name="sdx:show"/>
		</xsp:logic>
	</xsl:template>

	<xsl:template name="sdx:simpleQuery" match="sdx:simpleQuery">
		<xsp:logic>

			<xsl:call-template name="sdx:query-before"/>

			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'build simpleQuery'"/>
			</xsl:call-template>

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'query'"/>
				<xsl:with-param name="abbr" select="'q'"/>
			</xsl:call-template>sdx_q=sdx_parameter;

            	<xsl:call-template name="sdx:field"/>

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'op'"/>
			</xsl:call-template>
    if (sdx_check(sdx_q))
    {
        sdx_query=new SimpleQuery();
        sdx_query.enableLogging(sdx_log);
        if (sdx_op &gt; 0) ((SimpleQuery)sdx_query).setUp(sdx_locations, sdx_field, sdx_q, sdx_op);
        else ((SimpleQuery)sdx_query).setUp(sdx_locations, sdx_field, sdx_q);
    }
			<xsl:call-template name="sdx:query-after"/>

		</xsp:logic>

	</xsl:template>


	<!--
            FieldQuery : search one value upon one field
    -->
	<xsl:template match="sdx:executeFieldQuery">
		<xsp:logic>

			<xsl:call-template name="comment"/>

			<xsl:call-template name="sdx:fieldQuery"/>

			<xsl:call-template name="sdx:results"/>

			<xsl:call-template name="sdx:show"/>

		</xsp:logic>

	</xsl:template>


	<xsl:template name="sdx:fieldQuery" match="sdx:fieldQuery">
		<xsp:logic>

			<xsl:call-template name="sdx:query-before"/>

			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'build simpleQuery'"/>
			</xsl:call-template>

			<xsl:call-template name="sdx:field"/>

			<xsl:call-template name="sdx:value"/>
    if (sdx_value != null )
    {
        sdx_query=new FieldQuery();
        sdx_query.enableLogging(sdx_log);
        ((FieldQuery)sdx_query).setUp(sdx_locations, sdx_value, sdx_field);
    }
			<xsl:call-template name="sdx:query-after"/>

		</xsp:logic>

	</xsl:template>


	<!--
		ListQuery : search an array of values upon on field
     -->
     <!-- TODO set operator (or default) -->
	<xsl:template match="sdx:executeListQuery">
		<xsp:logic>

			<xsl:call-template name="comment"/>

			<xsl:call-template name="sdx:listQuery"/>

			<xsl:call-template name="sdx:results"/>

			<xsl:call-template name="sdx:show"/>

		</xsp:logic>
	</xsl:template>


	<xsl:template name="sdx:listQuery" match="sdx:listQuery">
		<xsp:logic title="listQuery">

			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'build listQuery'"/>
			</xsl:call-template>

			<xsl:call-template name="sdx:query-before"/>

			<xsl:call-template name="sdx:field" />

			<xsl:call-template name="sdx:values" />

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'op'"/>
			</xsl:call-template>
    if (sdx_values != null)
    {
        sdx_query = new ComplexQuery();
        sdx_query.enableLogging(sdx_log);
        ((ComplexQuery)sdx_query).setUp(sdx_locations, sdx_op);
        for ( sdx_i=0; sdx_i &lt; sdx_values.length; sdx_i++ )
        {
          <!--
          	Le test !" ".equals(sdx_values[sdx_i]) a été conservé de SDX-1 ; Martin s'en souvient.
			Je crois que cela vient des select html sous certains navigateurs, n'envoyant pas la chaîne vide
		-->
            if (sdx_check(sdx_values[sdx_i]))
            {
                sdx_query2=new FieldQuery();
                sdx_query2.enableLogging(sdx_log);
                ((FieldQuery)sdx_query2).setUp(sdx_locations, sdx_values[sdx_i], sdx_field);
                        ((ComplexQuery)sdx_query).addComponent(sdx_query2);
          }
        }
    }
		<!--
		if (sdx_query != null &amp;&amp; ((ComplexQuery)sdx_query).size() == 0) sdx_query=null;
		-->
			<xsl:call-template name="sdx:query-after"/>

		</xsp:logic>

	</xsl:template>


	<xsl:template match="sdx:executeDateQuery | sdx:executeDateIntervalQuery">
		<xsp:logic>

			<xsl:call-template name="comment"/>

			<xsl:call-template name="sdx:dateQuery"/>

			<xsl:call-template name="sdx:results"/>

			<xsl:call-template name="sdx:show"/>

		</xsp:logic>

	</xsl:template>


	<!--
		Request on dates. from - to against one or two date fields

		- field [field] :   date field[s] to search against
		- from          :   begin date
		- to            :   end date
	-->
	<xsl:template name="sdx:dateQuery" match="sdx:dateIntervalQuery | sdx:dateQuery">
		<xsp:logic>

			<xsl:call-template name="sdx:query-before"/>

			<xsl:call-template name="sdx:fields"/>

			<xsl:call-template name="sdx:from"/>

			<xsl:call-template name="sdx:to"/>

            <xsl:call-template name="sdx:parameters">
                <xsl:with-param name="name" select="'inclusive'"/>
            </xsl:call-template>

    if (sdx_parameters == null || !sdx_check(sdx_parameters[0]))
        sdx_bool = true;//Bounds are inclusive by default
    else sdx_bool = sdx_boolean(sdx_parameters[0]);

    if (sdx_fields != null &amp;&amp; sdx_fields.length &gt; 0 &amp;&amp; (sdx_from!=null || sdx_to!=null))
    {
        <!-- match an interval from to, against another interval, fields[0], fields[1] -->
         if(sdx_from == null)
		sdx_from = fr.gouv.culture.sdx.utils.Date.parseDate("0001");
	  if(sdx_to == null)
		sdx_to = fr.gouv.culture.sdx.utils.Date.parseDate("9999");
        if (sdx_fields.length &gt; 1)
        {
            sdx_query = new ComplexQuery();
            sdx_query.enableLogging(sdx_log);
            ((ComplexQuery)sdx_query).setUp(sdx_locations, Query.OPERATOR_AND);
            sdx_object=sdx_query;
                        sdx_query = new DateIntervalQuery();
                        sdx_query.enableLogging(sdx_log);
                        ((DateIntervalQuery)sdx_query).setUp(sdx_locations, sdx_fields[0], fr.gouv.culture.sdx.utils.Date.parseDate("0001"), sdx_to, sdx_bool);
           ((ComplexQuery)sdx_object).addComponent(sdx_query);
                        sdx_query = new DateIntervalQuery();
                        sdx_query.enableLogging(sdx_log);
                if (sdx_parameters == null || !sdx_check(sdx_parameters[1]))
                    sdx_bool = true;//Bounds are inclusive by default
                else sdx_bool = sdx_boolean(sdx_parameters[1]);
                        ((DateIntervalQuery)sdx_query).setUp(sdx_locations, sdx_fields[1], sdx_from, fr.gouv.culture.sdx.utils.Date.parseDate("9999"), sdx_bool);
            ((ComplexQuery)sdx_object).addComponent(sdx_query);
            sdx_query=(ComplexQuery)sdx_object;
        }
        else
        {
                        sdx_query = new DateIntervalQuery();
                        sdx_query.enableLogging(sdx_log);
                        ((DateIntervalQuery)sdx_query).setUp(sdx_locations, sdx_fields[0], sdx_from, sdx_to, sdx_bool);
        }
    }
			<xsl:call-template name="sdx:query-after"/>

		</xsp:logic>

	</xsl:template>


	<!--
		LinearQuery

		A linear query is a line of "field=value operator", "field=value operator"...
			if no field given, it's default field
			if no operator given it's AND
		Value could not be complex Lucene query
     -->
	<xsl:template match="sdx:executeLinearQuery">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:linearQuery"/>
			<xsl:call-template name="sdx:results"/>
			<xsl:call-template name="sdx:show"/>
		</xsp:logic>
	</xsl:template>

	<xsl:template name="sdx:linearQuery" match="sdx:linearQuery">
		<xsp:logic>

			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'build linearQuery'"/>
			</xsl:call-template>

			<xsl:call-template name="sdx:query-before"/>

			<xsl:call-template name="sdx:fields"/>

			<xsl:call-template name="sdx:values"/>

			<xsl:call-template name="sdx:parameters">
				<xsl:with-param name="name" select="'op'"/>
			</xsl:call-template>
    if (sdx_values != null &amp;&amp; sdx_values.length!=0)
    {
        sdx_query=new LinearQuery();
        sdx_query.enableLogging(sdx_log);
        ((LinearQuery)sdx_query).setUp(sdx_locations, sdx_values, sdx_fields, sdx_ops, QueryParser.DEFAULT_OPERATOR);
    }
			<xsl:call-template name="sdx:query-after"/>

		</xsp:logic>

	</xsl:template>


	<!--
		ComplexQuery

		A complex query is an empty query to wich add components
	-->
	<xsl:template match="sdx:executeComplexQuery">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:complexQuery"/>
			<xsl:call-template name="sdx:results"/>
			<xsl:call-template name="sdx:show"/>
		</xsp:logic>
	</xsl:template>

	<xsl:template name="sdx:complexQuery" match="sdx:complexQuery">
		<xsl:param name="id" select="generate-id()"/>

		<xsp:logic>

        <xsl:call-template name="sdx:query-before"/>

    /* root is an OR query */
    // a unique variable name in the scope of this document, to allow nested complex query
    ComplexQuery sdx_cq<xsl:value-of select="$id"/> = new ComplexQuery();
    sdx_cq<xsl:value-of select="$id"/>.enableLogging(sdx_log);
    sdx_cq<xsl:value-of select="$id"/>.setUp(sdx_locations, Query.OPERATOR_OR);
    // another unique complex query, used for "and" operator
    ComplexQuery sdx_cqAnd<xsl:value-of select="$id"/> = new ComplexQuery();
    sdx_cqAnd<xsl:value-of select="$id"/>.enableLogging(sdx_log);
    sdx_cqAnd<xsl:value-of select="$id"/>.setUp(sdx_locations, Query.OPERATOR_AND);
    // another unique complex query, used for "or" operator
    ComplexQuery sdx_cqOr<xsl:value-of select="$id"/> = new ComplexQuery();
    sdx_cqOr<xsl:value-of select="$id"/>.enableLogging(sdx_log);
    sdx_cqOr<xsl:value-of select="$id"/>.setUp(sdx_locations, Query.OPERATOR_OR);
    // another unique complex query, used for "not" operator
    ComplexQuery sdx_cqNot<xsl:value-of select="$id"/> = new ComplexQuery();
    sdx_cqNot<xsl:value-of select="$id"/>.enableLogging(sdx_log);
    sdx_cqNot<xsl:value-of select="$id"/>.setUp(sdx_locations, Query.OPERATOR_NOT);


		<xsl:for-each select="sdx:*[contains(local-name(), 'Query') ]">
    sdx_query=null;
			<xsl:apply-templates select="."/>
				<!--
					Here we have the possible sdx_query, getting a possible operator.
				-->
				<xsl:call-template name="sdx:parameter">
					<xsl:with-param name="name" select="'complexop'"/>
				</xsl:call-template>
    if (sdx_query != null) // add a query, but careful to the logic, it's "complex"
    {
        if ( sdx_op == Query.OPERATOR_OR)
            sdx_cqOr<xsl:value-of select="$id"/>.addComponent(sdx_query);
        else if ( sdx_op == Query.OPERATOR_NOT)
           sdx_cqNot<xsl:value-of select="$id"/>.addComponent(sdx_query);
        else//default behavior if operator not present is "and" operator
            sdx_cqAnd<xsl:value-of select="$id"/>.addComponent(sdx_query);
     }
		</xsl:for-each>
    // stick the last if not empty
    if ( sdx_cqAnd<xsl:value-of select="$id"/>.size() &gt; 0 )
            sdx_cq<xsl:value-of select="$id"/>.addComponent(sdx_cqAnd<xsl:value-of select="$id"/>);
    if ( sdx_cqOr<xsl:value-of select="$id"/>.size() &gt; 0 )
            sdx_cq<xsl:value-of select="$id"/>.addComponent(sdx_cqOr<xsl:value-of select="$id"/>);
    if ( sdx_cqNot<xsl:value-of select="$id"/>.size() &gt; 0 )
            sdx_cq<xsl:value-of select="$id"/>.addComponent(sdx_cqNot<xsl:value-of select="$id"/>);
    sdx_query=null; // clean all first
    // give it, if there's something
    if (sdx_cq<xsl:value-of select="$id"/>.size() &gt; 0) sdx_query=sdx_cq<xsl:value-of select="$id"/>;
			<xsl:call-template name="sdx:query-after"/>

		</xsp:logic>

	</xsl:template>

	<!--
		ExpandQuery
	-->
	<xsl:template match="sdx:expandQuery" name="sdx:expandQuery">
		<xsp:logic>

			<xsl:choose>

				<xsl:when test="sdx:thesaurus">
					<xsl:apply-templates select="sdx:thesaurus"/>
				</xsl:when>

				<xsl:otherwise>
					<xsl:call-template name="sdx:thesaurus"/>
				</xsl:otherwise>

			</xsl:choose>


            <xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'field'"/>
			</xsl:call-template>
            sdx_field = sdx_parameter;

    if (sdx_thesaurus != null) /* the Thesaurus.expandQuery() method affects directly the sdx_query object by manipulating the underlying lucene query directly */
        sdx_results = sdx_thesaurus.expandQuery(sdx_query, sdx_field, sdx_relations, sdx_relationDepth, sdx_relationLangs);
        </xsp:logic>
	</xsl:template>


	<!--
		BaseQuery
	-->
	<xsl:template name="sdx:baseQuery">
		<xsp:logic>
    if (sdx_query!= null)
    {
	          <xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'bqid'"/>
			</xsl:call-template>
        if (sdx_parameter != null)
        {
            sdx_object=getSessionObject(session, sdx_parameter);
            if (sdx_object != null &amp;&amp; sdx_object instanceof Results)
            { <xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'bop'"/>
			</xsl:call-template>
                sdx_i=AbstractQuery.getOperator(sdx_parameter);
                sdx_query.addBaseQuery((Results)sdx_object, sdx_i);
            }
        }
    }
		</xsp:logic>

	</xsl:template>

	<!--
		BoostQuery
	-->
	<xsl:template name="sdx:boostQuery">
        <xsp:logic>
            if (sdx_query!= null)
            {
                  <xsl:call-template name="sdx:parameter">
                    <xsl:with-param name="name" select="'boost'"/>
                </xsl:call-template>
                if (sdx_parameter != null)
                {
                    sdx_query.setBoost(sdx_parameter);
                }
            }
        </xsp:logic>
    </xsl:template>

	<!--
		Build a filter.
	-->
	<!--TODO, a better nested syntax, <sdx:filter/> is not yet matched
    match="sdx:page//sdx:filter"
    perhaps something like?-rbp:
    <sdx:filter fop="et">
        <sdx:filter ff="dosslang" fv="fr"/>
        <sdx:filter fop="ou">
            <sdx:filter ff="dosstype" fv="Collectif"/>
            <sdx:filter ff="dosstype" fv="Artiste"/>
        </sdx:filter>
    </sdx:filter>
     -->
	<xsl:template name="sdx:filter">
    sdx_filter=null;
        <xsl:call-template name="sdx:parameters">
			<xsl:with-param name="name" select="'ff'"/>
		</xsl:call-template>
    sdx_fields=sdx_parameters;
        <xsl:call-template name="sdx:parameters">
			<xsl:with-param name="name" select="'fv'"/>
		</xsl:call-template>
    sdx_values=sdx_parameters;
    if (sdx_get(sdx_fields,0) != null &amp;&amp; sdx_get(sdx_values,0) != null)
    {
        sdx_filter=new Filter();
        <xsl:call-template name="sdx:parameter">
			<xsl:with-param name="name" select="'fop'"/>
		</xsl:call-template>
        sdx_filter.enableLogging(sdx_log);
        sdx_filter.setUp(sdx_op);
        for (sdx_i=0; sdx_i &lt; sdx_fields.length; sdx_i++)
        {
            sdx_field=sdx_get(sdx_fields, sdx_i);
            sdx_value=sdx_get(sdx_values, sdx_i);
            if (sdx_check(sdx_field) &amp;&amp; sdx_check(sdx_value))
            {
                sdx_criteria=new Criteria();
                sdx_criteria.setUp(sdx_locations.getField(sdx_field), sdx_value);
                sdx_filter.add(sdx_criteria);
            }
        }
    }
        	<xsl:if test="ancestor::sdx:debug">
			<sdx:debug title="FILTER" element="{name()}">
				<xsp:attribute name="class">
					<xsp:expr>sdx_filter</xsp:expr>
				</xsp:attribute>
				<xsp:expr>sdx_filter</xsp:expr>
			</sdx:debug>
		</xsl:if>

	</xsl:template>

	<!--
		sdx:criteria
	-->
	<xsl:template match="sdx:page//sdx:criteria">
    sdx_criteria=new Criteria();
        <xsl:call-template name="sdx:parameter">
			<xsl:with-param name="name" select="'field'"/>
			<xsl:with-param name="htpp" select="''"/>
		</xsl:call-template>
    sdx_field=sdx_parameter;
        <xsl:call-template name="sdx:parameter">
			<xsl:with-param name="name" select="'value'"/>
			<xsl:with-param name="htpp" select="''"/>
		</xsl:call-template>

		<!--
			TOTHINK

			This need the current sdx_locations to get a field, that means it's not easy
			to build a criteria (only a field-value couple), outside an executeQuery process
		-->
    sdx_value=sdx_parameter;
    if (sdx_check(sdx_field) &amp;&amp; sdx_check(sdx_value))
    {
        sdx_criteria.setUp(sdx_locations.getField(sdx_field), sdx_value);
    }
    </xsl:template>

</xsl:stylesheet>
