Search3Resource.java
/*
* Copyright © 2024-2025 The CTAN Team and individual authors
*
* This file is distributed under the 3-clause BSD license.
* See file LICENSE for details.
*/
package org.ctan.site.resources;
import java.io.IOException;
import java.util.Locale;
import java.util.Set;
import org.apache.lucene.queryparser.classic.ParseException;
import org.ctan.site.services.search.QueryContainer;
import org.ctan.site.services.search.SearchService;
import org.ctan.site.services.search.base.IndexType;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.security.PermitAll;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response.Status;
import lombok.NonNull;
/**
* The class <code>Search3Resource</code> contains the controller for the search
* resource.
*
* @author <a href="mailto:gene@ctan.org">Gerd Neugebauer</a>
*/
@Path("/3.0")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public class Search3Resource {
/**
* The field <code>VERSION</code> contains the current version.
*/
private static final String VERSION = "3.0";
/**
* The field <code>service</code> contains the underlying service.
*/
private SearchService service;
/**
* This is the constructor for the class <code>Content3Resource</code>.
*
* @param service the underlying service
*/
@SuppressFBWarnings(value = {"CT_CONSTRUCTOR_THROW", "EI_EXPOSE_REP2"})
public Search3Resource(@NonNull SearchService service) {
this.service = service;
}
/**
* The method <code>getHits</code> provides means to retrieve search
* results.
*
* @param phrase the query string
* @param sections the section to include in the search as single letter
* string
* @param page the current page; it is 0-based
* @param size the page size or 16
* @param lang the ISO language code
* @return the list of hits
*/
@GET
@Path("/search")
public QueryContainer search(@QueryParam("for") String phrase,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("16") int size,
@QueryParam("lang") String lang,
@QueryParam("in") String sections) {
try {
Set<IndexType> secs = sections == null || sections.isBlank()
? Set.of()
: IndexType.decode(sections);
QueryContainer query = QueryContainer.builder()
.phrase(phrase)
.max(size)
.offset(page * size)
.sections(secs)
.locale(lang == null ? Locale.ENGLISH : Locale.of(lang))
.build();
return service.find(query);
} catch (IOException e) {
throw new WebApplicationException(e.getMessage(),
Status.INTERNAL_SERVER_ERROR);
} catch (ParseException | IllegalArgumentException e) {
throw new WebApplicationException(e.getMessage(),
Status.BAD_REQUEST);
}
}
/**
* The method <code>searchVersion</code> provides means to retrieve the
* current version number.
*
* @return the version number as string
*/
@GET
@Path("search/version")
@Produces(MediaType.APPLICATION_JSON)
@PermitAll
public String searchVersion() {
return VERSION;
}
}