diff --git a/docs/about/naming_rest_api_brief_introduction.odt b/docs/about/naming_rest_api_brief_introduction.odt index 08b862cb4f464caa49450f038d2e5b0c6e0fff76..db978abbf8b8ee8b7255e91744f87661348d86e0 100644 Binary files a/docs/about/naming_rest_api_brief_introduction.odt and b/docs/about/naming_rest_api_brief_introduction.odt differ diff --git a/docs/about/naming_rest_api_brief_introduction.pdf b/docs/about/naming_rest_api_brief_introduction.pdf index 04f08ee6b32ef01dd12888887e73e2e52a8cc47e..a57e2cddc350ad52c2edff95c7e9fca4b8b6d80a 100644 Binary files a/docs/about/naming_rest_api_brief_introduction.pdf and b/docs/about/naming_rest_api_brief_introduction.pdf differ diff --git a/docs/about/naming_rest_api_migration.odt b/docs/about/naming_rest_api_migration.odt index 6ea3ad635b56bd1229294729da10f6a2e66954a4..c2c8156a26bfe75823d2e73d91a71db0e1284aba 100644 Binary files a/docs/about/naming_rest_api_migration.odt and b/docs/about/naming_rest_api_migration.odt differ diff --git a/docs/about/naming_rest_api_migration.pdf b/docs/about/naming_rest_api_migration.pdf index 74cde2c881182cfd7b0eab7f84ebf84ffd42dd11..a03af63e32af5099877147527b8461d414db1b1a 100644 Binary files a/docs/about/naming_rest_api_migration.pdf and b/docs/about/naming_rest_api_migration.pdf differ diff --git a/src/main/java/org/openepics/names/repository/NameRepository.java b/src/main/java/org/openepics/names/repository/NameRepository.java index b949d580184b3a27711508b80ae364119f2e6fb9..31e2c1eb84577447f248435d7a761c39710c183e 100644 --- a/src/main/java/org/openepics/names/repository/NameRepository.java +++ b/src/main/java/org/openepics/names/repository/NameRepository.java @@ -29,11 +29,13 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; 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.repository.model.Persistable; import org.openepics.names.rest.beans.FieldName; import org.openepics.names.util.RepositoryUtil; import org.springframework.stereotype.Repository; @@ -60,12 +62,13 @@ public class NameRepository { * @param deviceStructure device structure mnemonic * @param index index * @param description description + * @param who who * @return count of names */ public Long countNames(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description) { + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who) { return countNames(deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, Boolean.FALSE); } @@ -80,11 +83,12 @@ public class NameRepository { * @param deviceStructure device structure mnemonic * @param index index * @param description description + * @param who who * @param includeHistory include history * @return count of names */ public Long countNames(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, Boolean includeHistory) { // note @@ -98,7 +102,7 @@ public class NameRepository { Root<Name> from = cq.from(Name.class); cq.where(cb.and(preparePredicatesNames(cb, from, deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, includeHistory).toArray(new Predicate[0]))); cq.select(cb.count(from)); @@ -116,13 +120,14 @@ public class NameRepository { * @param deviceStructure device structure mnemonic * @param index index * @param description description + * @param who who * @return list of names */ public List<Name> readNames(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description) { + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who) { return readNames(deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, Boolean.FALSE, null, null, null, null); } @@ -137,6 +142,7 @@ public class NameRepository { * @param deviceStructure device structure mnemonic * @param index index * @param description description + * @param who who * @param orderBy order by * @param isAsc is ascending * @param offset offset @@ -144,10 +150,10 @@ public class NameRepository { * @return list of names */ public List<Name> readNames(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { return readNames(deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, Boolean.FALSE, orderBy, isAsc, offset, limit); } @@ -162,6 +168,7 @@ public class NameRepository { * @param deviceStructure device structure mnemonic * @param index index * @param description description + * @param who who * @param includeHistory include history * @param orderBy order by * @param isAsc is ascending @@ -170,7 +177,7 @@ public class NameRepository { * @return list of names */ public List<Name> readNames(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, Boolean includeHistory, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { // note @@ -188,7 +195,7 @@ public class NameRepository { Root<Name> from = cq.from(Name.class); cq.where(cb.and(preparePredicatesNames(cb, from, deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, includeHistory).toArray(new Predicate[0]))); cq.select(from); @@ -241,6 +248,215 @@ public class NameRepository { return query.getResultList(); } + /** + * Prepare predicates for names. + * + * @param cb criteria builder + * @param from criteria query root + * @param deleted deleted + * @param uuid uuid + * @param name name + * @param nameEquivalence name equivalence + * @param systemStructure system structure mnemonic + * @param deviceStructure device structure mnemonic + * @param index index + * @param description description + * @param who who + * @param includeHistory include history + * @return list of predicates + */ + private List<Predicate> preparePredicatesNames(CriteriaBuilder cb, Root<Name> from, Boolean deleted, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, + Boolean includeHistory) { + + List<Predicate> predicates = new ArrayList<>(); + + if (!Boolean.TRUE.equals(includeHistory)) { + // purpose of Naming to show valid entries + // therefore + // exclude some values unless history requested + // make sure to not exclude present and future values + // + // exclude not latest + // select * from Name n where + // not(n.latest = false) + + Predicate predicateNotLatest = cb.equal(from.get(NameStructure.FIELD_LATEST), Boolean.FALSE); + Predicate predicateExclude = cb.not(cb.and(predicateNotLatest)); + predicates.add(predicateExclude); + } + + if (deleted != null) { + predicates.add(cb.equal(from.get(NameStructure.FIELD_DELETED), deleted)); + } + + // 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(index)) { + predicates.add(cb.and(cb.like(cb.function(NameStructure.FUNCTION_GET_INSTANCE_INDEX, String.class, from.get(Name.FIELD_CONVENTION_NAME)), RepositoryUtil.preparePattern(index)))); + } + if (!StringUtils.isEmpty(description)) { + predicates.add(cb.and(cb.like(from.get(NameStructure.FIELD_DESCRIPTION), RepositoryUtil.preparePattern(description)))); + } + if (!StringUtils.isEmpty(who)) { + predicates.add(cb.and(cb.like(from.get(NameStructure.FIELD_REQUESTED_BY), RepositoryUtil.preparePattern(who)))); + } + + return predicates; + } + + /** + * Count names history. + * + * @param uuid uuid + * @param name name + * @param nameEquivalence name equivalence + * @param systemStructure system structure mnemonic + * @param deviceStructure device structure mnemonic + * @param index index + * @param description description + * @param who who + * @return count of names + */ + public Long countNamesHistory( + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who) { + + // note + // use of function for mnemonic path + // deleted - null + // includeHistory - true + // where + // queryFields, queryValues + + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery<Long> cq = cb.createQuery(Long.class); + Root<Name> from = cq.from(Name.class); + + Subquery<String> sub = cq.subquery(String.class); + Root<Name> fromSub = sub.from(Name.class); + sub.where(cb.and(preparePredicatesNames(cb, fromSub, null, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, + Boolean.TRUE).toArray(new Predicate[0]))); + sub.select(fromSub.get(NameStructure.FIELD_UUID)); + + cq.where(cb.and(cb.in(from.get(NameStructure.FIELD_UUID)).value(sub))); + cq.select(cb.count(from)); + + return em.createQuery(cq).getSingleResult(); + } + + /** + * Find names history. + * + * @param uuid uuid + * @param name name + * @param nameEquivalence name equivalence + * @param systemStructure system structure mnemonic + * @param deviceStructure device structure mnemonic + * @param index index + * @param description description + * @param who who + * @param orderBy order by + * @param isAsc is ascending + * @param offset offset + * @param limit limit + * @return list of names + */ + public List<Name> readNamesHistory( + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, + FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { + + // note + // use of function for mnemonic path + // deleted - null + // includeHistory - true + // where + // queryFields, queryValues + // order + // orderBy, isAsc + // paging + // offset, limit + + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery<Name> cq = cb.createQuery(Name.class); + Root<Name> from = cq.from(Name.class); + + Subquery<String> sub = cq.subquery(String.class); + Root<Name> fromSub = sub.from(Name.class); + sub.where(cb.and(preparePredicatesNames(cb, fromSub, null, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, + Boolean.TRUE).toArray(new Predicate[0]))); + sub.select(fromSub.get(NameStructure.FIELD_UUID)); + + cq.where(cb.and(cb.in(from.get(NameStructure.FIELD_UUID)).value(sub))); + cq.select(from); + + if (orderBy != null) { + if (BooleanUtils.toBoolean(isAsc)) { + if (FieldName.NAME.equals(orderBy)) { + cq.orderBy(cb.asc(from.get(Name.FIELD_CONVENTION_NAME))); + } else if (FieldName.NAMEEQUIVALENCE.equals(orderBy)) { + cq.orderBy(cb.asc(from.get(Name.FIELD_CONVENTION_NAME_EQUIVALENCE))); + } else if (FieldName.SYSTEMSTRUCTURE.equals(orderBy)) { + cq.orderBy(cb.asc(cb.function(NameStructure.FUNCTION_GET_MNEMONIC_PATH_SYSTEM_STRUCTURE, String.class, from.get(Name.FIELD_CONVENTION_NAME)))); + } else if (FieldName.DEVICESTRUCTURE.equals(orderBy)) { + cq.orderBy(cb.asc(cb.function(NameStructure.FUNCTION_GET_MNEMONIC_PATH_DEVICE_STRUCTURE, String.class, from.get(Name.FIELD_CONVENTION_NAME)))); + } else if (FieldName.INDEX.equals(orderBy)) { + cq.orderBy(cb.asc(cb.function(NameStructure.FUNCTION_GET_INSTANCE_INDEX, String.class, from.get(Name.FIELD_CONVENTION_NAME)))); + } else if (FieldName.DESCRIPTION.equals(orderBy)) { + cq.orderBy(cb.asc(from.get(NameStructure.FIELD_DESCRIPTION))); + } else if (FieldName.WHEN.equals(orderBy)) { + cq.orderBy(cb.asc(from.get(NameStructure.FIELD_REQUESTED))); + } else { + cq.orderBy(cb.asc(from.get(NameStructure.FIELD_UUID)), cb.asc(from.get(Persistable.FIELD_ID))); + } + } else { + if (FieldName.NAME.equals(orderBy)) { + cq.orderBy(cb.desc(from.get(Name.FIELD_CONVENTION_NAME))); + } else if (FieldName.NAMEEQUIVALENCE.equals(orderBy)) { + cq.orderBy(cb.desc(from.get(Name.FIELD_CONVENTION_NAME_EQUIVALENCE))); + } else if (FieldName.SYSTEMSTRUCTURE.equals(orderBy)) { + cq.orderBy(cb.desc(cb.function(NameStructure.FUNCTION_GET_MNEMONIC_PATH_SYSTEM_STRUCTURE, String.class, from.get(Name.FIELD_CONVENTION_NAME)))); + } else if (FieldName.DEVICESTRUCTURE.equals(orderBy)) { + cq.orderBy(cb.desc(cb.function(NameStructure.FUNCTION_GET_MNEMONIC_PATH_DEVICE_STRUCTURE, String.class, from.get(Name.FIELD_CONVENTION_NAME)))); + } else if (FieldName.INDEX.equals(orderBy)) { + cq.orderBy(cb.desc(cb.function(NameStructure.FUNCTION_GET_INSTANCE_INDEX, String.class, from.get(Name.FIELD_CONVENTION_NAME)))); + } else if (FieldName.DESCRIPTION.equals(orderBy)) { + cq.orderBy(cb.desc(from.get(NameStructure.FIELD_DESCRIPTION))); + } else if (FieldName.WHEN.equals(orderBy)) { + cq.orderBy(cb.desc(from.get(NameStructure.FIELD_REQUESTED))); + } else { + cq.orderBy(cb.desc(from.get(NameStructure.FIELD_UUID)), cb.desc(from.get(Persistable.FIELD_ID))); + } + } + } + + TypedQuery<Name> query = em.createQuery(cq); + if (offset != null && limit != null) { + query.setFirstResult(offset * limit); + query.setMaxResults(limit); + } + + return query.getResultList(); + } + /** * Count legacy names * @@ -283,11 +499,11 @@ public class NameRepository { * Find legacy names. * * @param name name - * @param orderBy order by - * @param isAsc is ascending - * @param offset offset - * @param limit limit - * @return list of names + * @param orderBy order by + * @param isAsc is ascending + * @param offset offset + * @param limit limit + * @return list of names * @return */ @SuppressWarnings("unchecked") @@ -370,76 +586,6 @@ public class NameRepository { return query.getResultList(); } - /** - * Prepare predicates for names. - * - * @param cb criteria builder - * @param from criteria query root - * @param deleted deleted - * @param uuid uuid - * @param name name - * @param nameEquivalence name equivalence - * @param systemStructure system structure mnemonic - * @param deviceStructure device structure mnemonic - * @param index index - * @param description description - * @param includeHistory include history - * @return list of predicates - */ - private List<Predicate> preparePredicatesNames(CriteriaBuilder cb, Root<Name> from, Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, - Boolean includeHistory) { - - List<Predicate> predicates = new ArrayList<>(); - - if (!Boolean.TRUE.equals(includeHistory)) { - // purpose of Naming to show valid entries - // therefore - // exclude some values unless history requested - // make sure to not exclude present and future values - // - // exclude not latest - // select * from Name n where - // not(n.latest = false) - - Predicate predicateNotLatest = cb.equal(from.get(NameStructure.FIELD_LATEST), Boolean.FALSE); - Predicate predicateExclude = cb.not(cb.and(predicateNotLatest)); - predicates.add(predicateExclude); - } - - if (deleted != null) { - predicates.add(cb.equal(from.get(NameStructure.FIELD_DELETED), deleted)); - } - - // 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(index)) { - predicates.add(cb.and(cb.like(cb.function(NameStructure.FUNCTION_GET_INSTANCE_INDEX, String.class, from.get(Name.FIELD_CONVENTION_NAME)), RepositoryUtil.preparePattern(index)))); - } - if (!StringUtils.isEmpty(description)) { - predicates.add(cb.and(cb.like(from.get(NameStructure.FIELD_DESCRIPTION), RepositoryUtil.preparePattern(description)))); - } - - return predicates; - } - /** * Persist name into persistence context. * 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 f353cb126b99a492d079b5d027235896997bdc1e..463f51ce71678464b729c8d7ae7214e50c3b60a1 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 @@ -89,30 +89,32 @@ public interface INames { who (String) Methods - create POST /names - createNames (List<NameElementCommandCreate>) - create POST /names/upload - createNames (MultipartFile) + create POST /names - createNames + create POST /names/upload - createNames upload Excel file ---------------------------------------------------------------------------------------------------- - 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) - read GET /names/history/{uuid} - readNamesHistory (String, FieldName, Boolean, Integer, Integer) + read GET /names - readNames + read GET /names/download - readNamesDownload download Excel file + read GET /names/{name} - readNames + read GET /names/systemStructure/{mnemonicPath} - readNamesSystemStructure + read GET /names/deviceStructure/{mnemonicPath} - readNamesDeviceStructure + read GET /names/history - readNamesHistory + read GET /names/history/{uuid} - readNamesHistory + read GET /names/legacy - readNamesLegacy ---------------------------------------------------------------------------------------------------- - read GET /names/equivalence/{name} - equivalenceName (String) - read GET /names/exists/{name} - existsName (String) - read GET /names/isLegacy/{name} - isLegacyName (String) - read GET /names/isValidToCreate/{name} - isValidToCreateName (String) + read GET /names/equivalence/{name} - equivalenceName + read GET /names/exists/{name} - existsName + read GET /names/isLegacy/{name} - isLegacyName + read GET /names/isValidToCreate/{name} - isValidToCreateName ---------------------------------------------------------------------------------------------------- - read GET /names/validateCreate - validateNamesCreate (List<NameElementCommandCreate>) - read GET /names/validateUpdate - validateNamesUpdate (List<NameElementCommandUpdate>) - read GET /names/validateDelete - validateNamesDelete (List<NameElementCommandConfirm>) + read GET /names/validateCreate - validateNamesCreate hidden from Swagger UI + read GET /names/validateUpdate - validateNamesUpdate hidden from Swagger UI + read GET /names/validateDelete - validateNamesDelete hidden from Swagger UI ---------------------------------------------------------------------------------------------------- - update PUT /names - updateNames (List<NameElementCommandUpdate>) - update PUT /names/upload - updateNames (MultipartFile) + update PUT /names - updateNames + update PUT /names/upload - updateNames upload Excel file ---------------------------------------------------------------------------------------------------- - delete DELETE /names - deleteNames (List<NameElementCommandConfirm>) - delete DELETE /names/upload - deleteNames (MultipartFile) + delete DELETE /names - deleteNames + delete DELETE /names/upload - deleteNames upload Excel file Note read GET /names/{name} - both name and uuid (name - exact and search, uuid exact) @@ -298,6 +300,7 @@ public interface INames { * @param deviceStructure device structure mnemonic path * @param index index * @param description description + * @param who who * @param orderBy order by field * @param isAsc sort order, ascending or descending * @param page page starting from 0, offset @@ -341,13 +344,14 @@ 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 by uuid") @RequestParam(required = false) String uuid, + @Parameter(in = ParameterIn.QUERY, description = "find 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 index") @RequestParam(required = false) String index, @Parameter(in = ParameterIn.QUERY, description = "search by description") @RequestParam(required = false) String description, + @Parameter(in = ParameterIn.QUERY, description = "search by who") @RequestParam(required = false) String who, @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, @@ -366,6 +370,7 @@ public interface INames { * @param deviceStructure device structure mnemonic path * @param index index * @param description description + * @param who who * @param orderBy order by field * @param isAsc sort order, ascending or descending * @param page page starting from 0, offset @@ -408,13 +413,14 @@ 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 by uuid") @RequestParam(required = false) String uuid, + @Parameter(in = ParameterIn.QUERY, description = "find 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 index") @RequestParam(required = false) String index, @Parameter(in = ParameterIn.QUERY, description = "search by description") @RequestParam(required = false) String description, + @Parameter(in = ParameterIn.QUERY, description = "search by who") @RequestParam(required = false) String who, @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, @@ -468,7 +474,7 @@ public interface INames { value = "/{name}", produces = {"application/json"}) public ResponsePageNameElements readNames( - @Parameter(in = ParameterIn.PATH, description = "search by name or uuid") @PathVariable("name") String name, + @Parameter(in = ParameterIn.PATH, description = "search by name or find by 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, @@ -582,9 +588,82 @@ public interface INames { @Parameter(in = ParameterIn.QUERY, description = "page starting from 0, offset") @RequestParam(required = false, defaultValue = DEFAULT_PAGE) Integer page, @Parameter(in = ParameterIn.QUERY, description = "page size, limit") @RequestParam(required = false, defaultValue = DEFAULT_PAGE_SIZE) Integer pageSize); + /** + * Find history for name (search). + * History consists of lines of uuid. + * The line of uuid is not broken in retrieving history. If combination of parameters is found in name entries, the entire lines of uuid are returned. + * Return paged list of name elements. + * + * @param uuid uuid + * @param name name + * @param nameEquivalence name equivalence + * @param systemStructure system structure mnemonic path + * @param deviceStructure device structure mnemonic path + * @param index index + * @param description description + * @param who who + * @param orderBy order by field + * @param isAsc sort order, ascending or descending + * @param page page starting from 0, offset + * @param pageSize page size, limit + * @return paged list of name elements + */ + @Operation( + summary = "Find history for name (search)", + description = """ + Find history for name (search). + History consists of lines of uuid. + The line of uuid is not broken in retrieving history. If combination of parameters is found in name entries, the entire lines of uuid are returned. + Return paged array of name elements. + """ + ) + @ApiResponses(value = { + @ApiResponse( + responseCode = "200", + description = "OK. Return paged array of name elements.", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = ResponsePageNameElements.class))), + @ApiResponse( + responseCode = "400", + description = "Bad request. Reason and information such as message, details, field are available.", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = Response.class))), + @ApiResponse( + responseCode = "422", + description = "Unprocessable entity. Reason and information such as message, details, field are available.", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = Response.class))), + @ApiResponse( + responseCode = "500", + description = "Internal server error. Reason and information such as message, details, field are available.", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = Response.class))) + }) + @GetMapping( + value = "/history", + produces = {"application/json"}) + public ResponsePageNameElements readNamesHistory( + @Parameter(in = ParameterIn.QUERY, description = "find 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 index") @RequestParam(required = false) String index, + @Parameter(in = ParameterIn.QUERY, description = "search by description") @RequestParam(required = false) String description, + @Parameter(in = ParameterIn.QUERY, description = "search by who") @RequestParam(required = false) String who, + @Parameter(in = ParameterIn.QUERY, description = "order by field") @RequestParam(required = false, defaultValue = DEFAULT_SORT_FIELD_WHEN) FieldName orderBy, + @Parameter(in = ParameterIn.QUERY, description = "sort order, ascending or descending") @RequestParam(required = false, defaultValue = DEFAULT_SORT_ORDER_ASC) Boolean isAsc, + @Parameter(in = ParameterIn.QUERY, description = "page starting from 0, offset") @RequestParam(required = false, defaultValue = DEFAULT_PAGE) Integer page, + @Parameter(in = ParameterIn.QUERY, description = "page size, limit") @RequestParam(required = false, defaultValue = DEFAULT_PAGE_SIZE) Integer pageSize); + /** * Find history for name by uuid (exact match). * History consists of line of uuid. + * The line of uuid is not broken in retrieving history. If the uuid is found in a name entry, the entire line of uuid is returned. * Return paged list of name elements. * * @param uuid uuid @@ -599,6 +678,7 @@ public interface INames { description = """ Find history for name by uuid (exact match). History consists of line of uuid. + The line of uuid is not broken in retrieving history. If the uuid is found in a name entry, the entire line of uuid is returned. Return paged array of name elements. """ ) @@ -632,7 +712,7 @@ public interface INames { value = "/history/{uuid}", produces = {"application/json"}) public ResponsePageNameElements readNamesHistory( - @Parameter(in = ParameterIn.PATH, description = "search by uuid") @PathVariable("uuid") String uuid, + @Parameter(in = ParameterIn.PATH, description = "find by uuid") @PathVariable("uuid") String uuid, @Parameter(in = ParameterIn.QUERY, description = "order by field") @RequestParam(required = false, defaultValue = DEFAULT_SORT_FIELD_WHEN) FieldName orderBy, @Parameter(in = ParameterIn.QUERY, description = "sort order, ascending or descending") @RequestParam(required = false, defaultValue = DEFAULT_SORT_ORDER_ASC) 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 61f92e1463c55a71e3c49379b0672c444960e495..a30f1c23744a43c42a4549c04c9e0dcc5958aa87 100644 --- a/src/main/java/org/openepics/names/rest/controller/NamesController.java +++ b/src/main/java/org/openepics/names/rest/controller/NamesController.java @@ -152,7 +152,7 @@ public class NamesController implements INames { @Override public ResponsePageNameElements readNames(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { // validate // read names @@ -160,12 +160,12 @@ public class NamesController implements INames { try { ValidateNameElementUtil.validateNamesInputRead( deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, null, orderBy, isAsc, page, pageSize); return namesService.readNames(deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, orderBy, isAsc, page, pageSize); } catch (ServiceException e) { logService.logServiceException(LOGGER, Level.WARNING, e); @@ -179,14 +179,14 @@ public class NamesController implements INames { @Override public ResponseEntity<Resource> readNamesDownload(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { // validate // read names // convert to output ResponsePageNameElements nameElements = readNames(deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, orderBy, isAsc, page, pageSize); InputStreamResource isr = new InputStreamResource(ExcelUtil.nameElementsToExcel(nameElements)); return ResponseEntity.ok() @@ -254,6 +254,35 @@ public class NamesController implements INames { } } + @Override + public ResponsePageNameElements readNamesHistory( + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, + FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { + // validate + // read names + + try { + ValidateUtil.validateInputAvailable( + !ValidateUtil.areAllNull(uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who)); + ValidateNameElementUtil.validateNamesInputRead( + null, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, + null, + orderBy, isAsc, + page, pageSize); + return namesService.readNamesHistory( + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, + orderBy, isAsc, page, pageSize); + } catch (ServiceException e) { + logService.logServiceException(LOGGER, Level.WARNING, e); + logService.logStackTraceElements(LOGGER, Level.WARNING, e); + throw e; + } catch (Exception e) { + logService.logStackTraceElements(LOGGER, Level.WARNING, e); + throw e; + } + } + @Override public ResponsePageNameElements readNamesHistory(String uuid, FieldName orderBy, Boolean isAsc, Integer page, Integer pageSize) { 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 146c0f5adc9d8ed2ec40182be2e8cbff05844dd1..5ae9c2d478f643bbdffaca6386fce4a446f1f4b6 100644 --- a/src/main/java/org/openepics/names/rest/controller/ReportController.java +++ b/src/main/java/org/openepics/names/rest/controller/ReportController.java @@ -139,9 +139,9 @@ public class ReportController { // prepare metrics // read names - latest, latest deleted, latest not deleted // count names - kind of name - ResponsePageNameElements nameElementsEssNames = namesService.readNames(null, 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, null, Boolean.FALSE, null, null, null, null); - ResponsePageNameElements nameElementsEssNamesNotDeleted = namesService.readNames(Boolean.FALSE, null, null, null, null, null, null, null, Boolean.FALSE, null, null, null, null); + ResponsePageNameElements nameElementsEssNames = namesService.readNames(null, null, 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, null, null, Boolean.FALSE, null, null, null, null); + ResponsePageNameElements nameElementsEssNamesNotDeleted = namesService.readNames(Boolean.FALSE, null, null, null, null, null, null, null, null, Boolean.FALSE, null, null, null, null); ResponsePageNameElements nameElementsEssNamesNotDeletedLegacy = namesService.readNamesLegacy(null, null, null, null, null); long nbrEssNameSystemstructure = 0; diff --git a/src/main/java/org/openepics/names/service/NamesService.java b/src/main/java/org/openepics/names/service/NamesService.java index e69af5870999eea46ec36733aecd42722796ca7e..cb099d6dd6bf42dcc540f877056d867e74271e21 100644 --- a/src/main/java/org/openepics/names/service/NamesService.java +++ b/src/main/java/org/openepics/names/service/NamesService.java @@ -228,15 +228,15 @@ public class NamesService { // ---------------------------------------------------------------------------------------------------- public ResponsePageNameElements readNames(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { return readNames(deleted, - uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, Boolean.FALSE, orderBy, isAsc, offset, limit); } public ResponsePageNameElements readNames(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, Boolean includeHistory, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { // validation outside method // read names @@ -251,6 +251,7 @@ public class NamesService { LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "deviceStructure", deviceStructure)); LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "index", index)); LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "description", description)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "who", who)); LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "includeHistory", includeHistory)); LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "orderBy", orderBy)); LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "isAsc", isAsc)); @@ -258,8 +259,15 @@ public class NamesService { LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "limit", limit)); } - List<Name> names = nameRepository.readNames(deleted, uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, includeHistory, orderBy, isAsc, offset, limit); - Long totalCount = nameRepository.countNames(deleted, uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, includeHistory); + List<Name> names = null; + Long totalCount = null; + if (Boolean.TRUE.equals(includeHistory)) { + names = nameRepository.readNamesHistory(uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, orderBy, isAsc, offset, limit); + totalCount = nameRepository.countNamesHistory(uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who); + } else { + names = nameRepository.readNames(deleted, uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, includeHistory, orderBy, isAsc, offset, limit); + totalCount = nameRepository.countNames(deleted, uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, includeHistory); + } final List<NameElement> nameElements = NameElementUtil.getNameElements(names); @@ -290,7 +298,7 @@ public class NamesService { } } catch (IllegalArgumentException e) { return readNames(false, - null, name, null, null, null, null, null, + null, name, null, null, null, null, null, null, orderBy, isAsc, offset, limit); } @@ -303,10 +311,10 @@ public class NamesService { // read mnemonic path // return name elements - LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, "Read names system structure", "mnemonicPath", mnemonicPath)); + LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_SYSTEM_STRUCTURE, "mnemonicPath", mnemonicPath)); return readNames(false, - null, null, null, mnemonicPath, null, null, null, + null, null, null, mnemonicPath, null, null, null, null, orderBy, isAsc, offset, limit); } @@ -316,23 +324,50 @@ public class NamesService { // read mnemonic path // return name elements - LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, "Read names device structure", "mnemonicPath", mnemonicPath)); + LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_DEVICE_STRUCTURE, "mnemonicPath", mnemonicPath)); return readNames(false, - null, null, null, null,mnemonicPath, null, null, + null, null, null, null,mnemonicPath, null, null, null, orderBy, isAsc, offset, limit); } + public ResponsePageNameElements readNamesHistory( + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, + FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { + // validation outside method + // read history for name + // return name elements for names + + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "uuid", uuid)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "name", name)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "nameEquivalence", nameEquivalence)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "systemStructure", systemStructure)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "deviceStructure", deviceStructure)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "index", index)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "description", description)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "who", who)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "orderBy", orderBy)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "isAsc", isAsc)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "offset", offset)); + LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "limit", limit)); + } + + return readNames(null, + uuid, name, nameEquivalence, systemStructure, deviceStructure, index, description, who, + Boolean.TRUE, orderBy, isAsc, offset, limit); + } + public ResponsePageNameElements readNamesHistory(String uuid, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { // validation outside method // read history for name // return name elements for names - LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, "Read names history", "uuid", uuid)); + LOGGER.log(Level.INFO, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "uuid", uuid)); return readNames(null, - uuid, null, null, null, null, null, null, + uuid, null, null, null, null, null, null, null, Boolean.TRUE, orderBy, isAsc, offset, limit); } @@ -371,7 +406,7 @@ public class NamesService { // validation outside method // read equivalence - LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, "Equivalence name", "name", name)); + LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.EQUIVALENCE_NAME, "name", name)); return namingConvention.equivalenceClassRepresentative(name); } @@ -380,10 +415,10 @@ public class NamesService { // validation outside method // read exists - LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, "Exists name", "name", name)); + LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.EXISTS_NAME, "name", name)); List<Name> names = nameRepository.readNames(false, - null, name, null, null, null, null, null); + null, name, null, null, null, null, null, null); return !names.isEmpty(); } @@ -393,9 +428,9 @@ public class NamesService { // note // legacy - name exists but either parent does not exist (latest, not deleted, by uuid) - LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, "Is legacy name", "name", name)); + LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.IS_LEGACY_NAME, "name", name)); - List<Name> names = nameRepository.readNames(false, null, name, null, null, null, null, null); + List<Name> names = nameRepository.readNames(false, null, name, null, null, null, null, null, null); ExceptionUtil.validateConditionDataNotFoundException(ValidateUtil.isSize(names, 1), "name not found", name, null); Name toBeChecked = names.get(0); @@ -470,7 +505,7 @@ public class NamesService { // validation outside method // validate data - not exists - LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, "Is valid to create name", "name", name)); + LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.IS_VALID_TO_CREATE_NAME, "name", name)); // initiate holder of system and device structure content, for performance reasons // note false to not include deleted entries diff --git a/src/main/java/org/openepics/names/util/TextUtil.java b/src/main/java/org/openepics/names/util/TextUtil.java index 008fec0c59bcadb71b9a7453f22a02fc89a3848c..0280213333a61922d5afa7db84a506f276212f4a 100644 --- a/src/main/java/org/openepics/names/util/TextUtil.java +++ b/src/main/java/org/openepics/names/util/TextUtil.java @@ -133,18 +133,27 @@ public class TextUtil { public static final String ELEMENT_IN = "element (in)"; public static final String ELEMENT_OUT = "element (out)"; public static final String NOTIFICATION = "notification"; + public static final String PREPARE_NOTIFICATION = "Prepare notification"; + public static final String CREATE_NAME = "Create name"; public static final String UPDATE_NAME = "Update name"; public static final String DELETE_NAME = "Delete name"; + public static final String READ_NAMES = "Read names"; + public static final String READ_NAMES_SYSTEM_STRUCTURE = "Read names system structure"; + public static final String READ_NAMES_DEVICE_STRUCTURE = "Read names device structure"; + public static final String READ_NAMES_HISTORY = "Read names history"; + public static final String EQUIVALENCE_NAME = "Equivalence name"; + public static final String EXISTS_NAME = "Exists name"; + public static final String IS_LEGACY_NAME = "Is legacy name"; + public static final String IS_VALID_TO_CREATE_NAME = "Is valid to create name"; + public static final String CREATE_STRUCTURE = "Create structure"; public static final String UPDATE_STRUCTURE = "Update structure"; public static final String DELETE_STRUCTURE = "Delete structure"; public static final String APPROVE_STRUCTURE = "Approve structure"; public static final String CANCEL_STRUCTURE = "Cancel structure"; public static final String REJECT_STRUCTURE = "Reject structure"; - public static final String READ_NAMES = "Read names"; public static final String READ_STRUCTURES = "Read structures"; - public static final String PREPARE_NOTIFICATION = "Prepare notification"; /** * This class is not to be instantiated. diff --git a/src/main/java/org/openepics/names/util/ValidateNameElementUtil.java b/src/main/java/org/openepics/names/util/ValidateNameElementUtil.java index aa37d8bac7a735d5c5291990575973432c7d3c39..fb6da8304d5a88470aa71941d0e56c78d084aab0 100644 --- a/src/main/java/org/openepics/names/util/ValidateNameElementUtil.java +++ b/src/main/java/org/openepics/names/util/ValidateNameElementUtil.java @@ -72,6 +72,7 @@ public class ValidateNameElementUtil { * @param deviceStructure device structure mnemonic * @param index index * @param description description + * @param who, who * @param includeHistory include history * @param orderBy order by * @param isAsc is ascending @@ -79,7 +80,7 @@ public class ValidateNameElementUtil { * @param limit limit */ public static void validateNamesInputRead(Boolean deleted, - String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, + String uuid, String name, String nameEquivalence, String systemStructure, String deviceStructure, String index, String description, String who, Boolean includeHistory, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) { // validate input @@ -249,7 +250,7 @@ public class ValidateNameElementUtil { // update, delete - uuid available, not deleted // retrieve for uuid and check if (ValidateUtil.isAnyEqual(nameCommand, NameCommand.UPDATE, NameCommand.DELETE)) { - List<Name> names = nameRepository.readNames(false, uuid.toString(), null, null, null, null, null, null); + List<Name> names = nameRepository.readNames(false, uuid.toString(), null, null, null, null, null, null, null); ExceptionUtil.validateConditionDataNotFoundException(ValidateUtil.isSize(names, 1), TextUtil.DATA_IS_NOT_FOUND, details, TextUtil.UUID); } @@ -329,7 +330,7 @@ public class ValidateNameElementUtil { // name // ok with same name, name equivalence if same uuid - List<Name> names = nameRepository.readNames(false, null, derivedName, null, null, null, null, null); + List<Name> names = nameRepository.readNames(false, null, derivedName, null, null, null, null, null, null); if (NameCommand.CREATE.equals(nameCommand)) { condition = ValidateUtil.isNullOrEmpty(names); } else { @@ -339,7 +340,7 @@ public class ValidateNameElementUtil { ExceptionUtil.validateConditionDataConflictException(condition, TextUtil.CONVENTION_NAME_EXISTS, details, TextUtil.PARENTSYSTEMSTRUCTURE); - names = nameRepository.readNames(false, null, null, namingConvention.equivalenceClassRepresentative(derivedName), null, null, null, null); + names = nameRepository.readNames(false, null, null, namingConvention.equivalenceClassRepresentative(derivedName), null, null, null, null, null); if (NameCommand.CREATE.equals(nameCommand)) { condition = ValidateUtil.isNullOrEmpty(names); } else { @@ -468,11 +469,11 @@ public class ValidateNameElementUtil { ExceptionUtil.validateConditionDataNotCorrectException(StringUtils.equals(name, derivedName), TextUtil.CONVENTION_NAME_IS_NOT_CORRECT, details, field); - List<Name> names = holderRepositories.nameRepository().readNames(false, null, name, null, null, null, null, null); + List<Name> names = holderRepositories.nameRepository().readNames(false, null, name, null, null, null, null, null, null); ExceptionUtil.validateConditionDataConflictException(names.isEmpty(), TextUtil.CONVENTION_NAME_EXISTS, details, field); - names = holderRepositories.nameRepository().readNames(false, null, null, namingConvention.equivalenceClassRepresentative(name), null, null, null, null); + names = holderRepositories.nameRepository().readNames(false, null, null, namingConvention.equivalenceClassRepresentative(name), null, null, null, null, null); ExceptionUtil.validateConditionDataConflictException(names.isEmpty(), TextUtil.CONVENTION_NAME_EQUIVALENCE_EXISTS, details, field); } diff --git a/src/main/java/org/openepics/names/util/ValidateUtil.java b/src/main/java/org/openepics/names/util/ValidateUtil.java index 7094dcd97f0d7362cd3a3493332b5b24faf622d0..a49d1c3f1c701193c108924b1d46861f99ed6f8e 100644 --- a/src/main/java/org/openepics/names/util/ValidateUtil.java +++ b/src/main/java/org/openepics/names/util/ValidateUtil.java @@ -177,6 +177,11 @@ public class ValidateUtil { } } + public static void validateInputAvailable(boolean inputAvailable) { + ExceptionUtil.validateConditionInputNotAvailableException(inputAvailable, + TextUtil.VALUE_IS_NOT_AVAILABLE, null, null); + } + // ---------------------------------------------------------------------------------------------------- /** @@ -275,6 +280,25 @@ public class ValidateUtil { return false; } + /** + * Validate given objects such that <tt>true</tt> is returned if all objects are null. + * This may be used to validate that given objects are not null. + * + * @param values values + * @return boolean if validation is ok + */ + public static boolean areAllNull(Object... values) { + if (values == null) { + return true; + } + for (Object value : values) { + if (value != null) { + return false; + } + } + return true; + } + /** * Validate given enums such that <tt>true</tt> is returned if any enum in values is equal to given input enum. * diff --git a/src/main/resources/static/pdfs/naming_rest_api_brief_introduction.pdf b/src/main/resources/static/pdfs/naming_rest_api_brief_introduction.pdf index 04f08ee6b32ef01dd12888887e73e2e52a8cc47e..a57e2cddc350ad52c2edff95c7e9fca4b8b6d80a 100644 Binary files a/src/main/resources/static/pdfs/naming_rest_api_brief_introduction.pdf and b/src/main/resources/static/pdfs/naming_rest_api_brief_introduction.pdf differ diff --git a/src/main/resources/static/pdfs/naming_rest_api_migration.pdf b/src/main/resources/static/pdfs/naming_rest_api_migration.pdf index 74cde2c881182cfd7b0eab7f84ebf84ffd42dd11..a03af63e32af5099877147527b8461d414db1b1a 100644 Binary files a/src/main/resources/static/pdfs/naming_rest_api_migration.pdf and b/src/main/resources/static/pdfs/naming_rest_api_migration.pdf differ diff --git a/src/test/java/org/openepics/names/docker/NamesIT.java b/src/test/java/org/openepics/names/docker/NamesIT.java index dbd9fb2be13c9f99e8d21f50e89b5f0352a723bb..abfbd8e9622e4aa27b276b97c33e70245d924f43 100644 --- a/src/test/java/org/openepics/names/docker/NamesIT.java +++ b/src/test/java/org/openepics/names/docker/NamesIT.java @@ -1005,6 +1005,17 @@ class NamesIT { ITUtilNameElement.assertRead("?description=updated description%", 1, -1); ITUtilNameElement.assertRead("?description=updated description again", 1); + ITUtilNameElement.assertRead("?who=test who", 8, -1); + ITUtilNameElement.assertRead("?who=test", 0); + ITUtilNameElement.assertRead("?who=who", 0); + ITUtilNameElement.assertRead("?who=test%", 8, -1); + ITUtilNameElement.assertRead("?who=%who", 8, -1); + ITUtilNameElement.assertRead("?who=%est%", 8, -1); + ITUtilNameElement.assertRead("?who=%wh%", 8, -1); + ITUtilNameElement.assertRead("?who=wh%", 0); + ITUtilNameElement.assertRead("?who=asdf", 0); + ITUtilNameElement.assertRead("?who=%asdf%", 0); + ITUtilNameElement.assertRead("?nameEquivalence=RFQ-10%&deviceStructure=EMR-FS", 6, -1); // name or uuid @@ -1045,6 +1056,20 @@ class NamesIT { ITUtilNameElement.assertRead("/history/" + deviceTypeFS.toString(), 0); ITUtilNameElement.assertRead("/history/" + uuid.toString(), 3); ITUtilNameElement.assertRead("/history/" + uuid2.toString(), 1); + + // /history?parameter=value + // parameter must be available + ITUtilNameElement.assertRead("/history?uuid=" + uuid.toString(), 3); + ITUtilNameElement.assertRead("/history?uuid=" + uuid2.toString(), 1); + ITUtilNameElement.assertRead("/history?name=%010%", 14, -1); + ITUtilNameElement.assertRead("/history?nameEquivalence=RFQ-10%", 14, -1); + ITUtilNameElement.assertRead("/history?systemStructure=RFQ-0__", 13, -1); + ITUtilNameElement.assertRead("/history?deviceStructure=EMR-FS", 12, -1); + ITUtilNameElement.assertRead("/history?index=003", 1, -1); + ITUtilNameElement.assertRead("/history?description=updated description%", 3, -1); + ITUtilNameElement.assertRead("/history?who=test%", 8, -1); + + ITUtilNameElement.assertRead("/history?uuid=" + uuid.toString() + "&description=updated%", 3); } catch (Exception e) { fail(); } diff --git a/src/test/java/org/openepics/names/util/ValidateUtilTest.java b/src/test/java/org/openepics/names/util/ValidateUtilTest.java index 00fab6391f6a0248774df52f41549af81a168ef1..82822acbe9cb962d1c8b9bdc2d3f8e9b1580ca12 100644 --- a/src/test/java/org/openepics/names/util/ValidateUtilTest.java +++ b/src/test/java/org/openepics/names/util/ValidateUtilTest.java @@ -553,6 +553,39 @@ class ValidateUtilTest { assertEquals(expected, ValidateUtil.isAnyNull(s, i, f)); } + /** + * Test of validate an array if all objects in array are null. + */ + @Test + void areAllNull() { + String s = null; + Calendar c = null; + + assertTrue (ValidateUtil.areAllNull(s)); + assertTrue (ValidateUtil.areAllNull(c)); + assertTrue (ValidateUtil.areAllNull(s, c)); + + s = "a"; + + assertFalse(ValidateUtil.areAllNull(s)); + assertTrue (ValidateUtil.areAllNull(c)); + assertFalse(ValidateUtil.areAllNull(s, c)); + + s = null; + c = Calendar.getInstance(); + + assertTrue (ValidateUtil.areAllNull(s)); + assertFalse(ValidateUtil.areAllNull(c)); + assertFalse(ValidateUtil.areAllNull(s, c)); + + s = "a"; + c = Calendar.getInstance(); + + assertFalse(ValidateUtil.areAllNull(s)); + assertFalse(ValidateUtil.areAllNull(c)); + assertFalse(ValidateUtil.areAllNull(s, c)); + } + /** * Test to validate an array if any object is equal to given enum. */ @@ -636,7 +669,7 @@ 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, null, null); }