SearchRest.java
package de.dlr.shepard.common.search.endpoints;
import de.dlr.shepard.common.search.io.CollectionSearchBody;
import de.dlr.shepard.common.search.io.CollectionSearchResult;
import de.dlr.shepard.common.search.io.ContainerSearchBody;
import de.dlr.shepard.common.search.io.ContainerSearchResult;
import de.dlr.shepard.common.search.io.ResponseBody;
import de.dlr.shepard.common.search.io.SearchBody;
import de.dlr.shepard.common.search.io.UserGroupSearchBody;
import de.dlr.shepard.common.search.io.UserGroupSearchResult;
import de.dlr.shepard.common.search.io.UserSearchBody;
import de.dlr.shepard.common.search.io.UserSearchResult;
import de.dlr.shepard.common.search.services.CollectionSearchService;
import de.dlr.shepard.common.search.services.ContainerSearchService;
import de.dlr.shepard.common.search.services.PaginatedCollectionList;
import de.dlr.shepard.common.search.services.SearchService;
import de.dlr.shepard.common.search.services.UserGroupSearchService;
import de.dlr.shepard.common.search.services.UserSearchService;
import de.dlr.shepard.common.util.Constants;
import de.dlr.shepard.common.util.PaginationHelper;
import de.dlr.shepard.common.util.SortingHelper;
import de.dlr.shepard.context.collection.io.CollectionIO;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.PositiveOrZero;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.Optional;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
@Path(Constants.SEARCH)
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RequestScoped
public class SearchRest {
@Inject
SearchService searchService;
@Inject
UserSearchService userSearchService;
@Inject
UserGroupSearchService userGroupSearchService;
@Inject
ContainerSearchService containerSearchService;
@Inject
CollectionSearchService collectionSearchService;
@POST
@Tag(name = Constants.SEARCH)
@Operation(description = "search")
@APIResponse(
description = "ok",
responseCode = "200",
content = @Content(schema = @Schema(implementation = ResponseBody.class))
)
@APIResponse(responseCode = "400", description = "bad request")
@APIResponse(responseCode = "401", description = "not authorized")
public Response search(
@RequestBody(
required = true,
content = @Content(schema = @Schema(implementation = SearchBody.class))
) @Valid SearchBody body
) {
ResponseBody ret = searchService.search(body);
return Response.ok(ret).build();
}
@POST
@Path("/" + Constants.COLLECTIONS)
@Tag(name = Constants.SEARCH)
@Operation(description = "Search collections with paginated response")
@APIResponse(
description = "ok",
responseCode = "200",
content = @Content(schema = @Schema(implementation = CollectionSearchResult.class))
)
@APIResponse(responseCode = "400", description = "bad request")
@APIResponse(responseCode = "401", description = "not authorized")
@Parameter(name = Constants.QP_PAGE, description = "Pagination starts at 0")
@Parameter(name = Constants.QP_SIZE)
@Parameter(name = Constants.QP_ORDER_BY_ATTRIBUTE, description = "Defaults to 'createdAt'")
@Parameter(name = Constants.QP_ORDER_DESC, description = "Defaults to 'true'")
public Response searchCollections(
@RequestBody(
required = true,
content = @Content(schema = @Schema(implementation = CollectionSearchBody.class)),
description = "You can search by ID, name or createdBy. Connect search parameters like this: {\"OR\":[{\"property\":\"name\",\"value\":\"ABC\",\"operator\":\"contains\"},{\"property\":\"id\",\"value\":123,\"operator\":\"contains\"}]}\"" +
" "
) @Valid CollectionSearchBody collectionSearchBody,
@QueryParam(Constants.QP_PAGE) @PositiveOrZero Integer page,
@QueryParam(Constants.QP_SIZE) @Positive Integer size,
@QueryParam(Constants.QP_ORDER_BY_ATTRIBUTE) BasicCollectionAttributes orderBy,
@QueryParam(Constants.QP_ORDER_DESC) Boolean orderDesc
) {
PaginatedCollectionList paginatedCollectionList = collectionSearchService.search(
collectionSearchBody.getSearchParams().getQuery(),
Optional.ofNullable(page),
Optional.ofNullable(size),
Optional.ofNullable(orderBy).orElse(BasicCollectionAttributes.createdAt),
Optional.ofNullable(orderDesc).orElse(true)
);
CollectionSearchResult collectionSearchResult = new CollectionSearchResult(
paginatedCollectionList.getResults().stream().map(CollectionIO::new).toList(),
collectionSearchBody.getSearchParams(),
paginatedCollectionList.getTotalResults()
);
return Response.ok(collectionSearchResult).build();
}
@POST
@Path("/" + Constants.CONTAINERS)
@Tag(name = Constants.SEARCH)
@Operation(description = "Search containers")
@APIResponse(
description = "ok",
responseCode = "200",
content = @Content(schema = @Schema(implementation = ContainerSearchResult.class))
)
@APIResponse(responseCode = "400", description = "bad request")
@APIResponse(responseCode = "401", description = "not authorized")
@Parameter(name = Constants.QP_PAGE, description = "Pagination starts at 0")
@Parameter(name = Constants.QP_SIZE)
@Parameter(name = Constants.QP_ORDER_BY_ATTRIBUTE, description = "Defaults to 'createdAt'")
@Parameter(name = Constants.QP_ORDER_DESC, description = "Defaults to 'true'")
public Response searchContainers(
@RequestBody(
required = true,
content = @Content(schema = @Schema(implementation = ContainerSearchBody.class))
) @Valid ContainerSearchBody containerSearchBody,
@QueryParam(Constants.QP_PAGE) @PositiveOrZero Integer page,
@QueryParam(Constants.QP_SIZE) @Positive Integer size,
@QueryParam(Constants.QP_ORDER_BY_ATTRIBUTE) BasicContainerAttributes orderBy,
@QueryParam(Constants.QP_ORDER_DESC) Boolean orderDesc
) {
PaginationHelper pagination = null;
if (page != null && size != null) pagination = new PaginationHelper(page, size);
SortingHelper sortingHelper = new SortingHelper(
Optional.ofNullable(orderBy).orElse(BasicContainerAttributes.createdAt),
Optional.ofNullable(orderDesc).orElse(true)
);
ContainerSearchResult ret = containerSearchService.search(containerSearchBody, pagination, sortingHelper);
return Response.ok(ret).build();
}
@POST
@Path("/" + Constants.USERS)
@Tag(name = Constants.SEARCH)
@Operation(description = "Search users")
@APIResponse(
description = "ok",
responseCode = "200",
content = @Content(schema = @Schema(implementation = UserSearchResult.class))
)
@APIResponse(responseCode = "400", description = "bad request")
@APIResponse(responseCode = "401", description = "not authorized")
public Response searchUsers(
@RequestBody(
required = true,
content = @Content(schema = @Schema(implementation = UserSearchBody.class))
) @Valid UserSearchBody userSearchBody
) {
UserSearchResult ret = userSearchService.search(userSearchBody);
return Response.ok(ret).build();
}
@POST
@Path("/" + Constants.USERGROUPS)
@Tag(name = Constants.SEARCH)
@Operation(description = "Search user groups")
@APIResponse(
description = "ok",
responseCode = "200",
content = @Content(schema = @Schema(implementation = UserGroupSearchResult.class))
)
@APIResponse(responseCode = "400", description = "bad request")
@APIResponse(responseCode = "401", description = "not authorized")
public Response searchUserGroups(
@RequestBody(
required = true,
content = @Content(schema = @Schema(implementation = UserSearchBody.class))
) @Valid UserGroupSearchBody userGroupSearchBody
) {
UserGroupSearchResult ret = userGroupSearchService.search(userGroupSearchBody);
return Response.ok(ret).build();
}
}