<?xml version="1.0" encoding="UTF-8"?>
<!--
SDX: Documentary System in XML.
Copyright (C) 2000  Ministere de
la culture et de la communication (France), AJLSM

Ministere de la culture et de la communication,
Mission de la recherche et de la technologie
3 rue de Valois, 75042 Paris Cedex 01 (France)
mrt@culture.fr, michel.bottin@culture.fr

AJLSM, 17, rue Vital Carles, 33000 Bordeaux (France)
sevigny@ajlsm.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
or connect to:
http://www.fsf.org/copyleft/gpl.html
-->
<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">
	<!--
	sdx.xsl is the main logicsheet ; it includes the four others stylesheets.
	//
	sdx.xsl est la logicsheet principale ; elle inclus les quatre autres feuilles.
	-->
	<xsl:include href="sdx-parameters.xsl"/>
	<xsl:include href="sdx-queries.xsl"/>
	<xsl:include href="sdx-actions.xsl"/>
	<xsl:include href="sdx-pipelines.xsl"/>
	<!--
		<xsl:include href="sdx-test.xsl"/>
	-->
	<!-- ============================== ROOT ================================ -->
	<!--
		This logicsheet matches a <sdx:page/> (like xsp:page) element
		to output a <sdx:document/>.
		This context allows to give informations and variables
		for the user's xsp.
		Usual java operations in a SDX context can be interpreted
		from XML tags.
		The data outputed should be choosable by attributes on the
		<sdx:page/> tag.
		It's impossible to strip a root element in XSP process (and
		there's some risks of multi root nodes), use your own pipe instead.
	-->
	<xsl:template match="xsp:page">
		<xsp:page>
			<xsl:copy-of select="@*"/>
			<xsl:apply-templates/>
		</xsp:page>
	</xsl:template>
	<xsl:template match="xsp:page/sdx:page">
		<xsl:call-template name="sdx:imports"/>
		<xsl:call-template name="sdx:vars-class"/>
		<xsl:call-template name="sdx:methods"/>
        <xsp:init-page>
            <xsl:call-template name="sdx:vars-generate"/>
            <xsl:call-template name="sdx:init"/>
        </xsp:init-page>
		<sdx:document xmlns:sdx="http://www.culture.gouv.fr/ns/sdx/sdx">
			<xsp:logic>
				<xsl:call-template name="sdx:document-atts"/>
			</xsp:logic>
			<xsp:logic>
				<xsl:call-template name="comment">
					<xsl:with-param name="name" select="'ACTIONS'"/>
				</xsl:call-template>
				try
				{
					<xsl:apply-templates select="*"/>
				}
				catch(Exception sdx_ee)
				{
					if (sdx_ee instanceof SDXException){
					<xsl:call-template name="comment">
						<xsl:with-param name="name" select="'EXCEPTIONS'"/>
					</xsl:call-template>
					((SDXException) sdx_ee).toSAX(contentHandler);
					if (sdx_log != null) sdx_log.error(sdx_ee.getMessage(), sdx_ee.fillInStackTrace());

					}
					sdx_ee.printStackTrace(System.err);
					if (sdx_log != null) sdx_log.error(sdx_ee.getMessage(), sdx_ee.fillInStackTrace());
					<sdx:exception>
					<sdx:message>
						<xsp:expr>sdx_ee.getMessage()</xsp:expr>
						<sdx:originalException>
							<xsp:expr>sdx_ee.fillInStackTrace()</xsp:expr>
						</sdx:originalException>
					</sdx:message>
				</sdx:exception>
				}
            </xsp:logic>
			<xsl:call-template name="sdx:infos"/>
			<xsp:logic>
                cocoon_serviceManager.release((Component)sdx_frame);
			</xsp:logic>
		</sdx:document>
	</xsl:template>
	<!-- ========================== Initialization ========================== -->
	<xsl:template name="sdx:imports">
		<xsp:structure>
			<xsp:include>java.io.*</xsp:include>
			<xsp:include>java.util.*</xsp:include>
			<xsp:include>java.text.*</xsp:include>
			<xsp:include>java.util.zip.*</xsp:include>
			<!-- <xsp:include>javax.xml.parsers.*</xsp:include> -->
			<xsp:include>org.apache.avalon.excalibur.io.FileUtil</xsp:include>
			<xsp:include>org.apache.avalon.framework.configuration.*</xsp:include>
			<xsp:include>org.apache.avalon.framework.context.ContextException</xsp:include>
			<xsp:include>org.apache.avalon.framework.logger.Logger</xsp:include>
			<xsp:include>org.apache.avalon.framework.service.ServiceManager</xsp:include>
			<xsp:include>org.apache.avalon.framework.service.WrapperServiceManager</xsp:include>
			<xsp:include>org.apache.avalon.framework.parameters.Parameters</xsp:include>
			<xsp:include>org.apache.commons.httpclient.methods.multipart.*</xsp:include>
			<xsp:include>org.apache.cocoon.environment.Session</xsp:include>
			<xsp:include>org.apache.cocoon.xml.*</xsp:include>
			<!-- <xsp:include>org.w3c.dom.Element</xsp:include>
			<xsp:include>org.w3c.dom.Node</xsp:include>
			<xsp:include>org.w3c.dom.NodeList</xsp:include>
			<xsp:include>org.w3c.dom.Text</xsp:include> -->
			<xsp:include>fr.gouv.culture.sdx.framework.Framework</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.framework.FrameworkImpl</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.application.Application</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.user.UserInformation</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.user.AnonymousUserInformation</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.documentbase.DocumentBase</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.documentbase.IndexParameters</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.repository.Repository</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.document.*</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.search.Searchable</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.search.lucene.queryparser.QueryParser</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.search.lucene.query.*</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.search.lucene.highlight.*</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.search.lucene.filter.Criteria</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.search.lucene.filter.Filter</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.search.TermHighlighter</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.pipeline.*</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.exception.SDXException</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.exception.SDXExceptionCode</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.utils.*</xsp:include>
			<xsp:include>fr.gouv.culture.sdx.thesaurus.*</xsp:include>
		</xsp:structure>
	</xsl:template>
	<xsl:template name="sdx:vars-class">
		<xsp:logic>
			String sdx_nsURI="<xsl:value-of select="namespace-uri()"/>";
			String sdx_nsPrefix="sdx";
			File context_upload_dir = null;
		</xsp:logic>
	</xsl:template>
	<!--
		declaration of common variables
	-->
	<xsl:template name="sdx:vars-generate">
		<!--
			/* Built-in parameters available for use in xsp
			context    - ServletContext
			request    - org.apache.cocoon.environment.Request
			response   - org.apache.cocoon.environment.Response
			parameters - parameters defined in the sitemap
			*/
		-->
		<xsp:logic>

			/* context parameters */

			ServiceManager      cocoon_serviceManager = new WrapperServiceManager(manager);/*the component/service manager for our classes*/
            Session				session=null;
			FrameworkImpl		sdx_frame=null;
			Application			sdx_application=null;				/* current application from path if available (not in api-url and sdx/admin) */
			Logger				sdx_log=null;						/* logger available if application by path */
			String              sdx_encoding = Framework.DEFAULT_ENCODING; /**Default encoding for string operations*/
            UserInformation	sdx_user;
			String				context_realPath;
			String				sdx_lang=null;

			/* reserved names for volatile java objects */

			boolean				sdx_bool=false;
			boolean[]			sdx_bools=null;
			int					sdx_i=-1;
			int					sdx_j=-1;
			int					sdx_max=-1;
			int[]				sdx_is=null;
			int[]				sdx_js=null;
			byte[]				sdx_bytes=null;
			String				sdx_string=null;
			String				sdx_string2=null;
			String[]			sdx_strings=null;
			Enumeration			sdx_enum=null;
			Enumeration			sdx_enum2=null;
			Vector				sdx_vector=null;
			Object				sdx_object=null;
			Object[]			sdx_objects=null;
			InputStream			sdx_in=null;
			OutputStream		sdx_out=null;

			/* sdx location objects defined by parameters */

			SearchLocations	sdx_locations=null;						/* a vector of locations to search */
			Index				sdx_location=null;					/* an index either from a remote machine or the local machine */

			Application			sdx_app=null;
			DocumentBase		sdx_base=null;						/* searchable and indexable */
			Searchable			sdx_searchable=null;				/* searchable (but could be not indexable) */
			Repository			sdx_repo=null;

			String[]			sdx_hosts = null;					/* hostnames to build an Index (sdx_location) */
			String				sdx_host=null;
			int[]				sdx_ports =null;					/* ports to build an Index (sdx_location) */
			int					sdx_port=-1;
			String[]			sdx_appIds = null;					/* appIds to build an Index (sdx_location) */
			String				sdx_appId=null;
			String[]			sdx_appbypaths = null;				/* appIds to build an Index (sdx_location) */
			String				sdx_appbypath=null;
			String[]			sdx_baseIds = null;					/* baseIds to build an Index (sdx_location) */
			String				sdx_baseId=null;

			/* reserved names for sdx objects */

			Terms				sdx_terms=null;						/* index of indexed terms from a field */

			/* pipes */

			XMLConsumer			sdx_consumer=(XMLConsumer)this.contentHandler;	/* the current consumer */
			Pipeline			sdx_pipeline=null;					/* generic pipeline, added in queue to the consumer */

			/* common parameters */

			String				sdx_id=null;						/* document id */

			/* queries parameters and objects */

			Query				sdx_query=null;						/* generic query */
			Query				sdx_query2=null;					/* generic query */
			SortSpecification	sdx_sorts=null;						/* sort specification added to query */
			Results				sdx_results=null;					/* results */
			Criteria			sdx_criteria=null;
			Filter				sdx_filter=null;

			String				sdx_q=null;							/* simple or lucene query string */
			String				sdx_field=null;
			String[]			sdx_fields=null;
			String				sdx_value=null;
			String[]			sdx_values=null;
			int					sdx_op=-1;
			int[]				sdx_ops=null;
			String				sdx_show=null;						/* current space separated list of sdx:objects to output */
			String				sdx_show2=null;						/* cache sdx_show */
			String				sdx_name=null;
			Date				sdx_from=null;
			Date				sdx_to=null;

			/* for cached results (of queries) */

			String			    sdx_qid=null;						/* query id */
			String[]		    sdx_qids=null;					    /* querys id */
			int					sdx_qmax=5;							/* maximum of queries cached per user */
			int					sdx_hppDefault=20;					/* default hits per page of a results page */
			int					sdx_hpp=sdx_hppDefault;				/* hits per page */
			int					sdx_page=1;							/* page of an identified query */
			int					sdx_no=-1;							/* result of an identified query */

			/* upload parameters */

			Document			sdx_document=null;					/* an sdx document */
			Document[]			sdx_documents=null;					/* an array of sdx document */
			IndexParameters	sdx_index=null;							/* index parameter */
			String				sdx_type=null;
			String				sdx_xml=null;
			String				sdx_pattern=null;					/* for includes and excludes in exploring directories */
			String				sdx_parameter=null;
			String[]			sdx_parameters=null;
			java.net.URL		sdx_url=null;
			File				sdx_dir=null;
			ZipFile				sdx_zip=null;
			File				sdx_file=null;
			File[]				sdx_files=null;
			org.w3c.dom.Document	sdx_dom=null;

			/* Thesaurus parameters*/

			SDXThesaurus		sdx_thesaurus=null;
			int					sdx_relationDepth=0;
			int[]				sdx_relations = null;
			String[]			sdx_relationLangs=null;

			/* Caddy parameters */
			javax.xml.parsers.DocumentBuilder sdx_dbd = null;
			int sdx_caddyNbDocs = 0;/* Docs numbers in caddy */
			int sdx_caddyLimit = 1000;/* Limit for the caddy, default: 1 000 */
			org.w3c.dom.Document	sdx_caddy = null;/* DOM representation of the caddy */
			org.w3c.dom.Element	caddyEl = null;/* DOM representation of the caddy */
			Results caddy_results = null;

			/* Historic parameters */
			int sdx_historicNb = 0;/* Historics numbers in historic */
			int sdx_historicLimit = 20;/* Limit for the historic, default: 20 */
			org.w3c.dom.Document	sdx_historic = null;/* DOM representation of the historic */
			org.w3c.dom.Element	historicEl = null;/* DOM representation of the historic */
			Results historic_results = null;

			/* other Java objects defined by parameters */

			Parameters			sdx_params=null;					/* framework object */
			Configuration 		sdx_conf=null;						/* framework object */
			Date					sdx_date=null;

		</xsp:logic>
	</xsl:template>
	<xsl:template name="sdx:methods">
		<xsp:logic>
			/** Contextualize this class */
			public void contextualize(Context context) throws ContextException
			{
				context_upload_dir = (File) context.get(Constants.CONTEXT_UPLOAD_DIR);
			}

			public String sdx_getRequestParameter (String name)
			{
				if (name == null || "".equals(name)) return null;
				String value=request.getParameter(name);
				if (value != null) return value;
				<!-- try to get object, usually String,	but could be a FilePartSource -->
				Object sdx_object=request.get(name);
				if (sdx_object instanceof FilePartSource)
				{
					<!--
						interesting info , what should I do with it ?
						((FilePartSource)sdx_object).getMimeType()
					-->
					return context_upload_dir + File.separator + ((FilePartSource)sdx_object).getFileName();
				}
				else if (sdx_object != null) return String.valueOf(sdx_object);
				<!-- try to find a value if a repeated parameter -->
				<!--
				else
				{
					sdx_strings = request.getParameterValues(sdx_string);
					if (sdx_strings != null &amp;&amp; sdx_strings.length != 0 )
					for (sdx_i=0 ; sdx_i &lt; sdx_strings.length ; sdx_i++)
					if (sdx_strings[sdx_i]!= null &amp;&amp; !"".equals(sdx_strings[sdx_i]))
					return sdx_strings[sdx_i];
				}
				-->
				return null;
			}

			public String[] sdx_getRequestParameters (String name)
			{
				if (name == null || "".equals(name) ) return null;
				String[] sdx_strings = request.getParameterValues(name);
				/**TODO: why was Fred returning the array only if the first value
                WAS VALID, other values for the same parameter name COULD be valid???*-rbp
                if (sdx_get(sdx_strings, 0) != null) return sdx_strings;
				return null;
                */
                return sdx_strings;
			}

			public String sdx_get (String[] tab, int i)
			{
				if (tab == null) return null;
				else if (tab.length &lt;= i) return null;
				else if (tab[i] == null) return null;
				else if ("".equals(tab[i])) return null;
				else return tab[i];
			}

			public int sdx_get (int[] tab, int i)
			{
				if (tab == null) return -1;
				else if (tab.length &lt;= i) return -1;
				else return tab[i];
			}

			<!--
			This function is setted here (and not in fr.gouv.culture.sdx.utils)
			because of specific http parameters questions.
			-->
			public boolean sdx_check (String string)
			{
				if (string == null) return false;
				if ("".equals(string.trim()) ) return false;
				return true;
			}

			public File sdx_unzip (ZipFile sdx_zip) throws Exception
			{
				return sdx_unzip(sdx_zip, context_upload_dir);
			}

			public File sdx_unzip(ZipFile sdx_zip, File sdx_dir) throws Exception
			{
				/* variables */
				int					sdx_i;
				ZipEntry				sdx_entry;
				File					sdx_file;
				byte[]				sdx_bytes;
				InputStream			sdx_in=null;
				OutputStream		sdx_out=null;
				Enumeration			sdx_enum = sdx_zip.entries();
                File                unzipDir=null;//subdirectory for unzipping zipfile

            /* folder where to unzip */
            //System.out.println("sdx_zip file : " + new File(sdx_zip.getName()).getName());
            unzipDir=File.createTempFile(new File(sdx_zip.getName()).getName() + "-","-sdxZip", sdx_dir);
                if (unzipDir.delete()){
                    //System.out.println("deleted tmp file : " + unzipDir.getCanonicalPath());
                    /*if (*/unzipDir.mkdirs();/*)*/
                        //System.out.println("created tmp dir : " + unzipDir.getCanonicalPath());
                }

            unzipDir.mkdirs();
            sdx_dir = unzipDir;

				/* unzip */
				while ( sdx_enum.hasMoreElements() )
				{
					sdx_entry = (ZipEntry)sdx_enum.nextElement();
                    if(sdx_entry.isDirectory()) (new File(sdx_dir, sdx_entry.getName())).mkdir();
					/* write file */
					else
					{
						sdx_bytes = new byte[4096];
						sdx_in = sdx_zip.getInputStream(sdx_entry);
						sdx_file = new File(sdx_dir, (sdx_entry).getName());
						if (!sdx_file.getParentFile().exists() ) sdx_file.getParentFile().mkdirs();
						sdx_out = new BufferedOutputStream(new FileOutputStream(sdx_file));
						while ( (sdx_i= sdx_in.read(sdx_bytes)) != -1 )
						sdx_out.write(sdx_bytes,0,sdx_i);
						sdx_in.close();
						sdx_out.close();
					}
				}
				sdx_zip.close();
				return sdx_dir;
			}

			public Vector sdx_dir(File file, String includes, String excludes, Vector files)
			{
				/* System.out.println("sdx_dir "+file+" "+includes+" "+excludes); */
				if (files == null) files=new Vector();
				if (file==null) return files;
				if (!file.canRead()) return files;
				if (file.isFile())
				{
					if (sdx_isGood(file.getName(), includes, excludes)) files.add(file);
					return files;
				}
				if (file.isDirectory())
				{
					File[] dir=file.listFiles();
					for (int i = 0; i &lt; dir.length; i++)
					{
						Vector files2=sdx_dir(dir[i], includes, excludes, files);
						if (files2.size() &gt; files.size()) files.addAll(files.size(), files2);
					}
					return files;
				}
				return files;
			}

			public boolean sdx_isGood(String name, String includes, String excludes)
			{
				if (name == null) return false;
				if (excludes != null) if (sdx_match(name, excludes)) return false;
				if (includes != null) return sdx_match(name, includes);
				return true;
			}

			public boolean sdx_match (String name, String pattern)
			{
			/* should be in jvm 1.4 regexp or cocoon ** matcher */
				if (pattern == null) return true;
				if (name == null) return false;
				int star=pattern.indexOf('*');
				if (star &lt; 0) return name.equals(pattern);
				if (star==0) return name.endsWith(pattern.substring(1));
				return name.startsWith(pattern.substring(0, star));
			}

			public boolean sdx_boolean(String string)
			{
				if ( !sdx_check(string) || "0".equals(string) || "false".equalsIgnoreCase(string) || "faux".equalsIgnoreCase(string)) return false;
				else return true;
			}

            public Object getSessionObject(Session session, String key){
				if (session == null || key == null) {
            		return null;
            	}
                Object obj=session.getAttribute(key);
                if (obj == null)
                    obj=session.getAttribute("sdx_" + key);
                return obj;
            }

             public String setShowSessionObject(Session session, String key, Object obj, int sdx_qmax){
            /* if no user qid given, cache in the limit of sdx_qmax objects */
                if (!sdx_check(key)){
                    int i=0;
					if (getSessionObject(session, "sdx_qi") != null) i=((Integer)getSessionObject(session, "sdx_qi")).intValue()+1;
					if (i &gt; sdx_qmax - 1) {
						/* First In First Out queue */
						session.removeAttribute("sdx_q"+(i - sdx_qmax));
					}
					String qid="q"+i;
					session.setAttribute("sdx_qi", new Integer(i));
                    key="sdx_" + qid;
                }
                session.setAttribute(key, obj);
                return key;
            }
		</xsp:logic>
	</xsl:template>
	<xsl:template name="sdx:init">
		<xsp:logic>
			/*
			* INIT
			*/

			session=request.getSession(true);
			try {
				sdx_frame=(FrameworkImpl)cocoon_serviceManager.lookup(Framework.ROLE);
				sdx_log = sdx_frame.getLogger();
                sdx_encoding = sdx_frame.getEncoding();//setting the runtime encoding for the framework from sdx.xconf
			}
			catch (Exception sdx_e) { }
			<!-- Better handling of framework exceptions ? -->
			<!-- probably, nothing could be done without -->
			/* get cached user information, if null will be obtained from sdx_app when will be setted */
			sdx_user=(UserInformation)getSessionObject(session, "sdx_user");

      /* 2005-06-09 [FG] make it possible to have a contextual app from a cocoon:/ call */

      // try an sdx:page parameter
	<xsl:call-template name="sdx:parameter">
		<xsl:with-param name="name" select="'appbypath'"/>
	</xsl:call-template>
	sdx_appbypath=sdx_parameter;

			/* if no global param, try to set appbypath from the requested URI "sdxInstall/sdxApp"
			doesn't work with cocoon:/ request */
			if (!sdx_check(sdx_appbypath) ) {
        sdx_enum = new java.util.StringTokenizer (request.getServletPath(), "/");
			  if (((java.util.StringTokenizer)sdx_enum).hasMoreTokens()) sdx_appbypath=((java.util.StringTokenizer)sdx_enum).nextToken();
			}
      if (sdx_check(sdx_appbypath) &amp;&amp; !"sdx".equals(sdx_appbypath)) try {
          sdx_application = sdx_frame.getApplicationByPath(sdx_appbypath);
          if (sdx_application != null) sdx_qmax = sdx_application.getSessionObjectLimit();
        }
        catch (Exception sdx_e) {
          // no element open here, so impossible to output message as XML
          // no log for app
        }

/* 2005-06-09 [/FG] */

			try {
				if (sdx_application != null) sdx_log=sdx_application.getLogger();
				/* if no anonymousUser setted in session, get it, put it in session */
				if (sdx_user == null)
				{
					if (sdx_application != null) sdx_user=sdx_application.getUserInformation(null);
					else sdx_user=new AnonymousUserInformation(sdx_frame.getLocale());
					session.setAttribute("sdx_user", sdx_user);
				}
			}
			catch (Exception sdx_e) {}


			// unsignificant with internal requests cocoon:/
			context_realPath=context.getRealPath(request.getServletPath());


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


			sdx_show=sdx_parameter;
			<!--
				Find a lang with in order :
					- an sdx parameter ;
					- an <xml:lang @lang>.
			-->
			<xsl:call-template name="sdx:parameter">
				<xsl:with-param name="name" select="'lang'"/>
			</xsl:call-template>

			sdx_lang=sdx_parameter;
			if (sdx_lang == null || "".equals(sdx_lang))
			{
				sdx_lang="<xsl:value-of select="ancestor-or-self::*/@xml:lang[1]"/>";
			}
			if ((sdx_lang == null || "".equals(sdx_lang)) &amp;&amp; sdx_user != null &amp;&amp; sdx_user.getPreferredLocale() != null)
			{
				sdx_object=sdx_user.getPreferredLocale();
				sdx_lang=((java.util.Locale) sdx_object).getLanguage();
				if (!"".equals(sdx_lang) &amp;&amp; !"".equals(((java.util.Locale) sdx_object).getCountry()))
					sdx_lang+="-"+((java.util.Locale) sdx_object).getCountry();
			}
			if ( (sdx_lang == null || "".equals(sdx_lang)) &amp;&amp; sdx_application != null) sdx_lang=sdx_application.getXmlLang();
			if (sdx_lang == null || "".equals(sdx_lang)) sdx_lang=sdx_frame.getXmlLang();
			if (sdx_lang == null || "".equals(sdx_lang)) sdx_lang="fr";
		</xsp:logic>
	</xsl:template>
	<!-- =========================== sdx templates ========================== -->
	<!--
		Templates of datas insertable by sdx.
	-->
	<!--
		Attributes of sdx:document root element.
	-->
	<xsl:template name="sdx:document-atts">
		<!-- Cocoon 2.1.8 compatibility. It's better to use XSP taglib. [MP 2006-02-16]
		xspAttr.addAttribute(
				"http://www.w3.org/XML/1998/namespace",
				"lang",
				"xml:lang",
				"CDATA",
				String.valueOf(sdx_lang)
			); -->
			<xsp:attribute name="lang" uri="http://www.w3.org/XML/1998/namespace" prefix="xml">
				<xsp:expr>sdx_lang</xsp:expr>
			</xsp:attribute>
		sdx_string="";
		sdx_string +=request.getScheme()+"://";
		sdx_string +=request.getServerName();
		if (request.getServerPort() != 80) sdx_string += ":" + request.getServerPort();

		<xsp:attribute name="server">
			<xsp:expr>sdx_string+request.getContextPath()</xsp:expr>
		</xsp:attribute>
		<xsp:attribute name="api-url">
			<xsp:expr>sdx_string+request.getContextPath()+"/sdx/api-url"</xsp:expr>
		</xsp:attribute>

		if (sdx_application != null)
		{

			<xsp:attribute name="app">
				<xsp:expr>sdx_application.getId()</xsp:expr>
			</xsp:attribute>
			<xsp:attribute name="appbypath">
				<xsp:expr>sdx_application.getPath()</xsp:expr>
			</xsp:attribute>

		}
		sdx_string += request.getRequestURI();

		<xsp:attribute name="uri">
			<xsp:expr>sdx_string</xsp:expr>
		</xsp:attribute>

		//sdx_string = request.getServletPath();
		//sdx_enum = new java.util.StringTokenizer (sdx_string, "/");
		//sdx_string = ((java.util.StringTokenizer)sdx_enum).nextToken();

		<!--
		<xsp:attribute name="appbypath">
			<xsp:expr>sdx_string</xsp:expr>
		</xsp:attribute>
		<xsp:attribute name="session">
			<xsp:expr>request.getSession(true).getId()</xsp:expr>
		</xsp:attribute>
		-->

		if (request.getQueryString() != null)
		{
			<xsp:attribute name="query">?<xsp:expr>request.getQueryString()</xsp:expr></xsp:attribute>
		}

		<xsp:attribute name="version">
			<xsp:expr>sdx_frame.VERSION</xsp:expr>
		</xsp:attribute>
		<xsp:attribute name="build">
			<xsp:expr>sdx_frame.BUILD</xsp:expr>
		</xsp:attribute>
		<xsp:attribute name="date">
			<xsp:expr>new Date()</xsp:expr>
		</xsp:attribute>
	</xsl:template>
	<!--
		sdx:parameters, request parameters with the especially useful "urlencode" version
	-->
	<xsl:template name="sdx:infos">
		<xsp:logic>
			<xsl:call-template name="comment">
				<xsl:with-param name="name" select="'INFOS'"/>
			</xsl:call-template>

			if (sdx_show==null) sdx_show="user get ";
			if (
					sdx_show.indexOf("session") != -1
					|| sdx_show.indexOf("get") != -1
					|| sdx_show.indexOf("post") != -1
					|| sdx_show.indexOf("put") != -1
					|| sdx_show.indexOf("headers") != -1
				)
				sdx_show += " parameters";

			if (sdx_application != null &amp;&amp; sdx_show.indexOf("application") != -1) sdx_application.toSAX(contentHandler);
			sdx_bool = (sdx_show == null);
			if (sdx_user != null &amp;&amp; sdx_show.indexOf("user") != -1)
			{
				if (request != null)
				{
					sdx_user.setIp(request.getRemoteAddr());
					/* ?? performances ?? */
					sdx_user.setHost(request.getRemoteHost());
				}
				sdx_user.toSAX(contentHandler);
			}

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

			if (sdx_show.indexOf("parameters") != -1)
			{

				<sdx:parameters>
				<xsp:logic>
						sdx_type=request.getMethod();
						if (
								("GET".equalsIgnoreCase(sdx_type) &amp;&amp; sdx_show.indexOf("get") != -1)
								|| ("POST".equalsIgnoreCase(sdx_type) &amp;&amp; sdx_show.indexOf("post") != -1)
								|| ("PUT".equalsIgnoreCase(sdx_type) &amp;&amp; sdx_show.indexOf("put") != -1)
							)
						{
							sdx_enum = request.getParameterNames();
							while (sdx_enum.hasMoreElements())
							{
								sdx_string = (String)sdx_enum.nextElement();
								sdx_strings = request.getParameterValues(sdx_string);
								for (sdx_i=0; sdx_i &lt; sdx_strings.length; sdx_i++)
								{
									sdx_parameter=Utilities.encodeURL(sdx_strings[sdx_i], sdx_encoding);
									<sdx:parameter>
										<xsp:attribute name="type">
											<xsp:expr>sdx_type.toLowerCase()</xsp:expr>
										</xsp:attribute>
										<xsp:attribute name="name">
											<xsp:expr>sdx_string</xsp:expr>
										</xsp:attribute>
										<xsp:attribute name="value">
											<xsp:expr>sdx_strings[sdx_i]</xsp:expr>
										</xsp:attribute>
										<xsp:attribute name="escapedValue">
											<xsp:expr>sdx_parameter</xsp:expr>
										</xsp:attribute>
									</sdx:parameter>
								}
							}
						}

						if (sdx_show.indexOf("session") != -1)
						{
							sdx_enum = session.getAttributeNames();
							while (sdx_enum.hasMoreElements())
							{
								sdx_string = (String)sdx_enum.nextElement();
								if (sdx_show.indexOf("objects") != -1)
								{
									sdx_object=getSessionObject(session, sdx_string);
									<sdx:parameter>
										<xsp:attribute name="type">session</xsp:attribute>
										<xsp:attribute name="name">
											<xsp:expr>sdx_string</xsp:expr>
										</xsp:attribute>
										<xsp:attribute name="value">
											<xsp:expr>sdx_object</xsp:expr>
										</xsp:attribute>
										<xsp:expr>sdx_object</xsp:expr>
									</sdx:parameter>
								}
								else
								{
									sdx_object=getSessionObject(session, sdx_string);
									<sdx:parameter>
										<xsp:attribute name="type">session</xsp:attribute>
										<xsp:attribute name="name">
											<xsp:expr>sdx_string</xsp:expr>
										</xsp:attribute>
										<xsp:attribute name="value">
											<xsp:expr>sdx_object</xsp:expr>
										</xsp:attribute>
									</sdx:parameter>
								}
							}
						}

						<!-- http headers -->
						if (sdx_show.indexOf("headers") != -1)
						{
							sdx_enum = request.getHeaderNames();
							while (sdx_enum.hasMoreElements())
							{
								sdx_string=(String)sdx_enum.nextElement();
								sdx_enum2 = request.getHeaders(sdx_string);
								while (sdx_enum2.hasMoreElements())
								{
									<sdx:parameter>
										<xsp:attribute name="type">header</xsp:attribute>
										<xsp:attribute name="name">
											<xsp:expr>sdx_string</xsp:expr>
										</xsp:attribute>
										<xsp:attribute name="value">
											<xsp:expr>sdx_enum2.nextElement()</xsp:expr>
										</xsp:attribute>
									</sdx:parameter>
								}
							}
						}
					</xsp:logic>
			</sdx:parameters>
			}
		</xsp:logic>
	</xsl:template>
	<!--
		Display the application's toSAX()
	-->
	<xsl:template match="sdx:explore">
	 <sdx:explore>
	 <xsp:logic>
	  sdx_app.toSAX(contentHandler);
	 </xsp:logic>
	 </sdx:explore>
	</xsl:template>
	<!--
		Save the application in it's current state
	-->
	<xsl:template match="sdx:saveApplication">
	 <sdx:saveApplication>
	 <xsp:logic>
	  sdx_app.saveApplication();
	 </xsp:logic>
	 </sdx:saveApplication>
	</xsl:template>
	<!-- ============================= GENERAL ============================== -->
	<!--
		Templates for copy or pass tags.
		Default : copy all tags for the consumer.
	-->
	<xsl:template match="sdx:comment">
		<xsl:comment>
			<xsl:copy-of select="node()"/>
		</xsl:comment>
	</xsl:template>
	<xsl:template name="comment">
		<xsl:param name="name" select="name()"/>
		<xsp:logic>
			/*----------------------------------------------
				<xsl:value-of select="$name"/>
			----------------------------------------------*/
		</xsp:logic>
	</xsl:template>
	<xsl:template name="sdx:escapeQuot" match="*|@*|text()" mode="escapeQuot">
		<xsl:param name="string" select="normalize-space(.)"/>
		<xsl:param name="quot">"</xsl:param>
		<xsl:choose>
			<xsl:when test="contains($string, $quot)">
				<xsl:value-of select="normalize-space(substring-before($string, $quot))"/>
				<xsl:text>\</xsl:text>
				<xsl:value-of select="$quot"/>
				<xsl:call-template name="sdx:escapeQuot">
					<xsl:with-param name="string" select="substring-after($string, $quot)"/>
					<xsl:with-param name="quot" select="$quot"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="normalize-space($string)"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<xsl:template match="sdx:page//sdx:debug">
		<xsl:apply-templates/>
	</xsl:template>
	<!--
		Process nodes of <sdx:fallback/> and <sdx:success/>,
		don't output elements, logical java is provide in context by the caller
	-->
	<xsl:template match="sdx:page//sdx:fallback">
		<xsl:apply-templates/>
	</xsl:template>
	<xsl:template match="sdx:page//sdx:success">
		<xsl:apply-templates/>
	</xsl:template>
	<!--
		Logicsheet must preserve all the declarations possibly
		generated by previous logicsheets.
	-->
	<xsl:template match="@*|*|text()|processing-instruction()" priority="-1">
		<xsl:copy>
			<xsl:apply-templates select="@*|*|text()|processing-instruction()"/>
		</xsl:copy>
	</xsl:template>
	<xsl:template name="path">
		<xsl:for-each select="ancestor-or-self::*">
			<xsl:variable name="position">
				<xsl:number/>
			</xsl:variable>
			<xsl:value-of select="concat('/',name(), '[', $position, ']')"/>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>
