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

openmrs / openmrs-core / 13853363634

14 Mar 2025 09:10AM UTC coverage: 65.081% (+0.1%) from 64.959%
13853363634

push

github

web-flow
TRUNK-6304 Refactor code to use Storage Service (#4944)

* TRUNK-6300 Add Storage Service

* TRUNK-6304 Refactor code to use Storage Service

319 of 401 new or added lines in 13 files covered. (79.55%)

17 existing lines in 4 files now uncovered.

23407 of 35966 relevant lines covered (65.08%)

0.65 hits per line

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

80.77
/api/src/main/java/org/openmrs/obs/handler/AbstractHandler.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.obs.handler;
11

12
import java.io.IOException;
13
import java.io.InputStream;
14
import java.io.UncheckedIOException;
15
import java.util.Arrays;
16

17
import org.apache.commons.io.IOUtils;
18
import org.apache.commons.lang3.StringUtils;
19
import org.openmrs.Obs;
20
import org.openmrs.api.APIException;
21
import org.openmrs.api.AdministrationService;
22
import org.openmrs.api.StorageService;
23
import org.openmrs.api.storage.ObjectMetadata;
24
import org.openmrs.obs.ComplexData;
25
import org.openmrs.util.OpenmrsConstants;
26
import org.slf4j.Logger;
27
import org.slf4j.LoggerFactory;
28
import org.springframework.beans.factory.annotation.Autowired;
29

30
/**
31
 * Abstract handler for some convenience methods Files are stored in the location specified by the
32
 * global property: "obs.complex_obs_dir"
33
 * 
34
 * @since 1.5
35
 */
36
public class AbstractHandler {
37
        
38
        private static final Logger log = LoggerFactory.getLogger(AbstractHandler.class);
1✔
39
        
40
        @Autowired
41
        StorageService storageService;
42
        
43
        @Autowired
44
        AdministrationService adminService;
45
        
46
        public AbstractHandler() {
1✔
47
        }
1✔
48
        
49
        public AbstractHandler(AdministrationService adminService, StorageService storageService) {
50
                this();
1✔
51
                this.adminService = adminService;
1✔
52
                this.storageService = storageService;
1✔
53
        }
1✔
54

55
        /**
56
         * @return obs dir
57
         * @since 2.8.0
58
         */
59
        public String getObsDir() {
60
                return adminService.getGlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_COMPLEX_OBS_DIR);
1✔
61
        }
62

63
        /**
64
         * @see org.openmrs.obs.ComplexObsHandler#getObs(Obs, String)
65
         */
66
        public Obs getObs(Obs obs, String view) {
67
                String key = parseDataKey(obs);
1✔
68
                
69
                byte[] bytes;
70
                try (InputStream is = storageService.getData(key)) {
1✔
71
                        bytes = IOUtils.toByteArray(is);
1✔
72
                }
NEW
73
                catch (IOException e) {
×
NEW
74
                        throw new UncheckedIOException(e);
×
75
                }
1✔
76
                
77
                ComplexData complexData = new ComplexData(parseDataTitle(obs), bytes);
1✔
78
                injectMissingMetadata(key, complexData);
1✔
79
                obs.setComplexData(complexData);
1✔
80
                return obs;
1✔
81
        }
82

83
        /**
84
         * @see org.openmrs.obs.ComplexObsHandler#saveObs(Obs) 
85
         */
86
        public Obs saveObs(Obs obs) throws APIException {
87
                try {
88
                        byte[] data = (byte[]) obs.getComplexData().getData();
1✔
89
                        
90
                        String key = storageService.saveData(outputStream -> {
1✔
91
                                IOUtils.write( data, outputStream);
1✔
92
                        }, ObjectMetadata.builder().setLength((long) data.length).build(), getObsDir());
1✔
93
                        // Store the filename in the Obs
94
                        obs.setValueComplex(StringUtils.defaultIfBlank(obs.getComplexData().getTitle(), key) + "|" + key);
1✔
95
                        obs.setComplexData(null);
1✔
96
                }
NEW
97
                catch (Exception e) {
×
NEW
98
                        throw new APIException("Obs.error.writing.binary.data.complex", null, e);
×
99
                }
1✔
100

101
                return obs;
1✔
102
        }
103
        
104
        /**
105
         * @see org.openmrs.obs.ComplexObsHandler#purgeComplexData(org.openmrs.Obs)
106
         */
107
        public boolean purgeComplexData(Obs obs) {
108
                String key = parseDataKey(obs);
1✔
109
                
110
                try {
111
                        storageService.purgeData(key);
1✔
112
                        obs.setComplexData(null);
1✔
113
                        return true;
1✔
NEW
114
                } catch (IOException e) {
×
NEW
115
                        log.warn("Could not delete complex data object for obsId={} located at {}", obs.getObsId(), key);
×
NEW
116
                        return false;
×
117
                }
118
        }
119

120
        /**
121
         * 
122
         * @param obs complex obs
123
         * @return key
124
         * @since 2.8.0
125
         */
126
        public String parseDataKey(Obs obs) {
127
                String[] names = obs.getValueComplex().split("\\|");
1✔
128
                String key = names.length < 2 ? names[0] : names[names.length - 1];
1✔
129
                
130
                if (!storageService.exists(key)) {
1✔
131
                        // prepend legacy storage location
132
                        key = getObsDir() + '/' + key;
1✔
133
                }
134
                return key;
1✔
135
        }
136

137
        /**
138
         * @param obs the obs
139
         * @return file title
140
         * @since 2.8.0
141
         */
142
        public String parseDataTitle(Obs obs) {
143
                String[] names = obs.getValueComplex().split("\\|");
1✔
144
                return names[0];
1✔
145
        }
146

147
        protected void injectMissingMetadata(String key, ComplexData complexData) {
148
                try {
149
                        ObjectMetadata metadata = storageService.getMetadata(key);
1✔
150
                        
151
                        if (complexData.getMimeType() == null) {
1✔
152
                                complexData.setMimeType(metadata.getMimeType());
1✔
153
                        }
154
                        complexData.setLength(metadata.getLength());
1✔
NEW
155
                } catch (IOException e) {
×
NEW
156
                        throw new UncheckedIOException(e);
×
157
                }
1✔
158
        }
1✔
159

160
        /**
161
         * @see org.openmrs.obs.ComplexObsHandler#getSupportedViews()
162
         */
163
        public String[] getSupportedViews() {
164
                return new String[0];
×
165
        }
166
        
167
        /**
168
         * @see org.openmrs.obs.ComplexObsHandler#supportsView(java.lang.String)
169
         */
170
        public boolean supportsView(String view) {
171
                return Arrays.asList(getSupportedViews()).contains(view);
1✔
172
        }
173
        
174
}
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