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

openmrs / openmrs-core / 24035792291

06 Apr 2026 02:28PM UTC coverage: 63.244% (+0.07%) from 63.176%
24035792291

push

github

ibacher
LUI-199: Editing the Address Template does not save the address template correctly (#5839)

13 of 23 new or added lines in 2 files covered. (56.52%)

44 existing lines in 4 files now uncovered.

23203 of 36688 relevant lines covered (63.24%)

0.63 hits per line

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

72.09
/api/src/main/java/org/openmrs/validator/PersonAddressValidator.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.validator;
11

12
import java.lang.reflect.InvocationTargetException;
13
import java.util.Date;
14
import java.util.List;
15

16
import org.apache.commons.beanutils.PropertyUtils;
17
import org.apache.commons.lang3.StringUtils;
18
import org.openmrs.PersonAddress;
19
import org.openmrs.annotation.Handler;
20
import org.openmrs.api.context.Context;
21
import org.openmrs.layout.address.AddressSupport;
22
import org.openmrs.layout.address.AddressTemplate;
23
import org.openmrs.util.OpenmrsUtil;
24
import org.slf4j.Logger;
25
import org.slf4j.LoggerFactory;
26
import org.springframework.validation.Errors;
27
import org.springframework.validation.Validator;
28

29
/**
30
 * This class validates a PersonAddress object.
31
 *
32
 * @since 1.9
33
 */
34
@Handler(supports = { PersonAddress.class }, order = 50)
35
public class PersonAddressValidator implements Validator {
1✔
36

37
        private static final Logger log = LoggerFactory.getLogger(PersonAddressValidator.class);
1✔
38

39
        /**
40
         * @see org.springframework.validation.Validator#supports(java.lang.Class)
41
         */
42
        @Override
43
        public boolean supports(Class<?> c) {
44
                return PersonAddress.class.isAssignableFrom(c);
1✔
45
        }
46

47
        /**
48
         * @see org.springframework.validation.Validator#validate(java.lang.Object,
49
         *      org.springframework.validation.Errors)
50
         * <strong>Should</strong> pass if all the dates are valid
51
         * <strong>Should</strong> fail if the startDate is in the future
52
         * <strong>Should</strong> fail if the endDate is before the startDate
53
         * <strong>Should</strong> pass if startDate and endDate are both null
54
         * <strong>Should</strong> pass if startDate is null
55
         * <strong>Should</strong> pass if endDate is null
56
         * <strong>Should</strong> fail if required fields are empty
57
         * <strong>Should</strong> pass if required fields are not empty
58
         * <strong>Should</strong> pass validation if field lengths are correct
59
         * <strong>Should</strong> fail validation if field lengths are not correct
60
         */
61
        @Override
62
        public void validate(Object object, Errors errors) {
63
                //TODO Validate other aspects of the personAddress object
64
                log.debug("{}.validate...", this.getClass().getName());
1✔
65

66
                if (object == null) {
1✔
67
                        throw new IllegalArgumentException("The personAddress object should not be null");
×
68
                }
69

70
                PersonAddress personAddress = (PersonAddress) object;
1✔
71

72
                //resolve a shorter name to display along with the error message
73
                String addressString;
74
                if (StringUtils.isNotBlank(personAddress.getAddress1())) {
1✔
75
                        addressString = personAddress.getAddress1();
1✔
76
                } else if (StringUtils.isNotBlank(personAddress.getAddress2())) {
1✔
77
                        addressString = personAddress.getAddress2();
×
78
                } else if (StringUtils.isNotBlank(personAddress.getCityVillage())) {
1✔
79
                        addressString = personAddress.getCityVillage();
1✔
80
                } else {
81
                        addressString = personAddress.toString();
1✔
82
                }
83

84
                if (OpenmrsUtil.compareWithNullAsEarliest(personAddress.getStartDate(), new Date()) > 0) {
1✔
85
                        errors.rejectValue("startDate", "PersonAddress.error.startDateInFuture", new Object[] { "'" + addressString
1✔
86
                                + "'" }, "The Start Date for address '" + addressString + "' shouldn't be in the future");
87
                }
88

89
                if (personAddress.getStartDate() != null
1✔
90
                        && OpenmrsUtil.compareWithNullAsLatest(personAddress.getStartDate(), personAddress.getEndDate()) > 0) {
1✔
91
                        errors.rejectValue("endDate", "PersonAddress.error.endDateBeforeStartDate", new Object[] { "'" + addressString
1✔
92
                                + "'" }, "The End Date for address '" + addressString + "' shouldn't be earlier than the Start Date");
93
                }
94

95
                List<String> requiredElements;
96

97
                try {
98
                        List<AddressTemplate> addressTemplates = AddressSupport.getInstance().getAddressTemplate();
1✔
99
                        if (addressTemplates == null || addressTemplates.isEmpty()) {
1✔
NEW
100
                                errors.reject(Context.getMessageSourceService().getMessage("AddressTemplate.error"));
×
NEW
101
                                return;
×
102
                        }
103

104
                        requiredElements = addressTemplates.get(0).getRequiredElements();
1✔
105
                }
106
                catch (Exception e) {
×
107
                        errors.reject(Context.getMessageSourceService().getMessage("AddressTemplate.error"));
×
108
                        return;
×
109
                }
1✔
110

111
                if (requiredElements != null) {
1✔
112
                        for (String fieldName : requiredElements) {
1✔
113
                                try {
114
                                        Object value = PropertyUtils.getProperty(personAddress, fieldName);
1✔
115
                                        if (StringUtils.isBlank((String) value)) {
1✔
116
                                                //required field not found
117
                                                errors.reject(Context.getMessageSourceService().getMessage(
1✔
118
                                                    "AddressTemplate.error.requiredAddressFieldIsBlank", new Object[] { fieldName },
119
                                                    Context.getLocale()));
1✔
120
                                        }
121
                                }
NEW
122
                                catch (IllegalAccessException | ClassCastException | InvocationTargetException | NoSuchMethodException e) {
×
123
                                        //wrong field declared in template
NEW
124
                                        errors.reject(Context.getMessageSourceService().getMessage(
×
125
                                            "AddressTemplate.error.fieldNotDeclaredInTemplate", new Object[] { fieldName },
NEW
126
                                            Context.getLocale()));
×
127
                                }
NEW
128
                                catch (Exception e) {
×
129
                                        //for any other exception
NEW
130
                                        errors.reject(Context.getMessageSourceService().getMessage("AddressTemplate.error"));
×
131
                                }
1✔
132
                        }
1✔
133
                }
134

135
                ValidateUtil.validateFieldLengths(errors, object.getClass(), "address1", "address2", "cityVillage", "stateProvince",
1✔
136
                    "postalCode", "country", "latitude", "longitude", "voidReason", "countyDistrict", "address3", "address4",
137
                    "address5", "address6", "address7", "address8", "address9", "address10", "address11", "address12", "address13",
138
                    "address14", "address15");
139
        }
1✔
140
}
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