org.fao.geonet.api.registries.vocabularies.KeywordsApi.java Source code

Java tutorial

Introduction

Here is the source code for org.fao.geonet.api.registries.vocabularies.KeywordsApi.java

Source

/*
 * Copyright (C) 2001-2016 Food and Agriculture Organization of the
 * United Nations (FAO-UN), United Nations World Food Programme (WFP)
 * and United Nations Environment Programme (UNEP)
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 * Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
 * Rome - Italy. email: geonetwork@osgeo.org
 */

package org.fao.geonet.api.registries.vocabularies;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.GeonetContext;
import org.fao.geonet.api.API;
import org.fao.geonet.api.ApiParams;
import org.fao.geonet.api.ApiUtils;
import org.fao.geonet.api.exception.ResourceNotFoundException;
import org.fao.geonet.api.exception.WebApplicationException;
import org.fao.geonet.api.tools.i18n.LanguageUtils;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.kernel.GeonetworkDataDirectory;
import org.fao.geonet.kernel.KeywordBean;
import org.fao.geonet.kernel.Thesaurus;
import org.fao.geonet.kernel.ThesaurusManager;
import org.fao.geonet.kernel.search.KeywordsSearcher;
import org.fao.geonet.kernel.search.keyword.KeywordSearchParamsBuilder;
import org.fao.geonet.kernel.search.keyword.KeywordSearchType;
import org.fao.geonet.kernel.search.keyword.KeywordSort;
import org.fao.geonet.kernel.search.keyword.SortDirection;
import org.fao.geonet.kernel.search.keyword.XmlParams;
import org.fao.geonet.kernel.setting.SettingManager;
import org.fao.geonet.languages.IsoLanguagesMapper;
import org.fao.geonet.lib.Lib;
import org.fao.geonet.repository.ThesaurusActivationRepository;
import org.fao.geonet.utils.FilePathChecker;
import org.fao.geonet.utils.GeonetHttpRequestFactory;
import org.fao.geonet.utils.IO;
import org.fao.geonet.utils.Log;
import org.fao.geonet.utils.Xml;
import org.fao.geonet.utils.XmlRequest;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import jeeves.server.UserSession;
import jeeves.server.context.ServiceContext;
import springfox.documentation.annotations.ApiIgnore;

/**
 * The Class KeywordsApi.
 */
@EnableWebMvc
@Service
@RequestMapping(value = { "/api/registries/vocabularies", "/api/" + API.VERSION_0_1 + "/registries/vocabularies" })
@Api(value = ApiParams.API_CLASS_REGISTRIES_TAG, tags = ApiParams.API_CLASS_REGISTRIES_TAG, description = ApiParams.API_CLASS_REGISTRIES_OPS)
public class KeywordsApi {

    /** The language utils. */
    @Autowired
    LanguageUtils languageUtils;

    /**
     * Search keywords.
     *
     * @param q the q
     * @param lang the lang
     * @param rows the rows
     * @param start the start
     * @param targetLangs the target langs
     * @param thesaurus the thesaurus
     * @param type the type
     * @param uri the uri
     * @param sort the sort
     * @param request the request
     * @param httpSession the http session
     * @return the list
     * @throws Exception the exception
     */
    @ApiOperation(value = "Search keywords", nickname = "searchKeywords", notes = "")
    @RequestMapping(path = "/search", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    public List<KeywordBean> searchKeywords(
            @ApiParam(value = "Query", required = false) @RequestParam(required = false) String q,
            @ApiParam(value = "Query in that language", required = false) @RequestParam(value = "lang", defaultValue = "eng") String lang,
            @ApiParam(value = "Number of rows", required = false) @RequestParam(required = false, defaultValue = "1000") int rows,
            @ApiParam(value = "Start from", required = false) @RequestParam(defaultValue = "0", required = false) int start,
            @ApiParam(value = "Return keyword information in one or more languages", required = false) @RequestParam(value = XmlParams.pLang, required = false) List<String> targetLangs,
            @ApiParam(value = "Thesaurus identifier", required = false) @RequestParam(required = false) String[] thesaurus,
            //        @ApiParam(
            //            value = "?",
            //            required = false
            //        )
            //        @RequestParam(
            //            required = false
            //        )
            //            String thesauriDomainName,
            @ApiParam(value = "Type of search", required = false) @RequestParam(defaultValue = "CONTAINS") KeywordSearchType type,
            @ApiParam(value = "URI query", required = false) @RequestParam(required = false) String uri,
            @ApiParam(value = "Sort by", required = false) @RequestParam(required = false, defaultValue = "DESC") String sort,
            @ApiIgnore HttpServletRequest request, @ApiIgnore @ApiParam(hidden = true) HttpSession httpSession)
            throws Exception {
        ConfigurableApplicationContext applicationContext = ApplicationContextHolder.get();
        ServiceContext context = ApiUtils.createServiceContext(request);
        UserSession session = ApiUtils.getUserSession(httpSession);

        //        Locale locale = languageUtils.parseAcceptLanguage(request.getLocales());
        //        lang = locale.getISO3Language();

        KeywordsSearcher searcher;
        // perform the search and save search result into session
        ThesaurusManager thesaurusMan = applicationContext.getBean(ThesaurusManager.class);

        if (Log.isDebugEnabled("KeywordsManager")) {
            Log.debug("KeywordsManager", "Creating new keywords searcher");
        }
        searcher = new KeywordsSearcher(context, thesaurusMan);

        IsoLanguagesMapper languagesMapper = applicationContext.getBean(IsoLanguagesMapper.class);
        String thesauriDomainName = null;

        KeywordSearchParamsBuilder builder = parseBuilder(lang, q, rows, start, targetLangs,
                Arrays.asList(thesaurus), thesauriDomainName, type, uri, languagesMapper);

        //            if (checkModified(webRequest, thesaurusMan, builder)) {
        //                return null;
        //            }

        if (q == null || q.trim().isEmpty()) {
            builder.setComparator(KeywordSort.defaultLabelSorter(SortDirection.parse(sort)));
        } else {
            builder.setComparator(KeywordSort.searchResultsSorter(q, SortDirection.parse(sort)));
        }

        searcher.search(builder.build());
        session.setProperty(Geonet.Session.SEARCH_KEYWORDS_RESULT, searcher);

        // get the results
        return searcher.getResults();
    }

    /** The mapper. */
    @Autowired
    IsoLanguagesMapper mapper;

    /** The thesaurus manager. */
    @Autowired
    ThesaurusManager thesaurusManager;

    /**
     * Gets the keyword by id.
     *
     * @param uri the uri
     * @param sThesaurusName the s thesaurus name
     * @param langs the langs
     * @param keywordOnly the keyword only
     * @param transformation the transformation
     * @param allRequestParams the all request params
     * @param request the request
     * @return the keyword by id
     * @throws Exception the exception
     */
    @ApiOperation(value = "Get keyword by id", nickname = "getKeywordById", notes = "Retrieve XML representation of keyword(s) from same thesaurus"
            + "using different transformations. "
            + "'to-iso19139-keyword' is the default and return an ISO19139 snippet."
            + "'to-iso19139-keyword-as-xlink' return an XLinked element. Custom transformation "
            + "can be create on a per schema basis.")
    @RequestMapping(path = "/keyword", method = RequestMethod.GET, produces = { MediaType.APPLICATION_XML_VALUE })
    @ApiResponses(value = { @ApiResponse(code = 200, message = "XML snippet with requested keywords."), })
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public Element getKeywordById(
            @ApiParam(value = "Keyword identifier or list of keyword identifiers comma separated.", required = true) @RequestParam(name = "id") String uri,
            @ApiParam(value = "Thesaurus to look info for the keyword(s).", required = true) @RequestParam(name = "thesaurus") String sThesaurusName,
            @ApiParam(value = "Languages.", required = false) @RequestParam(name = "lang", required = false) String[] langs,
            @ApiParam(value = "Only print the keyword, no thesaurus information.", required = false) @RequestParam(required = false, defaultValue = "false") boolean keywordOnly,
            @ApiParam(value = "XSL template to use (ISO19139 keyword by default, see convert.xsl).", required = false) @RequestParam(required = false) String transformation,
            @ApiIgnore @RequestParam Map<String, String> allRequestParams, HttpServletRequest request

    ) throws Exception {
        final String SEPARATOR = ",";
        ServiceContext context = ApiUtils.createServiceContext(request);

        if (langs == null) {
            langs = context.getLanguage().split(",");
        }
        String[] iso3langCodes = Arrays.copyOf(langs, langs.length);
        for (int i = 0; i < langs.length; i++) {
            if (StringUtils.isNotEmpty(langs[i])) {
                langs[i] = mapper.iso639_2_to_iso639_1(langs[i], langs[i].substring(2));
            }
        }

        Element descKeys;

        uri = URLDecoder.decode(uri, "UTF-8");

        if (uri == null) {
            descKeys = new Element("descKeys");
        } else {
            KeywordsSearcher searcher = new KeywordsSearcher(context, thesaurusManager);

            KeywordBean kb;
            if (!uri.contains(SEPARATOR)) {
                kb = searcher.searchById(uri, sThesaurusName, langs);
                if (kb == null) {
                    descKeys = new Element("descKeys");
                } else {
                    descKeys = KeywordsSearcher.toRawElement(new Element("descKeys"), kb);
                }
            } else {
                String[] url = uri.split(SEPARATOR);
                List<KeywordBean> kbList = new ArrayList<>();
                for (String currentUri : url) {
                    kb = searcher.searchById(currentUri, sThesaurusName, langs);
                    if (kb != null) {
                        kbList.add(kb);
                    }
                }
                descKeys = new Element("descKeys");
                for (KeywordBean keywordBean : kbList) {
                    KeywordsSearcher.toRawElement(descKeys, keywordBean);
                }
            }
        }

        GeonetworkDataDirectory dataDirectory = context.getBean(GeonetworkDataDirectory.class);
        SettingManager settingManager = context.getBean(SettingManager.class);
        Path convertXsl = dataDirectory.getWebappDir().resolve("xslt/services/thesaurus/convert.xsl");

        Element gui = new Element("gui");
        Element nodeUrl = new Element("nodeUrl").setText(settingManager.getNodeURL());
        Element nodeId = new Element("nodeId").setText(context.getNodeId());
        Element thesaurusEl = new Element("thesaurus");
        final Element root = new Element("root");

        gui.addContent(thesaurusEl);
        thesaurusEl.addContent(thesaurusManager.buildResultfromThTable(context));

        Element requestParams = new Element("request");
        for (Map.Entry<String, String> e : allRequestParams.entrySet()) {
            if (e.getKey().equals("lang")) {
                requestParams.addContent(new Element(e.getKey()).setText(String.join(",", iso3langCodes)));
            } else {
                requestParams.addContent(new Element(e.getKey()).setText(e.getValue()));
            }
        }
        root.addContent(requestParams);
        root.addContent(descKeys);
        root.addContent(gui);
        root.addContent(nodeUrl);
        root.addContent(nodeId);
        final Element transform = Xml.transform(root, convertXsl);

        return transform;
    }

    /**
     * Gets the thesaurus.
     *
     * @param thesaurus the thesaurus
     * @param request the request
     * @param response the response
     * @return the thesaurus
     * @throws Exception the exception
     */
    @ApiOperation(value = "Download a thesaurus by name", nickname = "getThesaurus", notes = "Download the thesaurus in SKOS format.")
    @RequestMapping(value = "/{thesaurus:.+}", method = RequestMethod.GET, produces = { MediaType.TEXT_XML_VALUE })
    @ApiResponses(value = { @ApiResponse(code = 200, message = "Thesaurus in SKOS format."),
            @ApiResponse(code = 404, message = ApiParams.API_RESPONSE_RESOURCE_NOT_FOUND) })
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public void getThesaurus(
            @ApiParam(value = "Thesaurus to download.", required = true) @PathVariable(value = "thesaurus") String thesaurus,
            HttpServletRequest request, HttpServletResponse response) throws Exception {

        ServiceContext context = ApiUtils.createServiceContext(request);
        GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);
        ThesaurusManager manager = gc.getBean(ThesaurusManager.class);

        Thesaurus directory = manager.getThesaurusByName(thesaurus);
        if (directory == null)
            throw new IllegalArgumentException("Thesaurus not found --> " + thesaurus);

        Path directoryFile = directory.getFile();
        if (!Files.exists(directoryFile))
            throw new IllegalArgumentException("Thesaurus file not found --> " + thesaurus);

        response.setContentType("text/xml");
        response.setHeader("Content-Disposition", "attachment;filename=" + directoryFile.getFileName());
        ServletOutputStream out = response.getOutputStream();
        BufferedReader reader1 = new BufferedReader(
                new InputStreamReader(new FileInputStream(directoryFile.toFile()), Charset.forName("UTF-8")));
        IOUtils.copy(reader1, out);
        out.flush();
        out.close();
    }

    /**
     * Delete thesaurus.
     *
     * @param thesaurus the thesaurus
     * @param request the request
     * @return the element
     * @throws Exception the exception
     */
    @ApiOperation(value = "Delete a thesaurus by name", nickname = "deleteThesaurus", notes = "Delete a thesaurus.")
    @RequestMapping(value = "/{thesaurus:.+}", method = RequestMethod.DELETE)
    @ApiResponses(value = { @ApiResponse(code = 200, message = "Thesaurus deleted."),
            @ApiResponse(code = 403, message = ApiParams.API_RESPONSE_NOT_ALLOWED_ONLY_USER_ADMIN),
            @ApiResponse(code = 404, message = ApiParams.API_RESPONSE_RESOURCE_NOT_FOUND) })
    @PreAuthorize("hasRole('UserAdmin')")
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public void deleteThesaurus(
            @ApiParam(value = "Thesaurus to delete.", required = true) @PathVariable(value = "thesaurus") String thesaurus,
            HttpServletRequest request) throws Exception {

        ServiceContext context = ApiUtils.createServiceContext(request);
        GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);
        ThesaurusManager manager = gc.getBean(ThesaurusManager.class);

        Thesaurus thesaurusObject = manager.getThesaurusByName(thesaurus);
        if (thesaurusObject == null) {
            throw new ResourceNotFoundException(
                    String.format("Thesaurus with identifier '%s' not found in the catalogue. Should be one of: %s",
                            thesaurus, manager.getThesauriMap().keySet().toString()));
        }
        Path item = thesaurusObject.getFile();

        // Remove old file from thesaurus manager
        manager.remove(thesaurus);

        // Remove file
        if (Files.exists(item)) {
            IO.deleteFile(item, true, Geonet.THESAURUS);

            // Delete thesaurus record in the database
            ThesaurusActivationRepository repo = context.getBean(ThesaurusActivationRepository.class);
            String thesaurusId = thesaurusObject.getFname();
            if (repo.exists(thesaurusId)) {
                repo.delete(thesaurusId);
            }
        } else {
            throw new IllegalArgumentException(String
                    .format("Thesaurus RDF file was not found for thesaurus with identifier '%s'.", thesaurus));
        }
    }

    /**
     * Upload thesaurus.
     *
     * @param file the file
     * @param type the type
     * @param dir the dir
     * @param stylesheet the stylesheet
     * @param request the request
     * @return the element
     * @throws Exception the exception
     */
    @ApiOperation(value = "Uploads a new thesaurus from a file", nickname = "uploadThesaurus", notes = "Uploads a new thesaurus.")
    @RequestMapping(method = RequestMethod.POST, produces = MediaType.TEXT_XML_VALUE)
    @ApiResponses(value = { @ApiResponse(code = 201, message = "Thesaurus uploaded in SKOS format."),
            @ApiResponse(code = 403, message = ApiParams.API_RESPONSE_NOT_ALLOWED_ONLY_REVIEWER) })

    @PreAuthorize("hasRole('Reviewer')")
    @ResponseBody
    @ResponseStatus(value = HttpStatus.CREATED)
    public String uploadThesaurus(
            @ApiParam(value = "If set, do a file upload.") @RequestParam(value = "file", required = false) MultipartFile file,
            @ApiParam(value = "Local or external (default).") @RequestParam(value = "type", defaultValue = "external") String type,
            @ApiParam(value = "Type of thesaurus, usually one of the ISO thesaurus type codelist value. Default is theme.") @RequestParam(value = "dir", defaultValue = "theme") String dir,
            @ApiParam(value = "XSL to be use to convert the thesaurus before load. Default _none_.") @RequestParam(value = "stylesheet", defaultValue = "_none_") String stylesheet,
            HttpServletRequest request) throws Exception {

        long start = System.currentTimeMillis();
        ServiceContext context = ApiUtils.createServiceContext(request);

        // Different options for upload
        boolean fileUpload = file != null && !file.isEmpty();

        // Upload RDF file
        Path rdfFile = null;
        String fname = null;
        File tempDir = null;

        if (fileUpload) {

            Log.debug(Geonet.THESAURUS, "Uploading thesaurus file: " + file.getOriginalFilename());

            tempDir = Files.createTempDirectory("thesaurus").toFile();

            Path tempFilePath = tempDir.toPath().resolve(file.getOriginalFilename());
            File convFile = tempFilePath.toFile();
            file.transferTo(convFile);

            rdfFile = convFile.toPath();
            fname = file.getOriginalFilename();
        } else {

            Log.debug(Geonet.THESAURUS, "No file provided for thesaurus upload.");
            throw new MissingServletRequestParameterException("Thesaurus source not provided", "file");
        }

        try {
            if (StringUtils.isEmpty(fname)) {
                throw new Exception("File upload from URL or file return null");
            }

            long fsize;
            if (rdfFile != null && Files.exists(rdfFile)) {
                fsize = Files.size(rdfFile);
            } else {
                throw new MissingServletRequestParameterException("Thesaurus file doesn't exist", "file");
            }

            // -- check that the archive actually has something in it
            if (fsize == 0) {
                throw new MissingServletRequestParameterException("Thesaurus file has zero size", "file");
            }

            String extension = FilenameUtils.getExtension(fname);

            if (extension.equalsIgnoreCase("rdf") || extension.equalsIgnoreCase("xml")) {
                Log.debug(Geonet.THESAURUS, "Uploading thesaurus: " + fname);

                // Rename .xml to .rdf for all thesaurus
                fname = fname.replace(extension, "rdf");
                uploadThesaurus(rdfFile, stylesheet, context, fname, type, dir);
            } else {
                Log.debug(Geonet.THESAURUS, "Incorrect extension for thesaurus named: " + fname);
                throw new Exception("Incorrect extension for thesaurus named: " + fname);
            }

            long end = System.currentTimeMillis();
            long duration = (end - start) / 1000;

            return String.format("Thesaurus '%s' loaded in %d sec.", fname, duration);
        } finally {
            if (tempDir != null) {
                FileUtils.deleteQuietly(tempDir);
            }
        }
    }

    /**
     * Upload thesaurus.
     *
     * @param url the url
     * @param registryUrl the registry url
     * @param registryLanguage the languages to retrieve from the registry
     * @param type the type
     * @param dir the dir
     * @param stylesheet the stylesheet
     * @param request the request
     * @return the element
     * @throws Exception the exception
     */
    @ApiOperation(value = "Uploads a new thesaurus from URL or Registry", nickname = "uploadThesaurusFromUrl", notes = "Uploads a new thesaurus.")
    @RequestMapping(method = RequestMethod.PUT, produces = MediaType.TEXT_XML_VALUE)
    @ApiResponses(value = { @ApiResponse(code = 201, message = "Thesaurus uploaded in SKOS format."),
            @ApiResponse(code = 403, message = ApiParams.API_RESPONSE_NOT_ALLOWED_ONLY_REVIEWER) })
    @PreAuthorize("hasRole('Reviewer')")
    @ResponseBody
    @ResponseStatus(value = HttpStatus.CREATED)
    public String uploadThesaurusFromUrl(
            @ApiParam(value = "If set, try to download from the Internet.") @RequestParam(value = "url", required = false) String url,
            @ApiParam(value = "If set, try to download from a registry.") @RequestParam(value = "registryUrl", required = false) String registryUrl,
            @ApiParam(value = "Languages to download from a registry.") @RequestParam(value = "registryLanguage", required = false) String[] registryLanguage,
            @ApiParam(value = "Local or external (default).") @RequestParam(value = "type", defaultValue = "external") String type,
            @ApiParam(value = "Type of thesaurus, usually one of the ISO thesaurus type codelist value. Default is theme.") @RequestParam(value = "dir", defaultValue = "theme") String dir,
            @ApiParam(value = "XSL to be use to convert the thesaurus before load. Default _none_.") @RequestParam(value = "stylesheet", defaultValue = "_none_") String stylesheet,
            HttpServletRequest request) throws Exception {

        long start = System.currentTimeMillis();
        ServiceContext context = ApiUtils.createServiceContext(request);

        boolean urlUpload = !StringUtils.isEmpty(url);
        boolean registryUpload = !StringUtils.isEmpty(registryUrl);

        // Upload RDF file
        Path rdfFile = null;
        String fname = null;

        // Specific upload steps
        if (urlUpload) {

            Log.debug(Geonet.THESAURUS, "Uploading thesaurus from URL: " + url);

            rdfFile = getXMLContentFromUrl(url, context);
            fname = url.substring(url.lastIndexOf("/") + 1, url.length()).replaceAll("\\s+", "");

            // File with no extension in URL
            if (fname.lastIndexOf('.') == -1) {
                fname += ".rdf";
            }

        } else if (registryUpload) {
            if (ArrayUtils.isEmpty(registryLanguage)) {
                throw new MissingServletRequestParameterException("Select at least one language.", "language");
            }

            Log.debug(Geonet.THESAURUS, "Uploading thesaurus from registry : " + registryUrl);

            String itemName = registryUrl.substring((registryUrl.lastIndexOf("/") + 1), registryUrl.length());

            rdfFile = extractSKOSFromRegistry(registryUrl, itemName, registryLanguage, context);
            fname = registryUrl.replaceAll("[^A-Za-z]+", "") + "-" + itemName + ".rdf";

        } else {

            Log.debug(Geonet.THESAURUS, "No URL or file name provided for thesaurus upload.");
            throw new MissingServletRequestParameterException("Thesaurus source not provided", "url");

        }

        if (StringUtils.isEmpty(fname)) {
            throw new ResourceNotFoundException("File upload from URL or file return null");
        }

        long fsize;
        if (rdfFile != null && Files.exists(rdfFile)) {
            fsize = Files.size(rdfFile);
        } else {
            throw new ResourceNotFoundException("Thesaurus file doesn't exist");
        }

        // -- check that the archive actually has something in it
        if (fsize == 0) {
            throw new ResourceNotFoundException("Thesaurus file has zero size");
        }

        String extension = FilenameUtils.getExtension(fname);

        if (extension.equalsIgnoreCase("rdf") || extension.equalsIgnoreCase("xml")) {
            Log.debug(Geonet.THESAURUS, "Uploading thesaurus: " + fname);

            // Rename .xml to .rdf for all thesaurus
            fname = fname.replace(extension, "rdf");
            uploadThesaurus(rdfFile, stylesheet, context, fname, type, dir);
        } else {
            Log.debug(Geonet.THESAURUS, "Incorrect extension for thesaurus named: " + fname);
            throw new MissingServletRequestParameterException("Incorrect extension for thesaurus", fname);
        }

        long end = System.currentTimeMillis();
        long duration = (end - start) / 1000;

        return String.format("Thesaurus '%s' loaded in %d sec.", fname, duration);
    }

    /**
     * Extract SKOS from registry.
     *
     * Download for each language the codelist from the registry. Combine
     * them into one XML document which is then XSLT processed for SKOS conversion.
     *
     * @param registryUrl the registry url
     * @param itemName the item name
     * @param lang the selected languages
     * @param context the context
     * @return the path
     * @throws Exception the exception
     */
    private Path extractSKOSFromRegistry(String registryUrl, String itemName, String[] lang, ServiceContext context)
            throws Exception {
        if (lang != null) {
            Element documents = new Element("documents");
            for (String language : lang) {
                try {
                    String languageFileUrl = registryUrl + "/" + itemName + "." + language + ".xml";
                    Path localRdf = getXMLContentFromUrl(languageFileUrl, context);
                    Element codeList = Xml.loadFile(localRdf);
                    documents.addContent(codeList);
                } catch (Exception e) {
                    Log.debug(Geonet.THESAURUS,
                            "Thesaurus not found for the requested translation: " + itemName + " " + language);
                    throw new ResourceNotFoundException(
                            "Thesaurus not found for the requested translation: " + itemName + " " + language);
                }
            }

            // Convert to SKOS
            GeonetworkDataDirectory dataDirectory = context.getBean(GeonetworkDataDirectory.class);
            Path skosTransform = dataDirectory.getWebappDir()
                    .resolve("xslt/services/thesaurus/registry-to-skos.xsl");
            Element transform = Xml.transform(documents, skosTransform);
            // Convert to file and return
            Path rdfFile = Files.createTempFile("thesaurus", ".rdf");
            XMLOutputter xmlOutput = new XMLOutputter();
            xmlOutput.setFormat(Format.getCompactFormat());
            xmlOutput.output(transform, new OutputStreamWriter(
                    new FileOutputStream(rdfFile.toFile().getCanonicalPath()), StandardCharsets.UTF_8));
            return rdfFile;

        }

        return null;
    }

    /**
     * Gets the XML content from url.
     *
     * @param url the url
     * @param context the context
     * @return the rdf content from url
     * @throws URISyntaxException the URI syntax exception
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws MalformedURLException the malformed URL exception
     */
    private Path getXMLContentFromUrl(String url, ServiceContext context)
            throws URISyntaxException, IOException, MalformedURLException {
        Path rdfFile;
        URI uri = new URI(url);
        rdfFile = Files.createTempFile("thesaurus", ".rdf");
        XmlRequest httpReq = context.getBean(GeonetHttpRequestFactory.class).createXmlRequest(uri.toURL());
        httpReq.setAddress(uri.getPath());
        Lib.net.setupProxy(context, httpReq);
        httpReq.executeLarge(rdfFile);
        return rdfFile;
    }

    /**
     * Load a thesaurus in the catalogue and optionnaly convert it using XSL.
     *
     * @param rdfFile the rdf file
     * @param style the style
     * @param context the context
     * @param fname the fname
     * @param type the type
     * @param dir the dir
     * @return Element thesaurus uploaded
     * @throws Exception the exception
     */
    private void uploadThesaurus(Path rdfFile, String style, ServiceContext context, String fname, String type,
            String dir) throws Exception {

        Path stylePath = context.getAppPath().resolve(Geonet.Path.STYLESHEETS);

        Element tsXml;
        Element xml = Xml.loadFile(rdfFile);
        xml.detach();

        if (!"_none_".equals(style)) {
            FilePathChecker.verify(style);

            tsXml = Xml.transform(xml, stylePath.resolve(style));
            tsXml.detach();
        } else {
            tsXml = xml;
        }

        // Load document and check namespace
        if (tsXml.getNamespacePrefix().equals("rdf") && tsXml.getName().equals("RDF")) {

            GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);
            ThesaurusManager thesaurusMan = gc.getBean(ThesaurusManager.class);

            // copy to directory according to type
            Path path = thesaurusMan.buildThesaurusFilePath(fname, type, dir);
            try (OutputStream out = Files.newOutputStream(path)) {
                Xml.writeResponse(new Document(tsXml), out);
            }

            final String siteURL = context.getBean(SettingManager.class).getSiteURL(context);
            final IsoLanguagesMapper isoLanguageMapper = context.getBean(IsoLanguagesMapper.class);
            Thesaurus gst = new Thesaurus(isoLanguageMapper, fname, type, dir, path, siteURL);
            thesaurusMan.addThesaurus(gst, false);
        } else {
            IO.deleteFile(rdfFile, false, Geonet.THESAURUS);
            throw new WebApplicationException("Unknown format (Must be in SKOS format).");
        }
    }

    /**
     * Parses the builder.
     *
     * @param uiLang the ui lang
     * @param q the q
     * @param maxResults the max results
     * @param offset the offset
     * @param targetLangs the target langs
     * @param thesauri the thesauri
     * @param thesauriDomainName the thesauri domain name
     * @param typeSearch the type search
     * @param uri the uri
     * @param mapper the mapper
     * @return the keyword search params builder
     */
    private KeywordSearchParamsBuilder parseBuilder(String uiLang, String q, int maxResults, int offset,
            List<String> targetLangs, List<String> thesauri, String thesauriDomainName,
            KeywordSearchType typeSearch, String uri, IsoLanguagesMapper mapper) {
        KeywordSearchParamsBuilder parsedParams = new KeywordSearchParamsBuilder(mapper).lenient(true);

        if (q != null) {
            parsedParams.keyword(q, typeSearch, true);
        }

        if (uri != null) {
            parsedParams.uri(uri);
        }

        parsedParams.maxResults(maxResults);
        parsedParams.offset(offset);

        if (thesauriDomainName != null) {
            parsedParams.thesauriDomainName(thesauriDomainName);
        }

        if (thesauri == null) {
            ConfigurableApplicationContext applicationContext = ApplicationContextHolder.get();
            ThesaurusManager thesaurusMan = applicationContext.getBean(ThesaurusManager.class);
            Map<String, Thesaurus> listOfThesaurus = thesaurusMan.getThesauriMap();
            for (String t : listOfThesaurus.keySet()) {
                parsedParams.addThesaurus(listOfThesaurus.get(t).getKey());
            }
        } else {
            for (String thesaurusName : thesauri) {
                if (!thesaurusName.trim().isEmpty()) {
                    parsedParams.addThesaurus(thesaurusName.trim());
                }
            }
        }

        boolean addedLang = false;
        if (targetLangs != null) {
            for (String targetLang : targetLangs) {
                if (!targetLang.trim().isEmpty()) {
                    parsedParams.addLang(targetLang.trim());
                    addedLang = true;
                }
            }
        }
        if (!addedLang) {
            parsedParams.addLang(uiLang);
        }

        return parsedParams;
    }
}