/* BdfServer_JsonProducers - Copyright (c) 2013-2025 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package fr.exemole.bdfserver.jsonproducers.pioche;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.instruction.OutputParameters;
import fr.exemole.bdfserver.api.interaction.InteractionConstants;
import fr.exemole.bdfserver.api.interaction.domains.PiocheDomain;
import fr.exemole.bdfserver.api.users.BdfUser;
import fr.exemole.bdfserver.tools.BdfServerUtils;
import fr.exemole.bdfserver.tools.externalsource.ExternalSourceUtils;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import fr.exemole.bdfserver.tools.instruction.BdfInstructionUtils;
import fr.exemole.bdfserver.tools.instruction.OutputRequestHandler;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import net.fichotheque.Fichotheque;
import net.fichotheque.SubsetKey;
import net.fichotheque.addenda.Addenda;
import net.fichotheque.addenda.Document;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.corpus.SortConstants;
import net.fichotheque.externalsource.ExternalItem;
import net.fichotheque.externalsource.ExternalSource;
import net.fichotheque.permission.PermissionSummary;
import net.fichotheque.selection.DocumentQuery;
import net.fichotheque.selection.FicheQuery;
import net.fichotheque.selection.FieldContentCondition;
import net.fichotheque.selection.MotcleQuery;
import net.fichotheque.selection.MotcleSelector;
import net.fichotheque.selection.RedacteurQuery;
import net.fichotheque.selection.SelectionContext;
import net.fichotheque.selection.SubsetCondition;
import net.fichotheque.sphere.Redacteur;
import net.fichotheque.sphere.Sphere;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.tools.permission.PermissionUtils;
import net.fichotheque.tools.selection.DocumentQueryBuilder;
import net.fichotheque.tools.selection.FicheQueryBuilder;
import net.fichotheque.tools.selection.MotcleQueryBuilder;
import net.fichotheque.tools.selection.RedacteurQueryBuilder;
import net.fichotheque.tools.selection.SelectionDOMUtils;
import net.fichotheque.tools.selection.SelectionEngines;
import net.fichotheque.tools.thesaurus.sortprecedence.PrecedenceComparator;
import net.fichotheque.utils.AddendaUtils;
import net.fichotheque.utils.Comparators;
import net.fichotheque.utils.CorpusUtils;
import net.fichotheque.utils.FichothequeUtils;
import net.fichotheque.utils.SelectionUtils;
import net.fichotheque.utils.ThesaurusUtils;
import net.fichotheque.utils.selection.DocumentSelectorBuilder;
import net.fichotheque.utils.selection.FicheSelectorBuilder;
import net.fichotheque.utils.selection.MotcleSelectorBuilder;
import net.fichotheque.utils.selection.RedacteurSelectorBuilder;
import net.mapeadores.util.conditions.ConditionsUtils;
import net.mapeadores.util.conditions.TextCondition;
import net.mapeadores.util.json.JsonProducer;
import net.mapeadores.util.localisation.CodeCatalog;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.text.StringUtils;
import net.mapeadores.util.xml.DOMUtils;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;


/**
 *
 * @author Vincent Calame
 */
public final class PiocheJsonProducerFactory {

    private PiocheJsonProducerFactory() {
    }

    public static JsonProducer getJsonProducer(OutputParameters parameters) throws ErrorMessageException {
        OutputRequestHandler requestHandler = OutputRequestHandler.init(parameters);
        String json = parameters.getOutput();
        BdfServer bdfServer = parameters.getBdfServer();
        RequestMap requestMap = parameters.getRequestMap();
        BdfUser bdfUser = parameters.getBdfUser();
        Lang lang = parameters.getWorkingLang();
        try {
            lang = Lang.parse(requestMap.getParameter("lang"));
        } catch (ParseException pe) {
        }
        switch (json) {
            case PiocheDomain.DOCUMENT_JSON: {
                return new DocumentArrayJsonProducer(getDocuments(requestHandler));
            }
            case PiocheDomain.FICHE_JSON: {
                return new FicheArrayJsonProducer(parameters.getPermissionSummary(), getFiches(requestHandler), BdfInstructionUtils.getCellConverter(parameters));
            }
            case PiocheDomain.MOTCLE_JSON: {
                return new MotcleArrayJsonProducer(lang, getMotcles(requestHandler, lang), BdfInstructionUtils.getCellConverter(parameters));
            }
            case PiocheDomain.EXTERNALITEM_JSON: {
                return new ExternalItemArrayJsonProducer(getExternalItems(requestHandler, lang));
            }
            case PiocheDomain.USER_JSON: {
                return new UserArrayJsonProducer(getRedacteurs(requestHandler), getDefaultSphereKey(requestHandler));
            }
            case PiocheDomain.LANGUAGE_JSON: {
                return new CodeArrayJsonProducer(bdfServer, bdfUser, getLangCodeSet(requestHandler));
            }
            case PiocheDomain.COUNTRY_JSON: {
                return new CodeArrayJsonProducer(bdfServer, bdfUser, getCountryCodeSet(requestHandler));
            }
            case PiocheDomain.FIELD_JSON: {
                TextCondition condition = getCondition(requestHandler);
                FieldArrayJsonProducer fieldArrayJsonProducer = new FieldArrayJsonProducer(bdfServer, bdfUser.getLangPreference(), getFieldType(requestHandler));
                fieldArrayJsonProducer.init(condition);
                return fieldArrayJsonProducer;
            }
            default:
                return null;
        }
    }

    private static SubsetKey getDefaultSphereKey(OutputRequestHandler requestHandler) {
        String param = requestHandler.getTrimedParameter(PiocheDomain.DEFAULSPHERE_PARAMNAME);
        if (param.isEmpty()) {
            return null;
        }
        try {
            SubsetKey sphereKey = SubsetKey.parse(param);
            if (sphereKey.isSphereSubset()) {
                return sphereKey;
            } else {
                return null;
            }
        } catch (java.text.ParseException pe) {
            return null;
        }
    }

    private static String getFieldType(OutputRequestHandler requestHandler) {
        String param = requestHandler.getTrimedParameter(PiocheDomain.FIELDTYPE_PARAMNAME);
        if (param.isEmpty()) {
            return PiocheDomain.ALL_FIELDTYPE;
        } else {
            return param;
        }
    }

    private static SubsetKey getCroisementSubsetKey(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String subsetString = requestHandler.getTrimedParameter(PiocheDomain.CROISEMENT_PARAMNAME);
        if (subsetString.isEmpty()) {
            return null;
        }
        try {
            SubsetKey subsetKey = SubsetKey.parse(subsetString);
            return subsetKey;
        } catch (ParseException pe) {
            throw BdfErrors.wrongParameterValue(PiocheDomain.CROISEMENT_PARAMNAME, subsetString);
        }
    }

    private static TextCondition getCondition(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String q = requestHandler.getMandatoryParameter(PiocheDomain.Q_PARAMNAME);
        return ConditionsUtils.parseSimpleCondition(q);
    }

    private static Collection<ExternalItem> getExternalItems(OutputRequestHandler requestHandler, Lang lang) throws ErrorMessageException {
        BdfServer bdfServer = requestHandler.getBdfServer();
        Thesaurus thesaurus = getThesaurus(requestHandler);
        ExternalSource externalSource = ExternalSourceUtils.getExternalSource(bdfServer, thesaurus);
        if (externalSource == null) {
            throw BdfErrors.wrongParameterValue("thesaurus or subsets", thesaurus.getSubsetName());
        }
        lang = BdfServerUtils.checkLangDisponibility(bdfServer, thesaurus, lang);
        String q = requestHandler.getMandatoryParameter(PiocheDomain.Q_PARAMNAME);
        if (q.isEmpty()) {
            return ExternalSourceUtils.EXTERNALITEM_EMPTYLIST;
        }
        Collection<ExternalItem> result = externalSource.search(q, lang);
        Comparator<ExternalItem> comparator = getExternalItemComparator(requestHandler);
        if (comparator != null) {
            TreeSet<ExternalItem> treeset = new TreeSet<ExternalItem>(comparator);
            treeset.addAll(result);
            result = treeset;
        }
        int limit = getLimit(requestHandler);
        if ((limit < 1) || (result.size() <= limit)) {
            return result;
        } else {
            int p = 0;
            List<ExternalItem> list = new ArrayList<ExternalItem>(limit);
            for (ExternalItem externalItem : result) {
                list.add(externalItem);
                p++;
                if (p == limit) {
                    break;
                }
            }
            return list;
        }
    }

    private static Collection<FicheMeta> getFiches(OutputRequestHandler requestHandler) throws ErrorMessageException {
        SelectionContext selectionContext = BdfServerUtils.initSelectionContextBuilder(requestHandler)
                .setSubsetAccessPredicate(requestHandler.getPermissionSummary().getSubsetAccessPredicate())
                .setFichePredicate(PermissionUtils.getFichePredicate(requestHandler.getPermissionSummary()))
                .toSelectionContext();
        Map<SubsetKey, Corpus> corpusMap = getCorpusMap(requestHandler);
        FicheQuery ficheQuery;
        String xml = requestHandler.getTrimedParameter(InteractionConstants.XML_PARAMNAME, true);
        if (xml != null) {
            org.w3c.dom.Document document;
            try {
                document = DOMUtils.parseDocument(xml);
            } catch (SAXException sae) {
                throw BdfErrors.error("_ error.exception.xml.sax", sae.getMessage());
            }
            Element root = document.getDocumentElement();
            switch (root.getTagName()) {
                case "fiche-query":
                case "fiche-select":
                    ficheQuery = SelectionDOMUtils.getFicheConditionEntry(requestHandler.getFichotheque(), root).getFicheQuery();
                    if (!corpusMap.isEmpty()) {
                        ficheQuery = derive(ficheQuery, corpusMap);
                    }
                    break;
                default:
                    throw BdfErrors.error("_ error.wrong.xml.root", root.getTagName(), "fiche-query");
            }
        } else {
            FicheQueryBuilder ficheQueryBuilder = FicheQueryBuilder.init()
                    .addCorpus(corpusMap.keySet());
            String q = requestHandler.getTrimedParameter(PiocheDomain.Q_PARAMNAME);
            if (!q.isEmpty()) {
                TextCondition condition = ConditionsUtils.parseSimpleCondition(q);
                if (condition != null) {
                    ficheQueryBuilder.setFieldContentCondition(condition, FieldContentCondition.TITLE_SCOPE, null);
                }
            }
            ficheQuery = ficheQueryBuilder.toFicheQuery();
        }
        if (ficheQuery != null) {
            Comparator<FicheMeta> comparator = requestHandler.getComparator(selectionContext.getWorkingLang());
            Collection<FicheMeta> result = SelectionEngines.run(selectionContext, FicheSelectorBuilder.init(selectionContext).add(ficheQuery).toFicheSelector(), comparator);
            int limit = getLimit(requestHandler);
            if ((limit < 1) || (result.size() <= limit)) {
                return result;
            } else {
                int p = 0;
                List<FicheMeta> list = new ArrayList<FicheMeta>(limit);
                for (FicheMeta ficheMeta : result) {
                    list.add(ficheMeta);
                    p++;
                    if (p == limit) {
                        break;
                    }
                }
                return list;
            }
        } else {
            return CorpusUtils.EMPTY_FICHEMETALIST;
        }
    }

    private static Collection<Motcle> getMotcles(OutputRequestHandler requestHandler, Lang lang) throws ErrorMessageException {
        RequestMap requestMap = requestHandler.getRequestMap();
        Map<SubsetKey, Thesaurus> thesaurusMap = getThesaurusMap(requestHandler);
        SubsetKey shouldNotCroisementSubsetKey = getCroisementSubsetKey(requestHandler);
        if (thesaurusMap.size() == 1) {
            Thesaurus thesaurus = thesaurusMap.values().iterator().next();
            lang = BdfServerUtils.checkLangDisponibility(requestHandler.getBdfServer(), thesaurus, lang);
        }
        SelectionContext selectionContext = BdfServerUtils.initSelectionContextBuilder(requestHandler.getBdfServer(), lang)
                .setSubsetAccessPredicate(requestHandler.getPermissionSummary().getSubsetAccessPredicate())
                .toSelectionContext();
        MotcleQuery motcleQuery;
        String xml = requestMap.getParameter(InteractionConstants.XML_PARAMNAME);
        if (xml != null) {
            org.w3c.dom.Document document;
            try {
                document = DOMUtils.parseDocument(xml);
            } catch (SAXException sae) {
                throw BdfErrors.error("_ error.exception.xml.sax", sae.getMessage());
            }
            Element root = document.getDocumentElement();
            switch (root.getTagName()) {
                case "motcle-query":
                case "motcle-select":
                    motcleQuery = SelectionDOMUtils.getMotcleConditionEntry(requestHandler.getFichotheque(), root).getMotcleQuery();
                    if (!thesaurusMap.isEmpty()) {
                        motcleQuery = derive(motcleQuery, thesaurusMap);
                    }
                    break;
                default:
                    throw BdfErrors.error("_ error.wrong.xml.root", root.getTagName(), "motcle-query");
            }
        } else {
            MotcleQueryBuilder motcleQueryBuilder = MotcleQueryBuilder.init()
                    .addThesaurus(thesaurusMap.keySet());
            String q = requestMap.getParameter(PiocheDomain.Q_PARAMNAME);
            if (q != null) {
                TextCondition condition = ConditionsUtils.parseSimpleCondition(q);
                if (condition != null) {
                    motcleQueryBuilder.setContentCondition(condition, MotcleQuery.SCOPE_IDALPHA_WITH);
                }
            }
            motcleQuery = motcleQueryBuilder.toMotcleQuery();
        }
        if (motcleQuery != null) {
            MotcleSelector motcleSelector = MotcleSelectorBuilder.init(selectionContext).add(motcleQuery).toMotcleSelector();
            Comparator<Motcle> comparator = getMotcleComparator(requestHandler, selectionContext.getWorkingLang(), motcleSelector);
            Collection<Motcle> result = SelectionEngines.run(selectionContext, shouldNotCroisementSubsetKey, motcleSelector, comparator);
            int limit = getLimit(requestHandler);
            if ((limit < 1) || (result.size() <= limit)) {
                return result;
            } else {
                int p = 0;
                List<Motcle> list = new ArrayList<Motcle>(limit);
                for (Motcle motcle : result) {
                    list.add(motcle);
                    p++;
                    if (p == limit) {
                        break;
                    }
                }
                return list;
            }
        } else {
            return ThesaurusUtils.EMPTY_MOTCLELIST;
        }
    }

    private static Collection<Document> getDocuments(OutputRequestHandler requestHandler) throws ErrorMessageException {
        RequestMap requestMap = requestHandler.getRequestMap();
        Map<SubsetKey, Addenda> addendaMap = getAddendaMap(requestHandler);
        if (addendaMap.isEmpty()) {
            return AddendaUtils.EMPTY_DOCUMENTLIST;
        }
        SelectionContext selectionContext = BdfServerUtils.initSelectionContextBuilder(requestHandler)
                .setSubsetAccessPredicate(requestHandler.getPermissionSummary().getSubsetAccessPredicate())
                .toSelectionContext();
        TextCondition condition = getCondition(requestHandler);
        DocumentQuery documentQuery = DocumentQueryBuilder.init()
                .addAddenda(addendaMap.keySet())
                .setNameCondition(condition)
                .toDocumentQuery();
        return SelectionEngines.run(selectionContext, DocumentSelectorBuilder.init(selectionContext).add(documentQuery, null).toDocumentSelector());
    }

    private static Collection<Redacteur> getRedacteurs(OutputRequestHandler requestHandler) throws ErrorMessageException {
        Map<SubsetKey, Sphere> sphereMap = getSphereMap(requestHandler);
        SelectionContext selectionContext = BdfServerUtils.initSelectionContextBuilder(requestHandler)
                .setSubsetAccessPredicate(requestHandler.getPermissionSummary().getSubsetAccessPredicate())
                .toSelectionContext();
        TextCondition condition = getCondition(requestHandler);
        RedacteurQuery redacteurQuery = RedacteurQueryBuilder.init()
                .addSphere(sphereMap.keySet())
                .setNomcompletCondition(condition)
                .toRedacteurQuery();
        return SelectionEngines.run(selectionContext, RedacteurSelectorBuilder.init(selectionContext).add(redacteurQuery).toRedacteurSelector());
    }

    private static Set<String> getCountryCodeSet(OutputRequestHandler requestHandler) throws ErrorMessageException {
        TextCondition condition = getCondition(requestHandler);
        CodeCatalog codeCatalog = requestHandler.getBdfServer().getL10nManager().getCodeCatalog();
        if (condition != null) {
            return codeCatalog.getCountryCodeSet(condition, requestHandler.getBdfUser().getLangPreference());
        } else {
            return codeCatalog.getCountryCodeSet();
        }
    }

    private static Set<String> getLangCodeSet(OutputRequestHandler requestHandler) throws ErrorMessageException {
        TextCondition condition = getCondition(requestHandler);
        CodeCatalog codeCatalog = requestHandler.getBdfServer().getL10nManager().getCodeCatalog();
        if (condition != null) {
            return codeCatalog.getLangCodeSet(condition, requestHandler.getBdfUser().getLangPreference());
        } else {
            return codeCatalog.getLangCodeSet();
        }
    }

    private static FicheQuery derive(FicheQuery originFicheQuery, Map<SubsetKey, Corpus> corpusMap) {
        SubsetCondition originSubsetCondition = originFicheQuery.getCorpusCondition();
        Set<SubsetKey> result = new HashSet<SubsetKey>();
        for (SubsetKey key : corpusMap.keySet()) {
            if (originSubsetCondition.accept(key)) {
                result.add(key);
            }
        }
        if (result.isEmpty()) {
            return originFicheQuery;
        } else {
            return SelectionUtils.derive(originFicheQuery, SelectionUtils.toSubsetCondition(result));
        }
    }

    private static MotcleQuery derive(MotcleQuery originMotcleQuery, Map<SubsetKey, Thesaurus> thesaurusMap) {
        SubsetCondition originSubsetCondition = originMotcleQuery.getThesaurusCondition();
        Set<SubsetKey> result = new HashSet<SubsetKey>();
        for (SubsetKey key : thesaurusMap.keySet()) {
            if (originSubsetCondition.accept(key)) {
                result.add(key);
            }
        }
        if (result.isEmpty()) {
            return originMotcleQuery;
        } else {
            return SelectionUtils.derive(originMotcleQuery, SelectionUtils.toSubsetCondition(result));
        }
    }

    private static Map<SubsetKey, Corpus> getCorpusMap(OutputRequestHandler requestHandler) throws ErrorMessageException {
        Fichotheque fichotheque = requestHandler.getFichotheque();
        Map<SubsetKey, Corpus> map = new LinkedHashMap<SubsetKey, Corpus>();
        String subsetsParam = requestHandler.getTrimedParameter(PiocheDomain.SUBSETS_PARAMNAME);
        String[] corpusArray = StringUtils.getTechnicalTokens(subsetsParam, true);
        if (corpusArray.length > 0) {
            for (String corpusName : corpusArray) {
                Corpus corpus = FichothequeUtils.getCorpus(fichotheque, corpusName);
                if (corpus != null) {
                    map.put(corpus.getSubsetKey(), corpus);
                }
            }
            if (map.isEmpty()) {
                throw BdfErrors.wrongParameterValue(PiocheDomain.SUBSETS_PARAMNAME, subsetsParam);
            }
        }
        return map;
    }

    private static Map<SubsetKey, Thesaurus> getThesaurusMap(OutputRequestHandler requestHandler) throws ErrorMessageException {
        Fichotheque fichotheque = requestHandler.getFichotheque();
        Map<SubsetKey, Thesaurus> map = new LinkedHashMap<SubsetKey, Thesaurus>();
        String subsetsParam = requestHandler.getTrimedParameter(PiocheDomain.SUBSETS_PARAMNAME);
        String[] thesaurusArray = StringUtils.getTechnicalTokens(subsetsParam, true);
        if (thesaurusArray.length > 0) {
            for (String thesaurusName : thesaurusArray) {
                Thesaurus thesaurus = FichothequeUtils.getThesaurus(fichotheque, thesaurusName);
                if (thesaurus != null) {
                    map.put(thesaurus.getSubsetKey(), thesaurus);
                }
            }
            if (map.isEmpty()) {
                throw BdfErrors.wrongParameterValue(PiocheDomain.SUBSETS_PARAMNAME, subsetsParam);
            }
        }
        return map;
    }

    private static Map<SubsetKey, Addenda> getAddendaMap(OutputRequestHandler requestHandler) throws ErrorMessageException {
        Fichotheque fichotheque = requestHandler.getFichotheque();
        PermissionSummary permissionSummary = requestHandler.getPermissionSummary();
        String subsetsParam = requestHandler.getTrimedParameter(PiocheDomain.SUBSETS_PARAMNAME);
        Map<SubsetKey, Addenda> map = new LinkedHashMap<SubsetKey, Addenda>();
        String[] addendaArray = StringUtils.getTechnicalTokens(subsetsParam, true);
        if (addendaArray.length > 0) {
            for (String addendaName : addendaArray) {
                Addenda addenda = FichothequeUtils.getAddenda(fichotheque, addendaName);
                if ((addenda != null) && (permissionSummary.isSubsetAdmin(addenda.getSubsetKey()))) {
                    map.put(addenda.getSubsetKey(), addenda);
                }
            }
        } else {
            for (Addenda addenda : fichotheque.getAddendaList()) {
                if (permissionSummary.isSubsetAdmin(addenda.getSubsetKey())) {
                    map.put(addenda.getSubsetKey(), addenda);
                }
            }
        }
        return map;
    }

    private static Map<SubsetKey, Sphere> getSphereMap(OutputRequestHandler requestHandler) throws ErrorMessageException {
        Fichotheque fichotheque = requestHandler.getFichotheque();
        String subsetsParam = requestHandler.getTrimedParameter(PiocheDomain.SUBSETS_PARAMNAME);
        Map<SubsetKey, Sphere> map = new LinkedHashMap<SubsetKey, Sphere>();
        String[] sphereArray = StringUtils.getTechnicalTokens(subsetsParam, true);
        if (sphereArray.length > 0) {
            for (String sphereName : sphereArray) {
                Sphere sphere = FichothequeUtils.getSphere(fichotheque, sphereName);
                if (sphere != null) {
                    map.put(sphere.getSubsetKey(), sphere);
                }
            }
            if (map.isEmpty()) {
                throw BdfErrors.wrongParameterValue(PiocheDomain.SUBSETS_PARAMNAME, subsetsParam);
            }
        }
        return map;
    }

    private static Comparator<ExternalItem> getExternalItemComparator(OutputRequestHandler requestHandler) throws ErrorMessageException {
        String sort = requestHandler.getTrimedParameter(InteractionConstants.SORT_PARAMNAME);
        if (sort.isEmpty()) {
            return null;
        }
        switch (sort) {
            case SortConstants.ID_ASC:
                return Comparators.EXTERNALITEMID_ASC;
            case SortConstants.ID_DESC:
                return Comparators.EXTERNALITEMID_DESC;
            default:
                throw BdfErrors.error("_ error.unknown.parametervalue", InteractionConstants.SORT_PARAMNAME, sort);
        }
    }

    private static Comparator<Motcle> getMotcleComparator(OutputRequestHandler requestHandler, Lang lang, MotcleSelector motcleSelector) throws ErrorMessageException {
        String sortPrecedence = requestHandler.getTrimedParameter(PiocheDomain.SORTPRECEDENCE_PARAMNAME);
        if (!sortPrecedence.isEmpty()) {
            return new PrecedenceComparator(sortPrecedence, lang);
        }
        String sort = requestHandler.getTrimedParameter(InteractionConstants.SORT_PARAMNAME);
        if (sort.isEmpty()) {
            List<Thesaurus> thesaurusList = motcleSelector.getThesaurusList();
            if (thesaurusList.size() == 1) {
                if (thesaurusList.get(0).isIdalphaType()) {
                    return null;
                } else {
                    return Comparators.label(lang);
                }
            } else {
                return Comparators.idalphaAndLabel(lang);
            }
        } else {
            switch (sort) {
                case SortConstants.ID_ASC:
                    return Comparators.MOTCLEID_ASC;
                case SortConstants.ID_DESC:
                    return Comparators.MOTCLEID_DESC;
                default:
                    throw BdfErrors.error("_ error.unknown.parametervalue", InteractionConstants.SORT_PARAMNAME, sort);
            }
        }
    }

    private static int getLimit(OutputRequestHandler requestHandler) {
        String limitString = requestHandler.getTrimedParameter(PiocheDomain.LIMIT_PARAMNAME);
        if (limitString.isEmpty()) {
            return -1;
        }
        try {
            return Integer.parseInt(limitString);
        } catch (NumberFormatException nfe) {
            return -1;
        }
    }

    private static Thesaurus getThesaurus(OutputRequestHandler requestHandler) throws ErrorMessageException {
        if (!requestHandler.getTrimedParameter(SubsetKey.CATEGORY_THESAURUS_STRING).isEmpty()) {
            return requestHandler.getMandatoryThesaurus();
        }
        String subsetsParam = requestHandler.getMandatoryParameter(PiocheDomain.SUBSETS_PARAMNAME);
        Map<SubsetKey, Thesaurus> thesaurusMap = getThesaurusMap(requestHandler);
        if (thesaurusMap.isEmpty()) {
            throw BdfErrors.wrongParameterValue(PiocheDomain.SUBSETS_PARAMNAME, subsetsParam);
        }
        return thesaurusMap.values().iterator().next();
    }


}
