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

openmrs / openmrs-core / 29433712829

15 Jul 2026 04:40PM UTC coverage: 65.967%. Remained the same
29433712829

push

github

ibacher
TRUNK-6444: Backport for 2.8.x (#6330)

24247 of 36756 relevant lines covered (65.97%)

0.66 hits per line

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

93.78
/api/src/main/java/org/openmrs/api/impl/ConceptServiceImpl.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.lang.reflect.InvocationTargetException;
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.Date;
17
import java.util.HashMap;
18
import java.util.HashSet;
19
import java.util.Iterator;
20
import java.util.List;
21
import java.util.Locale;
22
import java.util.Map;
23
import java.util.Set;
24
import java.util.UUID;
25

26
import org.apache.commons.beanutils.BeanUtils;
27
import org.apache.commons.text.StringEscapeUtils;
28
import org.apache.commons.collections.CollectionUtils;
29
import org.apache.commons.lang3.StringUtils;
30
import org.hibernate.Hibernate;
31
import org.openmrs.Concept;
32
import org.openmrs.ConceptAnswer;
33
import org.openmrs.ConceptAttribute;
34
import org.openmrs.ConceptAttributeType;
35
import org.openmrs.ConceptClass;
36
import org.openmrs.ConceptComplex;
37
import org.openmrs.ConceptDatatype;
38
import org.openmrs.ConceptDescription;
39
import org.openmrs.ConceptMap;
40
import org.openmrs.ConceptMapType;
41
import org.openmrs.ConceptName;
42
import org.openmrs.ConceptNameTag;
43
import org.openmrs.ConceptNumeric;
44
import org.openmrs.ConceptProposal;
45
import org.openmrs.ConceptReferenceRange;
46
import org.openmrs.ConceptReferenceRangeContext;
47
import org.openmrs.ConceptReferenceTerm;
48
import org.openmrs.ConceptReferenceTermMap;
49
import org.openmrs.ConceptSearchResult;
50
import org.openmrs.ConceptSet;
51
import org.openmrs.ConceptSource;
52
import org.openmrs.ConceptStopWord;
53
import org.openmrs.Drug;
54
import org.openmrs.DrugIngredient;
55
import org.openmrs.Obs;
56
import org.openmrs.Patient;
57
import org.openmrs.Person;
58
import org.openmrs.api.APIException;
59
import org.openmrs.api.AdministrationService;
60
import org.openmrs.api.ConceptInUseException;
61
import org.openmrs.api.ConceptNameInUseException;
62
import org.openmrs.api.ConceptService;
63
import org.openmrs.api.ConceptStopWordException;
64
import org.openmrs.api.ConceptsLockedException;
65
import org.openmrs.api.context.Context;
66
import org.openmrs.api.db.ConceptDAO;
67
import org.openmrs.api.db.DAOException;
68
import org.openmrs.api.db.hibernate.HibernateUtil;
69
import org.openmrs.customdatatype.CustomDatatypeUtil;
70
import org.openmrs.parameter.ConceptSearchCriteria;
71
import org.openmrs.parameter.ConceptSearchCriteriaBuilder;
72
import org.openmrs.util.ConceptReferenceRangeUtility;
73
import org.openmrs.util.OpenmrsConstants;
74
import org.openmrs.util.OpenmrsUtil;
75
import org.openmrs.validator.ValidateUtil;
76
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
78
import org.springframework.cache.annotation.CacheEvict;
79
import org.springframework.cache.annotation.Cacheable;
80
import org.springframework.transaction.annotation.Transactional;
81

82
/**
83
 * Default Implementation of ConceptService service layer classes
84
 * 
85
 * @see org.openmrs.api.ConceptService to access these methods
86
 */
87
@Transactional
88
public class ConceptServiceImpl extends BaseOpenmrsService implements ConceptService {
1✔
89
        
90
        private static final Logger log = LoggerFactory.getLogger(ConceptServiceImpl.class);
1✔
91
        
92
        private ConceptDAO dao;
93
        
94
        private static Concept trueConcept;
95
        
96
        private static Concept falseConcept;
97
        
98
        private static Concept unknownConcept;
99

100
        private static final String ERROR_MESSAGE = "Error generated";
101

102
        private static final String CONCEPT_IDS_BY_MAPPING_CACHE_NAME = "conceptIdsByMapping";
103

104
        /**
105
         * @see org.openmrs.api.ConceptService#setConceptDAO(org.openmrs.api.db.ConceptDAO)
106
         */
107
        @Override
108
        public void setConceptDAO(ConceptDAO dao) {
109
                this.dao = dao;
1✔
110
        }
1✔
111

112
        /**
113
         * @see org.openmrs.api.ConceptService#saveConcept(org.openmrs.Concept)
114
         * <strong>Should</strong> return the concept with new conceptID if creating new concept
115
         * <strong>Should</strong> return the concept with same conceptID if updating existing concept
116
         * <strong>Should</strong> leave preferred name preferred if set
117
         * <strong>Should</strong> set default preferred name to fully specified first
118
         * <strong>Should</strong> not set default preferred name to short or index terms
119
     * <strong>Should</strong> force set flag if set members exist
120
         */
121
        @Override
122
        @CacheEvict(value = CONCEPT_IDS_BY_MAPPING_CACHE_NAME, allEntries = true)
123
        public Concept saveConcept(Concept concept) throws APIException {
124
                ensureConceptMapTypeIsSet(concept);
1✔
125

126
                CustomDatatypeUtil.saveAttributesIfNecessary(concept);
1✔
127

128
                // make sure the administrator hasn't turned off concept editing
129
                checkIfLocked();
1✔
130
                checkIfDatatypeCanBeChanged(concept);
1✔
131
                
132
                List<ConceptName> changedConceptNames = null;
1✔
133
                Map<String, ConceptName> uuidClonedConceptNameMap = null;
1✔
134
                
135
                if (concept.getConceptId() != null) {
1✔
136
                        uuidClonedConceptNameMap = new HashMap<>();
1✔
137
                        for (ConceptName conceptName : concept.getNames()) {
1✔
138
                                // ignore newly added names
139
                                if (conceptName.getConceptNameId() != null) {
1✔
140
                                        ConceptName clone = cloneConceptName(conceptName);
1✔
141
                                        clone.setConceptNameId(null);
1✔
142
                                        uuidClonedConceptNameMap.put(conceptName.getUuid(), clone);
1✔
143
                                        
144
                                        if (hasNameChanged(conceptName)) {
1✔
145
                                                if (changedConceptNames == null) {
1✔
146
                                                        changedConceptNames = new ArrayList<>();
1✔
147
                                                }
148
                                                changedConceptNames.add(conceptName);
1✔
149
                                        } else {
150
                                                // put back the concept name id
151
                                                clone.setConceptNameId(conceptName.getConceptNameId());
1✔
152
                                                // Use the cloned version
153
                                                try {
154
                                                        BeanUtils.copyProperties(conceptName, clone);
1✔
155
                                                }
156
                                                catch (IllegalAccessException | InvocationTargetException e) {
×
157
                                                        log.error(ERROR_MESSAGE, e);
×
158
                                                }
1✔
159
                                        }
160
                                }
161
                        }
1✔
162
                }
163
                
164
                if (CollectionUtils.isNotEmpty(changedConceptNames)) {
1✔
165
                        for (ConceptName changedName : changedConceptNames) {
1✔
166
                                // void old concept name
167
                                changedName.setVoided(true);
1✔
168
                                changedName.setDateVoided(new Date());
1✔
169
                                changedName.setVoidedBy(Context.getAuthenticatedUser());
1✔
170
                                changedName.setVoidReason(Context.getMessageSourceService().getMessage("Concept.name.voidReason.nameChanged"));
1✔
171

172
                                makeVoidedNameSynonym(changedName);
1✔
173
                                makeLocaleNotPreferred(changedName);
1✔
174
                                
175
                                // create a new concept name from the matching cloned
176
                                // conceptName
177
                                ConceptName clone = uuidClonedConceptNameMap.get(changedName.getUuid());
1✔
178
                                clone.setUuid(UUID.randomUUID().toString());
1✔
179
                                clone.setDateCreated(null);
1✔
180
                                clone.setCreator(null);
1✔
181
                                concept.addName(clone);
1✔
182
                        }
1✔
183
                }
184
                ensurePreferredNameForLocale(concept);
1✔
185
                logConceptChangedData(concept);
1✔
186
                
187
                // force isSet when concept has members
188
                if (!concept.getSet() && (!concept.getSetMembers().isEmpty())) {
1✔
189
                        concept.setSet(true);
1✔
190
                }
191

192
                return dao.saveConcept(concept);
1✔
193
        }
194

195
        private void ensureConceptMapTypeIsSet(Concept concept) {
196
                ConceptMapType defaultConceptMapType = null;
1✔
197
                for (ConceptMap map : concept.getConceptMappings()) {
1✔
198
                        if (map.getConceptMapType() == null) {
1✔
199
                                if (defaultConceptMapType == null) {
×
200
                                        defaultConceptMapType = Context.getConceptService().getDefaultConceptMapType();
×
201
                                }
202
                                map.setConceptMapType(defaultConceptMapType);
×
203
                        }
204
                }
1✔
205
        }
1✔
206

207
        private void makeVoidedNameSynonym(ConceptName conceptName) {
208
                // Helps to avoid having  multiple fully
209
                // specified or preferred names in a locale
210
                // in case the name is unvoided
211
                if (!conceptName.isSynonym()) {
1✔
212
                        conceptName.setConceptNameType(null);
1✔
213
                }
214
        }
1✔
215

216
        private void makeLocaleNotPreferred(ConceptName conceptName) {
217
                if (conceptName.getLocalePreferred()) {
1✔
218
                        conceptName.setLocalePreferred(false);
1✔
219
                }
220
        }
1✔
221

222
        private void ensurePreferredNameForLocale(Concept concept) {
223
                //Ensure if there's a name for a locale that at least one suitable name is marked preferred in that locale
224
                //Order of preference is:
225
                // 1) any name that concept.getPreferredName returns
226
                // 2) fully specified name
227
                // 3) any synonym
228
                // short name and index terms are never preferred.
229

230
                Set<Locale> checkedLocales = new HashSet<>();
1✔
231
                for (ConceptName n : concept.getNames()) {
1✔
232
                        Locale locale = n.getLocale();
1✔
233
                        if (checkedLocales.contains(locale)) {
1✔
234
                                continue; //we've already checked this locale
1✔
235
                        }
236

237
                        //getPreferredName(locale) returns any name marked preferred,
238
                        //or the fullySpecifiedName even if not marked preferred
239
                        ConceptName possiblePreferredName = concept.getPreferredName(locale);
1✔
240

241
                        if (possiblePreferredName != null) {
1✔
242
                                //do nothing yet, but stick around to setLocalePreferred(true)
243
                        } else if (concept.getFullySpecifiedName(locale) != null) {
1✔
244
                                possiblePreferredName = concept.getFullySpecifiedName(locale);
×
245
                        } else if (!CollectionUtils.isEmpty(concept.getSynonyms(locale))) {
1✔
246
                                concept.getSynonyms(locale).iterator().next().setLocalePreferred(true);
1✔
247
                        }
248
                        //index terms are never used as preferred name
249

250
                        if (possiblePreferredName != null) { //there may have been none
1✔
251
                                possiblePreferredName.setLocalePreferred(true);
1✔
252
                        }
253
                        checkedLocales.add(locale);
1✔
254
                }
1✔
255
        }
1✔
256

257
        private void logConceptChangedData(Concept concept) {
258
                concept.setDateChanged(new Date());
1✔
259
                concept.setChangedBy(Context.getAuthenticatedUser());
1✔
260
        }
1✔
261

262
        /**
263
         * @see org.openmrs.api.ConceptService#saveDrug(org.openmrs.Drug)
264
         */
265
        @Override
266
        public Drug saveDrug(Drug drug) throws APIException {
267
                checkIfLocked();
1✔
268
                return dao.saveDrug(drug);
1✔
269
        }
270
        
271
        /**
272
         * @see org.openmrs.api.ConceptService#purgeConcept(Concept)
273
         */
274
        @Override
275
        public void purgeConcept(Concept concept) throws APIException {
276
                checkIfLocked();
1✔
277
                
278
                if (concept.getConceptId() != null) {
1✔
279
                        for (ConceptName conceptName : concept.getNames()) {
1✔
280
                                if (hasAnyObservation(conceptName)) {
1✔
281
                                        throw new ConceptNameInUseException("Can't delete concept with id : " + concept.getConceptId()
1✔
282
                                                + " because it has a name '" + conceptName.getName()
1✔
283
                                                + "' which is being used by some observation(s)");
284
                                }
285
                        }
1✔
286
                }
287
                
288
                dao.purgeConcept(concept);
1✔
289
        }
1✔
290
        
291
        /**
292
         * @see org.openmrs.api.ConceptService#retireConcept(org.openmrs.Concept, java.lang.String)
293
         */
294
        @Override
295
        public Concept retireConcept(Concept concept, String reason) throws APIException {
296
                if (StringUtils.isBlank(reason)) {
1✔
297
                        throw new IllegalArgumentException(Context.getMessageSourceService().getMessage("general.voidReason.empty"));
1✔
298
                }
299
                
300
                // only do this if the concept isn't retired already
301
                if (!concept.getRetired()) {
1✔
302
                        checkIfLocked();
×
303
                        
304
                        concept.setRetired(true);
×
305
                        concept.setRetireReason(reason);
×
306
                        return Context.getConceptService().saveConcept(concept);
×
307
                }
308
                
309
                return concept;
1✔
310
        }
311
        
312
        /**
313
         * @see org.openmrs.api.ConceptService#retireDrug(org.openmrs.Drug, java.lang.String)
314
         * @throws APIException
315
         */
316
        @Override
317
        public Drug retireDrug(Drug drug, String reason) throws APIException {
318
                return dao.saveDrug(drug);
1✔
319
        }
320
        
321
        /**
322
         * @see org.openmrs.api.ConceptService#unretireDrug(org.openmrs.Drug)
323
         */
324
        @Override
325
        public Drug unretireDrug(Drug drug) throws APIException {
326
                return Context.getConceptService().saveDrug(drug);
1✔
327
        }
328
        
329
        /**
330
         * @see org.openmrs.api.ConceptService#purgeDrug(org.openmrs.Drug)
331
         * @throws APIException
332
         */
333
        @Override
334
        public void purgeDrug(Drug drug) throws APIException {
335
                dao.purgeDrug(drug);
1✔
336
        }
1✔
337
        
338
        /**
339
         * @see org.openmrs.api.ConceptService#getConcept(java.lang.Integer)
340
         */
341
        @Override
342
        @Transactional(readOnly = true)
343
        public Concept getConcept(Integer conceptId) throws APIException {
344
                return dao.getConcept(conceptId);
1✔
345
        }
346

347
        /**
348
         * @see org.openmrs.api.ConceptService#getConceptByReference(String conceptRef)
349
         */
350
        @Override
351
        @Transactional(readOnly = true)
352
        public Concept getConceptByReference(String conceptRef) {
353
                if (StringUtils.isBlank(conceptRef)) {
1✔
354
                        return null;
1✔
355
                }
356
                ConceptSearchCriteria criteria = new ConceptSearchCriteriaBuilder().addConceptReference(conceptRef)
1✔
357
                        .includeRetired(true).build();
1✔
358
                List<Concept> concepts = getConcepts(criteria);
1✔
359
                return concepts.isEmpty() ? null : concepts.get(0);
1✔
360
        }
361
        
362
        /**
363
         * @see org.openmrs.api.ConceptService#getConceptName(java.lang.Integer)
364
         */
365
        @Override
366
        @Transactional(readOnly = true)
367
        public ConceptName getConceptName(Integer conceptNameId) throws APIException {
368
                return dao.getConceptName(conceptNameId);
1✔
369
        }
370
        
371
        /**
372
         * @see org.openmrs.api.ConceptService#getConceptAnswer(java.lang.Integer)
373
         */
374
        @Override
375
        @Transactional(readOnly = true)
376
        public ConceptAnswer getConceptAnswer(Integer conceptAnswerId) throws APIException {
377
                return dao.getConceptAnswer(conceptAnswerId);
1✔
378
        }
379
        
380
        /**
381
         * @see org.openmrs.api.ConceptService#getDrug(java.lang.Integer)
382
         */
383
        @Override
384
        @Transactional(readOnly = true)
385
        public Drug getDrug(Integer drugId) throws APIException {
386
                return dao.getDrug(drugId);
1✔
387
        }
388
        
389
        /**
390
         * @see org.openmrs.api.ConceptService#getConceptNumeric(java.lang.Integer)
391
         */
392
        @Override
393
        @Transactional(readOnly = true)
394
        public ConceptNumeric getConceptNumeric(Integer conceptId) throws APIException {
395
                return dao.getConceptNumeric(conceptId);
1✔
396
        }
397
        
398
        /**
399
         * @see org.openmrs.api.ConceptService#getConceptComplex(java.lang.Integer)
400
         */
401
        @Override
402
        @Transactional(readOnly = true)
403
        public ConceptComplex getConceptComplex(Integer conceptId) {
404
                return dao.getConceptComplex(conceptId);
1✔
405
        }
406
        
407
        /**
408
         * @see org.openmrs.api.ConceptService#getAllConcepts()
409
         */
410
        @Override
411
        @Transactional(readOnly = true)
412
        public List<Concept> getAllConcepts() throws APIException {
413
                return Context.getConceptService().getAllConcepts(null, true, true);
1✔
414
        }
415
        
416
        /**
417
         * @see org.openmrs.api.ConceptService#getAllConcepts(java.lang.String, boolean, boolean)
418
         */
419
        @Override
420
        @Transactional(readOnly = true)
421
        public List<Concept> getAllConcepts(String sortBy, boolean asc, boolean includeRetired) throws APIException {
422
                String tmpSortBy = sortBy == null ? "conceptId" : sortBy;
1✔
423
                
424
                return dao.getAllConcepts(tmpSortBy, asc, includeRetired);
1✔
425
        }
426

427
        /**
428
         * @see org.openmrs.api.ConceptService#getConceptsByName(java.lang.String)
429
         */
430
        @Override
431
        @Transactional(readOnly = true)
432
        public List<Concept> getConceptsByName(String name) throws APIException {
433
                return getConcepts(name, Context.getLocale(), true, null, null);
1✔
434
        }
435
        
436
        /**
437
         * @see org.openmrs.api.ConceptService#getConceptByName(java.lang.String)
438
         */
439
        @Override
440
        @Transactional(readOnly = true)
441
        public Concept getConceptByName(String name) {
442
                if (StringUtils.isBlank(name)) {
1✔
443
                        return null;
1✔
444
                }
445
                return dao.getConceptByName(name);
1✔
446
        }
447

448
        /**
449
         * @see org.openmrs.api.ConceptService#getConcept(java.lang.String)
450
         */
451
        @Override
452
        @Transactional(readOnly = true)
453
        public Concept getConcept(String conceptIdOrName) {
454
                Concept c;
455
                Integer conceptId;
456
                try {
457
                        conceptId = Integer.valueOf(conceptIdOrName);
1✔
458
                }
459
                catch (NumberFormatException nfe) {
1✔
460
                        conceptId = null;
1✔
461
                }
1✔
462
                
463
                if (conceptId != null) {
1✔
464
                        c = Context.getConceptService().getConcept(conceptId);
1✔
465
                } else {
466
                        c = Context.getConceptService().getConceptByName(conceptIdOrName);
1✔
467
                }
468
                return c;
1✔
469
        }
470
        
471
        /**
472
         * Generic getConcepts method (used internally) to get concepts matching a on name
473
         * 
474
         * @param name
475
         * @param loc
476
         * @param searchOnPhrase
477
         * @return
478
         */
479
        private List<Concept> getConcepts(String name, Locale loc, boolean searchOnPhrase, List<ConceptClass> classes,
480
                List<ConceptDatatype> datatypes) {
481
                List<ConceptClass> tmpClasses = classes == null ? new ArrayList<>() : classes;
1✔
482
                List<ConceptDatatype> tmpDatatypes = datatypes == null ? new ArrayList<>() : datatypes;
1✔
483
                
484
                return dao.getConcepts(name, loc, searchOnPhrase, tmpClasses, tmpDatatypes);
1✔
485
        }
486
        
487
        /**
488
         * @see org.openmrs.api.ConceptService#getDrug(java.lang.String)
489
         */
490
        @Override
491
        @Transactional(readOnly = true)
492
        public Drug getDrug(String drugNameOrId) {
493
                Integer drugId;
494
                
495
                try {
496
                        drugId = Integer.valueOf(drugNameOrId);
×
497
                }
498
                catch (NumberFormatException nfe) {
1✔
499
                        drugId = null;
1✔
500
                }
×
501
                
502
                if (drugId != null) {
1✔
503
                        return Context.getConceptService().getDrug(drugId);
×
504
                } else {
505
                        List<Drug> drugs = dao.getDrugs(drugNameOrId, null, false);
1✔
506
                        if (drugs.size() > 1) {
1✔
507
                                log.warn("more than one drug name returned with name:" + drugNameOrId);
×
508
                        }
509
                        if (drugs.isEmpty()) {
1✔
510
                                return null;
1✔
511
                        }
512
                        return drugs.get(0);
1✔
513
                }
514
        }
515
        
516
        /**
517
         * @see org.openmrs.api.ConceptService#getAllDrugs()
518
         */
519
        @Override
520
        @Transactional(readOnly = true)
521
        public List<Drug> getAllDrugs() {
522
                return Context.getConceptService().getAllDrugs(true);
1✔
523
        }
524
        
525
        /**
526
         * @see org.openmrs.api.ConceptService#getAllDrugs(boolean)
527
         */
528
        @Override
529
        @Transactional(readOnly = true)
530
        public List<Drug> getAllDrugs(boolean includeRetired) {
531
                return dao.getDrugs(null, null, includeRetired);
1✔
532
        }
533
        
534
        /**
535
         * @see org.openmrs.api.ConceptService#getDrugsByConcept(org.openmrs.Concept)
536
         */
537
        @Override
538
        @Transactional(readOnly = true)
539
        public List<Drug> getDrugsByConcept(Concept concept) {
540
                return dao.getDrugs(null, concept, false);
1✔
541
        }
542
        
543
        /**
544
         * @see org.openmrs.api.ConceptService#getDrugs(java.lang.String)
545
         */
546
        @Override
547
        @Transactional(readOnly = true)
548
        public List<Drug> getDrugs(String phrase) {
549
                List<Drug> drugs = new ArrayList<>();
1✔
550
                // trying to treat search phrase as drug id
551
                try {
552
                        Integer drugId = Integer.parseInt(phrase);
1✔
553
                        Drug targetDrug = Context.getConceptService().getDrug(drugId);
1✔
554
                        // if drug was found add it to result
555
                        if (targetDrug != null) {
1✔
556
                                drugs.add(targetDrug);
1✔
557
                        }
558
                }
559
                catch (NumberFormatException e) {
1✔
560
                        // do nothing
561
                }
1✔
562
                
563
                // also try to treat search phrase as drug concept id
564
                try {
565
                        Integer conceptId = Integer.parseInt(phrase);
1✔
566
                        Concept targetConcept = Context.getConceptService().getConcept(conceptId);
1✔
567
                        if (targetConcept != null) {
1✔
568
                                drugs.addAll(Context.getConceptService().getDrugsByConcept(targetConcept));
1✔
569
                        }
570
                }
571
                catch (NumberFormatException e) {
1✔
572
                        // do nothing
573
                }
1✔
574
                
575
                drugs.addAll(dao.getDrugs(phrase));
1✔
576
                return drugs;
1✔
577
        }
578
        
579
        /**
580
         * @see org.openmrs.api.ConceptService#getConceptsByClass(org.openmrs.ConceptClass)
581
         */
582
        @Override
583
        @Transactional(readOnly = true)
584
        public List<Concept> getConceptsByClass(ConceptClass cc) {                
585
                return dao.getConceptsByClass(cc);
1✔
586
        }
587
        
588
        /**
589
         * @see org.openmrs.api.ConceptService#getAllConceptClasses(boolean)
590
         */
591
        @Override
592
        @Transactional(readOnly = true)
593
        public List<ConceptClass> getAllConceptClasses(boolean includeRetired) {
594
                return dao.getAllConceptClasses(includeRetired);
1✔
595
        }
596
        
597
        /**
598
         * @see org.openmrs.api.ConceptService#getConceptClass(java.lang.Integer)
599
         */
600
        @Override
601
        @Transactional(readOnly = true)
602
        public ConceptClass getConceptClass(Integer i) {
603
                return dao.getConceptClass(i);
1✔
604
        }
605
        
606
        /**
607
         * @see org.openmrs.api.ConceptService#getConceptClassByName(java.lang.String)
608
         */
609
        @Override
610
        @Transactional(readOnly = true)
611
        public ConceptClass getConceptClassByName(String name) {
612
                List<ConceptClass> ccList = dao.getConceptClasses(name);
1✔
613
                if (ccList.size() > 1) {
1✔
614
                        log.warn("More than one ConceptClass found with name: " + name);
×
615
                }
616
                if (ccList.size() == 1) {
1✔
617
                        return ccList.get(0);
1✔
618
                }
619
                return null;
1✔
620
        }
621
        
622
        /**
623
         * @see org.openmrs.api.ConceptService#getAllConceptClasses(boolean)
624
         */
625
        @Override
626
        @Transactional(readOnly = true)
627
        public List<ConceptClass> getAllConceptClasses() throws APIException {
628
                return Context.getConceptService().getAllConceptClasses(true);
1✔
629
        }
630
        
631
        /**
632
         * @see org.openmrs.api.ConceptService#saveConceptClass(org.openmrs.ConceptClass)
633
         */
634
        @Override
635
        public ConceptClass saveConceptClass(ConceptClass cc) throws APIException {
636
                return dao.saveConceptClass(cc);
1✔
637
        }
638
        
639
        /**
640
         * @see org.openmrs.api.ConceptService#purgeConceptClass(org.openmrs.ConceptClass)
641
         */
642
        @Override
643
        public void purgeConceptClass(ConceptClass cc) {
644
                dao.purgeConceptClass(cc);
1✔
645
        }
1✔
646
        
647
        /**
648
         * @see org.openmrs.api.ConceptService#purgeConceptNameTag(org.openmrs.ConceptNameTag)
649
         */
650
        @Override
651
        public void purgeConceptNameTag(ConceptNameTag cnt) {
652
                dao.deleteConceptNameTag(cnt);
1✔
653
        }
1✔
654
        
655
        /**
656
         * @see org.openmrs.api.ConceptService#getAllConceptDatatypes()
657
         */
658
        @Override
659
        @Transactional(readOnly = true)
660
        public List<ConceptDatatype> getAllConceptDatatypes() {
661
                return Context.getConceptService().getAllConceptDatatypes(true);
1✔
662
        }
663
        
664
        /**
665
         * @see org.openmrs.api.ConceptService#getAllConceptDatatypes(boolean)
666
         */
667
        @Override
668
        @Transactional(readOnly = true)
669
        public List<ConceptDatatype> getAllConceptDatatypes(boolean includeRetired) throws APIException {
670
                return dao.getAllConceptDatatypes(includeRetired);
1✔
671
        }
672
        
673
        /**
674
         * @see org.openmrs.api.ConceptService#getConceptDatatype(java.lang.Integer)
675
         */
676
        @Override
677
        @Transactional(readOnly = true)
678
        public ConceptDatatype getConceptDatatype(Integer i) {
679
                return dao.getConceptDatatype(i);
1✔
680
        }
681
        
682
        /**
683
         * @see org.openmrs.api.ConceptService#getConceptDatatypeByName(java.lang.String)
684
         */
685
        @Override
686
        @Transactional(readOnly = true)
687
        public ConceptDatatype getConceptDatatypeByName(String name) {
688
                return dao.getConceptDatatypeByName(name);
1✔
689
        }
690
        
691
        /**
692
         * @see org.openmrs.api.ConceptService#getConceptSetsByConcept(org.openmrs.Concept)
693
         */
694
        @Override
695
        @Transactional(readOnly = true)
696
        public List<ConceptSet> getConceptSetsByConcept(Concept concept) throws APIException {
697
                return dao.getConceptSetsByConcept(concept);
1✔
698
        }
699
        
700
        /**
701
         * @see org.openmrs.api.ConceptService#getConceptsByConceptSet(Concept)
702
         */
703
        @Override
704
        @Transactional(readOnly = true)
705
        public List<Concept> getConceptsByConceptSet(Concept c) {
706
                Set<Integer> alreadySeen = new HashSet<>();
1✔
707
                List<Concept> ret = new ArrayList<>();
1✔
708
                explodeConceptSetHelper(c, ret, alreadySeen);
1✔
709
                return ret;
1✔
710
        }
711
        
712
        /**
713
         * @see org.openmrs.api.ConceptService#getSetsContainingConcept(org.openmrs.Concept)
714
         */
715
        @Override
716
        @Transactional(readOnly = true)
717
        public List<ConceptSet> getSetsContainingConcept(Concept concept) {
718
                if (concept.getConceptId() == null) {
1✔
719
                        return Collections.emptyList();
1✔
720
                }
721
                
722
                return dao.getSetsContainingConcept(concept);
1✔
723
        }
724
        
725
        /**
726
         * @see org.openmrs.api.ConceptService#getConceptProposal(java.lang.Integer)
727
         */
728
        @Override
729
        @Transactional(readOnly = true)
730
        public ConceptProposal getConceptProposal(Integer conceptProposalId) {
731
                return dao.getConceptProposal(conceptProposalId);
1✔
732
        }
733
        
734
        /**
735
         * @see org.openmrs.api.ConceptService#getAllConceptProposals(boolean)
736
         */
737
        @Override
738
        @Transactional(readOnly = true)
739
        public List<ConceptProposal> getAllConceptProposals(boolean includeCompleted) {
740
                return dao.getAllConceptProposals(includeCompleted);
1✔
741
        }
742
        
743
        /**
744
         * @see org.openmrs.api.ConceptService#getConceptProposals(java.lang.String)
745
         */
746
        @Override
747
        @Transactional(readOnly = true)
748
        public List<ConceptProposal> getConceptProposals(String cp) {
749
                return dao.getConceptProposals(cp);
1✔
750
        }
751
        
752
        /**
753
         * @see org.openmrs.api.ConceptService#getProposedConcepts(java.lang.String)
754
         */
755
        @Override
756
        @Transactional(readOnly = true)
757
        public List<Concept> getProposedConcepts(String text) {
758
                return dao.getProposedConcepts(text);
1✔
759
        }
760
        
761
        /**
762
         * @see org.openmrs.api.ConceptService#saveConceptProposal(org.openmrs.ConceptProposal)
763
         */
764
        @Override
765
        public ConceptProposal saveConceptProposal(ConceptProposal conceptProposal) throws APIException {
766
                return dao.saveConceptProposal(conceptProposal);
1✔
767
        }
768
        
769
        /**
770
         * @see org.openmrs.api.ConceptService#purgeConceptProposal(org.openmrs.ConceptProposal)
771
         */
772
        @Override
773
        public void purgeConceptProposal(ConceptProposal cp) throws APIException {
774
                dao.purgeConceptProposal(cp);
1✔
775
        }
1✔
776
        
777
        /**
778
         * @see org.openmrs.api.ConceptService#mapConceptProposalToConcept(ConceptProposal, Concept, Locale)
779
         */
780
        @Override
781
        public Concept mapConceptProposalToConcept(ConceptProposal cp, Concept mappedConcept, Locale locale) throws APIException {
782
                
783
                if (cp.getState().equals(OpenmrsConstants.CONCEPT_PROPOSAL_REJECT)) {
1✔
784
                        cp.rejectConceptProposal();
1✔
785
                        Context.getConceptService().saveConceptProposal(cp);
1✔
786
                        return null;
1✔
787
                }
788
                
789
                if (mappedConcept == null) {
1✔
790
                        throw new APIException("Concept.mapped.illegal", (Object[]) null);
1✔
791
                }
792
                
793
                ConceptName conceptName = null;
1✔
794
                if (cp.getState().equals(OpenmrsConstants.CONCEPT_PROPOSAL_CONCEPT) || StringUtils.isBlank(cp.getFinalText())) {
1✔
795
                        cp.setState(OpenmrsConstants.CONCEPT_PROPOSAL_CONCEPT);
1✔
796
                        cp.setFinalText("");
1✔
797
                } else if (cp.getState().equals(OpenmrsConstants.CONCEPT_PROPOSAL_SYNONYM)) {
1✔
798
                        
799
                        checkIfLocked();
1✔
800
                        
801
                        String finalText = cp.getFinalText();
1✔
802
                        conceptName = new ConceptName(finalText, null);
1✔
803
                        conceptName.setConcept(mappedConcept);
1✔
804
                        conceptName.setLocale(locale == null ? Context.getLocale() : locale);
1✔
805
                        conceptName.setDateCreated(new Date());
1✔
806
                        conceptName.setCreator(Context.getAuthenticatedUser());
1✔
807
                        //If this is pre 1.9
808
                        if (conceptName.getUuid() == null) {
1✔
809
                                conceptName.setUuid(UUID.randomUUID().toString());
×
810
                        }
811
                        mappedConcept.addName(conceptName);
1✔
812
                        mappedConcept.setChangedBy(Context.getAuthenticatedUser());
1✔
813
                        mappedConcept.setDateChanged(new Date());
1✔
814
                        ValidateUtil.validate(mappedConcept);
1✔
815
            Context.getConceptService().saveConcept(mappedConcept);
1✔
816
                }
817
                
818
                cp.setMappedConcept(mappedConcept);
1✔
819
                
820
                if (cp.getObsConcept() != null) {
1✔
821
                        Obs ob = new Obs();
1✔
822
                        ob.setEncounter(cp.getEncounter());
1✔
823
                        ob.setConcept(cp.getObsConcept());
1✔
824
                        ob.setValueCoded(cp.getMappedConcept());
1✔
825
                        if (cp.getState().equals(OpenmrsConstants.CONCEPT_PROPOSAL_SYNONYM)) {
1✔
826
                                ob.setValueCodedName(conceptName);
1✔
827
                        }
828
                        ob.setCreator(Context.getAuthenticatedUser());
1✔
829
                        ob.setDateCreated(new Date());
1✔
830
                        ob.setObsDatetime(cp.getEncounter().getEncounterDatetime());
1✔
831
                        ob.setLocation(cp.getEncounter().getLocation());
1✔
832
                        ob.setPerson(cp.getEncounter().getPatient());
1✔
833
                        if (ob.getUuid() == null) {
1✔
834
                                ob.setUuid(UUID.randomUUID().toString());
×
835
                        }
836
            Context.getObsService().saveObs(ob, null);
1✔
837
                        cp.setObs(ob);
1✔
838
                }
839
                
840
                return mappedConcept;
1✔
841
        }
842
        
843
        /**
844
         * @see org.openmrs.api.ConceptService#mapConceptProposalToConcept(org.openmrs.ConceptProposal,
845
         *      org.openmrs.Concept)
846
         */
847
        @Override
848
        public Concept mapConceptProposalToConcept(ConceptProposal cp, Concept mappedConcept) throws APIException {
849
                return Context.getConceptService().mapConceptProposalToConcept(cp, mappedConcept, null);
1✔
850
        }
851
        
852
        /**
853
         * @see org.openmrs.api.ConceptService#getConceptsByAnswer(org.openmrs.Concept)
854
         */
855
        @Override
856
        @Transactional(readOnly = true)
857
        public List<Concept> getConceptsByAnswer(Concept concept) throws APIException {
858
                if (concept.getConceptId() == null) {
1✔
859
                        return Collections.emptyList();
1✔
860
                }
861
                
862
                return dao.getConceptsByAnswer(concept);
1✔
863
        }
864
        
865
        /**
866
         * @see org.openmrs.api.ConceptService#getPrevConcept(org.openmrs.Concept)
867
         */
868
        @Override
869
        @Transactional(readOnly = true)
870
        public Concept getPrevConcept(Concept c) {
871
                return dao.getPrevConcept(c);
1✔
872
        }
873
        
874
        /**
875
         * @see org.openmrs.api.ConceptService#getNextConcept(org.openmrs.Concept)
876
         */
877
        @Override
878
        @Transactional(readOnly = true)
879
        public Concept getNextConcept(Concept c) {
880
                return dao.getNextConcept(c);
1✔
881
        }
882
        
883
        /**
884
         * @see org.openmrs.api.ConceptService#checkIfLocked()
885
         */
886
        @Override
887
        @Transactional(readOnly = true)
888
        public void checkIfLocked() throws ConceptsLockedException {
889
                String locked = Context.getAdministrationService().getGlobalProperty(
1✔
890
                    OpenmrsConstants.GLOBAL_PROPERTY_CONCEPTS_LOCKED, "false");
891
                if ("true".equalsIgnoreCase(locked)) {
1✔
892
                        throw new ConceptsLockedException();
×
893
                }
894
        }
1✔
895
        
896
        /**
897
         * @see org.openmrs.api.ConceptService#getConceptsWithDrugsInFormulary()
898
         */
899
        @Override
900
        @Transactional(readOnly = true)
901
        public List<Concept> getConceptsWithDrugsInFormulary() {
902
                return dao.getConceptsWithDrugsInFormulary();
1✔
903
        }
904
        
905
        /**
906
         * @see ConceptService#getMaxConceptId()
907
         */
908
        @Override
909
        @Transactional(readOnly = true)
910
        public Integer getMaxConceptId() {
911
                return dao.getMaxConceptId();
1✔
912
        }
913
        
914
        /**
915
         * Utility method used by getConceptsInSet(Concept concept)
916
         * 
917
         * @param concept
918
         * @param ret
919
         * @param alreadySeen
920
         */
921
        private void explodeConceptSetHelper(Concept concept, Collection<Concept> ret, Collection<Integer> alreadySeen) {
922
                if (alreadySeen.contains(concept.getConceptId())) {
1✔
923
                        return;
×
924
                }
925
                alreadySeen.add(concept.getConceptId());
1✔
926
                List<ConceptSet> cs = getConceptSetsByConcept(concept);
1✔
927
                for (ConceptSet set : cs) {
1✔
928
                        Concept c = set.getConcept();
1✔
929
                        if (c.getSet()) {
1✔
930
                                ret.add(c);
1✔
931
                                explodeConceptSetHelper(c, ret, alreadySeen);
1✔
932
                        } else {
933
                                ret.add(c);
1✔
934
                        }
935
                }
1✔
936
        }
1✔
937
        
938
        /**
939
         * @see org.openmrs.api.ConceptService#getConceptNameTagByName(java.lang.String)
940
         */
941
        @Override
942
        @Transactional(readOnly = true)
943
        public ConceptNameTag getConceptNameTagByName(String tagName) {
944
                return dao.getConceptNameTagByName(tagName);
1✔
945
        }
946
        
947
        /**
948
         * @see org.openmrs.api.ConceptService#getLocalesOfConceptNames()
949
         */
950
        @Override
951
        @Transactional(readOnly = true)
952
        public Set<Locale> getLocalesOfConceptNames() {
953
                return dao.getLocalesOfConceptNames();
1✔
954
        }
955
        
956
        /**
957
         * @see org.openmrs.api.ConceptService#getConceptSource(java.lang.Integer)
958
         */
959
        @Override
960
        @Transactional(readOnly = true)
961
        public ConceptSource getConceptSource(Integer conceptSourceId) {
962
                return dao.getConceptSource(conceptSourceId);
1✔
963
        }
964
        
965
        /**
966
         * @see org.openmrs.api.ConceptService#getAllConceptSources(boolean)
967
         */
968
        @Override
969
        @Transactional(readOnly = true)
970
        public List<ConceptSource> getAllConceptSources(boolean includeRetired) {
971
                return dao.getAllConceptSources(includeRetired);
1✔
972
        }
973
        
974
        /**
975
         * @see org.openmrs.api.ConceptService#purgeConceptSource(org.openmrs.ConceptSource)
976
         */
977
        @Override
978
        @CacheEvict(value = CONCEPT_IDS_BY_MAPPING_CACHE_NAME, allEntries = true)
979
        public ConceptSource purgeConceptSource(ConceptSource cs) throws APIException {
980
                return dao.deleteConceptSource(cs);
1✔
981
        }
982
        
983
        /**
984
         * @see org.openmrs.api.ConceptService#retireConceptSource(org.openmrs.ConceptSource, String)
985
         */
986
        @Override
987
        public ConceptSource retireConceptSource(ConceptSource cs, String reason) throws APIException {
988
                // retireReason is automatically set in BaseRetireHandler
989
                return Context.getConceptService().saveConceptSource(cs);
1✔
990
        }
991
        
992
        /**
993
         * @see org.openmrs.api.ConceptService#saveConceptSource(org.openmrs.ConceptSource)
994
         */
995
        @Override
996
        @CacheEvict(value = CONCEPT_IDS_BY_MAPPING_CACHE_NAME, allEntries = true)
997
        public ConceptSource saveConceptSource(ConceptSource conceptSource) throws APIException {
998
                return dao.saveConceptSource(conceptSource);
1✔
999
        }
1000
        
1001
        /**
1002
         * @see org.openmrs.api.ConceptService#saveConceptNameTag(org.openmrs.ConceptNameTag)
1003
         */
1004
        @Override
1005
        public ConceptNameTag saveConceptNameTag(ConceptNameTag nameTag) {
1006
                checkIfLocked();
1✔
1007
                
1008
                return dao.saveConceptNameTag(nameTag);
1✔
1009
        }
1010
        
1011
        /**
1012
         * @see org.openmrs.api.ConceptService#conceptIterator()
1013
         */
1014
        @Override
1015
        @Transactional(readOnly = true)
1016
        public Iterator<Concept> conceptIterator() {
1017
                return dao.conceptIterator();
1✔
1018
        }
1019
        
1020
        /**
1021
         * @see org.openmrs.api.ConceptService#getConceptByUuid(java.lang.String)
1022
         */
1023
        @Override
1024
        @Transactional(readOnly = true)
1025
        public Concept getConceptByUuid(String uuid) {
1026
                return dao.getConceptByUuid(uuid);
1✔
1027
        }
1028
        
1029
        /**
1030
         * @see org.openmrs.api.ConceptService#getConcepts(ConceptSearchCriteria)
1031
         */
1032
        @Override
1033
        @Transactional(readOnly = true)
1034
        public List<Concept> getConcepts(ConceptSearchCriteria conceptSearchCriteria) {
1035
                return dao.getConcepts(conceptSearchCriteria);
1✔
1036
        }
1037

1038
        /**
1039
         * @see org.openmrs.api.ConceptService#getConceptClassByUuid(java.lang.String)
1040
         */
1041
        @Override
1042
        @Transactional(readOnly = true)
1043
        public ConceptClass getConceptClassByUuid(String uuid) {
1044
                return dao.getConceptClassByUuid(uuid);
1✔
1045
        }
1046
        
1047
        @Override
1048
        @Transactional(readOnly = true)
1049
        public ConceptAnswer getConceptAnswerByUuid(String uuid) {
1050
                return dao.getConceptAnswerByUuid(uuid);
1✔
1051
        }
1052
        
1053
        @Override
1054
        @Transactional(readOnly = true)
1055
        public ConceptName getConceptNameByUuid(String uuid) {
1056
                return dao.getConceptNameByUuid(uuid);
1✔
1057
        }
1058
        
1059
        @Override
1060
        public ConceptSet getConceptSetByUuid(String uuid) {
1061
                return dao.getConceptSetByUuid(uuid);
1✔
1062
        }
1063
        
1064
        @Override
1065
        @Transactional(readOnly = true)
1066
        public ConceptSource getConceptSourceByUuid(String uuid) {
1067
                return dao.getConceptSourceByUuid(uuid);
1✔
1068
        }
1069
        
1070
        /**
1071
         * @see org.openmrs.api.ConceptService#getConceptDatatypeByUuid(java.lang.String)
1072
         */
1073
        @Override
1074
        @Transactional(readOnly = true)
1075
        public ConceptDatatype getConceptDatatypeByUuid(String uuid) {
1076
                return dao.getConceptDatatypeByUuid(uuid);
1✔
1077
        }
1078
        
1079
        /**
1080
         * @see org.openmrs.api.ConceptService#getConceptNumericByUuid(java.lang.String)
1081
         */
1082
        @Override
1083
        @Transactional(readOnly = true)
1084
        public ConceptNumeric getConceptNumericByUuid(String uuid) {
1085
                return dao.getConceptNumericByUuid(uuid);
1✔
1086
        }
1087
        
1088
        /**
1089
         * @see org.openmrs.api.ConceptService#getConceptProposalByUuid(java.lang.String)
1090
         */
1091
        @Override
1092
        @Transactional(readOnly = true)
1093
        public ConceptProposal getConceptProposalByUuid(String uuid) {
1094
                return dao.getConceptProposalByUuid(uuid);
1✔
1095
        }
1096
        
1097
        /**
1098
         * @see org.openmrs.api.ConceptService#getDrugByUuid(java.lang.String)
1099
         */
1100
        @Override
1101
        @Transactional(readOnly = true)
1102
        public Drug getDrugByUuid(String uuid) {
1103
                return dao.getDrugByUuid(uuid);
1✔
1104
        }
1105
        
1106
        /**
1107
         * @see org.openmrs.api.ConceptService#getDrugIngredientByUuid(java.lang.String)
1108
         */
1109
        @Override
1110
        @Transactional(readOnly = true)
1111
        public DrugIngredient getDrugIngredientByUuid(String uuid) {
1112
                return dao.getDrugIngredientByUuid(uuid);
1✔
1113
        }
1114
        
1115
        /**
1116
         * @see org.openmrs.api.ConceptService#getConceptDescriptionByUuid(java.lang.String)
1117
         */
1118
        @Override
1119
        @Transactional(readOnly = true)
1120
        public ConceptDescription getConceptDescriptionByUuid(String uuid) {
1121
                return dao.getConceptDescriptionByUuid(uuid);
1✔
1122
        }
1123
        
1124
        /**
1125
         * @see org.openmrs.api.ConceptService#getConceptNameTagByUuid(java.lang.String)
1126
         */
1127
        @Override
1128
        @Transactional(readOnly = true)
1129
        public ConceptNameTag getConceptNameTagByUuid(String uuid) {
1130
                return dao.getConceptNameTagByUuid(uuid);
1✔
1131
        }
1132
        
1133
        /**
1134
         * @see org.openmrs.api.ConceptService#getAllConceptNameTags()
1135
         */
1136
        @Override
1137
        @Transactional(readOnly = true)
1138
        public List<ConceptNameTag> getAllConceptNameTags() {
1139
                return dao.getAllConceptNameTags();
1✔
1140
        }
1141
        
1142
        /**
1143
         * @see org.openmrs.api.ConceptService#getConceptNameTag(java.lang.Integer)
1144
         */
1145
        @Override
1146
        @Transactional(readOnly = true)
1147
        public ConceptNameTag getConceptNameTag(Integer id) {
1148
                return dao.getConceptNameTag(id);
1✔
1149
        }
1150
        
1151
        /**
1152
         * @see org.openmrs.api.ConceptService#getConceptByMapping(java.lang.String, java.lang.String)
1153
         */
1154
        @Override
1155
        @Transactional(readOnly = true)
1156
        public Concept getConceptByMapping(String code, String sourceName) throws APIException {
1157
                return Context.getConceptService().getConceptByMapping(code, sourceName, true);
1✔
1158
        }
1159
        
1160
        /**
1161
         * @see org.openmrs.api.ConceptService#getConceptByMapping(java.lang.String, java.lang.String,
1162
         *      java.lang.Boolean)
1163
         */
1164
        @Override
1165
        @Transactional(readOnly = true)
1166
        public Concept getConceptByMapping(String code, String sourceName, Boolean includeRetired) throws APIException {
1167
                List<Concept> concepts = Context.getConceptService().getConceptsByMapping(code, sourceName, includeRetired);
1✔
1168
                
1169
                if (concepts.isEmpty()) {
1✔
1170
                        return null;
1✔
1171
                }
1172
                // we want to throw an exception if there is more than one non-retired concept; 
1173
                // since the getConceptByMapping DAO method returns a list with all non-retired concept
1174
                // sorted to the front of the list, we can test if there is more than one retired concept
1175
                // by testing if the second concept in the list is retired or not
1176
                else if (concepts.size() > 1 && !concepts.get(1).getRetired()) {
1✔
1177
                        throw new APIException("Concept.error.multiple.non.retired", new Object[] { code, sourceName });
1✔
1178
                } else {
1179
                        return concepts.get(0);
1✔
1180
                }
1181
        }
1182
        
1183
        /**
1184
         * @see org.openmrs.api.ConceptService#getConceptsByMapping(java.lang.String, java.lang.String)
1185
         */
1186
        @Override
1187
        @Transactional(readOnly = true)
1188
        public List<Concept> getConceptsByMapping(String code, String sourceName) throws APIException {
1189
                return Context.getConceptService().getConceptsByMapping(code, sourceName, true);
1✔
1190
        }
1191
        
1192
        /**
1193
         * @see org.openmrs.api.ConceptService#getConceptsByMapping(java.lang.String, java.lang.String, boolean)
1194
         */
1195
        @Override
1196
        @Transactional(readOnly = true)
1197
        public List<Concept> getConceptsByMapping(String code, String sourceName, boolean includeRetired) throws APIException {
1198
                List<Concept> concepts = new ArrayList<>();
1✔
1199
                for (Integer conceptId : Context.getConceptService().getConceptIdsByMapping(code, sourceName, includeRetired)) {
1✔
1200
                        concepts.add(getConcept(conceptId));
1✔
1201
                }
1✔
1202
                return concepts;
1✔
1203
        }
1204

1205
        /**
1206
         * @see org.openmrs.api.ConceptService#getConceptIdsByMapping(java.lang.String, java.lang.String, boolean)
1207
         */
1208
        @Override
1209
        @Transactional(readOnly = true)
1210
        @Cacheable(value = CONCEPT_IDS_BY_MAPPING_CACHE_NAME)
1211
        public List<Integer> getConceptIdsByMapping(String code, String sourceName, boolean includeRetired) throws APIException {
1212
                return dao.getConceptIdsByMapping(code, sourceName, includeRetired);
1✔
1213
        }
1214
        
1215
        /**
1216
         * @see org.openmrs.api.ConceptService#getFalseConcept()
1217
         */
1218
        @Override
1219
        @Transactional(readOnly = true)
1220
        public Concept getFalseConcept() {
1221
                if (falseConcept == null) {
1✔
1222
                        setBooleanConcepts();
×
1223
                }
1224
                
1225
                return falseConcept;
1✔
1226
        }
1227
        
1228
        /**
1229
         * @see org.openmrs.api.ConceptService#getTrueConcept()
1230
         */
1231
        @Override
1232
        @Transactional(readOnly = true)
1233
        public Concept getTrueConcept() {
1234
                if (trueConcept == null) {
1✔
1235
                        setBooleanConcepts();
1✔
1236
                }
1237
                
1238
                return trueConcept;
1✔
1239
        }
1240
        
1241
        /**
1242
         * @see org.openmrs.api.ConceptService#getUnknownConcept()
1243
         */
1244
        @Override
1245
        @Transactional(readOnly = true)
1246
        public Concept getUnknownConcept() {
1247
                if (unknownConcept == null) {
1✔
1248
                        try {
1249
                                Concept unknownConcept = Context.getConceptService().getConcept(
1✔
1250
                                        Integer.parseInt(Context.getAdministrationService().getGlobalProperty(
1✔
1251
                                                OpenmrsConstants.GLOBAL_PROPERTY_UNKNOWN_CONCEPT)));
1252
                                initializeLazyPropertiesForConcept(unknownConcept);
1✔
1253
                                
1254
                                ConceptServiceImpl.setStaticUnknownConcept(unknownConcept);
1✔
1255
                        }
1256
                        catch (NumberFormatException e) {
×
1257
                                log.warn("Concept id for unknown concept should be a number");
×
1258
                        }
1✔
1259
                }
1260
                
1261
                return unknownConcept;
1✔
1262
        }
1263
        
1264
        /**
1265
         * Sets unknownConcept using static method
1266
         *
1267
         * @param currentUnknownConcept
1268
         */
1269
        private static void setStaticUnknownConcept(Concept currentUnknownConcept) {
1270
                ConceptServiceImpl.unknownConcept = currentUnknownConcept;
1✔
1271
        }
1✔
1272
        
1273
        /**
1274
         * Sets the TRUE and FALSE concepts by reading their ids from the global_property table
1275
         */
1276
        private void setBooleanConcepts() {
1277
                
1278
                try {
1279
                        trueConcept = Context.getConceptService().getConcept(
1✔
1280
                            Integer.parseInt(Context.getAdministrationService().getGlobalProperty(
1✔
1281
                                OpenmrsConstants.GLOBAL_PROPERTY_TRUE_CONCEPT)));
1282
                        initializeLazyPropertiesForConcept(trueConcept);
1✔
1283
                        
1284
                        falseConcept = Context.getConceptService().getConcept(
1✔
1285
                            Integer.parseInt(Context.getAdministrationService().getGlobalProperty(
1✔
1286
                                OpenmrsConstants.GLOBAL_PROPERTY_FALSE_CONCEPT)));
1287
                        initializeLazyPropertiesForConcept(falseConcept);
1✔
1288
                }
1289
                catch (NumberFormatException e) {
×
1290
                        log.warn("Concept ids for boolean concepts should be numbers");
×
1291
                }
1✔
1292
        }
1✔
1293

1294
        private void initializeLazyPropertiesForConcept(Concept concept) {
1295
                Hibernate.initialize(concept.getRetiredBy());
1✔
1296
                Hibernate.initialize(concept.getCreator());
1✔
1297
                Hibernate.initialize(concept.getChangedBy());
1✔
1298
                Hibernate.initialize(concept.getNames());
1✔
1299
                Hibernate.initialize(concept.getAnswers());
1✔
1300
                Hibernate.initialize(concept.getConceptSets());
1✔
1301
                Hibernate.initialize(concept.getDescriptions());
1✔
1302
                Hibernate.initialize(concept.getConceptMappings());
1✔
1303
                Hibernate.initialize(concept.getAttributes());
1✔
1304
        }
1✔
1305

1306
        /**
1307
         * @see org.openmrs.api.ConceptService#getConceptSourceByName(java.lang.String)
1308
         */
1309
        @Override
1310
        @Transactional(readOnly = true)
1311
        public ConceptSource getConceptSourceByName(String conceptSourceName) throws APIException {
1312
                return dao.getConceptSourceByName(conceptSourceName);
1✔
1313
        }
1314

1315
        /**
1316
         * @see org.openmrs.api.ConceptService#getConceptSourceByUniqueId(java.lang.String)
1317
         */
1318
        @Override
1319
        @Transactional(readOnly = true)
1320
        public ConceptSource getConceptSourceByUniqueId(String uniqueId) throws APIException {
1321
                if (uniqueId == null) {
1✔
1322
                        throw new IllegalArgumentException("uniqueId is required");
1✔
1323
                }
1324
                return dao.getConceptSourceByUniqueId(uniqueId);
1✔
1325
        }
1326

1327
        /**
1328
         * @see org.openmrs.api.ConceptService#getConceptSourceByHL7Code(java.lang.String)
1329
         */
1330
        @Override
1331
        @Transactional(readOnly = true)
1332
        public ConceptSource getConceptSourceByHL7Code(String hl7Code) throws APIException {
1333
                if (hl7Code == null) {
1✔
1334
                        throw new IllegalArgumentException("hl7Code is required");
1✔
1335
                }
1336
                return dao.getConceptSourceByHL7Code(hl7Code);
1✔
1337
        }
1338

1339
        /**
1340
         * Utility method to check if the concept is already attached to an observation (including
1341
         * voided ones) and if the datatype of the concept has changed, an exception indicating that the
1342
         * datatype cannot be modified will be reported if the concept is attached to an observation.
1343
         * This method will only allow changing boolean concepts to coded.
1344
         * 
1345
         * @param concept
1346
         * @throws ConceptInUseException
1347
         */
1348
        private void checkIfDatatypeCanBeChanged(Concept concept) {
1349
                if (concept.getId() != null && hasAnyObservation(concept) && hasDatatypeChanged(concept)) {
1✔
1350
                        // allow boolean concepts to be converted to coded
1351
                        if (!(dao.getSavedConceptDatatype(concept).isBoolean() && concept.getDatatype().isCoded())) {
1✔
1352
                                throw new ConceptInUseException();
1✔
1353
                        }
1354
                        log.debug("Converting datatype of concept with id {} from Boolean to coded", concept.getConceptId());
1✔
1355
                }
1356
        }
1✔
1357
        
1358
        /**
1359
         * Utility method which loads the previous version of a concept to check if the datatype has
1360
         * changed.
1361
         * 
1362
         * @param concept to be modified
1363
         * @return boolean indicating change in the datatype
1364
         */
1365
        private boolean hasDatatypeChanged(Concept concept) {
1366
                ConceptDatatype oldConceptDatatype = dao.getSavedConceptDatatype(concept);
1✔
1367
                return !oldConceptDatatype.equals(concept.getDatatype());
1✔
1368
        }
1369
        
1370
        /**
1371
         * @see org.openmrs.api.ConceptService#hasAnyObservation(org.openmrs.Concept)
1372
         */
1373
        @Override
1374
        @Transactional(readOnly = true)
1375
        public boolean hasAnyObservation(Concept concept) {
1376
                List<Concept> concepts = new ArrayList<>();
1✔
1377
                concepts.add(concept);
1✔
1378
                Integer count = Context.getObsService().getObservationCount(null, null, concepts, null, null, null, null, null,
1✔
1379
                    null, true);
1380
                return count > 0;
1✔
1381
        }
1382
        
1383
        /**
1384
         * @see org.openmrs.api.ConceptService#convertBooleanConceptToCoded(org.openmrs.Concept)
1385
         */
1386
        @Override
1387
        public void convertBooleanConceptToCoded(Concept conceptToChange) throws APIException {
1388
                if (conceptToChange != null) {
1✔
1389
                        if (!conceptToChange.getDatatype().isBoolean()) {
1✔
1390
                                throw new APIException("Concept.datatype.invalid", (Object[]) null);
1✔
1391
                        }
1392
                        
1393
                        conceptToChange.setDatatype(getConceptDatatypeByName("Coded"));
1✔
1394
                        conceptToChange.addAnswer(new ConceptAnswer(getTrueConcept()));
1✔
1395
                        conceptToChange.addAnswer(new ConceptAnswer(getFalseConcept()));
1✔
1396
                        Context.getConceptService().saveConcept(conceptToChange);
1✔
1397
                }
1398
        }
1✔
1399
        
1400
        /**
1401
         * @see org.openmrs.api.ConceptService#hasAnyObservation(org.openmrs.ConceptName)
1402
         */
1403
        @Override
1404
        @Transactional(readOnly = true)
1405
        public boolean hasAnyObservation(ConceptName conceptName) throws APIException {
1406
                List<ConceptName> conceptNames = new ArrayList<>();
1✔
1407
                conceptNames.add(conceptName);
1✔
1408
                Integer count = Context.getObsService().getObservationCount(conceptNames, true);
1✔
1409
                return count > 0;
1✔
1410
        }
1411
        
1412
        /**
1413
         * Utility method which loads the previous version of a conceptName to check if the name
1414
         * property of the given conceptName has changed.
1415
         * 
1416
         * @param conceptName to be modified
1417
         * @return boolean indicating change in the name property
1418
         */
1419
        private boolean hasNameChanged(ConceptName conceptName) {
1420
                String newName = conceptName.getName();
1✔
1421
                String oldName = dao.getSavedConceptName(conceptName).getName();
1✔
1422
                return !oldName.equalsIgnoreCase(newName);
1✔
1423
        }
1424
        
1425
        /**
1426
         * Creates a copy of a conceptName
1427
         * 
1428
         * @param conceptName the conceptName to be cloned
1429
         * @return the cloned conceptName
1430
         */
1431
        private ConceptName cloneConceptName(ConceptName conceptName) {
1432
                ConceptName copy = new ConceptName();
1✔
1433
                try {
1434
                        copy = (ConceptName) BeanUtils.cloneBean(conceptName);
1✔
1435
                }
1436
                catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e) {
×
1437
                        
1438
                        log.warn(ERROR_MESSAGE, e);
×
1439
                }
1✔
1440
                return copy;
1✔
1441
        }
1442
        
1443
        /**
1444
         * @see ConceptService#findConceptAnswers(String, Locale, Concept)
1445
         */
1446
        @Override
1447
        @Transactional(readOnly = true)
1448
        public List<ConceptSearchResult> findConceptAnswers(String phrase, Locale locale, Concept concept) throws APIException {
1449

1450
                return getConcepts(phrase, Collections.singletonList(locale), false, null, null, null, null,
1✔
1451
                    concept, null, null);
1452
        }
1453
        
1454
        /**
1455
         * @see org.openmrs.api.ConceptService#getConceptStopWords(java.util.Locale)
1456
         */
1457
        @Override
1458
        @Transactional(readOnly = true)
1459
        public List<String> getConceptStopWords(Locale locale) {
1460
                return dao.getConceptStopWords(locale);
1✔
1461
        }
1462
        
1463
        /**
1464
         * @see org.openmrs.api.ConceptService#saveConceptStopWord(org.openmrs.ConceptStopWord)
1465
         */
1466
        @Override
1467
        public ConceptStopWord saveConceptStopWord(ConceptStopWord conceptStopWord) throws APIException {
1468
                try {
1469
                        return dao.saveConceptStopWord(conceptStopWord);
1✔
1470
                }
1471
                catch (DAOException e) {
1✔
1472
                        if ("Duplicate ConceptStopWord Entry".equalsIgnoreCase(e.getMessage())) {
1✔
1473
                                throw new ConceptStopWordException("ConceptStopWord.duplicated", e);
1✔
1474
                        }
1475
                        throw new ConceptStopWordException("ConceptStopWord.notSaved", e);
×
1476
                }
1477
        }
1478
        
1479
        /**
1480
         * @see org.openmrs.api.ConceptService#deleteConceptStopWord(Integer)
1481
         */
1482
        @Override
1483
        public void deleteConceptStopWord(Integer conceptStopWordId) throws APIException {
1484
                try {
1485
                        dao.deleteConceptStopWord(conceptStopWordId);
1✔
1486
                }
1487
                catch (DAOException e) {
×
1488
                        if (StringUtils.contains(e.getMessage(), "Concept Stop Word not found or already deleted")) {
×
1489
                                throw new ConceptStopWordException("ConceptStopWord.error.notfound", e);
×
1490
                        }
1491
                        throw new ConceptStopWordException("general.cannot.delete", e);
×
1492
                }
1✔
1493
        }
1✔
1494
        
1495
        /**
1496
         * @see org.openmrs.api.ConceptService#getAllConceptStopWords()
1497
         */
1498
        @Override
1499
        @Transactional(readOnly = true)
1500
        public List<ConceptStopWord> getAllConceptStopWords() {
1501
                return dao.getAllConceptStopWords();
1✔
1502
        }
1503
        
1504
        /**
1505
         * @see ConceptService#getConcepts(String, List, boolean, List, List, List, List, Concept,
1506
         *      Integer, Integer)
1507
         */
1508
        @Override
1509
        @Transactional(readOnly = true)
1510
        public List<ConceptSearchResult> getConcepts(String phrase, List<Locale> locales, boolean includeRetired,
1511
                List<ConceptClass> requireClasses, List<ConceptClass> excludeClasses, List<ConceptDatatype> requireDatatypes,
1512
                List<ConceptDatatype> excludeDatatypes, Concept answersToConcept, Integer start, Integer size)
1513
                throws APIException {
1514

1515
                List<ConceptClass> tmpRequireClasses = requireClasses == null ? new ArrayList<>() : requireClasses;
1✔
1516
                List<ConceptClass> tmpExcludeClasses = excludeClasses == null ? new ArrayList<>() : excludeClasses;
1✔
1517
                List<ConceptDatatype> tmpRequireDatatypes = requireDatatypes == null ? new ArrayList<>() : requireDatatypes;
1✔
1518
                List<ConceptDatatype> tmpExcludeDatatypes = excludeDatatypes == null ? new ArrayList<>() : excludeDatatypes;
1✔
1519
                
1520
                return dao.getConcepts(phrase, locales, includeRetired, tmpRequireClasses, tmpExcludeClasses, tmpRequireDatatypes,
1✔
1521
                    tmpExcludeDatatypes, answersToConcept, start, size);
1522
                
1523
        }
1524
        
1525
        /**
1526
         * @see ConceptService#updateConceptIndex(Concept)
1527
         */
1528
        @Override
1529
        public void updateConceptIndex(Concept concept) throws APIException {
1530
                Context.updateSearchIndexForObject(concept);
×
1531
        }
×
1532
        
1533
        /**
1534
         * @see ConceptService#updateConceptIndexes()
1535
         */
1536
        @Override
1537
        @CacheEvict(value = CONCEPT_IDS_BY_MAPPING_CACHE_NAME, allEntries = true)
1538
        public void updateConceptIndexes() throws APIException {
1539
                Context.updateSearchIndexForType(ConceptName.class);
1✔
1540
        }
1✔
1541
        
1542
        /**
1543
         * @see ConceptService#getCountOfConcepts(String, List, boolean, List, List, List, List,
1544
         *      Concept)
1545
         */
1546
        @Override
1547
        @Transactional(readOnly = true)
1548
        public Integer getCountOfConcepts(String phrase, List<Locale> locales, boolean includeRetired,
1549
                List<ConceptClass> requireClasses, List<ConceptClass> excludeClasses, List<ConceptDatatype> requireDatatypes,
1550
                List<ConceptDatatype> excludeDatatypes, Concept answersToConcept) {
1551

1552
                List<ConceptClass> tmpRequireClasses = requireClasses == null ? new ArrayList<>() : requireClasses;
1✔
1553
                List<ConceptClass> tmpExcludeClasses = excludeClasses == null ? new ArrayList<>() : excludeClasses;
1✔
1554
                List<ConceptDatatype> tmpRequireDatatypes = requireDatatypes == null ? new ArrayList<>() : requireDatatypes;
1✔
1555
                List<ConceptDatatype> tmpExcludeDatatypes = excludeDatatypes == null ? new ArrayList<>() : excludeDatatypes;
1✔
1556
                
1557
                return dao.getCountOfConcepts(phrase, locales, includeRetired, tmpRequireClasses, tmpExcludeClasses, tmpRequireDatatypes,
1✔
1558
                    tmpExcludeDatatypes, answersToConcept);
1559
        }
1560
        
1561
        /**
1562
         * @see ConceptService#getCountOfDrugs(String, Concept, boolean, boolean, boolean)
1563
         */
1564
        @Override
1565
        @Transactional(readOnly = true)
1566
        public Integer getCountOfDrugs(String drugName, Concept concept, boolean searchOnPhrase, boolean searchDrugConceptNames,
1567
                boolean includeRetired) throws APIException {
1568
                return OpenmrsUtil.convertToInteger(dao.getCountOfDrugs(drugName, concept, searchOnPhrase, searchDrugConceptNames,
1✔
1569
                    includeRetired));
1570
        }
1571
        
1572
        /**
1573
         * @see ConceptService#getDrugs(String, Concept, boolean, boolean, boolean, Integer, Integer)
1574
         */
1575
        @Override
1576
        @Transactional(readOnly = true)
1577
        public List<Drug> getDrugs(String drugName, Concept concept, boolean searchOnPhrase, boolean searchDrugConceptNames,
1578
                boolean includeRetired, Integer start, Integer length) throws APIException {
1579
                return dao.getDrugs(drugName, concept, searchOnPhrase, searchDrugConceptNames, includeRetired, start, length);
1✔
1580
        }
1581
        
1582
        /**
1583
         * @see ConceptService#getConcepts(String, Locale, boolean)
1584
         */
1585
        @Override
1586
        @Transactional(readOnly = true)
1587
        public List<ConceptSearchResult> getConcepts(String phrase, Locale locale, boolean includeRetired) throws APIException {
1588
                List<Locale> locales = new ArrayList<>();
1✔
1589
                if (locale != null) {
1✔
1590
                        locales.add(locale);
1✔
1591
                }
1592
                
1593
                return Context.getConceptService().getConcepts(phrase, locales, includeRetired, null, null, null, null, null, null,
1✔
1594
                    null);
1595
        }
1596
        
1597
        /**
1598
         * @see org.openmrs.api.ConceptService#getDrugsByIngredient(org.openmrs.Concept)
1599
         */
1600
        @Override
1601
        @Transactional(readOnly = true)
1602
        public List<Drug> getDrugsByIngredient(Concept ingredient) throws APIException {
1603
                if (ingredient == null) {
1✔
1604
                        throw new IllegalArgumentException("ingredient is required");
1✔
1605
                }
1606
                
1607
                return dao.getDrugsByIngredient(ingredient);
1✔
1608
        }
1609
        
1610
        /**
1611
         * @see ConceptService#getConceptMappingsToSource(ConceptSource)
1612
         */
1613
        @Override
1614
        @Transactional(readOnly = true)
1615
        public List<ConceptMap> getConceptMappingsToSource(ConceptSource conceptSource) throws APIException {
1616
                return dao.getConceptMapsBySource(conceptSource);
1✔
1617
        }
1618
        
1619
        /**
1620
         * @see ConceptService#getActiveConceptMapTypes()
1621
         */
1622
        @Override
1623
        @Transactional(readOnly = true)
1624
        public List<ConceptMapType> getActiveConceptMapTypes() throws APIException {
1625
                return Context.getConceptService().getConceptMapTypes(true, false);
1✔
1626
        }
1627
        
1628
        /**
1629
         * @see ConceptService#getConceptMapTypes(boolean, boolean)
1630
         */
1631
        @Override
1632
        @Transactional(readOnly = true)
1633
        public List<ConceptMapType> getConceptMapTypes(boolean includeRetired, boolean includeHidden) throws APIException {
1634
                return dao.getConceptMapTypes(includeRetired, includeHidden);
1✔
1635
        }
1636
        
1637
        /**
1638
         * @see ConceptService#getConceptMapType(Integer)
1639
         */
1640
        @Override
1641
        @Transactional(readOnly = true)
1642
        public ConceptMapType getConceptMapType(Integer conceptMapTypeId) throws APIException {
1643
                return dao.getConceptMapType(conceptMapTypeId);
1✔
1644
        }
1645
        
1646
        /**
1647
         * @see ConceptService#getConceptMapTypeByUuid(String)
1648
         */
1649
        @Override
1650
        @Transactional(readOnly = true)
1651
        public ConceptMapType getConceptMapTypeByUuid(String uuid) throws APIException {
1652
                return dao.getConceptMapTypeByUuid(uuid);
1✔
1653
        }
1654
        
1655
        /**
1656
         * @see org.openmrs.api.ConceptService#getConceptMapTypeByName(java.lang.String)
1657
         */
1658
        @Override
1659
        @Transactional(readOnly = true)
1660
        public ConceptMapType getConceptMapTypeByName(String name) throws APIException {
1661
                return dao.getConceptMapTypeByName(name);
1✔
1662
        }
1663
        
1664
        /**
1665
         * @see org.openmrs.api.ConceptService#saveConceptMapType(org.openmrs.ConceptMapType)
1666
         */
1667
        @Override
1668
        public ConceptMapType saveConceptMapType(ConceptMapType conceptMapType) throws APIException {
1669
                return dao.saveConceptMapType(conceptMapType);
1✔
1670
        }
1671
        
1672
        /**
1673
         * @see org.openmrs.api.ConceptService#retireConceptMapType(org.openmrs.ConceptMapType,
1674
         *      java.lang.String)
1675
         */
1676
        @Override
1677
        public ConceptMapType retireConceptMapType(ConceptMapType conceptMapType, String retireReason) throws APIException {
1678
                String tmpRetireReason = retireReason;
1✔
1679
                if (StringUtils.isBlank(tmpRetireReason)) {
1✔
1680
                        tmpRetireReason = Context.getMessageSourceService().getMessage("general.default.retireReason");
1✔
1681
                }
1682
                conceptMapType.setRetireReason(tmpRetireReason);
1✔
1683
                return dao.saveConceptMapType(conceptMapType);
1✔
1684
        }
1685
        
1686
        /**
1687
         * @see org.openmrs.api.ConceptService#unretireConceptMapType(org.openmrs.ConceptMapType)
1688
         */
1689
        @Override
1690
        public ConceptMapType unretireConceptMapType(ConceptMapType conceptMapType) throws APIException {
1691
                return Context.getConceptService().saveConceptMapType(conceptMapType);
1✔
1692
        }
1693
        
1694
        /**
1695
         * @see org.openmrs.api.ConceptService#purgeConceptMapType(org.openmrs.ConceptMapType)
1696
         */
1697
        @Override
1698
        public void purgeConceptMapType(ConceptMapType conceptMapType) throws APIException {
1699
                if (dao.isConceptMapTypeInUse(conceptMapType)) {
1✔
1700
                        throw new APIException("ConceptMapType.inUse", (Object[]) null);
×
1701
                }
1702
                dao.deleteConceptMapType(conceptMapType);
1✔
1703
        }
1✔
1704
        
1705
        /**
1706
         * @see org.openmrs.api.ConceptService#getAllConceptReferenceTerms()
1707
         */
1708
        @Override
1709
        @Transactional(readOnly = true)
1710
        public List<ConceptReferenceTerm> getAllConceptReferenceTerms() throws APIException {
1711
                return Context.getConceptService().getConceptReferenceTerms(true);
1✔
1712
        }
1713
        
1714
        /**
1715
         * @see ConceptService#getConceptReferenceTerms(boolean)
1716
         */
1717
        @Override
1718
        @Transactional(readOnly = true)
1719
        public List<ConceptReferenceTerm> getConceptReferenceTerms(boolean includeRetired) throws APIException {
1720
                return dao.getConceptReferenceTerms(includeRetired);
1✔
1721
        }
1722
        
1723
        /**
1724
         * @see org.openmrs.api.ConceptService#getConceptReferenceTerm(java.lang.Integer)
1725
         */
1726
        @Override
1727
        @Transactional(readOnly = true)
1728
        public ConceptReferenceTerm getConceptReferenceTerm(Integer conceptReferenceTermId) throws APIException {
1729
                return dao.getConceptReferenceTerm(conceptReferenceTermId);
1✔
1730
        }
1731
        
1732
        /**
1733
         * @see org.openmrs.api.ConceptService#getConceptReferenceTermByUuid(java.lang.String)
1734
         */
1735
        @Override
1736
        @Transactional(readOnly = true)
1737
        public ConceptReferenceTerm getConceptReferenceTermByUuid(String uuid) throws APIException {
1738
                return dao.getConceptReferenceTermByUuid(uuid);
1✔
1739
        }
1740
        
1741
        /**
1742
         * @see org.openmrs.api.ConceptService#getConceptReferenceTermByName(java.lang.String,
1743
         *      org.openmrs.ConceptSource)
1744
         */
1745
        @Override
1746
        @Transactional(readOnly = true)
1747
        public ConceptReferenceTerm getConceptReferenceTermByName(String name, ConceptSource conceptSource) throws APIException {
1748
                //On addition of extra attributes to concept maps, terms that were generated from existing maps have 
1749
                //empty string values for the name property, ignore the search when name is an empty string but allow 
1750
                //white space characters
1751
                if (StringUtils.isBlank(name)) {
1✔
1752
                        return null;
1✔
1753
                }
1754
                return dao.getConceptReferenceTermByName(name, conceptSource);
1✔
1755
        }
1756
        
1757
        /**
1758
         * @see org.openmrs.api.ConceptService#getConceptReferenceTermByCode(java.lang.String,
1759
         *      org.openmrs.ConceptSource)
1760
         */
1761
        @Override
1762
        @Transactional(readOnly = true)
1763
        public ConceptReferenceTerm getConceptReferenceTermByCode(String code, ConceptSource conceptSource) throws APIException {
1764
                return dao.getConceptReferenceTermByCode(code, conceptSource);
1✔
1765
        }
1766

1767
        @Override
1768
        @Transactional(readOnly = true)
1769
        public List<ConceptReferenceTerm> getConceptReferenceTermByCode(String code, ConceptSource conceptSource, boolean includeRetired) throws APIException {
1770
                return dao.getConceptReferenceTermByCode(code, conceptSource, includeRetired);
1✔
1771
        }
1772

1773
        /**
1774
         * @see org.openmrs.api.ConceptService#saveConceptReferenceTerm(org.openmrs.ConceptReferenceTerm)
1775
         */
1776
        @Override
1777
        @CacheEvict(value = CONCEPT_IDS_BY_MAPPING_CACHE_NAME, allEntries = true)
1778
        public ConceptReferenceTerm saveConceptReferenceTerm(ConceptReferenceTerm conceptReferenceTerm) throws APIException {
1779
                return dao.saveConceptReferenceTerm(conceptReferenceTerm);
1✔
1780
        }
1781
        
1782
        /**
1783
         * @see org.openmrs.api.ConceptService#retireConceptReferenceTerm(ConceptReferenceTerm, String)
1784
         */
1785
        @Override
1786
        public ConceptReferenceTerm retireConceptReferenceTerm(ConceptReferenceTerm conceptReferenceTerm, String retireReason)
1787
                throws APIException {
1788
                String tmpRetireReason = retireReason;
1✔
1789
                if (StringUtils.isBlank(tmpRetireReason)) {
1✔
1790
                        tmpRetireReason = Context.getMessageSourceService().getMessage("general.default.retireReason");
1✔
1791
                }
1792
                conceptReferenceTerm.setRetireReason(tmpRetireReason);
1✔
1793
                return Context.getConceptService().saveConceptReferenceTerm(conceptReferenceTerm);
1✔
1794
        }
1795
        
1796
        /**
1797
         * @see org.openmrs.api.ConceptService#unretireConceptReferenceTerm(org.openmrs.ConceptReferenceTerm)
1798
         */
1799
        @Override
1800
        public ConceptReferenceTerm unretireConceptReferenceTerm(ConceptReferenceTerm conceptReferenceTerm) throws APIException {
1801
                return Context.getConceptService().saveConceptReferenceTerm(conceptReferenceTerm);
1✔
1802
        }
1803
        
1804
        /**
1805
         * @see org.openmrs.api.ConceptService#purgeConceptReferenceTerm(org.openmrs.ConceptReferenceTerm)
1806
         */
1807
        @Override
1808
        @CacheEvict(value = CONCEPT_IDS_BY_MAPPING_CACHE_NAME, allEntries = true)
1809
        public void purgeConceptReferenceTerm(ConceptReferenceTerm conceptReferenceTerm) throws APIException {
1810
                if (dao.isConceptReferenceTermInUse(conceptReferenceTerm)) {
1✔
1811
                        throw new APIException("ConceptRefereceTerm.inUse", (Object[]) null);
1✔
1812
                }
1813
                dao.deleteConceptReferenceTerm(conceptReferenceTerm);
1✔
1814
        }
1✔
1815
        
1816
        /**
1817
         * @see org.openmrs.api.ConceptService#getConceptReferenceTerms(java.lang.String,
1818
         *      org.openmrs.ConceptSource, java.lang.Integer, java.lang.Integer, boolean)
1819
         */
1820
        @Override
1821
        @Transactional(readOnly = true)
1822
        public List<ConceptReferenceTerm> getConceptReferenceTerms(String query, ConceptSource conceptSource, Integer start,
1823
                Integer length, boolean includeRetired) throws APIException {
1824
                Integer tmpLength = length;
1✔
1825
                if (tmpLength == null) {
1✔
1826
                        tmpLength = 10000;
1✔
1827
                }
1828
                return dao.getConceptReferenceTerms(query, conceptSource, start, tmpLength, includeRetired);
1✔
1829
        }
1830
        
1831
        /**
1832
         * @see org.openmrs.api.ConceptService#getCountOfConceptReferenceTerms(String, ConceptSource,
1833
         *      boolean)
1834
         */
1835
        @Override
1836
        @Transactional(readOnly = true)
1837
        public Integer getCountOfConceptReferenceTerms(String query, ConceptSource conceptSource, boolean includeRetired) {
1838
                return OpenmrsUtil.convertToInteger(dao.getCountOfConceptReferenceTerms(query, conceptSource, includeRetired));
1✔
1839
        }
1840
        
1841
        /**
1842
         * @see org.openmrs.api.ConceptService#getReferenceTermMappingsTo(ConceptReferenceTerm)
1843
         */
1844
        @Override
1845
        @Transactional(readOnly = true)
1846
        public List<ConceptReferenceTermMap> getReferenceTermMappingsTo(ConceptReferenceTerm term) throws APIException {
1847
                return dao.getReferenceTermMappingsTo(term);
1✔
1848
        }
1849
        
1850
        /**
1851
         * @see org.openmrs.api.ConceptService#getConceptsByName(java.lang.String, java.util.Locale,
1852
         *      java.lang.Boolean)
1853
         */
1854
        @Override
1855
        @Transactional(readOnly = true)
1856
        public List<Concept> getConceptsByName(String name, Locale locale, Boolean exactLocale) throws APIException {
1857
                return dao.getConceptsByName(name, locale, exactLocale);
1✔
1858
        }
1859
        
1860
        /**
1861
         * @see org.openmrs.api.ConceptService#getDefaultConceptMapType()
1862
         */
1863
        @Override
1864
        @Transactional(readOnly = true)
1865
        public ConceptMapType getDefaultConceptMapType() throws APIException {
1866
                //We need to fetch it in DAO since it must be done in the MANUAL fush mode to prevent pre-mature flushes.
1867
                return dao.getDefaultConceptMapType();
1✔
1868
        }
1869
        
1870
        /**
1871
         * @see org.openmrs.api.ConceptService#isConceptNameDuplicate(org.openmrs.ConceptName)
1872
         */
1873
        @Override
1874
        public boolean isConceptNameDuplicate(ConceptName name) {
1875
                return dao.isConceptNameDuplicate(name);
1✔
1876
        }
1877
        
1878
        /**
1879
         * @see ConceptService#getDrugs(String, java.util.Locale, boolean, boolean)
1880
         */
1881
        @Override
1882
        @Transactional(readOnly = true)
1883
        public List<Drug> getDrugs(String searchPhrase, Locale locale, boolean exactLocale, boolean includeRetired)
1884
                throws APIException {
1885
                if (searchPhrase == null) {
1✔
1886
                        throw new IllegalArgumentException("searchPhrase is required");
1✔
1887
                }
1888
                return dao.getDrugs(searchPhrase, locale, exactLocale, includeRetired);
1✔
1889
        }
1890
        
1891
        /**
1892
         * @see org.openmrs.api.ConceptService#getDrugsByMapping(String, ConceptSource, Collection,
1893
         *      boolean)
1894
         */
1895
        @Override
1896
        @Transactional(readOnly = true)
1897
        public List<Drug> getDrugsByMapping(String code, ConceptSource conceptSource,
1898
                Collection<ConceptMapType> withAnyOfTheseTypes, boolean includeRetired) throws APIException {
1899
                Collection<ConceptMapType> tmpWithAnyOfTheseTypes = withAnyOfTheseTypes == null ? Collections.emptyList() : withAnyOfTheseTypes;
1✔
1900

1901
                if (conceptSource == null) {
1✔
1902
                        throw new APIException("ConceptSource.is.required", (Object[]) null);
1✔
1903
                }
1904

1905
                return dao.getDrugsByMapping(code, conceptSource, tmpWithAnyOfTheseTypes, includeRetired);
1✔
1906
        }
1907
        
1908
        /**
1909
         * @see org.openmrs.api.ConceptService#getDrugByMapping(String, org.openmrs.ConceptSource, java.util.Collection)
1910
         */
1911
        @Override
1912
        @Transactional(readOnly = true)
1913
        public Drug getDrugByMapping(String code, ConceptSource conceptSource,
1914
                Collection<ConceptMapType> withAnyOfTheseTypesOrOrderOfPreference) throws APIException {
1915
                Collection<ConceptMapType> tmpWithAnyOfTheseTypesOrOrderOfPreference = withAnyOfTheseTypesOrOrderOfPreference == null
1✔
1916
                                ? Collections.emptyList() : withAnyOfTheseTypesOrOrderOfPreference;
1✔
1917

1918
                if (conceptSource == null) {
1✔
1919
                        throw new APIException("ConceptSource.is.required", (Object[]) null);
1✔
1920
                }
1921

1922
                return dao.getDrugByMapping(code, conceptSource, tmpWithAnyOfTheseTypesOrOrderOfPreference);
1✔
1923
        }
1924
        
1925
        /**
1926
         * @see org.openmrs.api.ConceptService#getOrderableConcepts(String, java.util.List, boolean,
1927
         *      Integer, Integer)
1928
         */
1929
        @Override
1930
        @Transactional(readOnly = true)
1931
        public List<ConceptSearchResult> getOrderableConcepts(String phrase, List<Locale> locales, boolean includeRetired,
1932
                Integer start, Integer length) {
1933
                List<ConceptClass> mappedClasses = getConceptClassesOfOrderTypes();
1✔
1934
                if (mappedClasses.isEmpty()) {
1✔
1935
                        return Collections.emptyList();
×
1936
                }
1937
                List<Locale> tmpLocales = locales;
1✔
1938
                if (tmpLocales == null) {
1✔
1939
                        tmpLocales = new ArrayList<>();
1✔
1940
                        tmpLocales.add(Context.getLocale());
1✔
1941
                }
1942
                return dao.getConcepts(phrase, tmpLocales, false, mappedClasses, Collections.emptyList(), Collections.emptyList(),
1✔
1943
                    Collections.emptyList(), null, start, length);
1✔
1944
        }
1945

1946
        /**
1947
         * @see ConceptService#getAllConceptAttributeTypes()
1948
         */
1949
        @Override
1950
        @Transactional(readOnly = true)
1951
        public List<ConceptAttributeType> getAllConceptAttributeTypes() {
1952
                return dao.getAllConceptAttributeTypes();
1✔
1953
        }
1954

1955
        /**
1956
         * @see org.openmrs.api.ConceptService#saveConceptAttributeType(ConceptAttributeType)
1957
         */
1958
        @Override
1959
        public ConceptAttributeType saveConceptAttributeType(ConceptAttributeType conceptAttributeType) {
1960
                return dao.saveConceptAttributeType(conceptAttributeType);
1✔
1961
        }
1962

1963
        /**
1964
         * @see org.openmrs.api.ConceptService#getConceptAttributeType(Integer)
1965
         */
1966
        @Override
1967
        @Transactional(readOnly = true)
1968
        public ConceptAttributeType getConceptAttributeType(Integer id) {
1969
                return dao.getConceptAttributeType(id);
1✔
1970
        }
1971

1972
        /**
1973
         * @see org.openmrs.api.ConceptService#getConceptAttributeTypeByUuid(String)
1974
         */
1975
        @Override
1976
        @Transactional(readOnly = true)
1977
        public ConceptAttributeType getConceptAttributeTypeByUuid(String uuid) {
1978
                return dao.getConceptAttributeTypeByUuid(uuid);
1✔
1979
        }
1980

1981
        /**
1982
         * @see org.openmrs.api.ConceptService#purgeConceptAttributeType(ConceptAttributeType)
1983
         */
1984
        @Override
1985
        public void purgeConceptAttributeType(ConceptAttributeType conceptAttributeType) {
1986
                dao.deleteConceptAttributeType(conceptAttributeType);
1✔
1987

1988
        }
1✔
1989

1990
        /**
1991
         * @see org.openmrs.api.ConceptService#getConceptAttributeTypes(String)
1992
         */
1993
        @Override
1994
        @Transactional(readOnly = true)
1995
        public List<ConceptAttributeType> getConceptAttributeTypes(String name) throws APIException {
1996
                return dao.getConceptAttributeTypes(name);
1✔
1997
        }
1998

1999
        /**
2000
         * @see org.openmrs.api.ConceptService#getConceptAttributeTypeByName(String)
2001
         */
2002
        @Override
2003
        @Transactional(readOnly = true)
2004
        public ConceptAttributeType getConceptAttributeTypeByName(String exactName) {
2005
                return dao.getConceptAttributeTypeByName(exactName);
1✔
2006
        }
2007

2008
        /**
2009
         * @see org.openmrs.api.ConceptService#retireConceptAttributeType(ConceptAttributeType, String)
2010
         */
2011
        @Override
2012
        public ConceptAttributeType retireConceptAttributeType(ConceptAttributeType conceptAttributeType, String reason) {
2013
                return dao.saveConceptAttributeType(conceptAttributeType);
1✔
2014
        }
2015

2016
        /**
2017
         * @see org.openmrs.api.ConceptService#unretireConceptAttributeType(ConceptAttributeType)
2018
         */
2019
        @Override
2020
        public ConceptAttributeType unretireConceptAttributeType(ConceptAttributeType conceptAttributeType) {
2021
                return Context.getConceptService().saveConceptAttributeType(conceptAttributeType);
1✔
2022
        }
2023

2024
        /**
2025
         * @see org.openmrs.api.ConceptService#getConceptAttributeByUuid(String)
2026
         */
2027
        @Override
2028
        @Transactional(readOnly = true)
2029
        public ConceptAttribute getConceptAttributeByUuid(String uuid) {
2030
                return dao.getConceptAttributeByUuid(uuid);
1✔
2031
        }
2032

2033
        /**
2034
         * @see org.openmrs.api.ConceptService#hasAnyConceptAttribute(ConceptAttributeType)
2035
         */
2036
        @Override
2037
        @Transactional(readOnly = true)
2038
        public boolean hasAnyConceptAttribute(ConceptAttributeType conceptAttributeType) {
2039
                return dao.getConceptAttributeCount(conceptAttributeType) > 0;
1✔
2040
        }
2041

2042
        /**
2043
         * @see ConceptService#saveConceptReferenceRange(ConceptReferenceRange)
2044
         */
2045
        @Override
2046
        public ConceptReferenceRange saveConceptReferenceRange(ConceptReferenceRange conceptReferenceRange) {
2047
                return dao.saveConceptReferenceRange(conceptReferenceRange);
1✔
2048
        }
2049

2050
        /**
2051
         * @see ConceptService#getConceptReferenceRangesByConceptId(Integer)
2052
         */
2053
        @Override
2054
        @Transactional(readOnly = true)
2055
        public List<ConceptReferenceRange> getConceptReferenceRangesByConceptId(Integer conceptId) {
2056
                return dao.getConceptReferenceRangesByConceptId(conceptId);
1✔
2057
        }
2058

2059
        @Override
2060
        public ConceptReferenceRange getConceptReferenceRangeByUuid(String uuid) {
2061
                return dao.getConceptReferenceRangeByUuid(uuid);
1✔
2062
        }
2063
        
2064
        @Override
2065
        public ConceptReferenceRange getConceptReferenceRange(Person person, Concept concept) {
2066
                if (person == null || concept == null) {
1✔
2067
                        return null;
1✔
2068
                }
2069
                return Context.getConceptService().getConceptReferenceRange(
1✔
2070
                        new ConceptReferenceRangeContext(person, concept, null));
2071
        }
2072

2073
        @Override
2074
        public ConceptReferenceRange getConceptReferenceRange(ConceptReferenceRangeContext context) {
2075
                if (context == null) {
1✔
2076
                        throw new IllegalArgumentException("ConceptReferenceRangeContext must not be null");
1✔
2077
                }
2078

2079
                Concept concept = HibernateUtil.getRealObjectFromProxy(context.getConcept());
1✔
2080
                if (!(concept instanceof ConceptNumeric) || concept.getDatatype() == null || !concept.getDatatype().isNumeric()) {
1✔
2081
                        return null;
1✔
2082
                }
2083
                ConceptNumeric conceptNumeric = (ConceptNumeric) concept;
1✔
2084

2085
                List<ConceptReferenceRange> referenceRanges =
2086
                        Context.getConceptService().getConceptReferenceRangesByConceptId(concept.getConceptId());
1✔
2087

2088
                if (referenceRanges.isEmpty()) {
1✔
2089
                        return getDefaultReferenceRange(conceptNumeric);
1✔
2090
                }
2091

2092
                ConceptReferenceRangeUtility referenceRangeUtility = new ConceptReferenceRangeUtility();
1✔
2093
                List<ConceptReferenceRange> validRanges = new ArrayList<>();
1✔
2094

2095
                for (ConceptReferenceRange referenceRange : referenceRanges) {
1✔
2096
                        if (referenceRangeUtility.evaluateCriteria(
1✔
2097
                                        StringEscapeUtils.unescapeHtml4(referenceRange.getCriteria()), context)) {
1✔
2098
                                validRanges.add(referenceRange);
1✔
2099
                        }
2100
                }
1✔
2101

2102
                if (validRanges.isEmpty()) {
1✔
2103
                        ConceptReferenceRange defaultReferenceRange = getDefaultReferenceRange(conceptNumeric);
1✔
2104
                        if (defaultReferenceRange != null) {
1✔
2105
                                return defaultReferenceRange;
1✔
2106
                        }
2107
                        return null;
×
2108
                }
2109

2110
                return findStrictestReferenceRange(validRanges);
1✔
2111
        }
2112

2113
        /**
2114
         * Returns a reference range derived from the ConceptNumeric's own range fields.
2115
         * Used as a fallback when no ConceptReferenceRange records exist or match.
2116
         */
2117
        private static ConceptReferenceRange getDefaultReferenceRange(ConceptNumeric conceptNumeric) {
2118
                if (conceptNumeric == null || (
1✔
2119
                        conceptNumeric.getHiAbsolute() == null &&
1✔
2120
                        conceptNumeric.getHiCritical() == null &&
1✔
2121
                        conceptNumeric.getHiNormal() == null &&
1✔
2122
                        conceptNumeric.getLowAbsolute() == null &&
1✔
2123
                        conceptNumeric.getLowCritical() == null &&
1✔
2124
                        conceptNumeric.getLowNormal() == null
1✔
2125
                )) {
2126
                        return null;
1✔
2127
                }
2128

2129
                ConceptReferenceRange defaultReferenceRange = new ConceptReferenceRange();
1✔
2130
                defaultReferenceRange.setConceptNumeric(conceptNumeric);
1✔
2131
                defaultReferenceRange.setHiAbsolute(conceptNumeric.getHiAbsolute());
1✔
2132
                defaultReferenceRange.setHiCritical(conceptNumeric.getHiCritical());
1✔
2133
                defaultReferenceRange.setHiNormal(conceptNumeric.getHiNormal());
1✔
2134
                defaultReferenceRange.setLowAbsolute(conceptNumeric.getLowAbsolute());
1✔
2135
                defaultReferenceRange.setLowCritical(conceptNumeric.getLowCritical());
1✔
2136
                defaultReferenceRange.setLowNormal(conceptNumeric.getLowNormal());
1✔
2137
                return defaultReferenceRange;
1✔
2138
        }
2139

2140
        /**
2141
         * Combines multiple matching reference ranges into one by selecting the strictest bound for
2142
         * each limit. For low bounds, the highest value is strictest; for high bounds, the lowest.
2143
         * For example, ranges 80-150 and 60-140 combine to 80-140.
2144
         */
2145
        private static ConceptReferenceRange findStrictestReferenceRange(List<ConceptReferenceRange> conceptReferenceRanges) {
2146
                if (conceptReferenceRanges.size() == 1) {
1✔
2147
                        return conceptReferenceRanges.get(0);
1✔
2148
                }
2149

2150
                ConceptReferenceRange strictestRange = new ConceptReferenceRange();
1✔
2151
                strictestRange.setConceptNumeric(conceptReferenceRanges.get(0).getConceptNumeric());
1✔
2152

2153
                for (ConceptReferenceRange conceptReferenceRange : conceptReferenceRanges) {
1✔
2154
                        if (conceptReferenceRange.getLowAbsolute() != null &&
1✔
2155
                                        (strictestRange.getLowAbsolute() == null || strictestRange.getLowAbsolute() < conceptReferenceRange.getLowAbsolute())) {
1✔
2156
                                strictestRange.setLowAbsolute(conceptReferenceRange.getLowAbsolute());
1✔
2157
                        }
2158

2159
                        if (conceptReferenceRange.getLowCritical() != null &&
1✔
2160
                                        (strictestRange.getLowCritical() == null || strictestRange.getLowCritical() < conceptReferenceRange.getLowCritical())) {
1✔
2161
                                strictestRange.setLowCritical(conceptReferenceRange.getLowCritical());
1✔
2162
                        }
2163

2164
                        if (conceptReferenceRange.getLowNormal() != null &&
1✔
2165
                                        (strictestRange.getLowNormal() == null || strictestRange.getLowNormal() < conceptReferenceRange.getLowNormal())) {
1✔
2166
                                strictestRange.setLowNormal(conceptReferenceRange.getLowNormal());
1✔
2167
                        }
2168

2169
                        if (conceptReferenceRange.getHiNormal() != null &&
1✔
2170
                                        (strictestRange.getHiNormal() == null || strictestRange.getHiNormal() > conceptReferenceRange.getHiNormal())) {
1✔
2171
                                strictestRange.setHiNormal(conceptReferenceRange.getHiNormal());
1✔
2172
                        }
2173

2174
                        if (conceptReferenceRange.getHiCritical() != null &&
1✔
2175
                                        (strictestRange.getHiCritical() == null || strictestRange.getHiCritical() > conceptReferenceRange.getHiCritical())) {
1✔
2176
                                strictestRange.setHiCritical(conceptReferenceRange.getHiCritical());
1✔
2177
                        }
2178

2179
                        if (conceptReferenceRange.getHiAbsolute() != null &&
1✔
2180
                                        (strictestRange.getHiAbsolute() == null || strictestRange.getHiAbsolute() > conceptReferenceRange.getHiAbsolute())) {
1✔
2181
                                strictestRange.setHiAbsolute(conceptReferenceRange.getHiAbsolute());
1✔
2182
                        }
2183
                }
1✔
2184

2185
                return strictestRange;
1✔
2186
        }
2187

2188
        private List<ConceptClass> getConceptClassesOfOrderTypes() {
2189
                List<ConceptClass> mappedClasses = new ArrayList<>();
1✔
2190
                AdministrationService administrationService = Context.getAdministrationService();
1✔
2191
                List<List<Object>> result = administrationService.executeSQL(
1✔
2192
                    "SELECT DISTINCT concept_class_id FROM order_type_class_map", true);
2193
                for (List<Object> temp : result) {
1✔
2194
                        for (Object value : temp) {
1✔
2195
                                if (value != null) {
1✔
2196
                                        mappedClasses.add(this.getConceptClass((Integer) value));
1✔
2197
                                }
2198
                        }
1✔
2199
                }
1✔
2200
                return mappedClasses;
1✔
2201
        }
2202
        
2203
        /**
2204
         * @see org.openmrs.api.ConceptService#purgeConceptReferenceRange(ConceptReferenceRange)
2205
         */
2206
        @Override
2207
        public void purgeConceptReferenceRange(ConceptReferenceRange conceptReferenceRange) {
2208
                checkIfLocked();
1✔
2209
                dao.purgeConceptReferenceRange(conceptReferenceRange);
1✔
2210
        }
1✔
2211
}
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