From 59b5c4759f5ecd29675d263a90959b75918f2dd7 Mon Sep 17 00:00:00 2001 From: Lars Johansson <lars.johansson@ess.eu> Date: Tue, 12 Jul 2022 09:06:26 +0200 Subject: [PATCH] Refactor REST API for names Use parameters one-by-one instead of arrays. Purpose to improve usability. --- .../names/repository/NameRepository.java | 172 +++++++++--------- .../openepics/names/rest/api/v1/INames.java | 52 ++++-- .../rest/controller/NamesController.java | 36 ++-- .../rest/controller/ReportController.java | 6 +- .../openepics/names/service/NamesService.java | 77 ++++---- .../openepics/names/util/RepositoryUtil.java | 67 +++++++ .../names/util/ValidateNameElementUtil.java | 47 ++--- .../org/openepics/names/docker/NamesIT.java | 5 +- .../names/util/ValidateUtilTest.java | 6 +- 9 files changed, 276 insertions(+), 192 deletions(-) create mode 100644 src/main/java/org/openepics/names/util/RepositoryUtil.java diff --git a/src/main/java/org/openepics/names/repository/NameRepository.java b/src/main/java/org/openepics/names/repository/NameRepository.java index 4db17939..02434fdf 100644 --- a/src/main/java/org/openepics/names/repository/NameRepository.java +++ b/src/main/java/org/openepics/names/repository/NameRepository.java @@ -30,9 +30,11 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import org.openepics.names.repository.model.Name; import org.openepics.names.repository.model.NameStructure; import org.openepics.names.rest.beans.FieldName; +import org.openepics.names.util.RepositoryUtil; import org.springframework.stereotype.Repository; /** @@ -43,8 +45,6 @@ import org.springframework.stereotype.Repository; @Repository public class NameRepository { - private static final String PERCENT = "%"; - @PersistenceContext private EntityManager em; @@ -52,26 +52,37 @@ public class NameRepository { * Count names. * * @param deleted deleted - * @param queryFields query fields - * @param queryValues query values + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic + * @param devicestructure device structure mnemonic + * @param description description * @return count of names */ - public Long countNames( - Boolean deleted, FieldName[] queryFields, String[] queryValues) { - return countNames(deleted, queryFields, queryValues, Boolean.FALSE); + public Long countNames(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description) { + return countNames(deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, + Boolean.FALSE); } /** * Count names. * * @param deleted deleted - * @param queryFields query fields - * @param queryValues query values + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic + * @param devicestructure device structure mnemonic + * @param description description * @param includeHistory include history * @return count of names */ - public Long countNames( - Boolean deleted, FieldName[] queryFields, String[] queryValues, Boolean includeHistory) { + public Long countNames(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, + Boolean includeHistory) { // note // use of function for mnemonic path @@ -83,7 +94,9 @@ public class NameRepository { CriteriaQuery<Long> cq = cb.createQuery(Long.class); Root<Name> from = cq.from(Name.class); - cq.where(cb.and(preparePredicatesNames(cb, from, deleted, queryFields, queryValues, includeHistory).toArray(new Predicate[0]))); + cq.where(cb.and(preparePredicatesNames(cb, from, deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, + includeHistory).toArray(new Predicate[0]))); cq.select(cb.count(from)); return em.createQuery(cq).getSingleResult(); @@ -93,47 +106,56 @@ public class NameRepository { * Find names. * * @param deleted deleted - * @param queryField query field - * @param queryValue query value + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic + * @param devicestructure device structure mnemonic + * @param description description * @return list of names */ - public List<Name> readNames( - Boolean deleted, FieldName queryField, String queryValue) { - - return readNames( - deleted, - queryField != null ? new FieldName[] {queryField} : null, - queryValue != null ? new String[] {queryValue} : null, - Boolean.FALSE, - null, null, null, null); + public List<Name> readNames(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description) { + + return readNames(deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, + Boolean.FALSE, null, null, null, null); } /** * Find names. * * @param deleted deleted - * @param queryFields query fields - * @param queryValues query values + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic + * @param devicestructure device structure mnemonic + * @param description description * @param orderBy order by * @param isAsc is ascending * @param offset offset * @param limit limit * @return list of names */ - public List<Name> readNames( - Boolean deleted, FieldName[] queryFields, String[] queryValues, + public List<Name> readNames(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { - return readNames( - deleted, queryFields, queryValues, Boolean.FALSE, - orderBy, isAsc, offset, limit); + return readNames(deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, + Boolean.FALSE, orderBy, isAsc, offset, limit); } /** * Find names. * * @param deleted deleted - * @param queryFields query fields - * @param queryValues query values + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic + * @param devicestructure device structure mnemonic + * @param description description * @param includeHistory include history * @param orderBy order by * @param isAsc is ascending @@ -141,9 +163,9 @@ public class NameRepository { * @param limit limit * @return list of names */ - public List<Name> readNames( - Boolean deleted, FieldName[] queryFields, String[] queryValues, Boolean includeHistory, - FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { + public List<Name> readNames(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, + Boolean includeHistory, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { // note // use of function for mnemonic path @@ -159,7 +181,9 @@ public class NameRepository { CriteriaQuery<Name> cq = cb.createQuery(Name.class); Root<Name> from = cq.from(Name.class); - cq.where(cb.and(preparePredicatesNames(cb, from, deleted, queryFields, queryValues, includeHistory).toArray(new Predicate[0]))); + cq.where(cb.and(preparePredicatesNames(cb, from, deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, + includeHistory).toArray(new Predicate[0]))); cq.select(from); if (orderBy != null) { @@ -213,14 +237,18 @@ public class NameRepository { * @param cb criteria builder * @param from criteria query root * @param deleted deleted - * @param queryFields query fields - * @param queryValues query values + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic + * @param devicestructure device structure mnemonic + * @param description description * @param includeHistory include history * @return list of predicates */ - private List<Predicate> preparePredicatesNames( - CriteriaBuilder cb, Root<Name> from, - Boolean deleted, FieldName[] queryFields, String[] queryValues, Boolean includeHistory) { + private List<Predicate> preparePredicatesNames(CriteriaBuilder cb, Root<Name> from, Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, + Boolean includeHistory) { List<Predicate> predicates = new ArrayList<>(); @@ -242,48 +270,28 @@ public class NameRepository { if (deleted != null) { predicates.add(cb.equal(from.get(NameStructure.FIELD_DELETED), deleted)); } - if (queryFields != null) { - for (int i=0; i<queryFields.length; i++) { - String queryValue = queryValues[i]; - - // jpa query characters % and _ - // remove excess % characters - if (queryValue.startsWith(PERCENT)) { - while (queryValue.startsWith(PERCENT)) { - queryValue = queryValue.substring(1); - } - queryValue = PERCENT + queryValue; - } - if (queryValue.endsWith(PERCENT)) { - while (queryValue.endsWith(PERCENT)) { - queryValue = queryValue.substring(0, queryValue.length()-1); - } - queryValue = queryValue + PERCENT; - } - switch (queryFields[i]) { - case UUID: - predicates.add(cb.and(cb.equal(from.get(NameStructure.FIELD_UUID), queryValue))); - break; - case NAME: - predicates.add(cb.and(cb.like(from.get(Name.FIELD_CONVENTION_NAME), queryValue))); - break; - case NAMEEQUIVALENCE: - predicates.add(cb.and(cb.like(from.get(Name.FIELD_CONVENTION_NAME_EQUIVALENCE), queryValue))); - break; - case SYSTEMSTRUCTURE: - predicates.add(cb.and(cb.like(cb.function(NameStructure.FUNCTION_GET_MNEMONIC_PATH_SYSTEM_STRUCTURE, String.class, from.get(Name.FIELD_CONVENTION_NAME)), queryValue))); - break; - case DEVICESTRUCTURE: - predicates.add(cb.and(cb.like(cb.function(NameStructure.FUNCTION_GET_MNEMONIC_PATH_DEVICE_STRUCTURE, String.class, from.get(Name.FIELD_CONVENTION_NAME)), queryValue))); - break; - case DESCRIPTION: - predicates.add(cb.and(cb.like(from.get(NameStructure.FIELD_DESCRIPTION), queryValue))); - break; - default: - continue; - } - } + // prepare pattern + // jpa query characters % and _ + // remove excess % characters + + if (!StringUtils.isEmpty(uuid)) { + predicates.add(cb.and(cb.equal(from.get(NameStructure.FIELD_UUID), RepositoryUtil.preparePattern(uuid)))); + } + if (!StringUtils.isEmpty(name)) { + predicates.add(cb.and(cb.like(from.get(Name.FIELD_CONVENTION_NAME), RepositoryUtil.preparePattern(name)))); + } + if (!StringUtils.isEmpty(nameequivalence)) { + predicates.add(cb.and(cb.like(from.get(Name.FIELD_CONVENTION_NAME_EQUIVALENCE), RepositoryUtil.preparePattern(nameequivalence)))); + } + if (!StringUtils.isEmpty(systemstructure)) { + predicates.add(cb.and(cb.like(cb.function(NameStructure.FUNCTION_GET_MNEMONIC_PATH_SYSTEM_STRUCTURE, String.class, from.get(Name.FIELD_CONVENTION_NAME)), RepositoryUtil.preparePattern(systemstructure)))); + } + if (!StringUtils.isEmpty(devicestructure)) { + predicates.add(cb.and(cb.like(cb.function(NameStructure.FUNCTION_GET_MNEMONIC_PATH_DEVICE_STRUCTURE, String.class, from.get(Name.FIELD_CONVENTION_NAME)), RepositoryUtil.preparePattern(devicestructure)))); + } + if (!StringUtils.isEmpty(description)) { + predicates.add(cb.and(cb.like(from.get(NameStructure.FIELD_DESCRIPTION), RepositoryUtil.preparePattern(description)))); } return predicates; diff --git a/src/main/java/org/openepics/names/rest/api/v1/INames.java b/src/main/java/org/openepics/names/rest/api/v1/INames.java index 2dc46bc1..f3a46b41 100644 --- a/src/main/java/org/openepics/names/rest/api/v1/INames.java +++ b/src/main/java/org/openepics/names/rest/api/v1/INames.java @@ -92,8 +92,8 @@ public interface INames { create POST /names - createNames (List<NameElementCommand>) create POST /names/upload - createNames (MultipartFile) ---------------------------------------------------------------------------------------------------- - read GET /names - readNames (Boolean, FieldName[], String[], FieldName, Boolean, Integer, Integer) - read GET /names/download - readNamesDownload (Boolean, FieldName[], String[], FieldName, Boolean, Integer, Integer) + read GET /names - readNames (Boolean, String, String, String, String, String, String, FieldName, Boolean, Integer, Integer) + read GET /names/download - readNamesDownload (Boolean, String, String, String, String, String, String, FieldName, Boolean, Integer, Integer) read GET /names/{name} - readNames (String, FieldName, Boolean, Integer, Integer) read GET /names/systemstructure/{mnemonicpath} - readNamesSystemStructure (String, FieldName, Boolean, Integer, Integer) read GET /names/devicestructure/{mnemonicpath} - readNamesDeviceStructure (String, FieldName, Boolean, Integer, Integer) @@ -260,8 +260,12 @@ public interface INames { * * @param deleted if deleted-only names are to be included * (false for non-deleted-only names, true for deleted-only names, not used for both cases) - * @param queryFields search fields - * @param queryValues search values corresponding to search fields + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic path + * @param devicestructure device structure mnemonic path + * @param description description * @param orderBy order by field * @param isAsc sort order, ascending or descending * @param page page starting from 0, offset @@ -305,8 +309,12 @@ public interface INames { produces = {"application/json"}) public ResponsePageNameElements readNames( @Parameter(in = ParameterIn.QUERY, description = "if deleted names are to be included or not, omitted for both deleted and not deleted names") @RequestParam(required = false) Boolean deleted, - @Parameter(in = ParameterIn.QUERY, description = "search fields") @RequestParam(required = false) FieldName[] queryFields, - @Parameter(in = ParameterIn.QUERY, description = "search values corresponding to search fields") @RequestParam(required = false) String[] queryValues, + @Parameter(in = ParameterIn.QUERY, description = "search by uuid") @RequestParam(required = false) String uuid, + @Parameter(in = ParameterIn.QUERY, description = "search by name") @RequestParam(required = false) String name, + @Parameter(in = ParameterIn.QUERY, description = "search by name equivalence") @RequestParam(required = false) String nameequivalence, + @Parameter(in = ParameterIn.QUERY, description = "search by system structure mnemonic path") @RequestParam(required = false) String systemstructure, + @Parameter(in = ParameterIn.QUERY, description = "search by device structure mnemonic path") @RequestParam(required = false) String devicestructure, + @Parameter(in = ParameterIn.QUERY, description = "search by description") @RequestParam(required = false) String description, @Parameter(in = ParameterIn.QUERY, description = "order by field") @RequestParam(required = false) FieldName orderBy, @Parameter(in = ParameterIn.QUERY, description = "sort order, ascending or descending") @RequestParam(required = false) Boolean isAsc, @Parameter(in = ParameterIn.QUERY, description = "page starting from 0, offset") @RequestParam(required = false, defaultValue = DEFAULT_PAGE) Integer page, @@ -318,8 +326,12 @@ public interface INames { * * @param deleted if deleted-only names are to be included * (false for non-deleted-only names, true for deleted-only names, not used for both cases) - * @param queryFields search fields - * @param queryValues search values corresponding to search fields + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic path + * @param devicestructure device structure mnemonic path + * @param description description * @param orderBy order by field * @param isAsc sort order, ascending or descending * @param page page starting from 0, offset @@ -362,8 +374,12 @@ public interface INames { produces = {"application/vnd.ms-excel"}) public ResponseEntity<Resource> readNamesDownload( @Parameter(in = ParameterIn.QUERY, description = "if deleted names are to be included or not, omitted for both deleted and not deleted names") @RequestParam(required = false) Boolean deleted, - @Parameter(in = ParameterIn.QUERY, description = "search fields") @RequestParam(required = false) FieldName[] queryFields, - @Parameter(in = ParameterIn.QUERY, description = "search values corresponding to search fields") @RequestParam(required = false) String[] queryValues, + @Parameter(in = ParameterIn.QUERY, description = "search by uuid") @RequestParam(required = false) String uuid, + @Parameter(in = ParameterIn.QUERY, description = "search by name") @RequestParam(required = false) String name, + @Parameter(in = ParameterIn.QUERY, description = "search by name equivalence") @RequestParam(required = false) String nameequivalence, + @Parameter(in = ParameterIn.QUERY, description = "search by system structure mnemonic path") @RequestParam(required = false) String systemstructure, + @Parameter(in = ParameterIn.QUERY, description = "search by device structure mnemonic path") @RequestParam(required = false) String devicestructure, + @Parameter(in = ParameterIn.QUERY, description = "search by description") @RequestParam(required = false) String description, @Parameter(in = ParameterIn.QUERY, description = "order by field") @RequestParam(required = false) FieldName orderBy, @Parameter(in = ParameterIn.QUERY, description = "sort order, ascending or descending") @RequestParam(required = false) Boolean isAsc, @Parameter(in = ParameterIn.QUERY, description = "page starting from 0, offset") @RequestParam(required = false, defaultValue = DEFAULT_PAGE) Integer page, @@ -373,7 +389,7 @@ public interface INames { * Find valid names by name or uuid (search). * Return paged list of name elements. * - * @param name name or uuid to search for + * @param name name or uuid * @param orderBy order by field * @param isAsc sort order, ascending or descending * @param page page starting from 0, offset @@ -417,7 +433,7 @@ public interface INames { value = "/{name}", produces = {"application/json"}) public ResponsePageNameElements readNames( - @Parameter(in = ParameterIn.PATH, description = "name or uuid to search for") @PathVariable("name") String name, + @Parameter(in = ParameterIn.PATH, description = "search by name or uuid") @PathVariable("name") String name, @Parameter(in = ParameterIn.QUERY, description = "order by field") @RequestParam(required = false) FieldName orderBy, @Parameter(in = ParameterIn.QUERY, description = "sort order, ascending or descending") @RequestParam(required = false) Boolean isAsc, @Parameter(in = ParameterIn.QUERY, description = "page starting from 0, offset") @RequestParam(required = false, defaultValue = DEFAULT_PAGE) Integer page, @@ -427,7 +443,7 @@ public interface INames { * Find valid names by system structure mnemonic path (search). * Return paged list of name elements. * - * @param mnemonicpath mnemonic path to search for + * @param mnemonicpath mnemonic path * @param orderBy order by field * @param isAsc sort order, ascending or descending * @param page page starting from 0, offset @@ -471,7 +487,7 @@ public interface INames { value = "/systemstructure/{mnemonicpath}", produces = {"application/json"}) public ResponsePageNameElements readNamesSystemStructure( - @Parameter(in = ParameterIn.PATH, description = "mnemonic path to search for") @PathVariable("mnemonicpath") String mnemonicpath, + @Parameter(in = ParameterIn.PATH, description = "search by system structure mnemonic path") @PathVariable("mnemonicpath") String mnemonicpath, @Parameter(in = ParameterIn.QUERY, description = "order by field") @RequestParam(required = false) FieldName orderBy, @Parameter(in = ParameterIn.QUERY, description = "sort order, ascending or descending") @RequestParam(required = false) Boolean isAsc, @Parameter(in = ParameterIn.QUERY, description = "page starting from 0, offset") @RequestParam(required = false, defaultValue = DEFAULT_PAGE) Integer page, @@ -481,7 +497,7 @@ public interface INames { * Find valid names by device structure mnemonic path (search). * Return paged list of name elements. * - * @param mnemonicpath mnemonic path to search for + * @param mnemonicpath mnemonic path * @param orderBy order by field * @param isAsc sort order, ascending or descending * @param page page starting from 0, offset @@ -525,7 +541,7 @@ public interface INames { value = "/devicestructure/{mnemonicpath}", produces = {"application/json"}) public ResponsePageNameElements readNamesDeviceStructure( - @Parameter(in = ParameterIn.PATH, description = "mnemonic path to search for") @PathVariable("mnemonicpath") String mnemonicpath, + @Parameter(in = ParameterIn.PATH, description = "search by device structure mnemonic path") @PathVariable("mnemonicpath") String mnemonicpath, @Parameter(in = ParameterIn.QUERY, description = "order by field") @RequestParam(required = false) FieldName orderBy, @Parameter(in = ParameterIn.QUERY, description = "sort order, ascending or descending") @RequestParam(required = false) Boolean isAsc, @Parameter(in = ParameterIn.QUERY, description = "page starting from 0, offset") @RequestParam(required = false, defaultValue = DEFAULT_PAGE) Integer page, @@ -535,7 +551,7 @@ public interface INames { * Find history for name by uuid (exact match). * Return paged list of name elements. * - * @param uuid uuid to find history for + * @param uuid uuid * @param orderBy order by field * @param isAsc sort order, ascending or descending * @param page page starting from 0, offset @@ -579,7 +595,7 @@ public interface INames { value = "/history/{uuid}", produces = {"application/json"}) public ResponsePageNameElements readNamesHistory( - @Parameter(in = ParameterIn.PATH, description = "uuid to find history for") @PathVariable("uuid") String uuid, + @Parameter(in = ParameterIn.PATH, description = "search by uuid") @PathVariable("uuid") String uuid, @Parameter(in = ParameterIn.QUERY, description = "order by field") @RequestParam(required = false) FieldName orderBy, @Parameter(in = ParameterIn.QUERY, description = "sort order, ascending or descending") @RequestParam(required = false) Boolean isAsc, @Parameter(in = ParameterIn.QUERY, description = "page starting from 0, offset") @RequestParam(required = false, defaultValue = DEFAULT_PAGE) Integer page, diff --git a/src/main/java/org/openepics/names/rest/controller/NamesController.java b/src/main/java/org/openepics/names/rest/controller/NamesController.java index c6853581..13a87312 100644 --- a/src/main/java/org/openepics/names/rest/controller/NamesController.java +++ b/src/main/java/org/openepics/names/rest/controller/NamesController.java @@ -132,12 +132,12 @@ public class NamesController implements INames { // ---------------------------------------------------------------------------------------------------- @Override - public ResponsePageNameElements readNames( - Boolean deleted, FieldName[] queryFields, String[] queryValues, + public ResponsePageNameElements readNames(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { try { - return namesService.readNames( - deleted, queryFields, queryValues, + return namesService.readNames(deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, orderBy, isAsc, page, pageSize); } catch (ServiceException e) { logService.logServiceException(LOGGER, Level.WARNING, e); @@ -150,9 +150,12 @@ public class NamesController implements INames { } @Override - public ResponseEntity<Resource> readNamesDownload(Boolean deleted, FieldName[] queryFields, String[] queryValues, + public ResponseEntity<Resource> readNamesDownload(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { - ResponsePageNameElements nameElements = readNames(deleted, queryFields, queryValues, orderBy, isAsc, page, pageSize); + ResponsePageNameElements nameElements = readNames(deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, + orderBy, isAsc, page, pageSize); InputStreamResource isr = new InputStreamResource(ExcelUtil.nameElementsToExcel(nameElements)); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, ATTACHMENT_FILENAME_NAME_ELEMENT_XLSX) @@ -161,8 +164,7 @@ public class NamesController implements INames { } @Override - public ResponsePageNameElements readNames( - String name, + public ResponsePageNameElements readNames(String name, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { try { return namesService.readNames(name, orderBy, isAsc, page, pageSize); @@ -177,11 +179,11 @@ public class NamesController implements INames { } @Override - public ResponsePageNameElements readNamesSystemStructure( - String mnemonicpath, + public ResponsePageNameElements readNamesSystemStructure(String mnemonicpath, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { try { - return namesService.readNamesSystemStructure(mnemonicpath, orderBy, isAsc, page, pageSize); + return namesService.readNamesSystemStructure(mnemonicpath, + orderBy, isAsc, page, pageSize); } catch (ServiceException e) { logService.logServiceException(LOGGER, Level.WARNING, e); logService.logStackTraceElements(LOGGER, Level.WARNING, e); @@ -193,11 +195,11 @@ public class NamesController implements INames { } @Override - public ResponsePageNameElements readNamesDeviceStructure( - String mnemonicpath, + public ResponsePageNameElements readNamesDeviceStructure(String mnemonicpath, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { try { - return namesService.readNamesDeviceStructure(mnemonicpath, orderBy, isAsc, page, pageSize); + return namesService.readNamesDeviceStructure(mnemonicpath, + orderBy, isAsc, page, pageSize); } catch (ServiceException e) { logService.logServiceException(LOGGER, Level.WARNING, e); logService.logStackTraceElements(LOGGER, Level.WARNING, e); @@ -209,11 +211,11 @@ public class NamesController implements INames { } @Override - public ResponsePageNameElements readNamesHistory( - String uuid, + public ResponsePageNameElements readNamesHistory(String uuid, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { try { - return namesService.readNamesHistory(uuid, orderBy, isAsc, page, pageSize); + return namesService.readNamesHistory(uuid, + orderBy, isAsc, page, pageSize); } catch (ServiceException e) { logService.logServiceException(LOGGER, Level.WARNING, e); logService.logStackTraceElements(LOGGER, Level.WARNING, e); diff --git a/src/main/java/org/openepics/names/rest/controller/ReportController.java b/src/main/java/org/openepics/names/rest/controller/ReportController.java index 3ba73869..56c108c9 100644 --- a/src/main/java/org/openepics/names/rest/controller/ReportController.java +++ b/src/main/java/org/openepics/names/rest/controller/ReportController.java @@ -132,9 +132,9 @@ public class ReportController { // metrics can be read with service layer or repository layer // prepare metrics - ResponsePageNameElements nameElementsEssNames = namesService.readNames(null, null, null, Boolean.FALSE, null, null, null, null); - ResponsePageNameElements nameElementsEssNamesDeleted = namesService.readNames(Boolean.TRUE, null, null, Boolean.FALSE, null, null, null, null); - ResponsePageNameElements nameElementsEssNamesNotDeleted = namesService.readNames(Boolean.FALSE, null, null, Boolean.FALSE, null, null, null, null); + ResponsePageNameElements nameElementsEssNames = namesService.readNames(null, null, null, null, null, null, null, Boolean.FALSE, null, null, null, null); + ResponsePageNameElements nameElementsEssNamesDeleted = namesService.readNames(Boolean.TRUE, null, null, null, null, null, null, Boolean.FALSE, null, null, null, null); + ResponsePageNameElements nameElementsEssNamesNotDeleted = namesService.readNames(Boolean.FALSE, null, null, null, null, null, null, Boolean.FALSE, null, null, null, null); long nbrEssNameSystemstructure = 0; long nbrEssNameSystemstructureDevicestructure = 0; diff --git a/src/main/java/org/openepics/names/service/NamesService.java b/src/main/java/org/openepics/names/service/NamesService.java index ae2845a5..fa15e74b 100644 --- a/src/main/java/org/openepics/names/service/NamesService.java +++ b/src/main/java/org/openepics/names/service/NamesService.java @@ -206,34 +206,30 @@ public class NamesService { // ---------------------------------------------------------------------------------------------------- - public ResponsePageNameElements readNames( - Boolean deleted, FieldName[] queryFields, String[] queryValues, + public ResponsePageNameElements readNames(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { - return readNames(deleted, queryFields, queryValues, Boolean.FALSE, orderBy, isAsc, offset, limit); + return readNames(deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, + Boolean.FALSE, orderBy, isAsc, offset, limit); } - public ResponsePageNameElements readNames( - Boolean deleted, FieldName[] queryFields, String[] queryValues, Boolean includeHistory, - FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { + public ResponsePageNameElements readNames(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, + Boolean includeHistory, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { LOGGER.log(Level.FINE, "readNames, deleted: {0}", deleted); - LOGGER.log(Level.FINE, "readNames, queryFields.length: {0}", String.valueOf(queryFields != null ? queryFields.length : "null")); - LOGGER.log(Level.FINE, "readNames, queryValues.length: {0}", String.valueOf(queryValues != null ? queryValues.length : "null")); + LOGGER.log(Level.FINE, "readNames, uuid: {0}", uuid); + LOGGER.log(Level.FINE, "readNames, name: {0}", name); + LOGGER.log(Level.FINE, "readNames, nameequivalence: {0}", nameequivalence); + LOGGER.log(Level.FINE, "readNames, systemstructure: {0}", systemstructure); + LOGGER.log(Level.FINE, "readNames, devicestructure: {0}", devicestructure); + LOGGER.log(Level.FINE, "readNames, description: {0}", description); LOGGER.log(Level.FINE, "readNames, includeHistory: {0}", includeHistory); LOGGER.log(Level.FINE, "readNames, orderBy: {0}", orderBy); LOGGER.log(Level.FINE, "readNames, isAsc: {0}", isAsc); LOGGER.log(Level.FINE, "readNames, offset: {0}", offset); LOGGER.log(Level.FINE, "readNames, limit: {0}", limit); - if (queryFields != null && queryFields.length > 0) { - for (FieldName queryField : queryFields) { - LOGGER.log(Level.FINE, "readNames, queryField: {0}", queryField); - } - } - if (queryValues != null && queryValues.length > 0) { - for (String queryValue : queryValues) { - LOGGER.log(Level.FINE, "readNames, queryValue: {0}", queryValue); - } - } // validate input // queryFields and queryValues @@ -245,18 +241,19 @@ public class NamesService { // validate input ValidateNameElementUtil.validateNamesInputRead( - deleted, queryFields, queryValues, + deleted, + uuid, name, nameequivalence, systemstructure, devicestructure, description, includeHistory, orderBy, isAsc, offset, limit); // do - List<Name> names = nameRepository.readNames(deleted, queryFields, queryValues, includeHistory, orderBy, isAsc, offset, limit); - Long totalCount = nameRepository.countNames(deleted, queryFields, queryValues, includeHistory); + List<Name> names = nameRepository.readNames(deleted, uuid, name, nameequivalence, systemstructure, devicestructure, description, includeHistory, orderBy, isAsc, offset, limit); + Long totalCount = nameRepository.countNames(deleted, uuid, name, nameequivalence, systemstructure, devicestructure, description, includeHistory); final List<NameElement> nameElements = Lists.newArrayList(); - for (Name name : names) { - nameElements.add(NameElementUtil.getNameElement(name)); + for (Name namee : names) { + nameElements.add(NameElementUtil.getNameElement(namee)); } ResponsePageNameElements response = new ResponsePageNameElements(nameElements, totalCount, nameElements.size(), offset, limit); @@ -264,8 +261,7 @@ public class NamesService { return response; } - public ResponsePageNameElements readNames( - String name, + public ResponsePageNameElements readNames(String name, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { LOGGER.log(Level.FINE, "readNames, name: {0}", name); @@ -291,14 +287,15 @@ public class NamesService { return new ResponsePageNameElements(nameElements, Long.valueOf(nameElements.size()), nameElements.size(), offset, limit); } } catch (IllegalArgumentException e) { - return readNames(false, new FieldName[] {FieldName.NAME}, new String[] {name}, orderBy, isAsc, offset, limit); + return readNames(false, + null, name, null, null, null, null, + orderBy, isAsc, offset, limit); } return new ResponsePageNameElements(); } - public ResponsePageNameElements readNamesSystemStructure( - String mnemonicpath, + public ResponsePageNameElements readNamesSystemStructure(String mnemonicpath, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { LOGGER.log(Level.FINE, "readNamesSystemStructure, mnemonicpath: {0}", mnemonicpath); @@ -314,11 +311,12 @@ public class NamesService { ValidateUtil.validateInputMnemonicpath(mnemonicpath); // do - return readNames(false, new FieldName[] {FieldName.SYSTEMSTRUCTURE}, new String[] {mnemonicpath}, orderBy, isAsc, offset, limit); + return readNames(false, + null, null, null, mnemonicpath, null, null, + orderBy, isAsc, offset, limit); } - public ResponsePageNameElements readNamesDeviceStructure( - String mnemonicpath, + public ResponsePageNameElements readNamesDeviceStructure(String mnemonicpath, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { LOGGER.log(Level.FINE, "readNamesDeviceStructure, mnemonicpath: {0}", mnemonicpath); @@ -334,11 +332,12 @@ public class NamesService { ValidateUtil.validateInputMnemonicpath(mnemonicpath); // do - return readNames(false, new FieldName[] {FieldName.DEVICESTRUCTURE}, new String[] {mnemonicpath}, orderBy, isAsc, offset, limit); + return readNames(false, + null, null, null, null,mnemonicpath, null, + orderBy, isAsc, offset, limit); } - public ResponsePageNameElements readNamesHistory( - String uuid, + public ResponsePageNameElements readNamesHistory(String uuid, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { LOGGER.log(Level.FINE, "readNamesHistory, uuid: {0}", uuid); @@ -355,7 +354,9 @@ public class NamesService { ValidateUtil.validateInputUuid(uuid); // do - ResponsePageNameElements response = readNames(null, new FieldName[] {FieldName.UUID}, new String[] {uuid}, Boolean.TRUE, orderBy, isAsc, offset, limit); + ResponsePageNameElements response = readNames(null, + uuid, null, null, null, null, null, + Boolean.TRUE, orderBy, isAsc, offset, limit); Collections.sort(response.getList(), new Comparator<NameElement>() { @Override public int compare(NameElement e1, NameElement e2) { @@ -393,7 +394,8 @@ public class NamesService { ValidateUtil.validateInputName(name); // do - List<Name> names = nameRepository.readNames(false, FieldName.NAME, name); + List<Name> names = nameRepository.readNames(false, + null, name, null, null, null, null); return !names.isEmpty(); } @@ -408,7 +410,8 @@ public class NamesService { ValidateUtil.validateInputName(name); // do - List<Name> names = nameRepository.readNames(false, FieldName.NAME, name); + List<Name> names = nameRepository.readNames(false, + null, name, null, null, null, null); ExceptionUtil.validateConditionDataNotFoundException(names != null && names.size() == 1, "name not found", name, null); Name toBeChecked = names.get(0); diff --git a/src/main/java/org/openepics/names/util/RepositoryUtil.java b/src/main/java/org/openepics/names/util/RepositoryUtil.java new file mode 100644 index 00000000..48dae098 --- /dev/null +++ b/src/main/java/org/openepics/names/util/RepositoryUtil.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022 European Spallation Source ERIC. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package org.openepics.names.util; + +import org.apache.commons.lang3.StringUtils; + +/** + * Utility class to assist in handling of patterns for queries. + * + * @author Lars Johansson + */ +public class RepositoryUtil { + + private static final String PERCENT = "%"; + + /** + * This class is not to be instantiated. + */ + private RepositoryUtil() { + throw new IllegalStateException("Utility class"); + } + + /** + * Prepare pattern for use in where clause (predicate). + * Purpose to remove excess characters and similar work. + * + * @param value value + * @return prepared pattern + */ + public static String preparePattern(String value) { + // jpa query characters % and _ + // remove excess % characters + String queryValue = value; + if (!StringUtils.isEmpty(queryValue)) { + if (queryValue.startsWith(PERCENT)) { + while (queryValue.startsWith(PERCENT)) { + queryValue = queryValue.substring(1); + } + queryValue = PERCENT + queryValue; + } + if (queryValue.endsWith(PERCENT)) { + while (queryValue.endsWith(PERCENT)) { + queryValue = queryValue.substring(0, queryValue.length()-1); + } + queryValue = queryValue + PERCENT; + } + } + return queryValue; + } + +} diff --git a/src/main/java/org/openepics/names/util/ValidateNameElementUtil.java b/src/main/java/org/openepics/names/util/ValidateNameElementUtil.java index be50a152..e1fb6af0 100644 --- a/src/main/java/org/openepics/names/util/ValidateNameElementUtil.java +++ b/src/main/java/org/openepics/names/util/ValidateNameElementUtil.java @@ -68,38 +68,27 @@ public class ValidateNameElementUtil { * Validate parameters for read names. * * @param deleted deleted - * @param queryFields query fields - * @param queryValues query values + * @param uuid uuid + * @param name name + * @param nameequivalence name equivalence + * @param systemstructure system structure mnemonic + * @param devicestructure device structure mnemonic + * @param description description * @param includeHistory include history * @param orderBy order by * @param isAsc is ascending * @param offset offset * @param limit limit */ - public static void validateNamesInputRead( - Boolean deleted, FieldName[] queryFields, String[] queryValues, - Boolean includeHistory, - FieldName orderBy, Boolean isAsc, - Integer offset, Integer limit) { + public static void validateNamesInputRead(Boolean deleted, + String uuid, String name, String nameequivalence, String systemstructure, String devicestructure, String description, + Boolean includeHistory, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { // validate input - // queryFields and queryValues - // either - // both null - // both non-null, same length, non-empty - // uuid - - boolean condition = ((queryFields == null && queryValues == null) - || (queryFields != null && queryValues != null && queryFields.length == queryValues.length && queryFields.length > 0)); - ExceptionUtil.validateConditionInputNotCorrectException(condition, - TextUtil.VALUES_ARE_NOT_CORRECT, "url and parameters (queryFields, queryValues) have different lengths or are empty", null); - - if (queryFields != null) { - for (int i=0; i<queryFields.length; i++) { - if (FieldName.UUID.equals(queryFields[i])) { - ValidateUtil.validateInputUuid(queryValues[i]); - } - } + // uuid + + if (!StringUtils.isEmpty(uuid)) { + ValidateUtil.validateInputUuid(uuid); } } @@ -259,7 +248,7 @@ public class ValidateNameElementUtil { // update, delete - uuid available, not deleted // retrieve for uuid and check if (NameChoice.UPDATE.equals(nameChoice) || NameChoice.DELETE.equals(nameChoice)) { - List<Name> names = nameRepository.readNames(false, FieldName.UUID, nameElement.getUuid().toString()); + List<Name> names = nameRepository.readNames(false, nameElement.getUuid().toString(), null, null, null, null, null); ExceptionUtil.validateConditionDataNotCorrectException(names != null && names.size() == 1, TextUtil.VALUE_IS_NOT_CORRECT, details, TextUtil.UUID); } @@ -335,7 +324,7 @@ public class ValidateNameElementUtil { // name // ok with same name, name equivalence if same uuid - List<Name> names = nameRepository.readNames(false, FieldName.NAME, derivedName); + List<Name> names = nameRepository.readNames(false, null, derivedName, null, null, null, null); if (NameChoice.CREATE.equals(nameChoice)) { condition = names == null || names.isEmpty(); } else { @@ -344,7 +333,7 @@ public class ValidateNameElementUtil { } ExceptionUtil.validateConditionDataExistException(condition, TextUtil.CONVENTION_NAME_EXISTS, details, TextUtil.PARENTSYSTEMSTRUCTURE); - names = nameRepository.readNames(false, FieldName.NAMEEQUIVALENCE, namingConvention.equivalenceClassRepresentative(derivedName)); + names = nameRepository.readNames(false, null, null, namingConvention.equivalenceClassRepresentative(derivedName), null, null, null); if (NameChoice.CREATE.equals(nameChoice)) { condition = names == null || names.isEmpty(); } else { @@ -469,10 +458,10 @@ public class ValidateNameElementUtil { // convention name equivalence not exists ExceptionUtil.validateConditionDataNotCorrectException(StringUtils.equals(name, derivedName), TextUtil.CONVENTION_NAME_IS_NOT_CORRECT, details, field); - List<Name> names = holderRepositories.getNameRepository().readNames(false, FieldName.NAME, name); + List<Name> names = holderRepositories.getNameRepository().readNames(false, null, name, null, null, null, null); ExceptionUtil.validateConditionDataExistException(names.isEmpty(), TextUtil.CONVENTION_NAME_EXISTS, details, field); - names = holderRepositories.getNameRepository().readNames(false, FieldName.NAMEEQUIVALENCE, namingConvention.equivalenceClassRepresentative(name)); + names = holderRepositories.getNameRepository().readNames(false, null, null, namingConvention.equivalenceClassRepresentative(name), null, null, null); ExceptionUtil.validateConditionDataExistException(names.isEmpty(), TextUtil.CONVENTION_NAME_EQUIVALENCE_EXISTS, details, field); } diff --git a/src/test/java/org/openepics/names/docker/NamesIT.java b/src/test/java/org/openepics/names/docker/NamesIT.java index 091c5ebf..b0abccfe 100644 --- a/src/test/java/org/openepics/names/docker/NamesIT.java +++ b/src/test/java/org/openepics/names/docker/NamesIT.java @@ -794,8 +794,9 @@ class NamesIT { ITUtilNameElement.assertRead("", 8, -1); - ITUtilNameElement.assertRead("?queryFields=UUID&queryValues=" + uuid.toString(), 1); - ITUtilNameElement.assertRead("?queryFields=NAMEEQUIVALENCE&queryValues=RFQ-10%25", 8, -1); + ITUtilNameElement.assertRead("?uuid=" + uuid.toString(), 1); + ITUtilNameElement.assertRead("?nameequivalence=RFQ-10%25", 8, -1); + ITUtilNameElement.assertRead("?nameequivalence=RFQ-10%25&devicestructure=EMR-FS", 6, -1); ITUtilNameElement.assertRead("?deleted=false", 6, -1); ITUtilNameElement.assertRead("?deleted=true", 2, -1); diff --git a/src/test/java/org/openepics/names/util/ValidateUtilTest.java b/src/test/java/org/openepics/names/util/ValidateUtilTest.java index b4a9910b..faba23cb 100644 --- a/src/test/java/org/openepics/names/util/ValidateUtilTest.java +++ b/src/test/java/org/openepics/names/util/ValidateUtilTest.java @@ -282,10 +282,8 @@ class ValidateUtilTest { @Test void validateInputReadNames() { ValidateNameElementUtil.validateNamesInputRead( - null, null, null, - null, - null, null, - null, null); + null, null, null, null, null, null, null, + null, null, null, null, null); } /** -- GitLab