diff --git a/api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/BaseFhirDao.java b/api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/BaseFhirDao.java index e85158607..daee3719d 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/BaseFhirDao.java +++ b/api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/BaseFhirDao.java @@ -172,19 +172,8 @@ public List getSearchResults(@Nonnull SearchParameterMap theParams) { OpenmrsFhirCriteriaContext criteriaContext = getSearchResultCriteria(theParams); handleSort(criteriaContext, theParams.getSortSpec()); - - String person = getIdPropertyName(Person.class); - String encounter = getIdPropertyName(Encounter.class); - String obs = getIdPropertyName(Obs.class); + handleIdPropertyOrdering(criteriaContext, getIdPropertyName((Class) typeToken.getRawType())); - if (Person.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyOrdering(criteriaContext, person); - } else if (Encounter.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyOrdering(criteriaContext, encounter); - } else if (Obs.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyOrdering(criteriaContext, obs); - } - criteriaContext.getEntityManager().createQuery(criteriaContext.getCriteriaQuery()) .setFirstResult(theParams.getFromIndex()); if (theParams.getToIndex() != Integer.MAX_VALUE) { @@ -202,55 +191,26 @@ public List getSearchResults(@Nonnull SearchParameterMap theParams) { Root root = (Root) criteriaQuery.from(typeToken.getRawType()); List> selectionList = new ArrayList<>(); - if (Person.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertySelection(selectionList, root, criteriaBuilder, person); - } else if (Encounter.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertySelection(selectionList, root, criteriaBuilder, encounter); - } else if (Obs.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertySelection(selectionList, root, criteriaBuilder, obs); - } - - criteriaQuery.multiselect(selectionList); + handleIdPropertySelection(selectionList, criteriaQuery, root, criteriaBuilder, getIdPropertyName((Class) typeToken.getRawType())); handleSort(criteriaContext, theParams.getSortSpec(), this::paramToProps).ifPresent( orders -> orders.forEach(order -> selectionList.add(root.get(getPropertyName(order.getExpression()))))); - List ids = new ArrayList<>(); + List ids = new ArrayList<>(); if (selectionList.size() > 1) { for (Object[] o : em.createQuery(criteriaQuery).getResultList()) { - ids.add((T) o[0]); + ids.add((Integer) o[0]); } } else { - EntityManager manager = sessionFactory.getCurrentSession(); - CriteriaBuilder builder = manager.getCriteriaBuilder(); - CriteriaQuery cq = (CriteriaQuery) builder.createQuery(typeToken.getRawType()); - Root rt = (Root) cq.from(typeToken.getRawType()); - cq.select(rt); - ids = manager.createQuery(cq).getResultList(); + return new ArrayList<>(criteriaContext.getEntityManager().createQuery(criteriaContext.getCriteriaQuery()).getResultList()); } CriteriaQuery idsCriteriaQuery = (CriteriaQuery) criteriaBuilder.createQuery(typeToken.getRawType()); Root idsRoot = (Root) idsCriteriaQuery.from(typeToken.getRawType()); - - if (Person.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyInCondition(idsCriteriaQuery, idsRoot, ids, person); - } else if (Encounter.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyInCondition(idsCriteriaQuery, idsRoot, ids, encounter); - } else if (Obs.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyInCondition(idsCriteriaQuery, idsRoot, ids, obs); - } - + handleIdPropertyInCondition(idsCriteriaQuery, idsRoot, ids, getIdPropertyName((Class) typeToken.getRawType())); results = em.createQuery(idsCriteriaQuery).getResultList(); // Need to reapply ordering handleSort(criteriaContext, theParams.getSortSpec()); - - if (Person.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyOrdering(criteriaBuilder,idsCriteriaQuery, idsRoot, person); - } else if (Encounter.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyOrdering(criteriaBuilder,idsCriteriaQuery, idsRoot, encounter); - } else if (Obs.class.isAssignableFrom(BaseOpenmrsObject.class)) { - handleIdPropertyOrdering(criteriaBuilder, idsCriteriaQuery, idsRoot,obs); - } - + handleIdPropertyOrdering(criteriaBuilder,idsCriteriaQuery, idsRoot, getIdPropertyName((Class) typeToken.getRawType())); results = criteriaContext.getEntityManager().createQuery(criteriaContext.getCriteriaQuery()).getResultList(); } return results.stream().map(this::deproxyResult).collect(Collectors.toList()); @@ -430,6 +390,20 @@ protected void applyExactTotal(OpenmrsFhirCriteriaContext criteriaContext, Se } } + /** + * Retrieves the path for the attribute ending with "Id" from the given root. + * + * @param root The root of the JPA criteria query representing the entity. + * @param idPropertyName The name of the property ending with "Id" for which to retrieve the path. + * @return The path representing the attribute ending with "Id," or null if not found. + */ + private Path getIdPath(Root root, String idPropertyName) { + if (idPropertyName.endsWith("Id")) { + return root.get(idPropertyName); + } + return null; + } + /** * Extracts the property name from the given JPA Criteria API expression. * @@ -453,7 +427,12 @@ public static String getPropertyName(Expression expression) { * @param idPropertyName The name of the id property to be used for ordering. */ private void handleIdPropertyOrdering(OpenmrsFhirCriteriaContext criteriaContext, String idPropertyName) { - criteriaContext.getCriteriaQuery().orderBy(criteriaContext.getCriteriaBuilder().asc(criteriaContext.getRoot().get(idPropertyName))); + Path idPath = getIdPath(criteriaContext.getRoot(), idPropertyName); + if (idPath != null) { + criteriaContext.getCriteriaQuery().orderBy(criteriaContext.getCriteriaBuilder().asc(idPath)); + } else { + throw new IllegalArgumentException("No field ending with 'Id' found in entity"); + } } /** @@ -465,20 +444,33 @@ private void handleIdPropertyOrdering(OpenmrsFhirCriteriaContext criteriaCont * @param idPropertyName The name of the id property to be used for ordering. */ private void handleIdPropertyOrdering(CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, Root idsRoot, String idPropertyName) { - criteriaQuery.orderBy(criteriaBuilder.asc(idsRoot.get(idPropertyName))); + Path idPath = getIdPath(idsRoot, idPropertyName); + if (idPath != null) { + criteriaQuery.orderBy(criteriaBuilder.asc(idsRoot.get(idPropertyName))); + } else { + throw new IllegalArgumentException("No field ending with 'Id' found in entity"); + } } /** * Handles the selection list based on the specified id property name, adding both the property and its distinct count. * * @param selectionList The list of selections to be populated. + * @param criteriaQuery The criteria query * @param root The root of the criteria query. * @param criteriaBuilder The criteria builder to build selection expressions. * @param idPropertyName The name of the id property to be used for selection. */ - private void handleIdPropertySelection(List> selectionList, Root root, CriteriaBuilder criteriaBuilder, String idPropertyName) { - selectionList.add(root.get(idPropertyName)); - selectionList.add(criteriaBuilder.countDistinct(root.get(idPropertyName))); + private void handleIdPropertySelection(List> selectionList, CriteriaQuery criteriaQuery, Root root, CriteriaBuilder criteriaBuilder, String idPropertyName) { + Path idPath = getIdPath(root, idPropertyName); + if (idPath != null) { + selectionList.add(root.get(idPropertyName)); + selectionList.add(criteriaBuilder.countDistinct(root.get(idPropertyName))); + criteriaQuery.groupBy(root.get(idPropertyName)); + criteriaQuery.multiselect(selectionList); + } else { + throw new IllegalArgumentException("No field ending with 'Id' found in entity"); + } } /** @@ -489,8 +481,14 @@ private void handleIdPropertySelection(List> selectionList, Root * @param ids The list of ids to be used in the "IN" condition. * @param idPropertyName The name of the id property to be used in the "IN" condition. */ - private void handleIdPropertyInCondition(CriteriaQuery idsCriteriaQuery, Root idsRoot, List ids, String idPropertyName) { - idsCriteriaQuery.where(idsRoot.get(idPropertyName).in(ids)); + private void handleIdPropertyInCondition(CriteriaQuery idsCriteriaQuery, Root idsRoot, List ids, String idPropertyName) { + Path idPath = getIdPath(idsRoot, idPropertyName); + if (idPath != null) { + idsCriteriaQuery.where(idsRoot.get(idPropertyName).in(ids)); +// criteriaContext.addPredicate(criteriaContext.getRoot().get("uuid").in(uuids)); + } else { + throw new IllegalArgumentException("No field ending with 'Id' found in entity"); + } } /**