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

openmrs / openmrs-core / 15205088843

23 May 2025 07:43AM UTC coverage: 65.083% (+0.01%) from 65.069%
15205088843

push

github

rkorytkowski
TRUNK-6300: Adding Windows test, cleaning up logs, adjusting variable name

2 of 2 new or added lines in 2 files covered. (100.0%)

336 existing lines in 18 files now uncovered.

23379 of 35922 relevant lines covered (65.08%)

0.65 hits per line

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

95.81
/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 javax.persistence.Cacheable;
15
import java.io.Serializable;
16
import java.util.ArrayList;
17
import java.util.Comparator;
18
import java.util.Date;
19
import java.util.List;
20

21
import org.apache.commons.lang3.builder.EqualsBuilder;
22
import org.codehaus.jackson.annotate.JsonIgnore;
23
import org.hibernate.annotations.Cache;
24
import org.hibernate.annotations.CacheConcurrencyStrategy;
25
import org.hibernate.envers.Audited;
26
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.AssociationInverseSide;
27
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.DocumentId;
28
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
29
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
30
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.IndexedEmbedded;
31
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.ObjectPath;
32
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.PropertyValue;
33
import org.openmrs.api.APIException;
34
import org.openmrs.api.db.hibernate.search.SearchAnalysis;
35
import org.openmrs.layout.name.NameSupport;
36
import org.openmrs.layout.name.NameTemplate;
37
import org.openmrs.util.OpenmrsConstants;
38
import org.openmrs.util.OpenmrsUtil;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41
import org.springframework.util.StringUtils;
42

43
/**
44
 * A Person can have zero to n PersonName(s).
45
 */
46
@Indexed
47
@Audited
48
@Cacheable
49
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
50
public class PersonName extends BaseChangeableOpenmrsData implements java.io.Serializable, Cloneable, Comparable<PersonName> {
51
        
52
        public static final long serialVersionUID = 4353L;
53

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

56
        // Fields
57
        @DocumentId
58
        private Integer personNameId;
59

60
        @IndexedEmbedded(includeEmbeddedObjectId = true)
61
        @AssociationInverseSide(inversePath = @ObjectPath({
62
                @PropertyValue(propertyName = "names")
63
        }))
64
        private Person person;
65

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

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

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