• 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

84.55
/api/src/main/java/org/openmrs/api/impl/LocationServiceImpl.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.impl;
11

12
import java.util.ArrayList;
13
import java.util.Date;
14
import java.util.List;
15
import java.util.Map;
16

17
import org.apache.commons.collections.CollectionUtils;
18
import org.openmrs.Address;
19
import org.openmrs.Location;
20
import org.openmrs.LocationAttribute;
21
import org.openmrs.LocationAttributeType;
22
import org.openmrs.LocationTag;
23
import org.openmrs.api.APIException;
24
import org.openmrs.api.LocationService;
25
import org.openmrs.api.context.Context;
26
import org.openmrs.api.db.LocationDAO;
27
import org.openmrs.customdatatype.CustomDatatypeUtil;
28
import org.openmrs.util.OpenmrsConstants;
29
import org.openmrs.util.OpenmrsUtil;
30
import org.springframework.transaction.annotation.Transactional;
31
import org.springframework.util.StringUtils;
32

33
/**
34
 * Default implementation of the {@link LocationService}
35
 * <p>
36
 * This class should not be instantiated alone, get a service class from the Context:
37
 * Context.getLocationService();
38
 *
39
 * @see org.openmrs.api.context.Context
40
 * @see org.openmrs.api.LocationService
41
 * @see org.openmrs.Location
42
 */
43
@Transactional
44
public class LocationServiceImpl extends BaseOpenmrsService implements LocationService {
1✔
45
        
46
        private LocationDAO dao;
47
        
48
        /**
49
         * @see org.openmrs.api.LocationService#setLocationDAO(org.openmrs.api.db.LocationDAO)
50
         */
51
        @Override
52
        public void setLocationDAO(LocationDAO dao) {
53
                this.dao = dao;
1✔
54
        }
1✔
55
        
56
        /**
57
         * @see org.openmrs.api.LocationService#saveLocation(org.openmrs.Location)
58
         */
59
        @Override
60
        public Location saveLocation(Location location) throws APIException {
61
                if (location.getName() == null) {
1✔
62
                        throw new APIException("Location.name.required", (Object[]) null);
×
63
                }
64
                
65
                // Check for transient tags. If found, try to match by name and overwrite, otherwise throw exception.
66
                if (location.getTags() != null) {
1✔
67
                        for (LocationTag tag : location.getTags()) {
1✔
68
                                
69
                                // only check transient (aka non-precreated) location tags
70
                                if (tag.getLocationTagId() == null) {
1✔
71
                                        if (!StringUtils.hasLength(tag.getName())) {
1✔
72
                                                throw new APIException("Location.tag.name.required", (Object[]) null);
1✔
73
                                        }
74
                                        
75
                                        LocationTag existing = Context.getLocationService().getLocationTagByName(tag.getName());
1✔
76
                                        if (existing != null) {
1✔
77
                                                location.removeTag(tag);
1✔
78
                                                location.addTag(existing);
1✔
79
                                        } else {
80
                                                throw new APIException("Location.cannot.add.transient.tags", (Object[]) null);
1✔
81
                                        }
82
                                }
83
                        }
1✔
84
                }
85
                
86
                CustomDatatypeUtil.saveAttributesIfNecessary(location);
1✔
87
                
88
                return dao.saveLocation(location);
1✔
89
        }
90
        
91
        /**
92
         * @see org.openmrs.api.LocationService#getLocation(java.lang.Integer)
93
         */
94
        @Override
95
        @Transactional(readOnly = true)
96
        public Location getLocation(Integer locationId) throws APIException {
97
                return dao.getLocation(locationId);
1✔
98
        }
99
        
100
        /**
101
         * @see org.openmrs.api.LocationService#getLocation(java.lang.String)
102
         */
103
        @Override
104
        @Transactional(readOnly = true)
105
        public Location getLocation(String name) throws APIException {
106
                return dao.getLocation(name);
1✔
107
        }
108
        
109
        /**
110
         * @see org.openmrs.api.LocationService#getDefaultLocation()
111
         */
112
        @Override
113
        @Transactional(readOnly = true)
114
        public Location getDefaultLocation() throws APIException {
115
                Location location = null;
1✔
116
                String locationGP = Context.getAdministrationService().getGlobalProperty(
1✔
117
                    OpenmrsConstants.GLOBAL_PROPERTY_DEFAULT_LOCATION_NAME);
118
                
119
                if (StringUtils.hasText(locationGP)) {
1✔
120
                        location = Context.getLocationService().getLocation(locationGP);
1✔
121
                }
122

123
                if (location == null) {
1✔
124
                        location = getDefaultLocation(null, locationGP);
1✔
125
                }
126
                
127
                // If neither exist, get the first available location
128
                if (location == null) {
1✔
129
                        location = Context.getLocationService().getLocation(1);
1✔
130
                }
131
                
132
                return location;
1✔
133
        }
134

135
        private Location getDefaultLocation(Location location, String locationGP) {
136
                //Try to look up 'Unknown Location' in case the global property is something else
137
                Location result = getDefaultLocationFromSting(location, locationGP, "Unknown Location");
1✔
138

139
                // If Unknown Location does not exist, try Unknown if the global property was different
140
                if (result == null) {
1✔
141
                        result = getDefaultLocationFromSting(location, locationGP, "Unknown");
1✔
142
                }
143

144
                return result;
1✔
145
        }
146

147
        private Location getDefaultLocationFromSting(Location location, String locationGP, String defaultLocation) {
148
                Location result = null;
1✔
149
                if (location == null && (!StringUtils.hasText(locationGP) || !defaultLocation.equalsIgnoreCase(locationGP))) {
1✔
150
                        result = Context.getLocationService().getLocation(defaultLocation);
1✔
151
                }
152

153
                return result;
1✔
154
        }
155
        
156
        /**
157
         * @see org.openmrs.api.LocationService#getLocationByUuid(java.lang.String)
158
         */
159
        @Override
160
        @Transactional(readOnly = true)
161
        public Location getLocationByUuid(String uuid) throws APIException {
162
                return dao.getLocationByUuid(uuid);
1✔
163
        }
164
        
165
        /**
166
         * @see org.openmrs.api.LocationService#getLocationTagByUuid(java.lang.String)
167
         */
168
        @Override
169
        @Transactional(readOnly = true)
170
        public LocationTag getLocationTagByUuid(String uuid) throws APIException {
171
                return dao.getLocationTagByUuid(uuid);
1✔
172
        }
173
        
174
        /**
175
         * @see org.openmrs.api.LocationService#getAllLocations()
176
         */
177
        @Override
178
        @Transactional(readOnly = true)
179
        public List<Location> getAllLocations() throws APIException {
180
                return dao.getAllLocations(true);
1✔
181
        }
182
        
183
        /**
184
         * @see org.openmrs.api.LocationService#getAllLocations(boolean)
185
         */
186
        @Override
187
        @Transactional(readOnly = true)
188
        public List<Location> getAllLocations(boolean includeRetired) throws APIException {
189
                return dao.getAllLocations(includeRetired);
1✔
190
        }
191
        
192
        /**
193
         * @see org.openmrs.api.LocationService#getLocations(java.lang.String)
194
         */
195
        @Override
196
        @Transactional(readOnly = true)
197
        public List<Location> getLocations(String nameFragment) throws APIException {
198
                return Context.getLocationService().getLocations(nameFragment, null, null, false, null, null);
1✔
199
        }
200
        
201
        /**
202
         * @see org.openmrs.api.LocationService#getLocationsByTag(LocationTag)
203
         */
204
        @Override
205
        @Transactional(readOnly = true)
206
        public List<Location> getLocationsByTag(LocationTag tag) throws APIException {
207
                List<Location> locations = new ArrayList<>();
1✔
208
                
209
                for (Location l : dao.getAllLocations(false)) {
1✔
210
                        if (l.getTags() != null && l.getTags().contains(tag)) {
1✔
211
                                locations.add(l);
1✔
212
                        }
213
                }
1✔
214
                
215
                return locations;
1✔
216
        }
217
        
218
        /**
219
         * @see org.openmrs.api.LocationService#getLocationsHavingAllTags(List)
220
         */
221
        @Override
222
        @Transactional(readOnly = true)
223
        public List<Location> getLocationsHavingAllTags(List<LocationTag> tags) throws APIException {
224
                return CollectionUtils.isEmpty(tags) ? getAllLocations(false) : dao.getLocationsHavingAllTags(tags);
1✔
225
        }
226
        
227
        /**
228
         * @see org.openmrs.api.LocationService#getLocationsHavingAnyTag(List)
229
         */
230
        @Override
231
        @Transactional(readOnly = true)
232
        public List<Location> getLocationsHavingAnyTag(List<LocationTag> tags) throws APIException {
233
                List<Location> locations = new ArrayList<>();
1✔
234
                
235
                for (Location loc : dao.getAllLocations(false)) {
1✔
236
                        for (LocationTag t : tags) {
1✔
237
                                if (loc.getTags().contains(t) && !locations.contains(loc)) {
1✔
238
                                        locations.add(loc);
1✔
239
                                }
240
                        }
1✔
241
                }
1✔
242
                
243
                return locations;
1✔
244
        }
245
        
246
        /**
247
         * @see org.openmrs.api.LocationService#retireLocation(Location, String)
248
         */
249
        @Override
250
        public Location retireLocation(Location location, String reason) throws APIException {
251
                location.setRetired(true);
1✔
252
                location.setRetireReason(reason);
1✔
253
                return Context.getLocationService().saveLocation(location);
1✔
254
        }
255
        
256
        /**
257
         * @see org.openmrs.api.LocationService#unretireLocation(org.openmrs.Location)
258
         */
259
        @Override
260
        public Location unretireLocation(Location location) throws APIException {
261
                location.setRetired(false);
1✔
262
                return Context.getLocationService().saveLocation(location);
1✔
263
        }
264
        
265
        /**
266
         * @see org.openmrs.api.LocationService#purgeLocation(org.openmrs.Location)
267
         */
268
        @Override
269
        public void purgeLocation(Location location) throws APIException {
270
                dao.deleteLocation(location);
1✔
271
        }
1✔
272
        
273
        /**
274
         * @see org.openmrs.api.LocationService#saveLocationTag(org.openmrs.LocationTag)
275
         */
276
        @Override
277
        public LocationTag saveLocationTag(LocationTag tag) throws APIException {
278
                return dao.saveLocationTag(tag);
1✔
279
        }
280
        
281
        /**
282
         * @see org.openmrs.api.LocationService#getLocationTag(java.lang.Integer)
283
         */
284
        @Override
285
        @Transactional(readOnly = true)
286
        public LocationTag getLocationTag(Integer locationTagId) throws APIException {
287
                return dao.getLocationTag(locationTagId);
1✔
288
        }
289
        
290
        /**
291
         * @see org.openmrs.api.LocationService#getLocationTagByName(java.lang.String)
292
         */
293
        @Override
294
        @Transactional(readOnly = true)
295
        public LocationTag getLocationTagByName(String tag) throws APIException {
296
                return dao.getLocationTagByName(tag);
1✔
297
        }
298
        
299
        /**
300
         * @see org.openmrs.api.LocationService#getAllLocationTags()
301
         */
302
        @Override
303
        @Transactional(readOnly = true)
304
        public List<LocationTag> getAllLocationTags() throws APIException {
305
                return dao.getAllLocationTags(true);
1✔
306
        }
307
        
308
        /**
309
         * @see org.openmrs.api.LocationService#getAllLocationTags(boolean)
310
         */
311
        @Override
312
        @Transactional(readOnly = true)
313
        public List<LocationTag> getAllLocationTags(boolean includeRetired) throws APIException {
314
                return dao.getAllLocationTags(includeRetired);
1✔
315
        }
316
        
317
        /**
318
         * @see org.openmrs.api.LocationService#getLocationTags(java.lang.String)
319
         */
320
        @Override
321
        @Transactional(readOnly = true)
322
        public List<LocationTag> getLocationTags(String search) throws APIException {
323
                if (StringUtils.isEmpty(search)) {
1✔
324
                        return Context.getLocationService().getAllLocationTags(true);
×
325
                }
326
                
327
                return dao.getLocationTags(search);
1✔
328
        }
329
        
330
        /**
331
         * @see org.openmrs.api.LocationService#retireLocationTag(LocationTag, String)
332
         */
333
        @Override
334
        public LocationTag retireLocationTag(LocationTag tag, String reason) throws APIException {
335
                if (tag.getRetired()) {
1✔
336
                        return tag;
1✔
337
                } else {
338
                        if (reason == null) {
×
339
                                throw new APIException("Location.retired.reason.required", (Object[]) null);
×
340
                        }
341
                        tag.setRetired(true);
×
342
                        tag.setRetireReason(reason);
×
343
                        tag.setRetiredBy(Context.getAuthenticatedUser());
×
344
                        tag.setDateRetired(new Date());
×
345
                        return Context.getLocationService().saveLocationTag(tag);
×
346
                }
347
        }
348
        
349
        /**
350
         * @see org.openmrs.api.LocationService#unretireLocationTag(org.openmrs.LocationTag)
351
         */
352
        @Override
353
        public LocationTag unretireLocationTag(LocationTag tag) throws APIException {
354
                tag.setRetired(false);
1✔
355
                tag.setRetireReason(null);
1✔
356
                tag.setRetiredBy(null);
1✔
357
                tag.setDateRetired(null);
1✔
358
                return Context.getLocationService().saveLocationTag(tag);
1✔
359
        }
360
        
361
        /**
362
         * @see org.openmrs.api.LocationService#purgeLocationTag(org.openmrs.LocationTag)
363
         */
364
        @Override
365
        public void purgeLocationTag(LocationTag tag) throws APIException {
366
                dao.deleteLocationTag(tag);
1✔
367
        }
1✔
368
        
369
        /**
370
         * @see org.openmrs.api.LocationService#getCountOfLocations(String, Boolean)
371
         */
372
        @Override
373
        @Transactional(readOnly = true)
374
        public Integer getCountOfLocations(String nameFragment, Boolean includeRetired) {
375
                return OpenmrsUtil.convertToInteger(dao.getCountOfLocations(nameFragment, includeRetired));
×
376
        }
377
        
378
        /**
379
         * @see LocationService#getLocations(String, org.openmrs.Location, java.util.Map, boolean,
380
         *      Integer, Integer)
381
         */
382
        @Override
383
        public List<Location> getLocations(String nameFragment, Location parent,
384
                Map<LocationAttributeType, Object> attributeValues, boolean includeRetired, Integer start, Integer length) {
385
                
386
                Map<LocationAttributeType, String> serializedAttributeValues = CustomDatatypeUtil
1✔
387
                        .getValueReferences(attributeValues);
1✔
388
                
389
                return dao.getLocations(nameFragment, parent, serializedAttributeValues, includeRetired, start, length);
1✔
390
        }
391
        
392
        /**
393
         * @see LocationService#getRootLocations(boolean)
394
         */
395
        @Override
396
        @Transactional(readOnly = true)
397
        public List<Location> getRootLocations(boolean includeRetired) throws APIException {
398
                return dao.getRootLocations(includeRetired);
1✔
399
        }
400
        
401
        /**
402
         * @see org.openmrs.api.LocationService#getPossibleAddressValues(Address, String)
403
         */
404
        @Override
405
        public List<String> getPossibleAddressValues(Address incomplete, String fieldName) throws APIException {
406
                // not implemented by default
407
                return null;
×
408
        }
409
        
410
        /**
411
         * @see org.openmrs.api.LocationService#getAllLocationAttributeTypes()
412
         */
413
        @Override
414
        @Transactional(readOnly = true)
415
        public List<LocationAttributeType> getAllLocationAttributeTypes() {
416
                return dao.getAllLocationAttributeTypes();
1✔
417
        }
418
        
419
        /**
420
         * @see org.openmrs.api.LocationService#getLocationAttributeType(java.lang.Integer)
421
         */
422
        @Override
423
        @Transactional(readOnly = true)
424
        public LocationAttributeType getLocationAttributeType(Integer id) {
425
                return dao.getLocationAttributeType(id);
1✔
426
        }
427
        
428
        /**
429
         * @see org.openmrs.api.LocationService#getLocationAttributeTypeByUuid(java.lang.String)
430
         */
431
        @Override
432
        @Transactional(readOnly = true)
433
        public LocationAttributeType getLocationAttributeTypeByUuid(String uuid) {
434
                return dao.getLocationAttributeTypeByUuid(uuid);
1✔
435
        }
436
        
437
        /**
438
         * @see org.openmrs.api.LocationService#saveLocationAttributeType(org.openmrs.LocationAttributeType)
439
         */
440
        @Override
441
        public LocationAttributeType saveLocationAttributeType(LocationAttributeType locationAttributeType) {
442
                return dao.saveLocationAttributeType(locationAttributeType);
1✔
443
        }
444
        
445
        /**
446
         * @see org.openmrs.api.LocationService#retireLocationAttributeType(org.openmrs.LocationAttributeType,
447
         *      java.lang.String)
448
         */
449
        @Override
450
        public LocationAttributeType retireLocationAttributeType(LocationAttributeType locationAttributeType, String reason) {
451
                return dao.saveLocationAttributeType(locationAttributeType);
1✔
452
        }
453
        
454
        /**
455
         * @see org.openmrs.api.LocationService#unretireLocationAttributeType(org.openmrs.LocationAttributeType)
456
         */
457
        @Override
458
        public LocationAttributeType unretireLocationAttributeType(LocationAttributeType locationAttributeType) {
459
                return Context.getLocationService().saveLocationAttributeType(locationAttributeType);
1✔
460
        }
461
        
462
        /**
463
         * @see org.openmrs.api.LocationService#purgeLocationAttributeType(org.openmrs.LocationAttributeType)
464
         */
465
        @Override
466
        public void purgeLocationAttributeType(LocationAttributeType locationAttributeType) {
467
                dao.deleteLocationAttributeType(locationAttributeType);
1✔
468
        }
1✔
469
        
470
        /**
471
         * @see org.openmrs.api.LocationService#getLocationAttributeByUuid(java.lang.String)
472
         */
473
        @Override
474
        @Transactional(readOnly = true)
475
        public LocationAttribute getLocationAttributeByUuid(String uuid) {
476
                return dao.getLocationAttributeByUuid(uuid);
1✔
477
        }
478
        
479
        /**
480
         * @see org.openmrs.api.LocationService#getAddressTemplate()
481
         */
482
        @Override
483
        @Transactional(readOnly = true)
484
        public String getAddressTemplate() throws APIException {
UNCOV
485
                String addressTemplate = Context.getAdministrationService().getGlobalProperty(
×
486
                    OpenmrsConstants.GLOBAL_PROPERTY_ADDRESS_TEMPLATE);
UNCOV
487
                if (!StringUtils.hasLength(addressTemplate)) {
×
UNCOV
488
                        addressTemplate = OpenmrsConstants.DEFAULT_ADDRESS_TEMPLATE;
×
489
                }
490
                
UNCOV
491
                return addressTemplate;
×
492
        }
493
        
494
        /**
495
         * @see org.openmrs.api.LocationService#saveAddressTemplate(String)
496
         */
497
        @Override
498
        public void saveAddressTemplate(String xml) throws APIException {
499
                Context.getAdministrationService().setGlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_ADDRESS_TEMPLATE, xml);
×
500
                
501
        }
×
502
        
503
        /**
504
         * @see org.openmrs.api.LocationService#getLocationAttributeTypeByName(java.lang.String)
505
         */
506
        @Override
507
        @Transactional(readOnly = true)
508
        public LocationAttributeType getLocationAttributeTypeByName(String name) {
509
                return dao.getLocationAttributeTypeByName(name);
1✔
510
        }
511
}
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