diff --git a/src/core/services-api/src/main/java/it/geosolutions/geostore/services/ResourceService.java b/src/core/services-api/src/main/java/it/geosolutions/geostore/services/ResourceService.java index bfae93fb..a10aecd5 100644 --- a/src/core/services-api/src/main/java/it/geosolutions/geostore/services/ResourceService.java +++ b/src/core/services-api/src/main/java/it/geosolutions/geostore/services/ResourceService.java @@ -200,6 +200,29 @@ List getResources( User authUser) throws BadRequestServiceEx, InternalErrorServiceEx; + /** + * @param filter + * @param page + * @param entries + * @param sortBy + * @param sortOrder + * @param includeAttributes + * @param includeData + * @return List + * @throws BadRequestServiceEx + * @throws InternalErrorServiceEx + */ + List getResources( + SearchFilter filter, + Integer page, + Integer entries, + String sortBy, + String sortOrder, + boolean includeAttributes, + boolean includeData, + User authUser) + throws BadRequestServiceEx, InternalErrorServiceEx; + /** * Return a list of resources joined with their data. This call can be very heavy for the system. Please use this method only when you are sure a * few data will be returned, otherwise consider using diff --git a/src/core/services-api/src/main/java/it/geosolutions/geostore/services/exception/BadRequestServiceEx.java b/src/core/services-api/src/main/java/it/geosolutions/geostore/services/exception/BadRequestServiceEx.java index a6932ddd..3537c2ea 100644 --- a/src/core/services-api/src/main/java/it/geosolutions/geostore/services/exception/BadRequestServiceEx.java +++ b/src/core/services-api/src/main/java/it/geosolutions/geostore/services/exception/BadRequestServiceEx.java @@ -28,4 +28,8 @@ public class BadRequestServiceEx extends GeoStoreServiceException { public BadRequestServiceEx(String message) { super(message); } + + public BadRequestServiceEx(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/core/services-impl/src/main/java/it/geosolutions/geostore/services/ResourceServiceImpl.java b/src/core/services-impl/src/main/java/it/geosolutions/geostore/services/ResourceServiceImpl.java index e0aa36d8..1f8f4dd5 100644 --- a/src/core/services-impl/src/main/java/it/geosolutions/geostore/services/ResourceServiceImpl.java +++ b/src/core/services-impl/src/main/java/it/geosolutions/geostore/services/ResourceServiceImpl.java @@ -52,6 +52,10 @@ import it.geosolutions.geostore.services.exception.InternalErrorServiceEx; import it.geosolutions.geostore.services.exception.NotFoundServiceEx; import it.geosolutions.geostore.util.SearchConverter; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.dao.DataIntegrityViolationException; + import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -61,9 +65,6 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.dao.DataIntegrityViolationException; /** * Class ResourceServiceImpl. @@ -735,6 +736,26 @@ public List getResources( boolean includeData, User authUser) throws BadRequestServiceEx, InternalErrorServiceEx { + return getResources( + filter, page, entries, "", "", includeAttributes, includeData, authUser); + } + + /* + * (non-Javadoc) + * + * @see it.geosolutions.geostore.services.ResourceService#getResources(it.geosolutions.geostore.services.dto.search.SearchFilter, + * java.lang.Integer, java.lang.Integer, java.lang.String, java.lang.String, boolean, boolean, it.geosolutions.geostore.core.model.User) + */ + public List getResources( + SearchFilter filter, + Integer page, + Integer entries, + String sortBy, + String sortOrder, + boolean includeAttributes, + boolean includeData, + User authUser) + throws BadRequestServiceEx, InternalErrorServiceEx { if (((page != null) && (entries == null)) || ((page == null) && (entries != null))) { throw new BadRequestServiceEx("Page and entries params should be declared together"); @@ -747,6 +768,10 @@ public List getResources( searchCriteria.setPage(page); } + if (sortBy != null && !sortBy.isBlank()) { + searchCriteria.addSort(sortBy, "DESC".equalsIgnoreCase(sortOrder)); + } + searchCriteria.addFetch("security"); searchCriteria.setDistinct(true); @@ -855,14 +880,18 @@ public List getResourcesFull(SearchFilter filter, User authUser) * @param searchCriteria search criteria * @return results of the search */ - private List search(Search searchCriteria) { - // apply defaults for sorting - if (searchCriteria != null) { - searchCriteria.addSort(new Sort("name")); - } + private List search(Search searchCriteria) throws BadRequestServiceEx { + try { + // apply defaults for sorting if not already set + if (searchCriteria != null && searchCriteria.getSorts().isEmpty()) { + searchCriteria.addSort(new Sort("name")); + } - // search - return resourceDAO.search(searchCriteria); + // search + return resourceDAO.search(searchCriteria); + } catch (IllegalArgumentException iaex) { + throw new BadRequestServiceEx("Resource search failed", iaex); + } } /* diff --git a/src/modules/rest/extjs/src/main/java/it/geosolutions/geostore/services/rest/RESTExtJsService.java b/src/modules/rest/extjs/src/main/java/it/geosolutions/geostore/services/rest/RESTExtJsService.java index 4f8bb7ac..c2a8a826 100644 --- a/src/modules/rest/extjs/src/main/java/it/geosolutions/geostore/services/rest/RESTExtJsService.java +++ b/src/modules/rest/extjs/src/main/java/it/geosolutions/geostore/services/rest/RESTExtJsService.java @@ -52,7 +52,7 @@ public interface RESTExtJsService { @GET - @Path("/search/{nameLike}") + @Path("/search//{nameLike: [^/]+}\")") @Produces({MediaType.APPLICATION_JSON}) @Secured({"ROLE_ADMIN", "ROLE_USER", "ROLE_ANONYMOUS"}) String getAllResources( @@ -114,6 +114,8 @@ ExtResourceList getExtResourcesList( @Context SecurityContext sc, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, + @QueryParam("sortBy") String sortBy, + @QueryParam("sortOrder") @DefaultValue("asc") String sortOrder, @QueryParam("includeAttributes") @DefaultValue("false") boolean includeAttributes, @QueryParam("includeData") @DefaultValue("false") boolean includeData, @Multipart("filter") SearchFilter filter) diff --git a/src/modules/rest/extjs/src/main/java/it/geosolutions/geostore/services/rest/impl/RESTExtJsServiceImpl.java b/src/modules/rest/extjs/src/main/java/it/geosolutions/geostore/services/rest/impl/RESTExtJsServiceImpl.java index 06035702..74e1bfda 100644 --- a/src/modules/rest/extjs/src/main/java/it/geosolutions/geostore/services/rest/impl/RESTExtJsServiceImpl.java +++ b/src/modules/rest/extjs/src/main/java/it/geosolutions/geostore/services/rest/impl/RESTExtJsServiceImpl.java @@ -284,13 +284,15 @@ public String getResourcesByCategory( * (non-Javadoc) * * @see it.geosolutions.geostore.services.rest.RESTExtJsService#getResourcesList(javax.ws.rs.core.SecurityContext, java.lang.Integer, - * java.lang.Integer, boolean, boolean, it.geosolutions.geostore.services.dto.search.SearchFilter) + * java.lang.Integer, java.lang.String, java.lang.String, boolean, boolean, it.geosolutions.geostore.services.dto.search.SearchFilter) */ @Override public ExtResourceList getExtResourcesList( SecurityContext sc, Integer start, Integer limit, + String sortBy, + String sortOrder, boolean includeAttributes, boolean includeData, SearchFilter filter) @@ -329,7 +331,14 @@ public ExtResourceList getExtResourcesList( List resources = filterOutUnadvertisedResources( resourceService.getResources( - filter, page, limit, includeAttributes, includeData, authUser), + filter, + page, + limit, + sortBy, + sortOrder, + includeAttributes, + includeData, + authUser), authUser); // Here the Read permission on each resource must be checked due to will be returned the diff --git a/src/modules/rest/extjs/src/test/java/it/geosolutions/geostore/services/rest/impl/RESTExtJsServiceImplTest.java b/src/modules/rest/extjs/src/test/java/it/geosolutions/geostore/services/rest/impl/RESTExtJsServiceImplTest.java index 7400bf7e..260aa727 100644 --- a/src/modules/rest/extjs/src/test/java/it/geosolutions/geostore/services/rest/impl/RESTExtJsServiceImplTest.java +++ b/src/modules/rest/extjs/src/test/java/it/geosolutions/geostore/services/rest/impl/RESTExtJsServiceImplTest.java @@ -26,11 +26,16 @@ import it.geosolutions.geostore.core.model.UserGroup; import it.geosolutions.geostore.core.model.enums.Role; import it.geosolutions.geostore.services.dto.ShortResource; +import it.geosolutions.geostore.services.dto.search.AndFilter; +import it.geosolutions.geostore.services.model.ExtResourceList; import it.geosolutions.geostore.services.rest.model.SecurityRuleList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import javax.ws.rs.core.SecurityContext; import net.sf.json.JSON; import net.sf.json.JSONArray; @@ -362,6 +367,45 @@ public void testGetAllResources_unadvertised() throws Exception { } } + @Test + public void testExtResourcesList_sorted() throws Exception { + final String CAT0_NAME = "CAT000"; + final String RES_ATTRIBUTE_A = "A"; + final String RES_ATTRIBUTE_B = "B"; + final String RES_ATTRIBUTE_C = "C"; + + assertEquals(0, resourceService.getResources(new AndFilter(), buildFakeAdminUser()).size()); + + long u0 = restCreateUser("u0", Role.USER, null, "p0"); + SecurityContext sc = new SimpleSecurityContext(u0); + + createCategory(CAT0_NAME); + + restCreateResource(RES_ATTRIBUTE_A, RES_ATTRIBUTE_A, CAT0_NAME, u0, true); + restCreateResource(RES_ATTRIBUTE_B, RES_ATTRIBUTE_B, CAT0_NAME, u0, true); + restCreateResource(RES_ATTRIBUTE_C, RES_ATTRIBUTE_C, CAT0_NAME, u0, true); + + { + ExtResourceList response = restExtJsService.getExtResourcesList(sc, 0, 1000, "description", "asc", false, false, new AndFilter()); + + List resources = response.getList(); + assertEquals(3, resources.size()); + List resourcesDescriptions = resources.stream().map(Resource::getName).collect(Collectors.toList()); + assertEquals(List.of(RES_ATTRIBUTE_A, RES_ATTRIBUTE_B, RES_ATTRIBUTE_C), resourcesDescriptions); + + } + + { + ExtResourceList response = restExtJsService.getExtResourcesList(sc, 0, 1000, "creation", "desc", false, false, new AndFilter()); + + List resources = response.getList(); + assertEquals(3, resources.size()); + List resourcesCreationDates = resources.stream().map(Resource::getCreation).collect(Collectors.toList()); + assertTrue(resourcesCreationDates.get(0).after(resourcesCreationDates.get(1))); + assertTrue(resourcesCreationDates.get(1).after(resourcesCreationDates.get(2))); + } + } + private JSONResult parse(String jsonString) { JSONResult ret = new JSONResult();