• 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

71.88
/api/src/main/java/org/openmrs/obs/handler/TextHandler.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.BufferedReader;
13
import java.io.BufferedWriter;
14
import java.io.IOException;
15
import java.io.InputStream;
16
import java.io.InputStreamReader;
17
import java.io.OutputStreamWriter;
18
import java.io.Reader;
19
import java.io.UncheckedIOException;
20
import java.nio.charset.StandardCharsets;
21

22
import org.apache.commons.io.IOUtils;
23
import org.openmrs.Obs;
24
import org.openmrs.api.APIException;
25
import org.openmrs.api.storage.ObjectMetadata;
26
import org.openmrs.obs.ComplexData;
27
import org.openmrs.obs.ComplexObsHandler;
28
import org.slf4j.Logger;
29
import org.slf4j.LoggerFactory;
30
import org.springframework.stereotype.Component;
31
import org.springframework.util.Assert;
32

33
/**
34
 * Handler for storing files for complex obs to the file system. Files are stored in the location
35
 * specified by the global property: "obs.complex_obs_dir"
36
 * The in coming data are either char[] or java.io.Reader
37
 *
38
 */
39
@Component
40
public class TextHandler extends AbstractHandler implements ComplexObsHandler {
41
        
42
        /** Views supported by this handler */
43
        private static final String[] supportedViews = { ComplexObsHandler.TEXT_VIEW, ComplexObsHandler.RAW_VIEW,
1✔
44
                ComplexObsHandler.URI_VIEW };
45
        
46
        private static final Logger log = LoggerFactory.getLogger(TextHandler.class);
1✔
47
        
48
        /**
49
         * Constructor initializes formats for alternative file names to protect from unintentionally
50
         * overwriting existing files.
51
         */
52
        public TextHandler() {
53
                super();
1✔
54
        }
1✔
55
        
56
        /**
57
         * 
58
         * 
59
         * @see org.openmrs.obs.ComplexObsHandler#getObs(org.openmrs.Obs, java.lang.String)
60
         */
61
        @Override
62
        public Obs getObs(Obs obs, String view) {
63
                String key = parseDataKey(obs);
1✔
64
                
65
                log.debug("value complex: {}", obs.getValueComplex());
1✔
66
                log.debug("file path: {}", key);
1✔
67
                ComplexData complexData = null;
1✔
68
                
69
                if (ComplexObsHandler.TEXT_VIEW.equals(view) || ComplexObsHandler.RAW_VIEW.equals(view)) {
1✔
70
                        // to handle problem with downloading/saving files with blank spaces or commas in their names
71
                        // also need to remove the "file" text appended to the end of the file name
72
                        String[] names = obs.getValueComplex().split("\\|");
1✔
73
                        String originalFilename = names[0];
1✔
74
                        originalFilename = originalFilename.replaceAll(",", "")
1✔
75
                                .replaceAll(" ", "").replaceAll("file$", "");
1✔
76
                        
77
                        try (InputStream is = storageService.getData(key)){
1✔
78
                                complexData = ComplexObsHandler.RAW_VIEW.equals(view) ? new ComplexData(originalFilename, 
1✔
79
                                        IOUtils.toByteArray(is)) : new ComplexData(originalFilename, 
1✔
80
                                        IOUtils.toString(is, StandardCharsets.UTF_8));
1✔
81
                        }
82
                        catch (IOException e) {
×
NEW
83
                                log.error("Trying to read file: {}", key, e);
×
84
                        }
1✔
85
                } else if (ComplexObsHandler.URI_VIEW.equals(view)) {
1✔
NEW
86
                        complexData = new ComplexData(parseDataTitle(obs), key);
×
87
                } else {
88
                        // No other view supported
89
                        // NOTE: if adding support for another view, don't forget to update supportedViews list above
90
                        return null;
×
91
                }
92
                Assert.notNull(complexData, "Complex data must not be null");
1✔
93
                
94
                // Get the Mime Type and set it
95
                ObjectMetadata metadata;
96
                try {
97
                        metadata = storageService.getMetadata(key);
1✔
NEW
98
                } catch (IOException e) {
×
NEW
99
                        throw new UncheckedIOException(e);
×
100
                }
1✔
101
                String mimeType = metadata.getMimeType();
1✔
102
                mimeType = !(mimeType.equals("application/octet-stream")) ? mimeType : "text/plain";
1✔
103
                complexData.setMimeType(mimeType);
1✔
104
                complexData.setLength(metadata.getLength());
1✔
105
                obs.setComplexData(complexData);
1✔
106
                
107
                return obs;
1✔
108
        }
109
        
110
        /**
111
         * @see org.openmrs.obs.ComplexObsHandler#getSupportedViews()
112
         */
113
        @Override
114
        public String[] getSupportedViews() {
115
                return supportedViews;
1✔
116
        }
117
        
118
        /**
119
         * 
120
         * 
121
         * @see org.openmrs.obs.ComplexObsHandler#saveObs(org.openmrs.Obs)
122
         */
123
        @Override
124
        public Obs saveObs(Obs obs) throws APIException {
125
                ComplexData complexData = obs.getComplexData();
1✔
126
                if (complexData == null) {
1✔
NEW
127
                        log.error("Cannot save complex data where obsId={} because its ComplexData is null.", obs.getObsId());
×
128
                        return obs;
×
129
                }
130
                try {
131
                        String assignedKey = storageService.saveData((out) -> {
1✔
132
                                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
1✔
133

134
                                Object data = obs.getComplexData().getData();
1✔
135
                                if (data instanceof char[]) {
1✔
NEW
136
                                        writer.write((char[]) data);
×
137
                                } else if (Reader.class.isAssignableFrom(data.getClass())) {
1✔
138
                                        try (Reader reader = new BufferedReader((Reader) data)){
1✔
139
                                                IOUtils.copy(reader, writer);
1✔
140
                                        }
NEW
141
                                        catch (IOException e) {
×
NEW
142
                                                throw new APIException("Obs.error.unable.convert.complex.data", new Object[] { "Reader" }, e);
×
143
                                        }
1✔
144
                                } else if (InputStream.class.isAssignableFrom(data.getClass())) {
1✔
NEW
145
                                        try (Reader reader = new BufferedReader(new InputStreamReader((InputStream) data, 
×
146
                                                StandardCharsets.UTF_8))) {
NEW
147
                                                IOUtils.copy(reader, writer);
×
148
                                        }
NEW
149
                                        catch (IOException e) {
×
NEW
150
                                                throw new APIException("Obs.error.unable.convert.complex.data", new Object[] { "input stream" }, e);
×
UNCOV
151
                                        }
×
152
                                }
153
                                writer.flush();
1✔
154
                        }, ObjectMetadata.builder().setFilename(obs.getComplexData().getTitle()).build(),  getObsDir());
1✔
155
                        
156
                        // Set the Title and URI for the valueComplex
157
                        obs.setValueComplex(obs.getComplexData().getTitle() + " file |" + assignedKey);
1✔
158
                        
159
                        // Remove the ComplexData from the Obs
160
                        obs.setComplexData(null);
1✔
161
                        
162
                }
163
                catch (IOException ioe) {
×
164
                        throw new APIException("Obs.error.trying.write.complex", null, ioe);
×
165
                }
1✔
166
                
167
                return obs;
1✔
168
        }
169
        
170
}
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