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

openmrs / openmrs-core / 29592249542

17 Jul 2026 02:16PM UTC coverage: 66.061% (+0.09%) from 65.967%
29592249542

push

github

ibacher
TRUNK-6688: Follow-up: run Mockito's inline MockMaker on older JVMs

24319 of 36813 relevant lines covered (66.06%)

0.66 hits per line

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

96.3
/api/src/main/java/org/openmrs/api/db/hibernate/HibernatePersonDAO.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 javax.persistence.criteria.CriteriaBuilder;
13
import javax.persistence.criteria.CriteriaQuery;
14
import javax.persistence.criteria.Expression;
15
import javax.persistence.criteria.Predicate;
16
import javax.persistence.criteria.Root;
17
import java.util.ArrayList;
18
import java.util.Date;
19
import java.util.LinkedHashSet;
20
import java.util.List;
21
import java.util.Set;
22

23
import org.apache.commons.lang3.StringUtils;
24
import org.hibernate.SQLQuery;
25
import org.hibernate.Session;
26
import org.hibernate.SessionFactory;
27
import org.openmrs.Person;
28
import org.openmrs.PersonAddress;
29
import org.openmrs.PersonAttribute;
30
import org.openmrs.PersonAttributeType;
31
import org.openmrs.PersonName;
32
import org.openmrs.Relationship;
33
import org.openmrs.RelationshipType;
34
import org.openmrs.api.db.DAOException;
35
import org.openmrs.api.db.PersonDAO;
36
import org.openmrs.api.db.hibernate.search.SearchQueryUnique;
37
import org.openmrs.api.db.hibernate.search.session.SearchSessionFactory;
38
import org.openmrs.person.PersonMergeLog;
39
import org.openmrs.util.ConfigUtil;
40
import org.openmrs.util.OpenmrsConstants;
41
import org.slf4j.Logger;
42
import org.slf4j.LoggerFactory;
43

44
/**
45
 * Hibernate specific Person database methods. <br>
46
 * <br>
47
 * This class should not be used directly. All database calls should go through the Service layer. <br>
48
 * <br>
49
 * Proper use: <code>
50
 *   PersonService ps = Context.getPersonService();
51
 *   ps.getPeople("name", false);
52
 * </code>
53
 * @see org.openmrs.api.db.PersonDAO
54
 * @see org.openmrs.api.PersonService
55
 * @see org.openmrs.api.context.Context
56
 */
57
public class HibernatePersonDAO implements PersonDAO {
1✔
58
        
59
        private static final Logger log = LoggerFactory.getLogger(HibernatePersonDAO.class);
1✔
60
        
61
        /**
62
         * Hibernate session factory
63
         */
64
        private SessionFactory sessionFactory;
65
        
66
        private SearchSessionFactory searchSessionFactory;
67
        
68
        /**
69
         * Set session factory
70
         * 
71
         * @param sessionFactory
72
         */
73
        public void setSessionFactory(SessionFactory sessionFactory) {
74
                this.sessionFactory = sessionFactory;
1✔
75
        }
1✔
76

77
        public void setSearchSessionFactory(SearchSessionFactory searchSessionFactory) {
78
                this.searchSessionFactory = searchSessionFactory;
1✔
79
        }
1✔
80

81
        /**
82
         * This method executes a Lucene search on persons based on the soundex filter with one search name given
83
         * 
84
         * @param name a person should match using soundex representation
85
         * @param birthyear the birthyear the searched person should have 
86
         * @param includeVoided true if voided person should be included 
87
         * @param gender of the person to search for 
88
         * @return the set of Persons that match the search criteria 
89
         */
90
        private Set<Person> executeSoundexOnePersonNameQuery(String name, Integer birthyear, boolean includeVoided , String gender) {
91
                PersonQuery personQuery = new PersonQuery();
1✔
92

93
                List<Person> results = SearchQueryUnique.search(searchSessionFactory, SearchQueryUnique.newQuery(PersonName.class,
1✔
94
                                f -> personQuery.getSoundexPersonNameQuery(f, name, birthyear, includeVoided,
1✔
95
                                        gender), "person.personId", PersonName::getPerson), null,
96
                        HibernatePersonDAO.getMaximumSearchResults());
1✔
97
                
98
                return new LinkedHashSet<>(results);
1✔
99
        }
100
        
101
        
102
        /**
103
         * This method executes a Lucene search on persons based on the soundex filter with three name elements given
104
         *
105
         * @param name1 basically represents the first name to be searched for in a person name
106
         * @param name2 basically represents the middle name to be searched for in a person name         
107
         * @param name3 basically represents the family name to be searched for in a person name
108
         * @param birthyear the birthyear the searched person should have 
109
         * @param includeVoided true if voided person should be included 
110
         * @param gender of the person to search for 
111
         * @return the set of Persons that match the search criteria 
112
         */
113
        private Set<Person> executeSoundexThreePersonNamesQuery(String name1, String name2, String name3, Integer birthyear, 
114
                                                                                                                        boolean includeVoided , String gender) {
115
                PersonQuery personQuery = new PersonQuery();
1✔
116

117
                List<Person> results = SearchQueryUnique.search(searchSessionFactory, SearchQueryUnique.newQuery(PersonName.class,
1✔
118
                                f -> personQuery.getSoundexPersonNameSearchOnThreeNames(f, name1, name2, name3,
1✔
119
                                        birthyear, includeVoided, gender), "person.personId",  PersonName::getPerson),
120
                        null, HibernatePersonDAO.getMaximumSearchResults());
1✔
121
                
122
                return new LinkedHashSet<>(results);
1✔
123
        }
124
        
125
        /**
126
         * This method executes a Lucene search on persons based on the soundex filter with two search names given
127
         *
128
         * @param searchName1 the first entered name by the user to be searched for
129
         * @param searchName2 the second entered name by the user to be searched  for
130
         * @param birthyear the birthyear the searched person should have 
131
         * @param includeVoided true if voided person should be included 
132
         * @param gender of the person to search for 
133
         * @return the set of Persons that match the search criteria
134
         */
135
        private Set<Person> executeSoundexTwoPersonNamesQuery(String searchName1, String searchName2, Integer birthyear, 
136
                                                                                                                  boolean includeVoided , String gender) {
137
                PersonQuery personQuery = new PersonQuery();
1✔
138

139
                List<Person> results = SearchQueryUnique.search(searchSessionFactory, SearchQueryUnique.newQuery(PersonName.class,
1✔
140
                                f -> personQuery.getSoundexPersonNameSearchOnTwoNames(f, searchName1, searchName2,
1✔
141
                                        birthyear, includeVoided, gender), "person.personId", PersonName::getPerson), null,
142
                        HibernatePersonDAO.getMaximumSearchResults());
1✔
143
                
144
                return new LinkedHashSet<>(results);
1✔
145
        }
146
        
147
        /**
148
         * This method executes a Lucence search based on the soundex filter with more than three search names given 
149
         * 
150
         * @param searchNames the names seperated by space that should be searched for 
151
         * @param birthyear the birthyear the searched person should have 
152
         * @param includeVoided true if voided person should be included 
153
         * @param gender of the person to search for 
154
         * @return the set of Persons that match the search criteria
155
         */
156
        private Set<Person> executeSoundexNPersonNamesQuery(String[] searchNames, Integer birthyear, boolean includeVoided, 
157
                                                                                                                String gender) {
158
                PersonQuery personQuery = new PersonQuery();
1✔
159

160
                List<Person> results = SearchQueryUnique.search(searchSessionFactory, SearchQueryUnique.newQuery(PersonName.class,
1✔
161
                                f -> personQuery.getSoundexPersonNameSearchOnNNames(f, searchNames, birthyear,
1✔
162
                                        includeVoided, gender), "person.personId",  PersonName::getPerson), null, 
163
                        HibernatePersonDAO.getMaximumSearchResults());
1✔
164
                
165
                return new LinkedHashSet<>(results);
1✔
166
                
167
        }
168
        
169
        /**
170
         * @see org.openmrs.api.PersonService#getSimilarPeople(String name, Integer birthyear, String gender)
171
         * @see org.openmrs.api.db.PersonDAO#getSimilarPeople(String name, Integer birthyear, String gender)
172
         */
173
        @Override
174
        @SuppressWarnings("unchecked")
175
        public Set<Person> getSimilarPeople(String name, Integer birthyear, String gender) throws DAOException {
176
                if (birthyear == null) {
1✔
177
                        birthyear = 0;
1✔
178
                }
179

180
                name = name.replaceAll("  ", " ");
1✔
181
                name = name.replace(", ", " ");
1✔
182
                String[] names = name.split(" ");
1✔
183
                
184
                if (names.length == 1) {
1✔
185
                        return  executeSoundexOnePersonNameQuery(name, birthyear, false, gender);
1✔
186
                } else if (names.length == 2) {
1✔
187
                        return executeSoundexTwoPersonNamesQuery(names[0], names[1], birthyear, false, gender);
1✔
188
                } else if (names.length == 3) {
1✔
189
                        return executeSoundexThreePersonNamesQuery(names[0], names[1], names[2], birthyear, false, gender);
1✔
190
                }
191
                else if (names.length > 3) {
1✔
192
                        return executeSoundexNPersonNamesQuery(names, birthyear, false, gender);
1✔
193
                }
194
                return new LinkedHashSet<>();
×
195
        }
196
        
197
        /**
198
         * @see org.openmrs.api.db.PersonDAO#getPeople(java.lang.String, java.lang.Boolean)
199
         * <strong>Should</strong> get no one by null
200
         * <strong>Should</strong> get every one by empty string
201
         * <strong>Should</strong> get no one by non-existing attribute
202
         * <strong>Should</strong> get no one by non-searchable attribute
203
         * <strong>Should</strong> get no one by voided attribute
204
         * <strong>Should</strong> get one person by attribute
205
         * <strong>Should</strong> get one person by random case attribute
206
         * <strong>Should</strong> get one person by searching for a mix of attribute and voided attribute
207
         * <strong>Should</strong> get multiple people by single attribute
208
         * <strong>Should</strong> get multiple people by multiple attributes
209
         * <strong>Should</strong> get no one by non-existing name
210
         * <strong>Should</strong> get one person by name
211
         * <strong>Should</strong> get one person by random case name
212
         * <strong>Should</strong> get multiple people by single name
213
         * <strong>Should</strong> get multiple people by multiple names
214
         * <strong>Should</strong> get no one by non-existing name and non-existing attribute
215
         * <strong>Should</strong> get no one by non-existing name and non-searchable attribute
216
         * <strong>Should</strong> get no one by non-existing name and voided attribute
217
         * <strong>Should</strong> get one person by name and attribute
218
         * <strong>Should</strong> get one person by name and voided attribute
219
         * <strong>Should</strong> get multiple people by name and attribute
220
         * <strong>Should</strong> get one person by given name
221
         * <strong>Should</strong> get multiple people by given name
222
         * <strong>Should</strong> get one person by middle name
223
         * <strong>Should</strong> get multiple people by middle name
224
         * <strong>Should</strong> get one person by family name
225
         * <strong>Should</strong> get multiple people by family name
226
         * <strong>Should</strong> get one person by family name2
227
         * <strong>Should</strong> get multiple people by family name2
228
         * <strong>Should</strong> get one person by multiple name parts
229
         * <strong>Should</strong> get multiple people by multiple name parts
230
         * <strong>Should</strong> get no one by voided name
231
         * <strong>Should</strong> not get voided person
232
         * <strong>Should</strong> not get dead person
233
         * <strong>Should</strong> get single dead person
234
         * <strong>Should</strong> get multiple dead people
235
         */
236
        @Override
237
        @SuppressWarnings("unchecked")
238
        public List<Person> getPeople(String searchString, Boolean dead, Boolean voided) {
239
                if (searchString == null) {
1✔
240
                        return new ArrayList<>();
1✔
241
                }
242

243
                int maxResults = HibernatePersonDAO.getMaximumSearchResults();
1✔
244

245
                boolean includeVoided = (voided != null) ? voided : false;
1✔
246

247
                if (StringUtils.isBlank(searchString)) {
1✔
248
                        Session session = sessionFactory.getCurrentSession();
1✔
249
                        CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
250
                        CriteriaQuery<Person> cq = cb.createQuery(Person.class);
1✔
251
                        Root<Person> root = cq.from(Person.class);
1✔
252

253
                        List<Predicate> predicates = new ArrayList<>();
1✔
254
                        if (dead != null) {
1✔
255
                                predicates.add(cb.equal(root.get("dead"), dead));
1✔
256
                        }
257

258
                        if (!includeVoided) {
1✔
259
                                predicates.add(cb.isFalse(root.get("personVoided")));
1✔
260
                        }
261

262
                        cq.where(predicates.toArray(new Predicate[]{}));
1✔
263

264
                        return session.createQuery(cq).setMaxResults(maxResults).getResultList();
1✔
265
                }
266

267
                PersonQuery personQuery = new PersonQuery();
1✔
268

269
                return SearchQueryUnique.search(searchSessionFactory, SearchQueryUnique.newQuery(PersonName.class,
1✔
270
                                f -> personQuery.getPersonNameQueryWithOrParser(f, searchString, includeVoided, dead),
1✔
271
                                "person.personId", PersonName::getPerson).join(SearchQueryUnique.newQuery(PersonAttribute.class,
1✔
272
                                f -> personQuery.getPersonAttributeQueryWithOrParser(f, searchString, includeVoided), 
1✔
273
                                "person.personId", PersonAttribute::getPerson)), null,
274
                        HibernatePersonDAO.getMaximumSearchResults());
1✔
275
        }
276
        
277
        @Override
278
        public List<Person> getPeople(String searchString, Boolean dead) {
279
                return getPeople(searchString, dead, null);
1✔
280
        }
281
        
282
        /**
283
         * Fetch the max results value from the global properties table
284
         * 
285
         * @return Integer value for the person search max results global property
286
         */
287
        public static Integer getMaximumSearchResults() {
288
                try {
289
                        String personSearchMaxGp = ConfigUtil
1✔
290
                                .getGlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS);
1✔
291
                        if (personSearchMaxGp == null) {
1✔
292
                                personSearchMaxGp = String.valueOf(OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS_DEFAULT_VALUE);
1✔
293
                        }
294
                        return Integer.valueOf(personSearchMaxGp);
1✔
295
                }
296
                catch (Exception e) {
×
297
                        log.warn("Unable to convert the global property " + OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS
×
298
                                + "to a valid integer. Returning the default "
299
                                + OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS_DEFAULT_VALUE);
300
                }
301
                
302
                return OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS_DEFAULT_VALUE;
×
303
        }
304
        
305
        /**
306
         * @see org.openmrs.api.PersonService#getPerson(java.lang.Integer)
307
         * @see org.openmrs.api.db.PersonDAO#getPerson(java.lang.Integer)
308
         */
309
        @Override
310
        public Person getPerson(Integer personId) {
311
                return sessionFactory.getCurrentSession().get(Person.class, personId);
1✔
312
        }
313
        
314
        /**
315
         * @see org.openmrs.api.PersonService#purgePersonAttributeType(org.openmrs.PersonAttributeType)
316
         * @see org.openmrs.api.db.PersonDAO#deletePersonAttributeType(org.openmrs.PersonAttributeType)
317
         */
318
        @Override
319
        public void deletePersonAttributeType(PersonAttributeType type) {
320
                sessionFactory.getCurrentSession().delete(type);
1✔
321
        }
1✔
322
        
323
        /**
324
         * @see org.openmrs.api.PersonService#savePersonAttributeType(org.openmrs.PersonAttributeType)
325
         * @see org.openmrs.api.db.PersonDAO#savePersonAttributeType(org.openmrs.PersonAttributeType)
326
         */
327
        @Override
328
        public PersonAttributeType savePersonAttributeType(PersonAttributeType type) {
329
                sessionFactory.getCurrentSession().saveOrUpdate(type);
1✔
330
                return type;
1✔
331
        }
332
        
333
        /**
334
         * @see org.openmrs.api.PersonService#getPersonAttributeType(java.lang.Integer)
335
         * @see org.openmrs.api.db.PersonDAO#getPersonAttributeType(java.lang.Integer)
336
         */
337
        @Override
338
        public PersonAttributeType getPersonAttributeType(Integer typeId) {
339
                return sessionFactory.getCurrentSession().get(PersonAttributeType.class, typeId);
1✔
340
        }
341
        
342
        /**
343
         * @see org.openmrs.api.PersonService#getPersonAttribute(java.lang.Integer)
344
         * @see org.openmrs.api.db.PersonDAO#getPersonAttribute(java.lang.Integer)
345
         */
346
        @Override
347
        public PersonAttribute getPersonAttribute(Integer id) {
348
                return sessionFactory.getCurrentSession().get(PersonAttribute.class, id);
1✔
349
        }
350
        
351
        /**
352
         * @see org.openmrs.api.PersonService#getAllPersonAttributeTypes(boolean)
353
         * @see org.openmrs.api.db.PersonDAO#getAllPersonAttributeTypes(boolean)
354
         */
355
        @Override
356
        public List<PersonAttributeType> getAllPersonAttributeTypes(boolean includeRetired) throws DAOException {
357
                Session session = sessionFactory.getCurrentSession();
1✔
358
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
359
                CriteriaQuery<PersonAttributeType> cq = cb.createQuery(PersonAttributeType.class);
1✔
360
                Root<PersonAttributeType> root = cq.from(PersonAttributeType.class);
1✔
361

362
                if (!includeRetired) {
1✔
363
                        cq.where(cb.isFalse(root.get("retired")));
1✔
364
                }
365

366
                cq.orderBy(cb.asc(root.get("sortWeight")));
1✔
367

368
                return session.createQuery(cq).getResultList();
1✔
369
        }
370

371
        /**
372
         * @see org.openmrs.api.db.PersonDAO#getPersonAttributeTypes(java.lang.String, java.lang.String,
373
         *      java.lang.Integer, java.lang.Boolean)
374
         */
375
        @Override
376
        // TODO - PersonServiceTest fails here
377
        public List<PersonAttributeType> getPersonAttributeTypes(String exactName, String format, Integer foreignKey, Boolean searchable) throws DAOException {
378
                Session session = sessionFactory.getCurrentSession();
1✔
379
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
380
                CriteriaQuery<PersonAttributeType> cq = cb.createQuery(PersonAttributeType.class);
1✔
381
                Root<PersonAttributeType> root = cq.from(PersonAttributeType.class);
1✔
382

383
                List<Predicate> predicates = new ArrayList<>();
1✔
384
                if (exactName != null) {
1✔
385
                        predicates.add(cb.equal(root.get("name"), exactName));
1✔
386
                }
387

388
                if (format != null) {
1✔
389
                        predicates.add(cb.equal(root.get("format"), format));
1✔
390
                }
391

392
                if (foreignKey != null) {
1✔
393
                        predicates.add(cb.equal(root.get("foreignKey"), foreignKey));
×
394
                }
395

396
                if (searchable != null) {
1✔
397
                        predicates.add(cb.equal(root.get("searchable"), searchable));
1✔
398
                }
399

400
                cq.where(predicates.toArray(new Predicate[]{}));
1✔
401

402
                return session.createQuery(cq).getResultList();
1✔
403
        }
404

405
        /**
406
         * @see org.openmrs.api.PersonService#getRelationship(java.lang.Integer)
407
         * @see org.openmrs.api.db.PersonDAO#getRelationship(java.lang.Integer)
408
         */
409
        @Override
410
        public Relationship getRelationship(Integer relationshipId) throws DAOException {
411

412
                return sessionFactory.getCurrentSession()
1✔
413
                        .get(Relationship.class, relationshipId);
1✔
414
        }
415
        
416
        /**
417
         * @see org.openmrs.api.PersonService#getAllRelationships(boolean)
418
         * @see org.openmrs.api.db.PersonDAO#getAllRelationships(boolean)
419
         */
420
        @Override
421
        public List<Relationship> getAllRelationships(boolean includeVoided) throws DAOException {
422
                Session session = sessionFactory.getCurrentSession();
1✔
423
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
424
                CriteriaQuery<Relationship> cq = cb.createQuery(Relationship.class);
1✔
425
                Root<Relationship> root = cq.from(Relationship.class);
1✔
426

427
                if (!includeVoided) {
1✔
428
                        cq.where(cb.isFalse(root.get("voided")));
1✔
429
                }
430

431
                return session.createQuery(cq).getResultList();
1✔
432
        }
433

434

435
        /**
436
         * @see org.openmrs.api.PersonService#getRelationships(org.openmrs.Person, org.openmrs.Person,
437
         *      org.openmrs.RelationshipType)
438
         * @see org.openmrs.api.db.PersonDAO#getRelationships(org.openmrs.Person, org.openmrs.Person,
439
         *      org.openmrs.RelationshipType)
440
         */
441
        @Override
442
        public List<Relationship> getRelationships(Person fromPerson, Person toPerson, RelationshipType relType) {
443
                Session session = sessionFactory.getCurrentSession();
1✔
444
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
445
                CriteriaQuery<Relationship> cq = cb.createQuery(Relationship.class);
1✔
446
                Root<Relationship> root = cq.from(Relationship.class);
1✔
447

448
                List<Predicate> predicates = new ArrayList<>();
1✔
449
                if (fromPerson != null) {
1✔
450
                        predicates.add(cb.equal(root.get("personA"), fromPerson));
1✔
451
                }
452
                if (toPerson != null) {
1✔
453
                        predicates.add(cb.equal(root.get("personB"), toPerson));
1✔
454
                }
455
                if (relType != null) {
1✔
456
                        predicates.add(cb.equal(root.get("relationshipType"), relType));
1✔
457
                }
458

459
                predicates.add(cb.isFalse(root.get("voided")));
1✔
460

461
                cq.where(predicates.toArray(new Predicate[]{}));
1✔
462

463
                return session.createQuery(cq).getResultList();
1✔
464
        }
465

466
        /**
467
         * @see org.openmrs.api.PersonService#getRelationships(org.openmrs.Person, org.openmrs.Person,
468
         *      org.openmrs.RelationshipType, java.util.Date, java.util.Date)
469
         * @see org.openmrs.api.db.PersonDAO#getRelationships(org.openmrs.Person, org.openmrs.Person,
470
         *      org.openmrs.RelationshipType, java.util.Date, java.util.Date)
471
         */
472
        @Override
473
        public List<Relationship> getRelationships(Person fromPerson, Person toPerson, RelationshipType relType, Date startEffectiveDate, Date endEffectiveDate) {
474
                Session session = sessionFactory.getCurrentSession();
1✔
475
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
476
                CriteriaQuery<Relationship> cq = cb.createQuery(Relationship.class);
1✔
477
                Root<Relationship> root = cq.from(Relationship.class);
1✔
478

479
                List<Predicate> predicates = new ArrayList<>();
1✔
480
                if (fromPerson != null) {
1✔
481
                        predicates.add(cb.equal(root.get("personA"), fromPerson));
1✔
482
                }
483
                if (toPerson != null) {
1✔
484
                        predicates.add(cb.equal(root.get("personB"), toPerson));
1✔
485
                }
486
                if (relType != null) {
1✔
487
                        predicates.add(cb.equal(root.get("relationshipType"), relType));
1✔
488
                }
489
                if (startEffectiveDate != null) {
1✔
490
                        Predicate startDatePredicate = cb.or(
1✔
491
                                cb.and(cb.lessThanOrEqualTo(root.get("startDate"), startEffectiveDate),
1✔
492
                                        cb.greaterThanOrEqualTo(root.get("endDate"), startEffectiveDate)),
1✔
493
                                cb.and(cb.lessThanOrEqualTo(root.get("startDate"), startEffectiveDate),
1✔
494
                                        cb.isNull(root.get("endDate"))),
1✔
495
                                cb.and(cb.isNull(root.get("startDate")),
1✔
496
                                        cb.greaterThanOrEqualTo(root.get("endDate"), startEffectiveDate)),
1✔
497
                                cb.and(cb.isNull(root.get("startDate")),
1✔
498
                                        cb.isNull(root.get("endDate")))
1✔
499
                        );
500
                        predicates.add(startDatePredicate);
1✔
501
                }
502
                if (endEffectiveDate != null) {
1✔
503
                        Predicate endDatePredicate = cb.or(
1✔
504
                                cb.and(cb.lessThanOrEqualTo(root.get("startDate"), endEffectiveDate),
1✔
505
                                        cb.greaterThanOrEqualTo(root.get("endDate"), endEffectiveDate)),
1✔
506
                                cb.and(cb.lessThanOrEqualTo(root.get("startDate"), endEffectiveDate),
1✔
507
                                        cb.isNull(root.get("endDate"))),
1✔
508
                                cb.and(cb.isNull(root.get("startDate")),
1✔
509
                                        cb.greaterThanOrEqualTo(root.get("endDate"), endEffectiveDate)),
1✔
510
                                cb.and(cb.isNull(root.get("startDate")),
1✔
511
                                        cb.isNull(root.get("endDate")))
1✔
512
                        );
513
                        predicates.add(endDatePredicate);
1✔
514
                }
515

516
                predicates.add(cb.isFalse(root.get("voided")));
1✔
517

518
                cq.where(predicates.toArray(new Predicate[]{}));
1✔
519

520
                return session.createQuery(cq).getResultList();
1✔
521
        }
522

523
        /**
524
         * @see org.openmrs.api.PersonService#getRelationshipType(java.lang.Integer)
525
         * @see org.openmrs.api.db.PersonDAO#getRelationshipType(java.lang.Integer)
526
         */
527
        @Override
528
        public RelationshipType getRelationshipType(Integer relationshipTypeId) throws DAOException {
529
                return sessionFactory.getCurrentSession().get(
1✔
530
                    RelationshipType.class, relationshipTypeId);
531
        }
532
        
533
        /**
534
         * @see org.openmrs.api.PersonService#getRelationshipTypes(java.lang.String, java.lang.Boolean)
535
         * @see org.openmrs.api.db.PersonDAO#getRelationshipTypes(java.lang.String, java.lang.Boolean)
536
         */
537
        @Override
538
        public List<RelationshipType> getRelationshipTypes(String relationshipTypeName, Boolean preferred) throws DAOException {
539
                Session session = sessionFactory.getCurrentSession();
1✔
540
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
541
                CriteriaQuery<RelationshipType> cq = cb.createQuery(RelationshipType.class);
1✔
542
                Root<RelationshipType> root = cq.from(RelationshipType.class);
1✔
543

544
                List<Predicate> predicates = new ArrayList<>();
1✔
545
                if (StringUtils.isNotEmpty(relationshipTypeName)) {
1✔
546
                        Expression<String> concatenatedFields = cb.concat(root.get("aIsToB"),
1✔
547
                                cb.concat("/", root.get("bIsToA")));
1✔
548
                        predicates.add(cb.like(concatenatedFields, relationshipTypeName));
1✔
549
                } else {
1✔
550
                        // Add a predicate that is always false
551
                        predicates.add(cb.or());
1✔
552
                }
553

554
                if (preferred != null) {
1✔
555
                        predicates.add(cb.equal(root.get("preferred"), preferred));
1✔
556
                }
557

558
                cq.where(predicates.toArray(new Predicate[]{}));
1✔
559
                return session.createQuery(cq).getResultList();
1✔
560
        }
561

562
        /**
563
         * @see org.openmrs.api.PersonService#saveRelationshipType(org.openmrs.RelationshipType)
564
         * @see org.openmrs.api.db.PersonDAO#saveRelationshipType(org.openmrs.RelationshipType)
565
         */
566
        @Override
567
        public RelationshipType saveRelationshipType(RelationshipType relationshipType) throws DAOException {
568
                sessionFactory.getCurrentSession().saveOrUpdate(relationshipType);
1✔
569
                return relationshipType;
1✔
570
        }
571
        
572
        /**
573
         * @see org.openmrs.api.PersonService#purgeRelationshipType(org.openmrs.RelationshipType)
574
         * @see org.openmrs.api.db.PersonDAO#deleteRelationshipType(org.openmrs.RelationshipType)
575
         */
576
        @Override
577
        public void deleteRelationshipType(RelationshipType relationshipType) throws DAOException {
578
                sessionFactory.getCurrentSession().delete(relationshipType);
1✔
579
        }
1✔
580
        
581
        /**
582
         * @see org.openmrs.api.PersonService#purgePerson(org.openmrs.Person)
583
         * @see org.openmrs.api.db.PersonDAO#deletePerson(org.openmrs.Person)
584
         */
585
        @Override
586
        public void deletePerson(Person person) throws DAOException {
587
                HibernatePersonDAO.deletePersonAndAttributes(sessionFactory, person);
1✔
588
        }
1✔
589
        
590
        /**
591
         * @see org.openmrs.api.PersonService#savePerson(org.openmrs.Person)
592
         * @see org.openmrs.api.db.PersonDAO#savePerson(org.openmrs.Person)
593
         */
594
        @Override
595
        public Person savePerson(Person person) throws DAOException {
596
                sessionFactory.getCurrentSession().saveOrUpdate(person);
1✔
597
                return person;
1✔
598
        }
599
        
600
        /**
601
         * @see org.openmrs.api.PersonService#saveRelationship(org.openmrs.Relationship)
602
         * @see org.openmrs.api.db.PersonDAO#saveRelationship(org.openmrs.Relationship)
603
         */
604
        @Override
605
        public Relationship saveRelationship(Relationship relationship) throws DAOException {
606
                sessionFactory.getCurrentSession().saveOrUpdate(relationship);
1✔
607
                return relationship;
1✔
608
        }
609
        
610
        /**
611
         * @see org.openmrs.api.PersonService#purgeRelationship(org.openmrs.Relationship)
612
         * @see org.openmrs.api.db.PersonDAO#deleteRelationship(org.openmrs.Relationship)
613
         */
614
        @Override
615
        public void deleteRelationship(Relationship relationship) throws DAOException {
616
                sessionFactory.getCurrentSession().delete(relationship);
1✔
617
        }
1✔
618
        
619
        /**
620
         * Used by deletePerson, deletePatient, and deleteUser to remove all properties of a person
621
         * before deleting them.
622
         * 
623
         * @param sessionFactory the session factory from which to pull the current session
624
         * @param person the person to delete
625
         */
626
        public static void deletePersonAndAttributes(SessionFactory sessionFactory, Person person) {
627
                // delete properties and fields so hibernate can't complain
628
                for (PersonAddress address : person.getAddresses()) {
1✔
629
                        if (address.getDateCreated() == null) {
1✔
630
                                sessionFactory.getCurrentSession().evict(address);
×
631
                        } else {
632
                                sessionFactory.getCurrentSession().delete(address);
1✔
633
                        }
634
                }
1✔
635
                person.setAddresses(null);
1✔
636
                
637
                for (PersonAttribute attribute : person.getAttributes()) {
1✔
638
                        if (attribute.getDateCreated() == null) {
1✔
639
                                sessionFactory.getCurrentSession().evict(attribute);
×
640
                        } else {
641
                                sessionFactory.getCurrentSession().delete(attribute);
1✔
642
                        }
643
                }
1✔
644
                person.setAttributes(null);
1✔
645
                
646
                for (PersonName name : person.getNames()) {
1✔
647
                        if (name.getDateCreated() == null) {
1✔
648
                                sessionFactory.getCurrentSession().evict(name);
×
649
                        } else {
650
                                sessionFactory.getCurrentSession().delete(name);
1✔
651
                        }
652
                }
1✔
653
                person.setNames(null);
1✔
654
                
655
                // finally, just tell hibernate to delete our object
656
                sessionFactory.getCurrentSession().delete(person);
1✔
657
        }
1✔
658
        
659
        /**
660
         * @see org.openmrs.api.db.PersonDAO#getPersonAttributeTypeByUuid(java.lang.String)
661
         */
662
        @Override
663
        public PersonAttributeType getPersonAttributeTypeByUuid(String uuid) {
664
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, PersonAttributeType.class, uuid);
1✔
665
        }
666
        
667
        /**
668
         * @see org.openmrs.api.db.PersonDAO#getSavedPersonAttributeTypeName(org.openmrs.PersonAttributeType)
669
         */
670
        @Override
671
        public String getSavedPersonAttributeTypeName(PersonAttributeType personAttributeType) {
672
                SQLQuery sql = sessionFactory.getCurrentSession().createSQLQuery(
1✔
673
                    "select name from person_attribute_type where person_attribute_type_id = :personAttributeTypeId");
674
                sql.setParameter("personAttributeTypeId", personAttributeType.getId());
1✔
675
                return (String) sql.uniqueResult();
1✔
676
        }
677

678
        @Override
679
        public Boolean getSavedPersonAttributeTypeSearchable(PersonAttributeType personAttributeType) {
680
                SQLQuery sql = sessionFactory.getCurrentSession().createSQLQuery(
1✔
681
                        "select searchable from person_attribute_type where person_attribute_type_id = :personAttributeTypeId");
682
                sql.setParameter("personAttributeTypeId", personAttributeType.getId());
1✔
683
                return (Boolean) sql.uniqueResult();
1✔
684
        }
685

686
        /**
687
         * @see org.openmrs.api.db.PersonDAO#getPersonByUuid(java.lang.String)
688
         */
689
        @Override
690
        public Person getPersonByUuid(String uuid) {
691
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, Person.class, uuid);
1✔
692
        }
693
        
694
        @Override
695
        public PersonAddress getPersonAddressByUuid(String uuid) {
696
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, PersonAddress.class, uuid);
1✔
697
        }
698
        
699
        /**
700
         * @see org.openmrs.api.db.PersonDAO#savePersonMergeLog(PersonMergeLog)
701
         */
702
        @Override
703
        public PersonMergeLog savePersonMergeLog(PersonMergeLog personMergeLog) throws DAOException {
704
                sessionFactory.getCurrentSession().saveOrUpdate(personMergeLog);
1✔
705
                return personMergeLog;
1✔
706
        }
707
        
708
        /**
709
         * @see org.openmrs.api.db.PersonDAO#getPersonMergeLog(java.lang.Integer)
710
         */
711
        @Override
712
        public PersonMergeLog getPersonMergeLog(Integer id) throws DAOException {
713
                return sessionFactory.getCurrentSession().get(PersonMergeLog.class, id);
×
714
        }
715
        
716
        /**
717
         * @see org.openmrs.api.db.PersonDAO#getPersonMergeLogByUuid(String)
718
         */
719
        @Override
720
        public PersonMergeLog getPersonMergeLogByUuid(String uuid) throws DAOException {
721
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, PersonMergeLog.class, uuid);
1✔
722
        }
723
        
724
        /**
725
         * @see org.openmrs.api.db.PersonDAO#getWinningPersonMergeLogs(org.openmrs.Person)
726
         */
727
        @Override
728
        @SuppressWarnings("unchecked")
729
        public List<PersonMergeLog> getWinningPersonMergeLogs(Person person) throws DAOException {
730
                return (List<PersonMergeLog>) sessionFactory.getCurrentSession().createQuery(
1✔
731
                    "from PersonMergeLog p where p.winner.id = :winnerId").setParameter("winnerId", person.getId()).list();
1✔
732
        }
733
        
734
        /**
735
         * @see org.openmrs.api.db.PersonDAO#getLosingPersonMergeLogs(org.openmrs.Person)
736
         */
737
        @Override
738
        public PersonMergeLog getLosingPersonMergeLogs(Person person) throws DAOException {
739
                return (PersonMergeLog) sessionFactory.getCurrentSession().createQuery(
1✔
740
                    "from PersonMergeLog p where p.loser.id = :loserId").setParameter("loserId", person.getId()).uniqueResult();
1✔
741
        }
742
        
743
        /**
744
         * @see org.openmrs.api.db.PersonDAO#getAllPersonMergeLogs()
745
         */
746
        @Override
747
        @SuppressWarnings("unchecked")
748
        public List<PersonMergeLog> getAllPersonMergeLogs() throws DAOException {
749
                return (List<PersonMergeLog>) sessionFactory.getCurrentSession().createQuery("from PersonMergeLog p").list();
1✔
750
        }
751
        
752
        @Override
753
        public PersonAttribute getPersonAttributeByUuid(String uuid) {
754
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, PersonAttribute.class, uuid);
1✔
755
        }
756
        
757
        /**
758
         * @see org.openmrs.api.db.PersonDAO#getPersonName(Integer)
759
         */
760
        @Override
761
        public PersonName getPersonName(Integer personNameId) {
762
                return sessionFactory.getCurrentSession().get(PersonName.class, personNameId);
1✔
763
        }
764
        
765
        /**
766
         * @see org.openmrs.api.db.PersonDAO#getPersonNameByUuid(String)
767
         */
768
        @Override
769
        public PersonName getPersonNameByUuid(String uuid) {
770
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, PersonName.class, uuid);
1✔
771
        }
772
        
773
        /**
774
         * @see org.openmrs.api.db.PersonDAO#getRelationshipByUuid(java.lang.String)
775
         */
776
        @Override
777
        public Relationship getRelationshipByUuid(String uuid) {
778
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, Relationship.class, uuid);
1✔
779
        }
780
        
781
        /**
782
         * @see org.openmrs.api.db.PersonDAO#getRelationshipTypeByUuid(java.lang.String)
783
         */
784
        @Override
785
        public RelationshipType getRelationshipTypeByUuid(String uuid) {
786
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, RelationshipType.class, uuid);
1✔
787
        }
788
        
789
        /**
790
         * @see org.openmrs.api.db.PersonDAO#getAllRelationshipTypes(boolean)
791
         */
792
        @Override
793
        public List<RelationshipType> getAllRelationshipTypes(boolean includeRetired) {
794
                Session session = sessionFactory.getCurrentSession();
1✔
795
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
796
                CriteriaQuery<RelationshipType> cq = cb.createQuery(RelationshipType.class);
1✔
797
                Root<RelationshipType> root = cq.from(RelationshipType.class);
1✔
798

799
                if (!includeRetired) {
1✔
800
                        cq.where(cb.isFalse(root.get("retired")));
1✔
801
                }
802

803
                cq.orderBy(cb.asc(root.get("weight")));
1✔
804

805
                return session.createQuery(cq).getResultList();
1✔
806
        }
807

808
        /**
809
         * @see org.openmrs.api.PersonService#savePersonName(org.openmrs.PersonName)
810
         * @see org.openmrs.api.db.PersonDAO#savePersonName(org.openmrs.PersonName)
811
         */
812
        @Override
813
        public PersonName savePersonName(PersonName personName) {
814
                sessionFactory.getCurrentSession().saveOrUpdate(personName);
1✔
815
                return personName;
1✔
816
        }
817
        
818
        /**
819
         * @see org.openmrs.api.PersonService#savePersonAddress(org.openmrs.PersonAddress)
820
         * @see org.openmrs.api.db.PersonDAO#savePersonAddress(org.openmrs.PersonAddress)
821
         */
822
        @Override
823
        public PersonAddress savePersonAddress(PersonAddress personAddress) {
824
                sessionFactory.getCurrentSession().saveOrUpdate(personAddress);
1✔
825
                return personAddress;
1✔
826
        }
827
        
828
}
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