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

openmrs / openmrs-core / 15462307321

05 Jun 2025 08:30AM UTC coverage: 63.633% (-0.2%) from 63.8%
15462307321

push

github

rkorytkowski
TRUNK-6345 Fix testing framework to be used by modules for openmrs-core 2.4+

(cherry picked from commit 202eb8b65)
(cherry picked from commit bfb74a2d0)

4 of 9 new or added lines in 2 files covered. (44.44%)

54 existing lines in 14 files now uncovered.

21804 of 34265 relevant lines covered (63.63%)

0.64 hits per line

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

94.61
/api/src/main/java/org/openmrs/PersonName.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;
11

12
import static org.apache.commons.lang3.StringUtils.defaultString;
13

14
import java.io.Serializable;
15
import java.util.ArrayList;
16
import java.util.Comparator;
17
import java.util.Date;
18
import java.util.List;
19

20
import org.apache.commons.lang3.builder.EqualsBuilder;
21
import org.codehaus.jackson.annotate.JsonIgnore;
22
import org.hibernate.search.annotations.Analyzer;
23
import org.hibernate.search.annotations.Boost;
24
import org.hibernate.search.annotations.DocumentId;
25
import org.hibernate.search.annotations.Field;
26
import org.hibernate.search.annotations.Fields;
27
import org.hibernate.search.annotations.Indexed;
28
import org.hibernate.search.annotations.IndexedEmbedded;
29
import org.openmrs.api.APIException;
30
import org.openmrs.api.db.hibernate.search.LuceneAnalyzers;
31
import org.openmrs.layout.name.NameSupport;
32
import org.openmrs.layout.name.NameTemplate;
33
import org.openmrs.util.OpenmrsConstants;
34
import org.openmrs.util.OpenmrsUtil;
35
import org.slf4j.Logger;
36
import org.slf4j.LoggerFactory;
37
import org.springframework.util.StringUtils;
38

39
/**
40
 * A Person can have zero to n PersonName(s).
41
 */
42
@Indexed
43
public class PersonName extends BaseChangeableOpenmrsData implements java.io.Serializable, Cloneable, Comparable<PersonName> {
44
        
45
        public static final long serialVersionUID = 4353L;
46

47
        private static final Logger log = LoggerFactory.getLogger(PersonName.class);
1✔
48

49
        // Fields
50
        @DocumentId
51
        private Integer personNameId;
52

53
        @IndexedEmbedded(includeEmbeddedObjectId = true)
54
        private Person person;
55

56
        private Boolean preferred = false;
1✔
57

58
        @Fields({
59
                        @Field(name = "givenNameExact", analyzer = @Analyzer(definition = LuceneAnalyzers.EXACT_ANALYZER), boost = @Boost(8f)),
60
                        @Field(name = "givenNameStart", analyzer = @Analyzer(definition = LuceneAnalyzers.START_ANALYZER), boost = @Boost(4f)),
61
                        @Field(name = "givenNameAnywhere", analyzer = @Analyzer(definition = LuceneAnalyzers.ANYWHERE_ANALYZER), boost = @Boost(2f)),
62
                        @Field(name = "givenNameSoundex", analyzer =  @Analyzer(definition = LuceneAnalyzers.SOUNDEX_ANALYZER), boost = @Boost(1f))
63
        })
64
        private String givenName;
65
        private String prefix;
66

67
        @Fields({
68
                        @Field(name = "middleNameExact", analyzer = @Analyzer(definition = LuceneAnalyzers.EXACT_ANALYZER), boost = @Boost(4f)),
69
                        @Field(name = "middleNameStart", analyzer = @Analyzer(definition = LuceneAnalyzers.START_ANALYZER), boost = @Boost(2f)),
70
                        @Field(name = "middleNameAnywhere", analyzer = @Analyzer(definition = LuceneAnalyzers.ANYWHERE_ANALYZER)),
71
                        @Field(name = "middleNameSoundex", analyzer =  @Analyzer(definition = LuceneAnalyzers.SOUNDEX_ANALYZER), boost = @Boost(1f))
72
        })
73
        private String middleName;
74
        
75
        private String familyNamePrefix;
76

77
        @Fields({
78
                        @Field(name = "familyNameExact", analyzer = @Analyzer(definition = LuceneAnalyzers.EXACT_ANALYZER), boost = @Boost(8f)),
79
                        @Field(name = "familyNameStart", analyzer = @Analyzer(definition = LuceneAnalyzers.START_ANALYZER), boost = @Boost(4f)),
80
                        @Field(name = "familyNameAnywhere", analyzer = @Analyzer(definition = LuceneAnalyzers.ANYWHERE_ANALYZER), boost = @Boost(2f)),
81
                        @Field(name = "familyNameSoundex", analyzer =  @Analyzer(definition = LuceneAnalyzers.SOUNDEX_ANALYZER), boost = @Boost(1f))
82
        })
83
        private String familyName;
84

85
        @Fields({
86
                        @Field(name = "familyName2Exact", analyzer = @Analyzer(definition = LuceneAnalyzers.EXACT_ANALYZER), boost = @Boost(4f)),
87
                        @Field(name = "familyName2Start", analyzer = @Analyzer(definition = LuceneAnalyzers.START_ANALYZER), boost = @Boost(2f)),
88
                        @Field(name = "familyName2Anywhere", analyzer = @Analyzer(definition = LuceneAnalyzers.ANYWHERE_ANALYZER)),
89
                        @Field(name = "familyName2Soundex", analyzer =  @Analyzer(definition = LuceneAnalyzers.SOUNDEX_ANALYZER), boost = @Boost(1f))
90
        })
91
        private String familyName2;
92
        
93
        private String familyNameSuffix;
94
        
95
        private String degree;
96
        
97
        private static String format = OpenmrsConstants.PERSON_NAME_FORMAT_SHORT;
1✔
98
        
99
        // Constructors
100
        
101
        /** default constructor */
102
        public PersonName() {
1✔
103
        }
1✔
104
        
105
        /** constructor with id */
106
        public PersonName(Integer personNameId) {
1✔
107
                this.personNameId = personNameId;
1✔
108
        }
1✔
109
        
110
        /**
111
         * Convenience constructor with the basic requirements
112
         *
113
         * @param givenName String this person's first name
114
         * @param middleName String this person's middle name
115
         * @param familyName String this person's last name
116
         */
117
        public PersonName(String givenName, String middleName, String familyName) {
1✔
118
                this.givenName = givenName;
1✔
119
                this.middleName = middleName;
1✔
120
                this.familyName = familyName;
1✔
121
        }
1✔
122
        
123
        /**
124
         * Compares this PersonName object to the given otherName. This method differs from
125
         * {@link #equals(Object)} in that this method compares the inner fields of each name for
126
         * equality. Note: Null/empty fields on <code>otherName</code> /will not/ cause a false value to
127
         * be returned
128
         *
129
         * @param otherName PersonName with which to compare
130
         * @return boolean true/false whether or not they are the same names
131
         * <strong>Should</strong> return true if given middle and family name are equal
132
         */
133
        public boolean equalsContent(PersonName otherName) {
134
                return new EqualsBuilder().append(defaultString(otherName.getPrefix()), defaultString(prefix)).append(
1✔
135
                    defaultString(otherName.getGivenName()), defaultString(givenName)).append(
1✔
136
                    defaultString(otherName.getMiddleName()), defaultString(middleName)).append(
1✔
137
                    defaultString(otherName.getFamilyNamePrefix()), defaultString(familyNamePrefix)).append(
1✔
138
                    defaultString(otherName.getDegree()), defaultString(degree)).append(defaultString(otherName.getFamilyName()),
1✔
139
                    defaultString(familyName)).append(defaultString(otherName.getFamilyName2()), defaultString(familyName2)).append(
1✔
140
                    defaultString(otherName.getFamilyNameSuffix()), defaultString(familyNameSuffix)).isEquals();
1✔
141
        }
142
        
143
        /**
144
         * Bitwise copy of the personName object. NOTICE: THIS WILL NOT COPY THE PATIENT OBJECT. The
145
         * PersonName.person object in this object AND the cloned object will point at the same person
146
         *
147
         * @return New PersonName object
148
         * <strong>Should</strong> copy every property of given personName
149
         */
150
        public static PersonName newInstance(PersonName pn) {
151
                if (pn == null) {
1✔
152
                        throw new IllegalArgumentException();
×
153
                }
154
                PersonName newName = new PersonName(pn.getPersonNameId());
1✔
155
                if (pn.getGivenName() != null) {
1✔
156
                        newName.setGivenName(String.valueOf(pn.getGivenName()));
1✔
157
                }
158
                if (pn.getMiddleName() != null) {
1✔
159
                        newName.setMiddleName(String.valueOf(pn.getMiddleName()));
1✔
160
                }
161
                if (pn.getFamilyName() != null) {
1✔
162
                        newName.setFamilyName(String.valueOf(pn.getFamilyName()));
1✔
163
                }
164
                if (pn.getFamilyName2() != null) {
1✔
165
                        newName.setFamilyName2(String.valueOf(pn.getFamilyName2()));
1✔
166
                }
167
                if (pn.getFamilyNamePrefix() != null) {
1✔
168
                        newName.setFamilyNamePrefix(String.valueOf(pn.getFamilyNamePrefix()));
1✔
169
                }
170
                if (pn.getFamilyNameSuffix() != null) {
1✔
171
                        newName.setFamilyNameSuffix(String.valueOf(pn.getFamilyNameSuffix()));
1✔
172
                }
173
                if (pn.getPrefix() != null) {
1✔
174
                        newName.setPrefix(String.valueOf(pn.getPrefix()));
1✔
175
                }
176
                if (pn.getDegree() != null) {
1✔
177
                        newName.setDegree(String.valueOf(pn.getDegree()));
1✔
178
                }
179
                if (pn.getVoidReason() != null) {
1✔
180
                        newName.setVoidReason(String.valueOf(pn.getVoidReason()));
1✔
181
                }
182
                
183
                if (pn.getDateChanged() != null) {
1✔
184
                        newName.setDateChanged((Date) pn.getDateChanged().clone());
1✔
185
                }
186
                if (pn.getDateCreated() != null) {
1✔
187
                        newName.setDateCreated((Date) pn.getDateCreated().clone());
1✔
188
                }
189
                if (pn.getDateVoided() != null) {
1✔
190
                        newName.setDateVoided((Date) pn.getDateVoided().clone());
×
191
                }
192
                
193
                if (pn.getPreferred() != null) {
1✔
194
                        newName.setPreferred(pn.getPreferred());
1✔
195
                }
196
                if (pn.getVoided() != null) {
1✔
197
                        newName.setVoided(pn.getVoided());
1✔
198
                }
199
                
200
                newName.setPerson(pn.getPerson());
1✔
201
                newName.setVoidedBy(pn.getVoidedBy());
1✔
202
                newName.setChangedBy(pn.getChangedBy());
1✔
203
                newName.setCreator(pn.getCreator());
1✔
204
                
205
                return newName;
1✔
206
        }
207
        
208
        /**
209
         * @return Returns the degree.
210
         */
211
        public String getDegree() {
212
                return degree;
1✔
213
        }
214
        
215
        /**
216
         * @param degree The degree to set.
217
         */
218
        public void setDegree(String degree) {
219
                this.degree = degree;
1✔
220
        }
1✔
221
        
222
        /**
223
         * @return Returns the familyName.
224
         * <strong>Should</strong> return obscured name if obscure_patients is set to true
225
         */
226
        public String getFamilyName() {
227
                if (OpenmrsConstants.OBSCURE_PATIENTS) {
1✔
228
                        return OpenmrsConstants.OBSCURE_PATIENTS_FAMILY_NAME;
1✔
229
                }
230
                return familyName;
1✔
231
        }
232
        
233
        /**
234
         * @param familyName The familyName to set.
235
         */
236
        public void setFamilyName(String familyName) {
237
                this.familyName = familyName;
1✔
238
        }
1✔
239
        
240
        /**
241
         * @return Returns the familyName2.
242
         * <strong>Should</strong> return null if obscure_patients is set to true
243
         */
244
        public String getFamilyName2() {
245
                if (OpenmrsConstants.OBSCURE_PATIENTS) {
1✔
246
                        return null;
1✔
247
                }
248
                return familyName2;
1✔
249
        }
250
        
251
        /**
252
         * @param familyName2 The familyName2 to set.
253
         */
254
        public void setFamilyName2(String familyName2) {
255
                this.familyName2 = familyName2;
1✔
256
        }
1✔
257
        
258
        /**
259
         * @return Returns the familyNamePrefix.
260
         * <strong>Should</strong> return null if obscure_patients is set to true
261
         */
262
        public String getFamilyNamePrefix() {
263
                if (OpenmrsConstants.OBSCURE_PATIENTS) {
1✔
264
                        return null;
1✔
265
                }
266
                return familyNamePrefix;
1✔
267
        }
268
        
269
        /**
270
         * @param familyNamePrefix The familyNamePrefix to set.
271
         */
272
        public void setFamilyNamePrefix(String familyNamePrefix) {
273
                this.familyNamePrefix = familyNamePrefix;
1✔
274
        }
1✔
275
        
276
        /**
277
         * @return Returns the familyNameSuffix.
278
         * <strong>Should</strong> return null if obscure_patients is set to true
279
         */
280
        public String getFamilyNameSuffix() {
281
                if (OpenmrsConstants.OBSCURE_PATIENTS) {
1✔
282
                        return null;
1✔
283
                }
284
                return familyNameSuffix;
1✔
285
        }
286
        
287
        /**
288
         * @param familyNameSuffix The familyNameSuffix to set.
289
         */
290
        public void setFamilyNameSuffix(String familyNameSuffix) {
291
                this.familyNameSuffix = familyNameSuffix;
1✔
292
        }
1✔
293
        
294
        /**
295
         * @return Returns the givenName.
296
         * <strong>Should</strong> return obscured name if obscure_patients is set to true
297
         */
298
        public String getGivenName() {
299
                if (OpenmrsConstants.OBSCURE_PATIENTS) {
1✔
300
                        return OpenmrsConstants.OBSCURE_PATIENTS_GIVEN_NAME;
1✔
301
                }
302
                return givenName;
1✔
303
        }
304
        
305
        /**
306
         * @param givenName The givenName to set.
307
         */
308
        public void setGivenName(String givenName) {
309
                this.givenName = givenName;
1✔
310
        }
1✔
311
        
312
        /**
313
         * @return Returns the middleName.
314
         * <strong>Should</strong> return obscured name if obscure_patients is set to true
315
         */
316
        public String getMiddleName() {
317
                if (OpenmrsConstants.OBSCURE_PATIENTS) {
1✔
318
                        return OpenmrsConstants.OBSCURE_PATIENTS_MIDDLE_NAME;
1✔
319
                }
320
                return middleName;
1✔
321
        }
322
        
323
        /**
324
         * @param middleName The middleName to set.
325
         */
326
        public void setMiddleName(String middleName) {
327
                this.middleName = middleName;
1✔
328
        }
1✔
329
        
330
        /**
331
         * @return Returns the person.
332
         */
333
        public Person getPerson() {
334
                return person;
1✔
335
        }
336
        
337
        /**
338
         * @param person The person to set.
339
         */
340
        public void setPerson(Person person) {
341
                this.person = person;
1✔
342
        }
1✔
343
        
344
        /**
345
         * @return Returns the personNameId.
346
         */
347
        public Integer getPersonNameId() {
348
                return personNameId;
1✔
349
        }
350
        
351
        /**
352
         * @param personNameId The personNameId to set.
353
         */
354
        public void setPersonNameId(Integer personNameId) {
355
                this.personNameId = personNameId;
1✔
356
        }
1✔
357
        
358
        /**
359
         * @return Returns the preferred.
360
         *
361
         * @deprecated as of 2.0, use {@link #getPreferred()}
362
         */
363
        @Deprecated
364
        @JsonIgnore
365
        public Boolean isPreferred() {
366
                return getPreferred();
1✔
367
        }
368
        
369
        public Boolean getPreferred() {
370
                if (preferred == null) {
1✔
371
                        return Boolean.FALSE;
×
372
                }
373
                return preferred;
1✔
374
        }
375
        
376
        /**
377
         * @param preferred The preferred to set.
378
         */
379
        public void setPreferred(Boolean preferred) {
380
                this.preferred = preferred;
1✔
381
        }
1✔
382
        
383
        /**
384
         * @return Returns the prefix.
385
         * <strong>Should</strong> return null if obscure_patients is set to true
386
         */
387
        public String getPrefix() {
388
                if (OpenmrsConstants.OBSCURE_PATIENTS) {
1✔
389
                        return null;
1✔
390
                }
391
                return prefix;
1✔
392
        }
393
        
394
        /**
395
         * @param prefix The prefix to set.
396
         */
397
        public void setPrefix(String prefix) {
398
                this.prefix = prefix;
1✔
399
        }
1✔
400
        
401
        /**
402
         * Convenience method to get all the names of this PersonName and concatenating them together
403
         * with spaces in between. If any part of {@link #getPrefix()}, {@link #getGivenName()},
404
         * {@link #getMiddleName()}, etc are null, they are not included in the returned name
405
         *
406
         * @return all of the parts of this {@link PersonName} joined with spaces
407
         * <strong>Should</strong> not put spaces around an empty middle name
408
         */
409
        public String getFullName() {
410
                NameTemplate nameTemplate = null;
1✔
411
                try {
412
                        nameTemplate = NameSupport.getInstance().getDefaultLayoutTemplate();
1✔
413
                }
UNCOV
414
                catch (APIException ex) {
×
UNCOV
415
                        log.warn("No name layout format set");
×
416
                }
1✔
417
                
418
                if (nameTemplate != null) {
1✔
419
                        return nameTemplate.format(this);
×
420
                }
421

422
                List<String> temp = new ArrayList<>();
1✔
423
                if (StringUtils.hasText(getPrefix())) {
1✔
424
                        temp.add(getPrefix());
1✔
425
                }
426
                if (StringUtils.hasText(getGivenName())) {
1✔
427
                        temp.add(getGivenName());
1✔
428
                }
429
                if (StringUtils.hasText(getMiddleName())) {
1✔
430
                        temp.add(getMiddleName());
1✔
431
                }
432
                if (OpenmrsConstants.PERSON_NAME_FORMAT_LONG.equals(PersonName.getFormat())) {
1✔
433
                        
434
                        if (StringUtils.hasText(getFamilyNamePrefix())) {
1✔
435
                                temp.add(getFamilyNamePrefix());
1✔
436
                        }
437
                        if (StringUtils.hasText(getFamilyName())) {
1✔
438
                                temp.add(getFamilyName());
1✔
439
                        }
440
                        if (StringUtils.hasText(getFamilyName2())) {
1✔
441
                                temp.add(getFamilyName2());
1✔
442
                        }
443
                        if (StringUtils.hasText(getFamilyNameSuffix())) {
1✔
444
                                temp.add(getFamilyNameSuffix());
1✔
445
                        }
446
                        if (StringUtils.hasText(getDegree())) {
1✔
447
                                temp.add(getDegree());
1✔
448
                        }
449
                } else {
450
                        
451
                        if (StringUtils.hasText(getFamilyName())) {
1✔
452
                                temp.add(getFamilyName());
1✔
453
                        }
454
                }
455
                
456
                String nameString = StringUtils.collectionToDelimitedString(temp, " ");
1✔
457
                
458
                return nameString.trim();
1✔
459
        }
460
        
461
        /**
462
         * @see java.lang.Object#toString()
463
         */
464
        @Override
465
        public String toString() {
466
                //This should not be changed due to extensive usage in UI.
467
                return getFullName();
1✔
468
        }
469
        
470
        /**
471
         * @since 1.5
472
         * @see org.openmrs.OpenmrsObject#getId()
473
         */
474
        @Override
475
        public Integer getId() {
476
                return getPersonNameId();
1✔
477
        }
478
        
479
        /**
480
         * @see java.lang.Comparable#compareTo(java.lang.Object)
481
         * <strong>Should</strong> return negative if other name is voided
482
         * <strong>Should</strong> return negative if this name is preferred
483
         * <strong>Should</strong> return negative if other familyName is greater
484
         * <strong>Should</strong> return negative if other familyName2 is greater
485
         * <strong>Should</strong> return negative if other givenName is greater
486
         * <strong>Should</strong> return negative if other middleName is greater
487
         * <strong>Should</strong> return negative if other familynamePrefix is greater
488
         * <strong>Should</strong> return negative if other familyNameSuffix is greater
489
         * <strong>Should</strong> return negative if other dateCreated is greater
490
         * Note: this comparator imposes orderings that are inconsistent with equals.
491
         */
492
        @Override
493
        public int compareTo(PersonName other) {
494
                DefaultComparator pnDefaultComparator = new DefaultComparator();
1✔
495
                return pnDefaultComparator.compare(this, other);
1✔
496
        }
497
        
498
        /**
499
         * @since 1.5
500
         * @see org.openmrs.OpenmrsObject#setId(java.lang.Integer)
501
         */
502
        @Override
503
        public void setId(Integer id) {
504
                setPersonNameId(id);
×
505
                
506
        }
×
507
        
508
        public static void setFormat(String format) {
509
                if (StringUtils.isEmpty(format)) {
1✔
510
                        PersonName.format = OpenmrsConstants.PERSON_NAME_FORMAT_SHORT;
1✔
511
                } else {
512
                        PersonName.format = format;
1✔
513
                }
514
        }
1✔
515
        
516
        public static String getFormat() {
517
                return PersonName.format;
1✔
518
        }
519
        
520
        /**
521
         Provides a default comparator.
522
         @since 1.12
523
         **/
524
        public static class DefaultComparator implements Comparator<PersonName>, Serializable {
1✔
525

526
                private static final long serialVersionUID = 1L;
527
                
528
                @Override
529
                public int compare(PersonName pn1, PersonName pn2) {
530
                        int ret = pn1.getVoided().compareTo(pn2.getVoided());
1✔
531
                        if (ret == 0) {
1✔
532
                                ret = pn2.getPreferred().compareTo(pn1.getPreferred());
1✔
533
                        }
534
                        if (ret == 0) {
1✔
535
                                ret = OpenmrsUtil.compareWithNullAsGreatest(pn1.getFamilyName(), pn2.getFamilyName());
1✔
536
                        }
537
                        if (ret == 0) {
1✔
538
                                ret = OpenmrsUtil.compareWithNullAsGreatest(pn1.getFamilyName2(), pn2.getFamilyName2());
1✔
539
                        }
540
                        if (ret == 0) {
1✔
541
                                ret = OpenmrsUtil.compareWithNullAsGreatest(pn1.getGivenName(), pn2.getGivenName());
1✔
542
                        }
543
                        if (ret == 0) {
1✔
544
                                ret = OpenmrsUtil.compareWithNullAsGreatest(pn1.getMiddleName(), pn2.getMiddleName());
1✔
545
                        }
546
                        if (ret == 0) {
1✔
547
                                ret = OpenmrsUtil.compareWithNullAsGreatest(pn1.getFamilyNamePrefix(), pn2.getFamilyNamePrefix());
1✔
548
                        }
549
                        if (ret == 0) {
1✔
550
                                ret = OpenmrsUtil.compareWithNullAsGreatest(pn1.getFamilyNameSuffix(), pn2.getFamilyNameSuffix());
1✔
551
                        }
552
                        if (ret == 0 && pn1.getDateCreated() != null) {
1✔
553
                                ret = OpenmrsUtil.compareWithNullAsLatest(pn1.getDateCreated(), pn2.getDateCreated());
1✔
554
                        }
555
                        
556
                        // if we've gotten this far, just check all name values. If they are
557
                        // equal, leave the objects at 0. If not, arbitrarily pick retValue=1
558
                        // and return that (they are not equal).
559
                        if (ret == 0 && !pn1.equalsContent(pn2)) {
1✔
560
                                ret = 1;
×
561
                        }
562
                        
563
                        return ret;
1✔
564
                }
565
        }
566
        
567
}
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