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

openmrs / openmrs-core / 19233807477

10 Nov 2025 01:48PM UTC coverage: 64.874% (-0.02%) from 64.894%
19233807477

push

github

web-flow
Use the latest supported JDK17 for default docker images in 2.7.x (#5407)

23432 of 36119 relevant lines covered (64.87%)

0.65 hits per line

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

85.9
/api/src/main/java/org/openmrs/PatientIdentifier.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 java.io.Serializable;
13
import java.lang.reflect.InvocationTargetException;
14
import java.lang.reflect.Method;
15
import java.util.Comparator;
16

17
import org.codehaus.jackson.annotate.JsonIgnore;
18
import org.hibernate.envers.Audited;
19
import org.hibernate.search.annotations.Analyzer;
20
import org.hibernate.search.annotations.Boost;
21
import org.hibernate.search.annotations.DocumentId;
22
import org.hibernate.search.annotations.Field;
23
import org.hibernate.search.annotations.Fields;
24
import org.hibernate.search.annotations.Indexed;
25
import org.hibernate.search.annotations.IndexedEmbedded;
26
import org.hibernate.search.annotations.SortableField;
27
import org.openmrs.api.db.hibernate.search.LuceneAnalyzers;
28
import org.openmrs.util.OpenmrsUtil;
29
import org.slf4j.Logger;
30
import org.slf4j.LoggerFactory;
31

32
/**
33
 * A <code>Patient</code> can have zero to n identifying PatientIdentifier(s). PatientIdentifiers
34
 * are anything from medical record numbers, to social security numbers, to driver's licenses. The
35
 * type of identifier is defined by the PatientIdentifierType. A PatientIdentifier also contains a
36
 * Location.
37
 *
38
 * @see org.openmrs.PatientIdentifierType
39
 */
40
@Indexed
41
@Audited
42
public class PatientIdentifier extends BaseChangeableOpenmrsData implements java.io.Serializable, Cloneable, Comparable<PatientIdentifier> {
43
        
44
        public static final long serialVersionUID = 1123121L;
45
        
46
        private static final Logger log = LoggerFactory.getLogger(PatientIdentifier.class);
1✔
47
        
48
        // Fields
49
        
50
        /**
51
         * @since 1.5
52
         */
53
        @DocumentId
54
        private Integer patientIdentifierId;
55

56
        @IndexedEmbedded(includeEmbeddedObjectId = true)
57
        private Patient patient;
58

59
        @Fields({
60
                        @Field(name = "identifierPhrase", analyzer = @Analyzer(definition = LuceneAnalyzers.PHRASE_ANALYZER), boost = @Boost(8f)),
61
                        @Field(name = "identifierExact", analyzer = @Analyzer(definition = LuceneAnalyzers.EXACT_ANALYZER), boost = @Boost(4f)),
62
                        @Field(name = "identifierStart", analyzer = @Analyzer(definition = LuceneAnalyzers.START_ANALYZER), boost = @Boost(2f)),
63
                        @Field(name = "identifierAnywhere", analyzer = @Analyzer(definition = LuceneAnalyzers.ANYWHERE_ANALYZER))
64
        })
65
        @SortableField(forField = "identifierExact")
66
        private String identifier;
67

68
        @IndexedEmbedded(includeEmbeddedObjectId = true)
69
        private PatientIdentifierType identifierType;
70
        
71
        private Location location;
72

73
        private PatientProgram patientProgram;
74
        
75

76
        @Field
1✔
77
        private Boolean preferred = false;
1✔
78
        
79
        /** default constructor */
80
        public PatientIdentifier() {
1✔
81
        }
1✔
82
        
83
        /**
84
         * Convenience constructor for creating a basic identifier
85
         *
86
         * @param identifier String identifier
87
         * @param type PatientIdentifierType
88
         * @param location Location of the identifier
89
         */
90
        public PatientIdentifier(String identifier, PatientIdentifierType type, Location location) {
1✔
91
                this.identifier = identifier;
1✔
92
                this.identifierType = type;
1✔
93
                this.location = location;
1✔
94
        }
1✔
95
        
96
        /**
97
         * Compares this PatientIdentifier object to the given otherIdentifier. This method differs from
98
         * {@link #equals(Object)} in that this method compares the inner fields of each identifier for
99
         * equality. Note: Null/empty fields on <code>otherIdentifier</code> /will not/ cause a false
100
         * value to be returned
101
         *
102
         * @param otherIdentifier PatientiIdentifier with which to compare
103
         * @return boolean true/false whether or not they are the same names
104
         */
105
        public boolean equalsContent(PatientIdentifier otherIdentifier) {
106
                boolean returnValue = true;
1✔
107
                
108
                // these are the methods to compare.
109
                String[] methods = { "getIdentifier", "getIdentifierType", "getLocation" };
1✔
110
                
111
                Class<? extends PatientIdentifier> identifierClass = this.getClass();
1✔
112
                
113
                // loop over all of the selected methods and compare this and other
114
                for (String methodName : methods) {
1✔
115
                        try {
116
                                Method method = identifierClass.getMethod(methodName);
1✔
117
                                
118
                                Object thisValue = method.invoke(this);
1✔
119
                                Object otherValue = method.invoke(otherIdentifier);
1✔
120
                                
121
                                if (otherValue != null) {
1✔
122
                                        returnValue &= otherValue.equals(thisValue);
1✔
123
                                }
124
                                
125
                        }
126
                        catch (NoSuchMethodException e) {
×
127
                                log.warn("No such method for comparison " + methodName, e);
×
128
                        }
129
                        catch (IllegalAccessException | InvocationTargetException e) {
×
130
                                log.error("Error while comparing identifiers", e);
×
131
                        }
1✔
132

133
                }
134
                
135
                return returnValue;
1✔
136
        }
137
        
138
        //property accessors
139
        
140
        /**
141
         * @return Returns the identifier.
142
         */
143
        public String getIdentifier() {
144
                return identifier;
1✔
145
        }
146
        
147
        /**
148
         * @param identifier The identifier to set.
149
         */
150
        public void setIdentifier(String identifier) {
151
                this.identifier = identifier;
1✔
152
        }
1✔
153
        
154
        /**
155
         * @return Returns the identifierType.
156
         */
157
        public PatientIdentifierType getIdentifierType() {
158
                return identifierType;
1✔
159
        }
160
        
161
        /**
162
         * @param identifierType The identifierType to set.
163
         */
164
        public void setIdentifierType(PatientIdentifierType identifierType) {
165
                this.identifierType = identifierType;
1✔
166
        }
1✔
167
        
168
        /**
169
         * @return Returns the location.
170
         */
171
        public Location getLocation() {
172
                return location;
1✔
173
        }
174
        
175
        /**
176
         * @param location The location to set.
177
         */
178
        public void setLocation(Location location) {
179
                this.location = location;
1✔
180
        }
1✔
181
        
182
        /**
183
         * @return Returns the patient.
184
         */
185
        public Patient getPatient() {
186
                return patient;
1✔
187
        }
188
        
189
        /**
190
         * @param patient The patient to set.
191
         */
192
        public void setPatient(Patient patient) {
193
                this.patient = patient;
1✔
194
        }
1✔
195
        
196
        @Override
197
        public String toString() {
198
                return this.identifier;
1✔
199
        }
200
        
201
        /**
202
         * @return Returns the preferred.
203
         */
204
        public Boolean getPreferred() {
205
                return preferred;
1✔
206
        }
207
        
208
        /**
209
         * @param preferred The preferred to set.
210
         */
211
        public void setPreferred(Boolean preferred) {
212
                this.preferred = preferred;
1✔
213
        }
1✔
214
        
215
        /**
216
         * @return the preferred status
217
         * 
218
         * @deprecated as of 2.0, use {@link #getPreferred()}
219
         */
220
        @Deprecated
221
        @JsonIgnore
222
        public Boolean isPreferred() {
223
                return getPreferred();
×
224
        }
225
        
226
        /**
227
         * @see java.lang.Comparable#compareTo(java.lang.Object)
228
         * @deprecated since 1.12. Use DefaultComparator instead.
229
         * Note: this comparator imposes orderings that are inconsistent with equals.
230
         */
231
        @Deprecated
232
        @Override
233
        @SuppressWarnings("squid:S1210")
234
        public int compareTo(PatientIdentifier other) {
235
                DefaultComparator piDefaultComparator = new DefaultComparator();
1✔
236
                return piDefaultComparator.compare(this, other);
1✔
237
        }
238
        
239
        /**
240
         * @since 1.5
241
         * @see org.openmrs.OpenmrsObject#getId()
242
         */
243
        @Override
244
        public Integer getId() {
245
                return getPatientIdentifierId();
1✔
246
        }
247
        
248
        /**
249
         * @since 1.5
250
         * @see org.openmrs.OpenmrsObject#setId(java.lang.Integer)
251
         */
252
        @Override
253
        public void setId(Integer id) {
254
                setPatientIdentifierId(id);
×
255
        }
×
256
        
257
        /**
258
         * @since 1.5
259
         * @return the patientIdentifierId
260
         */
261
        public Integer getPatientIdentifierId() {
262
                return patientIdentifierId;
1✔
263
        }
264
        
265
        /**
266
         * @since 1.5
267
         * @param patientIdentifierId the patientIdentifierId to set
268
         */
269
        public void setPatientIdentifierId(Integer patientIdentifierId) {
270
                this.patientIdentifierId = patientIdentifierId;
1✔
271
        }
1✔
272

273
        /**
274
         * bitwise copy of the PatientIdentifier object. NOTICE: THIS WILL NOT COPY THE PATIENT OBJECT. The
275
         * PatientIdentifier.patient object in this object AND the cloned object will point at the same
276
         * patient
277
         *
278
         * @return New PatientIdentifier object
279
         * @since 2.2.0
280
         */
281
        @Override
282
        public Object clone() {
283
                try {
284
                        return super.clone();
1✔
285
                }
286
                catch (CloneNotSupportedException e) {
×
287
                        throw new InternalError("PatientIdentifier should be cloneable");
×
288
                }
289
        }
290
        
291
        /**
292
         Provides a default comparator.
293
         @since 1.12
294
         **/
295
        public static class DefaultComparator implements Comparator<PatientIdentifier>, Serializable {
1✔
296

297
                private static final long serialVersionUID = 1L;
298
                
299
                @Override
300
                public int compare(PatientIdentifier pi1, PatientIdentifier pi2) {
301
                        int retValue = 0;
1✔
302
                        if (pi2 != null) {
1✔
303
                                retValue = pi1.getVoided().compareTo(pi2.getVoided());
1✔
304
                                if (retValue == 0) {
1✔
305
                                        retValue = pi1.getPreferred().compareTo(pi2.getPreferred());
1✔
306
                                }
307
                                if (retValue == 0) {
1✔
308
                                        retValue = OpenmrsUtil.compareWithNullAsLatest(pi1.getDateCreated(), pi2.getDateCreated());
1✔
309
                                }
310
                                if (pi1.getIdentifierType() == null && pi2.getIdentifierType() == null) {
1✔
311
                                        return 0;
1✔
312
                                }
313
                                if (pi1.getIdentifierType() == null && pi2.getIdentifierType() != null) {
1✔
314
                                        retValue = 1;
×
315
                                }
316
                                if (pi1.getIdentifierType() == null && pi2.getIdentifierType() != null) {
1✔
317
                                        retValue = -1;
×
318
                                }
319
                                if (retValue == 0) {
1✔
320
                                        retValue = OpenmrsUtil.compareWithNullAsGreatest(pi1.getIdentifierType().getPatientIdentifierTypeId(),
1✔
321
                                            pi2.getIdentifierType().getPatientIdentifierTypeId());
1✔
322
                                }
323
                                if (retValue == 0) {
1✔
324
                                        retValue = OpenmrsUtil.compareWithNullAsGreatest(pi1.getIdentifier(), pi2.getIdentifier());
1✔
325
                                }
326
                                
327
                                // if we've gotten this far, just check all identifier values.  If they are
328
                                // equal, leave the objects at 0.  If not, arbitrarily pick retValue=1
329
                                // and return that (they are not equal).
330
                                if (retValue == 0 && !pi1.equalsContent(pi2)) {
1✔
331
                                        retValue = 1;
1✔
332
                                }
333
                        }
334
                        
335
                        return retValue;
1✔
336
                }
337
        }
338

339

340
        /**
341
         * Gets patient program associated to the identifier in context
342
         * @since 2.6.0
343
         * @return patientProgram the patient program associated to an identifier
344
         */
345
        public PatientProgram getPatientProgram() {
346
                return patientProgram;
1✔
347
        }
348

349
        /**
350
         * This method sets the patient program on a patient Identifier
351
         * @since 2.6.0
352
         * @param patientProgram The patientProgram to set.
353
         */
354
        public void setPatientProgram(PatientProgram patientProgram) {
355
                this.patientProgram = patientProgram;
1✔
356
        }
1✔
357
}
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