• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmrs / openmrs-core / 16357938490

17 Jul 2025 11:06PM UTC coverage: 65.244% (-0.1%) from 65.359%
16357938490

push

github

web-flow
TRUNK-6318: Add S3 Storage Service (#5110)

111 of 156 new or added lines in 5 files covered. (71.15%)

48 existing lines in 8 files now uncovered.

23568 of 36123 relevant lines covered (65.24%)

0.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.95
/api/src/main/java/org/openmrs/api/db/hibernate/HibernateProviderDAO.java
1
/**
2
 * This Source Code Form is subject to the terms of the Mozilla Public License,
3
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
4
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6
 *
7
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8
 * graphic logo is a trademark of OpenMRS Inc.
9
 */
10
package org.openmrs.api.db.hibernate;
11

12
import java.util.ArrayList;
13
import java.util.Collection;
14
import java.util.List;
15
import java.util.Map;
16

17
import javax.persistence.TypedQuery;
18
import javax.persistence.criteria.CriteriaBuilder;
19
import javax.persistence.criteria.CriteriaQuery;
20
import javax.persistence.criteria.Join;
21
import javax.persistence.criteria.JoinType;
22
import javax.persistence.criteria.Order;
23
import javax.persistence.criteria.Predicate;
24
import javax.persistence.criteria.Root;
25

26
import org.apache.commons.collections.CollectionUtils;
27
import org.apache.commons.lang3.StringUtils;
28
import org.hibernate.Session;
29
import org.hibernate.SessionFactory;
30
import org.openmrs.Person;
31
import org.openmrs.PersonName;
32
import org.openmrs.Provider;
33
import org.openmrs.ProviderAttribute;
34
import org.openmrs.ProviderAttributeType;
35
import org.openmrs.ProviderRole;
36
import org.openmrs.api.context.Context;
37
import org.openmrs.api.db.ProviderDAO;
38
import org.openmrs.util.OpenmrsConstants;
39

40
/**
41
 * Hibernate specific Provider related functions. This class should not be used directly. All calls
42
 * should go through the {@link org.openmrs.api.ProviderService} methods.
43
 *
44
 * @since 1.9
45
 */
46
public class HibernateProviderDAO implements ProviderDAO {
1✔
47
        
48
        private SessionFactory sessionFactory;
49
        
50
        public void setSessionFactory(SessionFactory sessionFactory) {
51
                this.sessionFactory = sessionFactory;
1✔
52
        }
1✔
53
        
54
        /**
55
         * @see org.openmrs.api.db.ProviderDAO#getAllProviders(boolean)
56
         */
57
        @Override
58
        public List<Provider> getAllProviders(boolean includeRetired) {
59
                return getAll(includeRetired, Provider.class);
1✔
60
        }
61
        
62
        private Session getSession() {
63
                return sessionFactory.getCurrentSession();
1✔
64
        }
65
        
66
        /**
67
         * @see org.openmrs.api.db.ProviderDAO#saveProvider(org.openmrs.Provider)
68
         */
69
        @Override
70
        public Provider saveProvider(Provider provider) {
71
                getSession().saveOrUpdate(provider);
1✔
72
                return provider;
1✔
73
        }
74
        
75
        /**
76
         * @see org.openmrs.api.db.ProviderDAO#deleteProvider(org.openmrs.Provider)
77
         */
78
        @Override
79
        public void deleteProvider(Provider provider) {
80
                getSession().delete(provider);
1✔
81
        }
1✔
82
        
83
        /**
84
         * @see org.openmrs.api.db.ProviderDAO#getProvider(java.lang.Integer)
85
         */
86
        @Override
87
        public Provider getProvider(Integer id) {
88
                return getSession().get(Provider.class, id);
1✔
89
        }
90
        
91
        /**
92
         * @see org.openmrs.api.db.ProviderDAO#getProviderByUuid(java.lang.String)
93
         */
94
        @Override
95
        public Provider getProviderByUuid(String uuid) {
96
                return getByUuid(uuid, Provider.class);
1✔
97
        }
98
        
99
        /**
100
         * @see org.openmrs.api.db.ProviderDAO#getProvidersByPerson(org.openmrs.Person, boolean)
101
         */
102
        @Override
103
        public Collection<Provider> getProvidersByPerson(Person person, boolean includeRetired) {
104
                Session session = sessionFactory.getCurrentSession();
1✔
105
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
106
                CriteriaQuery<Provider> cq = cb.createQuery(Provider.class);
1✔
107
                Root<Provider> root = cq.from(Provider.class);
1✔
108

109
                List<Predicate> predicates = new ArrayList<>();
1✔
110
                List<Order> orders = new ArrayList<>();
1✔
111

112
                if (!includeRetired) {
1✔
113
                        predicates.add(cb.isFalse(root.get("retired")));
1✔
114
                } else {
115
                        //push retired Provider to the end of the returned list
116
                        orders.add(cb.asc(root.get("retired")));
1✔
117
                }
118
                predicates.add(cb.equal(root.get("person"), person));
1✔
119
                
120
                orders.add(cb.asc(root.get("providerId")));
1✔
121
                
122
                cq.where(predicates.toArray(new Predicate[]{})).orderBy(orders);
1✔
123
                return session.createQuery(cq).getResultList();
1✔
124
        }
125

126
        /**
127
         * @see org.openmrs.api.db.ProviderDAO#getProviderAttribute(Integer)
128
         */
129
        @Override
130
        public ProviderAttribute getProviderAttribute(Integer providerAttributeID) {
131
                return getSession().get(ProviderAttribute.class, providerAttributeID);
1✔
132
        }
133
        
134
        /**
135
         * @see org.openmrs.api.db.ProviderDAO#getProviderAttributeByUuid(String)
136
         */
137
        
138
        @Override
139
        public ProviderAttribute getProviderAttributeByUuid(String uuid) {
140
                return getByUuid(uuid, ProviderAttribute.class);
1✔
141
        }
142
        
143
        /**
144
         * @see org.openmrs.api.db.ProviderDAO#getProviders(String, Map, Integer, Integer, boolean)
145
         */
146
        @Override
147
        public List<Provider> getProviders(String name, Map<ProviderAttributeType, String> serializedAttributeValues,
148
                Integer start, Integer length, boolean includeRetired) {
149
                Session session = sessionFactory.getCurrentSession();
1✔
150
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
151
                CriteriaQuery<Provider> cq = cb.createQuery(Provider.class);
1✔
152
                Root<Provider> root = cq.from(Provider.class);
1✔
153

154
                List<Predicate> predicates = prepareProviderCriteria(cb, root, name, includeRetired);
1✔
155
                cq.where(predicates.toArray(new Predicate[]{})).distinct(true);
1✔
156
                
157
                if (includeRetired) {
1✔
158
                        //push retired Provider to the end of the returned list
159
                        cq.orderBy(cb.asc(root.get("retired")));
1✔
160
                }
161
                
162
                TypedQuery<Provider> typedQuery = session.createQuery(cq);
1✔
163
                if (start != null) {
1✔
164
                        typedQuery.setFirstResult(start);
1✔
165
                }
166
                if (length != null) {
1✔
UNCOV
167
                        typedQuery.setMaxResults(length);
×
168
                }
169
                
170
                List<Provider> providers = typedQuery.getResultList();
1✔
171
                if (serializedAttributeValues != null) {
1✔
172
                        CollectionUtils.filter(providers, new AttributeMatcherPredicate<Provider, ProviderAttributeType>(
1✔
173
                                serializedAttributeValues));
174
                }
175
                return providers;
1✔
176
        }
177
        
178
        private MatchMode getMatchMode() {
179
                String matchMode = Context.getAdministrationService().getGlobalProperty(
1✔
180
                    OpenmrsConstants.GLOBAL_PROPERTY_PROVIDER_SEARCH_MATCH_MODE);
181
                
182
                if (MatchMode.START.toString().equalsIgnoreCase(matchMode)) {
1✔
UNCOV
183
                        return MatchMode.START;
×
184
                }
185
                if (MatchMode.ANYWHERE.toString().equalsIgnoreCase(matchMode)) {
1✔
UNCOV
186
                        return MatchMode.ANYWHERE;
×
187
                }
188
                if (MatchMode.END.toString().equalsIgnoreCase(matchMode)) {
1✔
UNCOV
189
                        return MatchMode.END;
×
190
                }
191
                return MatchMode.EXACT;
1✔
192
        }
193

194
        /**
195
         * Prepares a list of JPA predicates for searching Provider entities based on a specified name
196
         * and retirement status.
197
         *
198
         * @param cb The CriteriaBuilder used for creating predicates.
199
         * @param root The root entity (Provider) in the CriteriaQuery.
200
         * @param name The provider's name or a part of it to be used in the search. If blank, it defaults to a wildcard search.
201
         * @param includeRetired Boolean flag indicating whether to include retired providers in the search.
202
         * @return List<Predicate> A list of predicates that can be added to a CriteriaQuery for filtering Provider entities.
203
         */
204
        private List<Predicate> prepareProviderCriteria(CriteriaBuilder cb, Root<Provider> root, String name, boolean includeRetired) {
205
                if (StringUtils.isBlank(name)) {
1✔
206
                        name = "%";
1✔
207
                }
208

209
                List<Predicate> predicates = new ArrayList<>();
1✔
210
                if (!includeRetired) {
1✔
211
                        predicates.add(cb.isFalse(root.get("retired")));
1✔
212
                }
213

214
                Predicate orCondition = cb.or(
1✔
215
                        cb.like(cb.lower(root.get("identifier")), getMatchMode().toLowerCasePattern(name)),
1✔
216
                        cb.like(cb.lower(root.get("name")), MatchMode.ANYWHERE.toLowerCasePattern(name))
1✔
217
                );
218

219
                Join<Provider, Person> personJoin = root.join("person", JoinType.LEFT);
1✔
220
                Join<Person, PersonName> personNameJoin = personJoin.join("names", JoinType.LEFT);
1✔
221

222
                List<Predicate> splitNamePredicates = new ArrayList<>();
1✔
223
                String[] splitNames = name.split(" ");
1✔
224
                
225
                for (String splitName : splitNames) {
1✔
226
                        splitNamePredicates.add(getNameSearchExpression(splitName, cb, personNameJoin));
1✔
227
                }
228
                Predicate andCondition = cb.and(splitNamePredicates.toArray(new Predicate[]{}));
1✔
229

230
                predicates.add(cb.or(orCondition, andCondition));
1✔
231
                
232
                return predicates;
1✔
233
        }
234
        
235
        /**
236
         * Creates or that matches the input name with Provider-Person-Names (not voided)
237
         *
238
         * @param name The name string to be matched against the PersonName fields.
239
         * @param cb The CriteriaBuilder used for creating the CriteriaQuery predicates.
240
         * @param personNameJoin The join to the PersonName entity, allowing access to its fields.
241
         * @return Predicate The compound predicate representing the desired search conditions.
242
         */
243
        private Predicate getNameSearchExpression(String name, CriteriaBuilder cb, Join<Person, PersonName> personNameJoin) {
244
                MatchMode mode = MatchMode.ANYWHERE;
1✔
245

246
                Predicate voidedPredicate = cb.isFalse(personNameJoin.get("voided"));
1✔
247

248
                Predicate givenNamePredicate = cb.like(cb.lower(personNameJoin.get("givenName")), mode.toLowerCasePattern(name));
1✔
249
                Predicate middleNamePredicate = cb.like(cb.lower(personNameJoin.get("middleName")), mode.toLowerCasePattern(name));
1✔
250
                Predicate familyNamePredicate = cb.like(cb.lower(personNameJoin.get("familyName")), mode.toLowerCasePattern(name));
1✔
251
                Predicate familyName2Predicate = cb.like(cb.lower(personNameJoin.get("familyName2")), mode.toLowerCasePattern(name));
1✔
252

253
                Predicate orPredicate = cb.or(givenNamePredicate, middleNamePredicate, familyNamePredicate, familyName2Predicate);
1✔
254

255
                return cb.and(voidedPredicate, orPredicate);
1✔
256
        }
257

258
        /**
259
         * @see org.openmrs.api.db.ProviderDAO#getCountOfProviders(String, boolean)
260
         */
261
        @Override
262
        public Long getCountOfProviders(String name, boolean includeRetired) {
263
                Session session = sessionFactory.getCurrentSession();
1✔
264
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
265
                CriteriaQuery<Long> cq = cb.createQuery(Long.class);
1✔
266
                Root<Provider> root = cq.from(Provider.class);
1✔
267

268
                List<Predicate> predicates = prepareProviderCriteria(cb, root, name, includeRetired);
1✔
269

270
                cq.select(cb.countDistinct(root)).where(predicates.toArray(new Predicate[]{}));
1✔
271

272
                return session.createQuery(cq).getSingleResult();
1✔
273
        }
274

275

276
        /* (non-Javadoc)
277
         * @see org.openmrs.api.db.ProviderDAO#getAllProviderAttributeTypes(boolean)
278
         */
279
        @Override
280
        public List<ProviderAttributeType> getAllProviderAttributeTypes(boolean includeRetired) {
281
                return getAll(includeRetired, ProviderAttributeType.class);
1✔
282
        }
283

284
        private <T> List<T> getAll(boolean includeRetired, Class<T> clazz) {
285
                Session session = sessionFactory.getCurrentSession();
1✔
286
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
287
                CriteriaQuery<T> cq = cb.createQuery(clazz);
1✔
288
                Root<T> root = cq.from(clazz);
1✔
289

290
                List<Order> orderList = new ArrayList<>();
1✔
291
                if (!includeRetired) {
1✔
292
                        cq.where(cb.isFalse(root.get("retired")));
1✔
293
                } else {
294
                        //push retired Provider to the end of the returned list
295
                        orderList.add(cb.asc(root.get("retired")));
1✔
296
                }
297
                orderList.add(cb.asc(root.get("name")));
1✔
298
                cq.orderBy(orderList);
1✔
299

300
                return session.createQuery(cq).getResultList();
1✔
301
        }
302
        
303
        private <T> T getByUuid(String uuid, Class<T> clazz) {
304
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, clazz, uuid);
1✔
305
        }
306
        
307
        /* (non-Javadoc)
308
         * @see org.openmrs.api.db.ProviderDAO#getProviderAttributeType(java.lang.Integer)
309
         */
310
        @Override
311
        public ProviderAttributeType getProviderAttributeType(Integer providerAttributeTypeId) {
312
                return getSession().get(ProviderAttributeType.class, providerAttributeTypeId);
1✔
313
        }
314
        
315
        /* (non-Javadoc)
316
         * @see org.openmrs.api.db.ProviderDAO#getProviderAttributeTypeByUuid(java.lang.String)
317
         */
318
        @Override
319
        public ProviderAttributeType getProviderAttributeTypeByUuid(String uuid) {
320
                return getByUuid(uuid, ProviderAttributeType.class);
1✔
321
        }
322
        
323
        /* (non-Javadoc)
324
         * @see org.openmrs.api.db.ProviderDAO#getProviderAttributeTypeByName(java.lang.String)
325
         */
326
        @Override
327
        public ProviderAttributeType getProviderAttributeTypeByName(String name) {
328
                Session session = sessionFactory.getCurrentSession();
1✔
329
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
330
                CriteriaQuery<ProviderAttributeType> cq = cb.createQuery(ProviderAttributeType.class);
1✔
331
                Root<ProviderAttributeType> root = cq.from(ProviderAttributeType.class);
1✔
332

333
                cq.where(cb.isFalse(root.get("retired")),
1✔
334
                                 cb.equal(root.get("name"), name));
1✔
335

336
                List<ProviderAttributeType> list = session.createQuery(cq).getResultList();
1✔
337

338
                if (list.isEmpty()) {
1✔
339
                        return null;
1✔
340
                }
341
                return list.get(0);
1✔
342
        }
343
        
344
        /* (non-Javadoc)
345
         * @see org.openmrs.api.db.ProviderDAO#saveProviderAttributeType(org.openmrs.ProviderAttributeType)
346
         */
347
        @Override
348
        public ProviderAttributeType saveProviderAttributeType(ProviderAttributeType providerAttributeType) {
349
                getSession().saveOrUpdate(providerAttributeType);
1✔
350
                return providerAttributeType;
1✔
351
        }
352
        
353
        /* (non-Javadoc)
354
         * @see org.openmrs.api.db.ProviderDAO#deleteProviderAttributeType(org.openmrs.ProviderAttributeType)
355
         */
356
        @Override
357
        public void deleteProviderAttributeType(ProviderAttributeType providerAttributeType) {
358
                getSession().delete(providerAttributeType);
1✔
359
        }
1✔
360
        
361
        /**
362
         * @see org.openmrs.api.db.ProviderDAO#getProviderByIdentifier(java.lang.String)
363
         */
364
        @Override
365
        public boolean isProviderIdentifierUnique(Provider provider) {
366
                Session session = sessionFactory.getCurrentSession();
1✔
367
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
368
                CriteriaQuery<Long> cq = cb.createQuery(Long.class);
1✔
369
                Root<Provider> root = cq.from(Provider.class);
1✔
370

371
                List<Predicate> predicates = new ArrayList<>();
1✔
372
                predicates.add(cb.equal(root.get("identifier"), provider.getIdentifier()));
1✔
373
                if (provider.getProviderId() != null) {
1✔
374
                        predicates.add(cb.notEqual(root.get("providerId"), provider.getProviderId()));
1✔
375
                }
376

377
                cq.select(cb.countDistinct(root.get("providerId")))
1✔
378
                        .where(predicates.toArray(new Predicate[]{}));
1✔
379

380
                return session.createQuery(cq).uniqueResult() == 0L;
1✔
381
        }
382
        
383
        /**
384
         * @see org.openmrs.api.db.ProviderDAO#getProviderByIdentifier(java.lang.String)
385
         */
386
        @Override
387
        public Provider getProviderByIdentifier(String identifier) {
388
                Session session = sessionFactory.getCurrentSession();
1✔
389
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
390
                CriteriaQuery<Provider> cq = cb.createQuery(Provider.class);
1✔
391
                Root<Provider> root = cq.from(Provider.class);
1✔
392
                
393
                cq.where(cb.equal(cb.lower(root.get("identifier")), MatchMode.EXACT.toLowerCasePattern(identifier)));
1✔
394

395
                return session.createQuery(cq).uniqueResult();
1✔
396
        }
397

398
        /**
399
         * @see org.openmrs.api.db.ProviderDAO#getProviderRole(Integer) 
400
         */
401
        @Override
402
        public ProviderRole getProviderRole(Integer providerRoleId) {
403
                return sessionFactory.getCurrentSession().get(ProviderRole.class, providerRoleId);
1✔
404
        }
405

406
        /**
407
         * @see org.openmrs.api.db.ProviderDAO#getProviderRoleByUuid(String)
408
         */
409
        @Override
410
        public ProviderRole getProviderRoleByUuid(String uuid) {
411
                return getByUuid(uuid, ProviderRole.class);
1✔
412
        }
413

414
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc