<?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">
	<!--                                                                      -->
	<!-- ============================ OUTPUTS =============================== -->
	<!--                                                                      -->
	<!--
		<sdx:terms> : includes the list of terms of an index
	-->
	<xsl:template match="sdx:terms">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			sdx_terms=null;
			sdx_page=-1;
			<xsl:call-template name="sdx:build-locations"/>
			<xsl:call-template name="sdx:fields"/>
			<xsl:call-template name="sdx:values"/>
			<xsl:call-template name="sdx:hpp"/>
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'qid'"/>
			</xsl:call-template>
			sdx_object=getSessionObject(session, sdx_parameter);
			if (sdx_object != null &amp;&amp; sdx_object instanceof Terms)
			{
				sdx_terms=(Terms)sdx_object;
				<!-- dynamic changes of hitsPerPage
				try to give best page from requested
				not useful for base query -->
				if (sdx_hpp != sdx_terms.getHitsPerPage()) {
					/* if new 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_terms.getHitsPerPage())+1)/sdx_hpp )+1;
					sdx_terms.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>
				}
			}
			else if (sdx_fields != null &amp;&amp; sdx_fields.length != 0)
			{
				sdx_terms=new Terms();
				sdx_terms.enableLogging(sdx_log);
                sdx_terms.setEncoding(sdx_encoding);
				// more than one field, multi-key sort
				if (sdx_fields.length &gt; 1)
				{
                        <!--we try to get a qid, if none is provided we build terms as normal using a locations object-->
                        <xsl:call-template name="sdx:parameter">
                            <xsl:with-param name="name" select="'qid'"/>
                        </xsl:call-template>
                    if (sdx_check(sdx_parameter)) /* if we hava query id, we try to get cached results */
                        {
                            sdx_object=getSessionObject(session, sdx_parameter);
                            if (sdx_object != null &amp;&amp; sdx_object instanceof Results)
                            {
                                sdx_results=(Results)sdx_object;
                                if (sdx_results != null) sdx_terms.setUp(sdx_results, sdx_fields, sdx_values);
                            }
                        }
                    else if (sdx_locations != null) sdx_terms.setUp(sdx_locations, sdx_fields, sdx_values);


				}
				// 1 field, 1 value
				else if (sdx_values != null &amp;&amp; sdx_values.length != 0)
				{
                      <xsl:call-template name="sdx:parameter">
                            <xsl:with-param name="name" select="'qid'"/>
                        </xsl:call-template>
                    if (sdx_check(sdx_parameter)) /* if we hava query id, we try to get cached results */
                        {
                            sdx_object=getSessionObject(session, sdx_parameter);
                            if (sdx_object != null &amp;&amp; sdx_object instanceof Results)
                            {
                                sdx_results=(Results)sdx_object;
                                if (sdx_results != null) sdx_terms.setUp(sdx_results, sdx_fields[0], sdx_values[0]);
                            }
                        }
                     else if (sdx_locations != null) sdx_terms.setUp(sdx_locations, sdx_fields[0], sdx_values[0]);

				}
				// default case, one field
				else
				{
                     <xsl:call-template name="sdx:parameter">
                            <xsl:with-param name="name" select="'qid'"/>
                        </xsl:call-template>
                    if (sdx_check(sdx_parameter)) /* if we hava query id, we try to get cached results */
                        {
                            sdx_object=getSessionObject(session, sdx_parameter);
                            if (sdx_object != null &amp;&amp; sdx_object instanceof Results)
                            {
                                sdx_results=(Results)sdx_object;
                                if (sdx_results != null) sdx_terms.setUp(sdx_results, sdx_fields[0], null);
                            }
                        }
                    else if (sdx_locations != null) sdx_terms.setUp(sdx_locations, sdx_fields[0]);


				}
				sdx_terms.setHitsPerPage(sdx_hpp);

				/* caching */
				sdx_string = setShowSessionObject(session, null, sdx_terms, sdx_qmax);//allowing called method to calculate key
				/* to inform the toSAX() method */
				sdx_terms.setId(sdx_string);
                sdx_qid=sdx_string;

			}
			if (sdx_page &lt; 1) {
				<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=sdx_i;
			}
			if (sdx_terms != null) sdx_terms.toSAX(contentHandler, sdx_page);
		</xsp:logic>
	</xsl:template>
	<!--
		<sdx:includeDocument> : includes a document from the current document application
	-->
	<xsl:template match="sdx:includeDocument">
		<xsl:call-template name="sdx:base"/>
		<xsl:call-template name="sdx:id"/>
		<xsp:logic>
			//TODO : can also use a qid/no combination
			if (sdx_check(sdx_id))
			{
				sdx_consumer=(XMLConsumer)contentHandler;
				<xsl:call-template name="sdx:hilite"/>
				if (sdx_pipeline != null) sdx_consumer=(XMLConsumer)sdx_pipeline;
				sdx_document=new XMLDocument(sdx_id);
				/* don't know type */
				sdx_bool=false;
				/* if a type param given */
				if (Document.DOCTYPE_HTML.equals(sdx_type))
				{
					sdx_document=new HTMLDocument(sdx_id);
					sdx_bool=false;
				}
				else if (Document.DOCTYPE_XML.equals(sdx_type))
				{
					sdx_bool=false;
				}
				/* send document to stream */
				sdx_base.getDocument(
					(ParsableDocument)sdx_document,
					new IncludeXMLConsumer(sdx_consumer),
					sdx_bool);
				<xsl:call-template name="sdx:navigation"/>
			}
		</xsp:logic>
	</xsl:template>
	<xsl:template match="sdx:navigation" name="sdx:navigation">
		<xsp:logic>
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'qid'"/>
			</xsl:call-template>
            sdx_object=getSessionObject(session, sdx_parameter);
			if (sdx_object != null &amp;&amp; sdx_object instanceof Results)
			{
				//If an id is provided, it take precedence over the document's position
				if (sdx_check(sdx_id))
					((Results)sdx_object).getNavigationAsSAX(contentHandler, sdx_id);
				else {
					<xsl:call-template name="sdx:parameter">
						<xsl:with-param name="name" select="'no'"/>
						<xsl:with-param name="abbr" select="'n'"/>
					</xsl:call-template>
					((Results)sdx_object).getNavigationAsSAX(contentHandler, sdx_i);
				}
			}
		</xsp:logic>
	</xsl:template>
	<!--                                                                      -->
	<!-- ============================ INPUTS ================================ -->
	<!--                                                                      -->
	<!--     Administration of documents bases (insert, delete)               -->
	<!--                                                                      -->
	<!--
		check a documentbase integrity
	-->
	<xsl:template name="sdx:checkIntegrity">
		if(sdx_base != null) sdx_base.checkIntegrity();
	</xsl:template>
	<!--
		optimize a documentbase
	-->
	<xsl:template name="sdx:optimize">
		if(sdx_base != null) sdx_base.optimize();
	</xsl:template>

	<!--
		build a IndexParameters sdx_index with parameters
	-->
	<xsl:template match="sdx:index" name="sdx:index">
		<xsp:logic>

			sdx_index = new IndexParameters();

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'sameId'"/>
			</xsl:call-template>
			if (sdx_check(sdx_parameter))
			{
				//the default behavior is IndexParameters.SAME_ID_REPLACE
				if (sdx_parameter.equalsIgnoreCase("replace")) sdx_index.setSameId(IndexParameters.SAME_ID_REPLACE);
				if (sdx_parameter.equalsIgnoreCase("error")) sdx_index.setSameId(IndexParameters.SAME_ID_ERROR);
				if (sdx_parameter.equalsIgnoreCase("ignore")) sdx_index.setSameId(IndexParameters.SAME_ID_IGNORE);
			}
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'attachedDocumentSameId'"/>
			</xsl:call-template>
			if (sdx_check(sdx_parameter))
			{
				//the default behavior is IndexParameters.SAME_ID_SHARED_DOCUMENT_REFRESH
				if (sdx_parameter.equalsIgnoreCase("refresh")) sdx_index.setAttachedDocumentSameId(IndexParameters.SAME_ID_REFRESH_SHARED_DOCUMENT);
				if (sdx_parameter.equalsIgnoreCase("replace")) sdx_index.setAttachedDocumentSameId(IndexParameters.SAME_ID_REPLACE);
				if (sdx_parameter.equalsIgnoreCase("error")) sdx_index.setAttachedDocumentSameId(IndexParameters.SAME_ID_ERROR);
				if (sdx_parameter.equalsIgnoreCase("ignore")) sdx_index.setAttachedDocumentSameId(IndexParameters.SAME_ID_IGNORE);
			}
            <!--setting the parameter for shared secondary documents (attached and sub documents) having ids as existing documents-->
            <xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'subDocumentSameId'"/>
			</xsl:call-template>
			if (sdx_check(sdx_parameter))
			{
				//the default behavior is IndexParameters.REFRESH_SHARED_DOCUMENT
				if (sdx_parameter.equalsIgnoreCase("refresh")) sdx_index.setSubDocumentSameId(IndexParameters.SAME_ID_REFRESH_SHARED_DOCUMENT);
				if (sdx_parameter.equalsIgnoreCase("replace")) sdx_index.setSubDocumentSameId(IndexParameters.SAME_ID_REPLACE);
				if (sdx_parameter.equalsIgnoreCase("error")) sdx_index.setSubDocumentSameId(IndexParameters.SAME_ID_ERROR);
				if (sdx_parameter.equalsIgnoreCase("ignore")) sdx_index.setSubDocumentSameId(IndexParameters.SAME_ID_IGNORE);
			}
            <!--TODO what other index parameters for same id are possible? one parameter specifically for subdocument?-->


			<!-- 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
			-->

			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'show'"/>
				<xsl:with-param name="http" select="''"/>
			</xsl:call-template>
			sdx_show2=sdx_show;
			if (sdx_check(sdx_parameter)) sdx_show2=sdx_parameter;
			if (sdx_show2 != null)
			{
				if (sdx_show2.indexOf("summary") != -1) sdx_index.setSendIndexationEvents(IndexParameters.SEND_STATS_EVENTS);
				if (sdx_show2.indexOf("failures") != -1) sdx_index.setSendIndexationEvents(IndexParameters.SEND_ERRORS_EVENTS);
				if (sdx_show2.indexOf("additions") != -1) sdx_index.setSendIndexationEvents(IndexParameters.SEND_ALL_EVENTS);
			}
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'batch'"/>
			</xsl:call-template>
			if (sdx_i &gt; 0) sdx_index.setBatchMax(sdx_i);
			<xsl:choose>
				<!-- if user pipeline given, parse it, if not, get default -->
				<xsl:when test="sdx:pipeline/sdx:transformation">
					<xsl:apply-templates select="sdx:pipeline"/>
					if (sdx_pipeline != null) sdx_index.setPipeline(sdx_pipeline);
					sdx_pipeline=null;
				</xsl:when>
				<xsl:when test="sdx:pipeline/sdx:parameter">
					if (sdx_base != null) sdx_pipeline=sdx_base.getIndexationPipeline();
				</xsl:when>
			</xsl:choose>
			<xsl:if test="sdx:pipeline/sdx:parameter">
				if (sdx_pipeline != null)
				//TODO?:fred why are you nullifying the pipe above?-rbp
					sdx_params=sdx_pipeline.getParameters();
				if (sdx_index != null &amp;&amp; sdx_index.getPipeline() != null)
					sdx_params=sdx_index.getPipeline().getParameters();
				if (sdx_params == null)
					sdx_params=new Parameters();
				<!-- add indexation parameters on each tag sdx:parameter -->
				<xsl:for-each select="sdx:pipeline/sdx:parameter">
					<xsl:apply-templates select="."/>
					if (sdx_params != null &amp;&amp; sdx_name != null &amp;&amp; sdx_parameter != null)
						sdx_params.setParameter(sdx_name, sdx_parameter);
				</xsl:for-each>
				sdx_index.setPipelineParams(sdx_params);
			</xsl:if>
			<xsl:if test="ancestor::sdx:debug">
				<sdx:debug title="INDEXATION PARAMETERS">
					<xsp:attribute name="element">
						<xsl:value-of select="name()"/>
					</xsp:attribute>
				</sdx:debug>
			</xsl:if>
		</xsp:logic>
	</xsl:template>
	<!-- build a document -->
	<xsl:template name="sdx:document" match="sdx:page//sdx:document">
		<xsl:param name="parameters" select="true()"/>
		<xsp:logic>
			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'DOCUMENT'"/>
			</xsl:call-template> sdx_document=null;
			<xsl:if test="$parameters">
				<!-- id could be modified or setted by url, or indexed content -->
				<xsl:call-template name="sdx:id"/>
				<!-- type could be modified by content -->
				<xsl:call-template name="sdx:type"/>
				<xsl:call-template name="sdx:url"/>
				<xsl:call-template name="sdx:file"/>
				<xsl:call-template name="sdx:xml"/>
				<xsl:call-template name="sdx:dom"/>
			</xsl:if>
			/* set type */
			if ("text/xml".equals(sdx_type)) sdx_document=new XMLDocument();
			else if ("text/html".equals(sdx_type)) sdx_document=new HTMLDocument();
			else if (Document.DOCTYPE_XML.equals(sdx_type)) { sdx_type="text/xml"; sdx_document=new XMLDocument(); }
			else if (Document.DOCTYPE_HTML.equals(sdx_type)) { sdx_type="text/html"; sdx_document=new HTMLDocument(); }
			else if (sdx_check(sdx_xml)) { sdx_type="text/xml"; sdx_document=new XMLDocument();}
			else if (sdx_url != null) { sdx_type="text/xml"; sdx_document=new XMLDocument(); }
			else if (sdx_dom != null) { sdx_type="text/xml"; sdx_document=new XMLDocument(); }
			else { sdx_document=new XMLDocument(); sdx_type="text/xml"; }

			if (sdx_check(sdx_type)) sdx_document.setMimeType(sdx_type);

			/* set id */
			if (sdx_check(sdx_id)) sdx_document.setId(sdx_id);
			else if (sdx_url != null) sdx_document.setId(sdx_url.toExternalForm());
			/* set content */
			if (sdx_url != null) sdx_document.setContent(sdx_url);
			else if (sdx_check(sdx_xml)) sdx_document.setContent(sdx_xml.getBytes("UTF-8"));
			else if (sdx_file != null) sdx_document.setContent(sdx_file);
			else if (sdx_dom != null) ((XMLDocument)sdx_document).setContent(sdx_dom);
			else sdx_document=null;
		</xsp:logic>
	</xsl:template>
	<xsl:template match="sdx:uploadDocument">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			try{
				<xsl:call-template name="sdx:repo"/>
			}
			catch(SDXException e)
			{} // repo can be null

				<xsl:call-template name="sdx:document"/>
				if (sdx_document != null)
				{
					<xsl:call-template name="sdx:index"/>
					sdx_base.index((IndexableDocument)sdx_document, sdx_repo, sdx_index , contentHandler);
					<xsl:apply-templates select="sdx:success/node()"/>
					<xsl:call-template name="sdx:parameter">
						<xsl:with-param name="name" select="'optimize'"/>
					</xsl:call-template>
					if ( sdx_bool ) {
						<xsl:call-template name="sdx:optimize"/>
					}
					<!--<xsl:if test="@optimize='true'"><xsl:call-template name="sdx:optimize"/></xsl:if>-->
				}
				else
				{
					<xsl:apply-templates select="sdx:fallback/*"/>
				}

		</xsp:logic>
	</xsl:template>
	<xsl:template match="sdx:uploadDocuments">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			try{
				<xsl:call-template name="sdx:repo"/>
			}
			catch(SDXException e)
			{} // repo can be null

			if (sdx_check(sdx_type)) sdx_type="text/xml";

				<!-- sources for documents -->
				<xsl:call-template name="sdx:dir"/>
				<xsl:call-template name="sdx:url"/>
				<xsl:call-template name="sdx:zip"/>
				<xsl:call-template name="sdx:type"/>
				if (sdx_zip != null) sdx_dir=sdx_unzip(sdx_zip);
				if (sdx_dir != null)
				{
					<xsl:call-template name="sdx:parameter">
						<xsl:with-param name="name" select="'includes'"/>
					</xsl:call-template>
					sdx_pattern=sdx_parameter;
					<xsl:call-template name="sdx:parameter">
						<xsl:with-param name="name" select="'excludes'"/>
					</xsl:call-template>
					sdx_vector=sdx_dir(sdx_dir, sdx_pattern, sdx_parameter, null);
					sdx_enum = sdx_vector.elements();
					sdx_documents=new IndexableDocument[sdx_vector.size()];
					<xsl:if test="ancestor::sdx:debug">
						<sdx:debug title="DOCUMENTS">
							<xsp:attribute name="size">
								<xsp:expr>sdx_vector.size()</xsp:expr>
							</xsp:attribute>
						</sdx:debug>
					</xsl:if>
					sdx_i=0;
					while (sdx_enum.hasMoreElements())
					{
						sdx_document=new XMLDocument();
						if (false) {}
						else if ("text/html".equals(sdx_type)) sdx_document=new HTMLDocument();
						else if (Document.DOCTYPE_HTML.equals(sdx_type))
						{
							sdx_type="text/html";
							sdx_document=new HTMLDocument();
						}
						sdx_file=(File)sdx_enum.nextElement();
                        if (sdx_url != null)
                            sdx_document.setContent(sdx_file.toURL());
						else
                            sdx_document.setContent(sdx_file);
						<xsl:if test="ancestor::sdx:debug">
							<sdx:debug title="DOCUMENT">
								<xsp:attribute name="n">
									<xsp:expr>sdx_i</xsp:expr>
								</xsp:attribute>
								<xsp:attribute name="file">
									<xsp:expr>sdx_file</xsp:expr>
								</xsp:attribute>
							</sdx:debug>
						</xsl:if>
						sdx_documents[sdx_i]=sdx_document;
						sdx_i++;
					}
					<xsl:call-template name="sdx:index"/>
					sdx_base.index((IndexableDocument[])sdx_documents, sdx_repo, sdx_index , contentHandler);
					<xsl:call-template name="sdx:parameter">
						<xsl:with-param name="name" select="'optimize'"/>
					</xsl:call-template>
					if ( sdx_bool ) {
						<xsl:call-template name="sdx:optimize"/>
					}
					<!--<xsl:if test="@optimize='true'"><xsl:call-template name="sdx:optimize"/></xsl:if>-->
					<xsl:apply-templates select="sdx:success/node()"/>
                    if (sdx_zip != null &amp;&amp; sdx_dir != null)
                            FileUtil.deleteDirectory(sdx_dir);//recursive delete of tmp zip dir
				}
				else
				{
					<xsl:apply-templates select="sdx:fallback/node()"/>
				}

		</xsp:logic>
	</xsl:template>
	<!--
            Ce tag permet de supprimer un document d'une base. Il prend un paramètre,
            soit le nom du paramètre qui contient l'identificateur du document.
            Ce paramètre doit être dans l'attribut "idParam".
    -->
	<xsl:template match="sdx:deleteDocument ">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:base"/>
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'delete'"/>
			</xsl:call-template>
			if (sdx_bool)
			{
				<xsl:call-template name="sdx:id"/>

				if (sdx_check(sdx_id))
				{

					<!-- in fact, we don't need to know the type of document before delete, TEMP -->
					sdx_document=new XMLDocument(sdx_id);


					sdx_base.delete(sdx_document, contentHandler);


					<xsl:apply-templates select="sdx:success"/>


					<xsl:call-template name="sdx:parameter">
						<xsl:with-param name="name" select="'optimize'"/>
					</xsl:call-template>
					if ( sdx_bool ) {


						<xsl:call-template name="sdx:optimize"/>
					}
					<!--<xsl:if test="@optimize='true'"><xsl:call-template name="sdx:optimize"/></xsl:if>-->
				}
			}
			<xsl:if test="sdx:fallback">
				else
				{
					<xsl:apply-templates select="sdx:fallback"/>
				}
			</xsl:if>
		</xsp:logic>
	</xsl:template>
	<!--
		Behaviour : reacts on a qid attribute,
		or on the queries nested ;
		queries may be executed before deleting
	-->
	<xsl:template match="sdx:deleteDocuments">
		<xsp:logic>
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'delete'"/>
			</xsl:call-template>
			if (sdx_bool)
			{
				<xsl:call-template name="comment"/>
				sdx_query=null;
				sdx_results=null;
				<xsl:call-template name="sdx:build-locations"/>
				<xsl:apply-templates select="*[contains(name(), 'Query')]"/>
				<xsl:call-template name="sdx:results"/>
				if (sdx_results != null)
				{
					sdx_pipeline = new DeleteResultsPipeline();
					sdx_pipeline.enableLogging(sdx_log);
					/* needed so that the framework will be available for executing the deletions */
					sdx_pipeline.service(cocoon_serviceManager);
					/* indicates the id of the application from which deletion is desired */
					((DeleteResultsPipeline)sdx_pipeline).setApplicationId(sdx_application.getId());
					/* the content handler to feed with deletion events */
					sdx_pipeline.setConsumer((XMLConsumer)contentHandler);
					/* passing result events to the delete results transformation */
					<!-- use the show template -->
					// sdx_results.toSAX(sdx_pipeline);
					<xsl:call-template name="sdx:show"/>
					sdx_results=null;
					session.removeAttribute("sdx_"+sdx_qid);
					<xsl:call-template name="sdx:parameter">
						<xsl:with-param name="name" select="'optimize'"/>
					</xsl:call-template>
					if ( sdx_bool ) {
						<xsl:call-template name="sdx:optimize"/>
					}
					<!--<xsl:if test="@optimize='true'"><xsl:call-template name="sdx:optimize"/></xsl:if>-->
				}
			}
		</xsp:logic>
	</xsl:template>
	<!--                                                                      -->
	<!-- ========================== RIGHTS =================================== -->
	<!--                                                                      -->
	<xsl:template match="sdx:login">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:app"/>
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'id'"/>
			</xsl:call-template> sdx_id=sdx_parameter;
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'pass'"/>
			</xsl:call-template>
			<xsl:if test="ancestor::sdx:debug">
				<sdx:debug title="LOGIN">
					<xsp:attribute name="id">
						<xsp:expr>sdx_id</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="pass">
						<xsp:expr>sdx_parameter</xsp:expr>
					</xsp:attribute>
					<xsp:attribute name="element">
						<xsl:value-of select="name()"/>
					</xsp:attribute>
					<xsp:attribute name="app">
						<xsp:expr>sdx_app</xsp:expr>
					</xsp:attribute>
				</sdx:debug>
			</xsl:if>
			if (sdx_check(sdx_id))
			{
                if (sdx_app != null &amp;&amp; sdx_app.validateUser(sdx_id, sdx_parameter))
				{
					/* logged-in */
					sdx_user=sdx_app.getUserInformation(sdx_id);
					session.setAttribute("sdx_user", sdx_user);
					<xsl:apply-templates select="*[name()!='sdx:fallback']"/>
				}
				/* not logged-in */
				else
				{
					<xsl:apply-templates select="sdx:fallback/*"/>
				}
			}
		</xsp:logic>
	</xsl:template>
	<xsl:template match="sdx:loginSu">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'id'"/>
			</xsl:call-template>
			sdx_id=sdx_parameter;
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'pass'"/>
			</xsl:call-template>
			if (sdx_check(sdx_id) &amp;&amp; sdx_check(sdx_parameter))
			{
				try {
					sdx_user=sdx_frame.validateSuperUser(sdx_id, sdx_parameter);
					session.setAttribute("sdx_user", sdx_user);
					<xsl:apply-templates select="*[name()!='sdx:fallback']"/>
				}
				catch(Exception e) {
					<xsl:apply-templates select="sdx:fallback/*"/>
				}
			}
		</xsp:logic>
	</xsl:template>
	<!--
    When this tag is matched,
    if the sdx:parameter @logout is set to true
    then any user saved in session is replaced
    by anonymous user
   -->
	<xsl:template match="sdx:logout">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:app"/>
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'logout'"/>
			</xsl:call-template>
			if (sdx_check(sdx_parameter))
			{
				if (sdx_app != null) sdx_user=sdx_app.getUserInformation(null);
				else sdx_user=null;
				session.setAttribute("sdx_user", sdx_user);
			}
		</xsp:logic>
	</xsl:template>
	<xsl:template match="sdx:userIsAdmin ">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:app"/>
			if (sdx_app != null) sdx_parameter=sdx_app.getDefaultAdminGroupId();
			if (sdx_user != null &amp;&amp; sdx_app != null &amp;&amp;
				sdx_app.getId().equals(sdx_user.getAppId()) &amp;&amp;
				sdx_user.isMember(sdx_parameter))
			{
				<xsp:logic>
					<xsl:apply-templates select="*[name()!='sdx:fallback']"/>
				</xsp:logic>
			}
			<xsl:if test="sdx:fallback">
				/* not Member */
				else
				{
					<xsp:logic>
						<xsl:apply-templates select="sdx:fallback/*"/>
					</xsp:logic>
				}
			</xsl:if>
		</xsp:logic>
	</xsl:template>
	<xsl:template match="sdx:userIsMember">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			<xsl:call-template name="sdx:app"/>
			<xsl:call-template name="sdx:parameters">
				<xsl:with-param name="name" select="'group'"/>
			</xsl:call-template>
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'op'"/>
			</xsl:call-template>
			if (sdx_op == Query.OPERATOR_AND) sdx_bool=true;
			else sdx_bool=false;
			/* isMember */
			if (sdx_user != null &amp;&amp; sdx_app != null &amp;&amp;
				sdx_app.getId().equals(sdx_user.getAppId()) &amp;&amp;
				sdx_user.isMember(sdx_parameters, sdx_bool))
			{
				<xsl:apply-templates select="*[name()!='sdx:fallback']"/>
			}
			/* not Member */
			else
			{
				<xsl:apply-templates select="sdx:fallback/*"/>
			}
		</xsp:logic>
	</xsl:template>
	<xsl:template match="sdx:userIsSu">
		<xsp:logic>
			<xsl:call-template name="comment"/>
			if (sdx_frame.isSuperUserSet() &amp;&amp; sdx_user != null &amp;&amp; sdx_user.isSuperuser())
			/* isMember */
			{
				<xsl:apply-templates select="*[name()!='sdx:fallback']"/>
			}
			/* not isMember */
			else
			{
				<xsl:apply-templates select="sdx:fallback/*"/>
			}
		</xsp:logic>
	</xsl:template>
	<xsl:template match="sdx:userIsAdminOrSu">
		<xsl:call-template name="comment"/>
		<xsl:call-template name="sdx:app"/>
		<xsp:logic>
			if (
				(sdx_app !=null &amp;&amp;
				sdx_app.getId().equals(sdx_user.getAppId()) &amp;&amp;
				sdx_user.isMember(sdx_app.getDefaultAdminGroupId()))
				||
				(sdx_frame.isSuperUserSet() &amp;&amp; sdx_user != null &amp;&amp; sdx_user.isSuperuser())
			)
			/* isMember */
			{
				<xsl:apply-templates select="*[name()!='sdx:fallback']"/>
			}
			/* not isMember */
			else
			{
				<xsl:apply-templates select="sdx:fallback/*"/>
			}
		</xsp:logic>
	</xsl:template>


	<!--=======================================================================-->
	<!--   add id document to a session caddy                                  -->
	<!--=======================================================================-->
	<xsl:template match="sdx:addToCaddy">

		<xsp:logic>

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

		org.w3c.dom.Node currentNotice = null;

		<!-- ids documents -->
		<xsl:call-template name="sdx:parameters">
			<xsl:with-param name="name" select="'id'"/>
		</xsl:call-template>
		String[] caddy_docIds2add = sdx_parameters;

		<!-- id search -->
		<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 -->
		<!-- get cached results if there are and not force execute query -->
    if (sdx_object != null &amp;&amp; sdx_object instanceof Results &amp;&amp; !sdx_bool)
				caddy_results = (Results) sdx_object;
		<!-- if(sdx_results!=null) docIds = sdx_results.getDocIds(); -->

		<!-- adding all documents in the caddy -->
		if( caddy_results!=null &amp;&amp; caddy_results.count() > -1 ){
			 caddy_docIds2add = caddy_results.getDocIds();
		}

		if(caddy_docIds2add!=null &amp;&amp; caddy_docIds2add.length > 0){

			int nb2add = caddy_docIds2add.length;

			<!-- the batch of documents exceeds the limit of the caddy -->
			if( (nb2add + sdx_caddyNbDocs) > sdx_caddyLimit){
				<xsl:apply-templates select="sdx:fallback/node()" />
			}
			else {

				<!-- loop on ids to add -->
				sdx_id = null;
				for( sdx_i = 0; sdx_i &lt; nb2add; sdx_i++ ){

					<!-- current id -->
					sdx_id = caddy_docIds2add[sdx_i];
					<!-- is the current doc in the caddy ? so we don't add it -->
						org.w3c.dom.NodeList pnl = caddyEl.getChildNodes();
						if(pnl.getLength() > 0){
							for(sdx_j = 0; sdx_j &lt; pnl.getLength(); sdx_j++){
								if(pnl.item(sdx_j).getAttributes().getNamedItem("id").getNodeValue().equals(sdx_id)){
									currentNotice = pnl.item(sdx_j);
								}
							}
						}

					if(caddy_docIds2add!=null){
						<!-- add current doc in the caddy -->
						if(currentNotice==null){
							org.w3c.dom.Element sdx_doc = sdx_caddy.createElementNS("http://www.culture.gouv.fr/ns/sdx/sdx","sdx:document");
							sdx_doc.setAttribute("id", sdx_id);
							<!-- notice.setAttribute("date",new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime())); -->
							<!-- others user's params -->
							<xsl:for-each select=".//sdx:parameter">
								<xsl:call-template name="sdx:parameter">
									<xsl:with-param name="name" select="normalize-space(current()/@name)" />
									<xsl:with-param name="att" select="'value'" />
									<xsl:with-param name="http"/>
								</xsl:call-template>
								if(sdx_name!=null &amp;&amp; !sdx_name.equals("") &amp;&amp; sdx_parameter!=null &amp;&amp; !sdx_parameter.equals("")){
									sdx_doc.setAttribute(sdx_name, sdx_parameter);
								}
							</xsl:for-each>
							caddyEl.appendChild(sdx_doc);
							sdx_caddyNbDocs++;
						}
					}

					<!-- update the DOM -->
					caddyEl.getAttributeNode("nb").setValue(sdx_caddyNbDocs+"");

					currentNotice = null;
				}

				<!-- update the caddy in session -->
				session.setAttribute("sdx_caddy", sdx_caddy);

			}

		}

		caddy_docIds2add = null;
		caddy_results = null;
		sdx_bool = false;
		sdx_i = -1;
		sdx_j = -1;

		</xsp:logic>

	</xsl:template>

	<!--=======================================================================-->
	<!--  Remove documents from the caddy                                      -->
	<!--=======================================================================-->
	<xsl:template match="sdx:deleteFromCaddy">

		<xsp:logic>

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

		<!-- ids of documents -->
		<xsl:call-template name="sdx:parameters">
			<xsl:with-param name="name" select="'id'"/>
		</xsl:call-template>
		String[] caddy_docIds2delete = sdx_parameters;

			<!-- do nothing if the caddy is empty -->
			if( caddyEl != null ){

				<!-- caddy's documents list -->
				org.w3c.dom.NodeList caddyDocs = caddyEl.getChildNodes();

				<!-- do nothing if there isn't to take from the caddy -->
				if(caddy_docIds2delete != null &amp;&amp; caddy_docIds2delete.length > 0){

					<!-- loop on ids -->
					for( sdx_i=0; sdx_i &lt; caddy_docIds2delete.length; sdx_i++ ){

						<!-- remove all docs from the caddy -->
						if( caddy_docIds2delete[sdx_i].equals("all") ){
							if( caddyDocs != null &amp;&amp; caddyDocs.getLength() > 0 ){
								int nb2delete = caddyDocs.getLength();
								for(sdx_j = 0; sdx_j &lt; nb2delete; sdx_j++){
									if( caddyDocs.item(0) != null ) caddyEl.removeChild( caddyDocs.item(0) );
									<!-- else System.out.println("pas d'élément pour sdx_j="+sdx_j); -->
								}
								sdx_i = caddy_docIds2delete.length;
								sdx_caddyNbDocs = 0;
							}
						}

						<!-- remove one or more docs from the caddy -->
						else {
							<!-- loop on docs to remove -->
							for(sdx_j = 0; sdx_j &lt; caddyDocs.getLength() ; sdx_j++){
								if( caddyDocs.item(sdx_j).getAttributes().getNamedItem("id").getNodeValue().equals( caddy_docIds2delete[sdx_i] ) ){
									caddyEl.removeChild( caddyDocs.item(sdx_j) );
									sdx_caddyNbDocs--;
									sdx_j = caddyDocs.getLength();
								}
							}
						}

					}

					<!-- update the DOM -->
					caddyEl.getAttributeNode("nb").setValue(sdx_caddyNbDocs+"");

					<!-- update the caddy in session -->
					session.setAttribute("sdx_caddy", sdx_caddy);

				}

			}

			caddy_docIds2delete = null;
			sdx_bool = false;
			sdx_i = sdx_j = 0;

		</xsp:logic>

	</xsl:template>

	<!--=======================================================================-->
	<!--    get the docs from the caddy                                        -->
	<!--=======================================================================-->
	<xsl:template match="sdx:getCaddy">

		<xsp:logic>

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

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

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

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

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

		</xsp:logic>

	</xsl:template>

	<!--=======================================================================-->
	<!--    search documents in the caddy session                              -->
	<!--=======================================================================-->
	<xsl:template match="sdx:searchCaddy">
		<xsl:call-template name="searchCaddy" />
	</xsl:template>
	<xsl:template name="searchCaddy">

		<xsp:logic title="searchCaddy">

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

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

			<xsl:call-template name="sdx:values"/>
			if( sdx_values==null || sdx_values.length &lt; 1 ) {

				org.w3c.dom.NodeList nl = caddyEl.getChildNodes();
				if(nl.getLength() &gt; 0){
					sdx_values = new String[nl.getLength()];
					for(sdx_i = 0; sdx_i &lt; nl.getLength(); sdx_i++){
						sdx_values[sdx_i] = nl.item(sdx_i).getAttributes().getNamedItem("id").getNodeValue();
					}
				} else{ <!-- System.out.println("caddy's empty"); --> }

			}

			<!-- for a caddy, the field is always "sdxdocid" and the operator is always "OR" -->
			sdx_field = "sdxdocid";
			sdx_op = Query.OPERATOR_OR;

			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++ ){
						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);
						}
					}

			}

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

		</xsp:logic>

	</xsl:template>

	<!--=======================================================================-->
	<!--    get the caddy in session                                           -->
	<!--=======================================================================-->
	<xsl:template match="sdx:initializeCaddy">
		<xsl:call-template name="getCaddy" />
	</xsl:template>
	<xsl:template name="getCaddy">

		<!-- the limit of the caddy -->
		<xsl:call-template name="sdx:parameter">
			<xsl:with-param name="name" select="'limit'"/>
		</xsl:call-template>
		if( sdx_i >= 0 ) sdx_caddyLimit = sdx_i;

		<!-- build the DOM -->
		sdx_dbd = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
		sdx_caddy = sdx_dbd.newDocument();
		caddyEl = sdx_caddy.createElementNS("http://www.culture.gouv.fr/ns/sdx/sdx","sdx:caddy");
		caddyEl.setAttribute("limit", sdx_caddyLimit+"");
		caddyEl.setAttribute("nb", sdx_caddyNbDocs+"");

		<!-- is the caddy already in session ? -->
		if( session.getAttribute("sdx_caddy") != null ) sdx_bool = true;
		else sdx_bool = false;

		<!-- if the caddy is already in session, take it ! -->
		if( sdx_bool ){
			sdx_caddy = (org.w3c.dom.Document)session.getAttribute("sdx_caddy");
			caddyEl = sdx_caddy.getDocumentElement();
			sdx_caddyNbDocs = new Integer( caddyEl.getAttributeNode("nb").getNodeValue() ).intValue();
			<!-- a sdx parameter indicate that we must update the limit of the caddy -->
			if( sdx_i >=0 &amp;&amp; sdx_i != new Integer( caddyEl.getAttributeNode("limit").getNodeValue() ).intValue() )
					caddyEl.getAttributeNode("limit").setValue(sdx_caddyLimit+"");
		}
		<!-- the caddy is not in session before, update the DOM -->
		else{
			sdx_caddy.appendChild(caddyEl);
			session.setAttribute("sdx_caddy", sdx_caddy);
			sdx_bool = true;
		}

	</xsl:template>


	<!--=======================================================================-->
	<!--  show DOM represenation of the caddy session                          -->
	<!--=======================================================================-->
	<xsl:template match="sdx:showCaddy">

		<xsp:logic>

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

		<!-- sdx:caddy -->
		String caddyEln = caddyEl.getLocalName();
		<xsp:element uri="http://www.culture.gouv.fr/ns/sdx/sdx" prefix="sdx">
			<xsp:param name="name"><xsp:expr>caddyEln</xsp:expr></xsp:param>
			<!-- attributes of the caddy -->
			<xsp:logic>
				org.w3c.dom.NamedNodeMap catts = caddyEl.getAttributes();
				for( sdx_i = 0; sdx_i &lt; catts.getLength(); sdx_i++ ){
					String attn = catts.item(sdx_i).getNodeName();
					String attv = catts.item(sdx_i).getNodeValue();
					<xsp:attribute><xsp:param name="name"><xsp:expr>attn</xsp:expr></xsp:param><xsp:expr>attv</xsp:expr></xsp:attribute>
				}
			</xsp:logic>

			<xsp:logic>

				<!-- sdx:document -->
				org.w3c.dom.NodeList caddyDocs = caddyEl.getChildNodes();
				for(int i1=0; i1 &lt; caddyDocs.getLength(); i1++){
					org.w3c.dom.Node caddyDoc = caddyDocs.item(i1);
					String caddyDocn = caddyDoc.getLocalName();
					String caddyDocv = caddyDoc.getNodeValue();
					<xsp:element uri="http://www.culture.gouv.fr/ns/sdx/sdx" prefix="sdx">
						<xsp:param name="name"><xsp:expr>caddyDocn</xsp:expr></xsp:param>
						<!-- attributes of sdx:document -->
						<xsp:logic>
							catts = caddyDoc.getAttributes();
							for( sdx_i = 0; sdx_i &lt; catts.getLength(); sdx_i++ ){
								String attn = catts.item(sdx_i).getNodeName();
								String attv = catts.item(sdx_i).getNodeValue();
								<xsp:attribute><xsp:param name="name"><xsp:expr>attn</xsp:expr></xsp:param><xsp:expr>attv</xsp:expr></xsp:attribute>
							}
						</xsp:logic>
						<xsp:expr>caddyDocv</xsp:expr>
					</xsp:element>
				}

			</xsp:logic>

		</xsp:element>

		</xsp:logic>

	</xsl:template>

	<!--=======================================================================-->
	<!--   add a search to a session historic                                  -->
	<!--=======================================================================-->
	<xsl:template match="sdx:addToHistoric">

		<xsp:logic>

		<!-- id search -->
		<xsl:call-template name="sdx:parameters">
			<xsl:with-param name="name" select="'qid'"/>
		</xsl:call-template>
		sdx_qids = sdx_parameters;
		// If there's no qid parameter, try to use the variable "sdx_qid" (ie, current query)
		if( sdx_qids == null || sdx_qids.length &lt;= 0 ){
			sdx_qids = new String[1]; sdx_qids[0] = sdx_qid;
		}

		if(sdx_qids!=null &amp;&amp; sdx_qids.length > 0){

			int m_search2add = 0;

			<!-- loop on searches to add -->
			for(sdx_j=0; sdx_j &lt; sdx_qids.length; sdx_j++){

				sdx_qid = sdx_qids[sdx_j];

				<!-- get the results of the current search -->
				<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 -->
				<!-- get cached results if there are and not force execute query -->
				if (sdx_object != null &amp;&amp; sdx_object instanceof Results &amp;&amp; !sdx_bool)
						historic_results = (Results) sdx_object;

				if( historic_results!=null ){

					<!-- the query of the search -->
					fr.gouv.culture.sdx.search.lucene.query.Query m_query = sdx_query;

					<!-- Trying to get the query from sdx_results -->
					if( m_query == null )
							m_query = historic_results.getQuery();

					<!-- get the Lucene query as a string -->
					String m_lucene = null; m_lucene = m_query.getLuceneQuery().toString();
					<!-- get the number of results -->
					int m_nb = -1; m_nb = historic_results.count();

					if(m_lucene!=null &amp;&amp; !m_lucene.equals("")){


						<!-- get the historic from session -->
						<xsl:call-template name="getHistoric" />

						<!-- current ISO date -->
						Calendar dateNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
						String dateNowIso = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(dateNow.getTime());

						<!-- is the current search already in session ? Work with 1 criterion: Lucene query -->
						boolean m_sameQuery = false;
						org.w3c.dom.NodeList m_reqs = historicEl.getChildNodes();
						if(m_reqs.getLength() &gt; 0){
							for(int i=0; i &lt; m_reqs.getLength(); i++){
								org.w3c.dom.Node m_req = m_reqs.item(i);
								<!-- the current search already in historic, we are going to update its date and the number of results -->
								if( m_req.getAttributes().getNamedItem("lucene").getNodeValue().equals(m_lucene) ){
									m_sameQuery = true;
									m_req.getAttributes().getNamedItem("date").setNodeValue( dateNowIso );
									m_req.getAttributes().getNamedItem("nb").setNodeValue( m_nb+"" );
									<!-- update others user's params -->
									<xsl:for-each select=".//sdx:parameter">
										<xsl:call-template name="sdx:parameter">
											<xsl:with-param name="name" select="normalize-space(current()/@name)" />
											<xsl:with-param name="att" select="'value'" />
											<xsl:with-param name="http"/>
										</xsl:call-template>
										if( Utilities.checkString(sdx_name) &amp;&amp; Utilities.checkString(sdx_parameter) &amp;&amp; m_req.getAttributes().getNamedItem(sdx_name) != null )
												m_req.getAttributes().getNamedItem(sdx_name).setNodeValue( sdx_parameter );
									</xsl:for-each>
								}
							}
						}

						<!-- add the search only if it's not already in historic -->
						if( !m_sameQuery ){

							<!-- id search: it's possible to force id generation -->
							String _idSearch = "";
							<xsl:call-template name="sdx:parameters">
								<xsl:with-param name="name" select="'id'"/>
							</xsl:call-template>
							if( sdx_string != null &amp;&amp; !sdx_string.trim().equals("") ){
								_idSearch = sdx_string;
							}
							else{
								_idSearch = dateNow.getTimeInMillis()+"";
							}

							<!-- create a DOM : <sdx:search id="" lucene="" nb="" date="" /> -->
							org.w3c.dom.Element sdx_search = sdx_historic.createElementNS("http://www.culture.gouv.fr/ns/sdx/sdx","sdx:search");
							sdx_search.setAttribute("id", _idSearch);
							sdx_search.setAttribute("lucene", m_lucene);
							sdx_search.setAttribute("nb", m_nb+"");
							sdx_search.setAttribute("date", dateNowIso);
							<!-- others user's params -->
							<xsl:for-each select=".//sdx:parameter">
								<xsl:call-template name="sdx:parameter">
									<xsl:with-param name="name" select="normalize-space(current()/@name)" />
									<xsl:with-param name="att" select="'value'" />
									<xsl:with-param name="http"/>
								</xsl:call-template>
								if(sdx_name!=null &amp;&amp; !sdx_name.equals("") &amp;&amp; sdx_parameter!=null &amp;&amp; !sdx_parameter.equals("")){
									sdx_search.setAttribute(sdx_name, sdx_parameter);
								}
							</xsl:for-each>
							<!-- newer first -->
							historicEl.insertBefore(sdx_search, historicEl.getFirstChild());
							<!-- to be sure of the value, recalculate the number of entries -->
							sdx_historicNb = historicEl.getElementsByTagNameNS("http://www.culture.gouv.fr/ns/sdx/sdx","search").getLength();

							<!-- history limit, delete the oldest entries -->
							while( (sdx_historicNb) > sdx_historicLimit){
								sdx_historicNb--;
								historicEl.removeChild(historicEl.getLastChild());
							}

							<!-- update the DOM -->
							historicEl.getAttributeNode("nb").setValue(sdx_historicNb+"");
							<!-- update the caddy in session -->
							session.setAttribute("sdx_historic", sdx_historic);

						}

						<!-- reset params -->
						m_lucene = null;
						m_sameQuery = false;




					}

					m_search2add++;

				}

				sdx_qid = null;

			}

			<!-- problem ! -->
			if(m_search2add == 0){
				<xsl:apply-templates select="sdx:fallback/node()" />
			}

		}

		</xsp:logic>

	</xsl:template>

	<!--=======================================================================-->
	<!--  Remove documents from the historic                                   -->
	<!--=======================================================================-->
	<xsl:template match="sdx:deleteFromHistoric">

		<xsp:logic>

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

		<!-- ids of documents -->
		<xsl:call-template name="sdx:parameters">
			<xsl:with-param name="name" select="'id'"/>
		</xsl:call-template>
		String[] historic_ids2delete = sdx_parameters;

			<!-- do nothing if the historic is empty -->
			if( historicEl != null ){

				<!-- historic's documents list -->
				org.w3c.dom.NodeList historicDocs = historicEl.getChildNodes();

				<!-- do nothing if there isn't to take from the historic -->
				if(historic_ids2delete != null &amp;&amp; historic_ids2delete.length > 0){

					<!-- loop on ids -->
					for( sdx_i=0; sdx_i &lt; historic_ids2delete.length; sdx_i++ ){

						<!-- remove all docs from the historic -->
						if( historic_ids2delete[sdx_i].equals("all") ){
							if( historicDocs != null &amp;&amp; historicDocs.getLength() > 0 ){
								int nb2delete = historicDocs.getLength();
								for(sdx_j = 0; sdx_j &lt; nb2delete; sdx_j++){
									if( historicDocs.item(0) != null ) historicEl.removeChild( historicDocs.item(0) );
									<!-- else System.out.println("pas d'élément pour sdx_j="+sdx_j); -->
								}
								sdx_i = historic_ids2delete.length;
								sdx_historicNb = 0;
							}
						}

						<!-- remove one or more docs from the historic -->
						else {
							<!-- loop on search to remove -->
							for(sdx_j = 0; sdx_j &lt; historicDocs.getLength() ; sdx_j++){
								if( historicDocs.item(sdx_j).getAttributes().getNamedItem("id").getNodeValue().equals( historic_ids2delete[sdx_i] ) ){
									historicEl.removeChild( historicDocs.item(sdx_j) );
									sdx_historicNb--;
									sdx_j = historicDocs.getLength();
								}
							}
						}

					}

					<!-- update the DOM -->
					historicEl.getAttributeNode("nb").setValue(sdx_historicNb+"");
					<!-- update the historic in session -->
					session.setAttribute("sdx_historic", sdx_historic);

				}

			}

			historic_ids2delete = null;
			sdx_bool = false;
			sdx_i = sdx_j = 0;

		</xsp:logic>

	</xsl:template>

	<!--=======================================================================-->
	<!--    get the historic in session                                        -->
	<!--=======================================================================-->
	<xsl:template name="getHistoric">

		<!-- the limit of the historic -->
		<xsl:call-template name="sdx:parameter">
			<xsl:with-param name="name" select="'limit'"/>
		</xsl:call-template>
		if( sdx_i >= 0 ) sdx_historicLimit = sdx_i;

		<!-- build the DOM -->
		sdx_dbd = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
		sdx_historic = sdx_dbd.newDocument();
		historicEl = sdx_historic.createElementNS("http://www.culture.gouv.fr/ns/sdx/sdx","sdx:historic");
		historicEl.setAttribute("limit", sdx_historicLimit+"");
		historicEl.setAttribute("nb", sdx_historicNb+"");

		<!-- is the historic already in session ? -->
		if( session.getAttribute("sdx_historic") != null ) sdx_bool = true;
		else sdx_bool = false;

		<!-- if the historic is already in session, take it ! -->
		if( sdx_bool ){
			sdx_historic = (org.w3c.dom.Document)session.getAttribute("sdx_historic");
			historicEl = sdx_historic.getDocumentElement();
			sdx_historicNb = new Integer( historicEl.getAttributeNode("nb").getNodeValue() ).intValue();
			<!-- a sdx parameter indicate that we must update the limit of the caddy -->
			if( sdx_i >=0 &amp;&amp; sdx_i != new Integer( historicEl.getAttributeNode("limit").getNodeValue() ).intValue() )
					historicEl.getAttributeNode("limit").setValue(sdx_historicLimit+"");
		}
		<!-- the historic is not in session before, update the DOM -->
		else{
			sdx_historic.appendChild(historicEl);
			session.setAttribute("sdx_historic", sdx_historic);
			sdx_bool = true;
		}

	</xsl:template>

	<!--=======================================================================-->
	<!--  show DOM represenation of the historic session                       -->
	<!--=======================================================================-->
	<xsl:template match="sdx:showHistoric">

		<xsp:logic>

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

		<!-- sdx:caddy -->
		String historicEln = historicEl.getLocalName();
		<xsp:element uri="http://www.culture.gouv.fr/ns/sdx/sdx" prefix="sdx">
			<xsp:param name="name"><xsp:expr>historicEln</xsp:expr></xsp:param>
			<!-- attributes of the caddy -->
			<xsp:logic>
				org.w3c.dom.NamedNodeMap hatts = historicEl.getAttributes();
				for( sdx_i = 0; sdx_i &lt; hatts.getLength(); sdx_i++ ){
					String attn = hatts.item(sdx_i).getNodeName();
					String attv = hatts.item(sdx_i).getNodeValue();
					<xsp:attribute><xsp:param name="name"><xsp:expr>attn</xsp:expr></xsp:param><xsp:expr>attv</xsp:expr></xsp:attribute>
				}
			</xsp:logic>

			<xsp:logic>

				<!-- sdx:document -->
				org.w3c.dom.NodeList historicDocs = historicEl.getChildNodes();
				for(int i1=0; i1 &lt; historicDocs.getLength(); i1++){
					org.w3c.dom.Node historicDoc = historicDocs.item(i1);
					String historicDocn = historicDoc.getLocalName();
					String historicDocv = historicDoc.getNodeValue();
					<xsp:element uri="http://www.culture.gouv.fr/ns/sdx/sdx" prefix="sdx">
						<xsp:param name="name"><xsp:expr>historicDocn</xsp:expr></xsp:param>
						<!-- attributes of sdx:document -->
						<xsp:logic>
							hatts = historicDoc.getAttributes();
							for( sdx_i = 0; sdx_i &lt; hatts.getLength(); sdx_i++ ){
								String attn = hatts.item(sdx_i).getNodeName();
								String attv = hatts.item(sdx_i).getNodeValue();
								<xsp:attribute><xsp:param name="name"><xsp:expr>attn</xsp:expr></xsp:param><xsp:expr>attv</xsp:expr></xsp:attribute>
							}
						</xsp:logic>
						<xsp:expr>historicDocv</xsp:expr>
					</xsp:element>
				}

			</xsp:logic>

		</xsp:element>


		</xsp:logic>

	</xsl:template>

</xsl:stylesheet>
