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

IQSS / dataverse / #22987

23 Aug 2024 06:44PM UTC coverage: 20.61% (-0.2%) from 20.791%
#22987

Pull #10781

github

landreev
added an upfront locks check to the /addGlobusFiles api #10623
Pull Request #10781: Improved handling of Globus uploads

4 of 417 new or added lines in 15 files covered. (0.96%)

4194 existing lines in 35 files now uncovered.

17388 of 84365 relevant lines covered (20.61%)

0.21 hits per line

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

4.07
/src/main/java/edu/harvard/iq/dataverse/metrics/MetricsUtil.java
1
package edu.harvard.iq.dataverse.metrics;
2

3
import edu.harvard.iq.dataverse.Dataverse;
4
import java.io.StringReader;
5
import java.math.BigDecimal;
6
import java.time.LocalDate;
7
import java.time.YearMonth;
8
import java.time.format.DateTimeFormatter;
9
import java.time.format.DateTimeParseException;
10
import java.util.ArrayList;
11
import java.util.HashMap;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.logging.Logger;
15
import jakarta.json.Json;
16
import jakarta.json.JsonArray;
17
import jakarta.json.JsonArrayBuilder;
18
import jakarta.json.JsonObject;
19
import jakarta.json.JsonObjectBuilder;
20
import jakarta.json.JsonReader;
21
import jakarta.ws.rs.BadRequestException;
22

UNCOV
23
public class MetricsUtil {
×
24

25
    private static final Logger logger = Logger.getLogger(MetricsUtil.class.getCanonicalName());
1✔
26

27
    public final static String CONTENTTYPE = "contenttype";
28
    public final static String COUNT = "count";
29
    public final static String CATEGORY = "category";
30
    public final static String ID = "id";
31
    public final static String PID = "pid";
32
    public final static String SUBJECT = "subject";
33
    public final static String DATE = "date";
34
    public final static String SIZE = "size";
35

36
    public static String YEAR_AND_MONTH_PATTERN = "yyyy-MM";
1✔
37

38
    public static final String DATA_LOCATION_LOCAL = "local";
39
    public static final String DATA_LOCATION_REMOTE = "remote";
40
    public static final String DATA_LOCATION_ALL = "all";
41

42
    public static JsonObjectBuilder countToJson(long count) {
UNCOV
43
        JsonObjectBuilder job = Json.createObjectBuilder();
×
UNCOV
44
        job.add(COUNT, count);
×
UNCOV
45
        return job;
×
46
    }
47

48
    public static JsonArrayBuilder dataversesByCategoryToJson(List<Object[]> listOfObjectArrays) {
UNCOV
49
        JsonArrayBuilder jab = Json.createArrayBuilder();
×
UNCOV
50
        for (Object[] arrayOfObjects : listOfObjectArrays) {
×
UNCOV
51
            JsonObjectBuilder job = Json.createObjectBuilder();
×
UNCOV
52
            String categoryNameUppercase = (String) arrayOfObjects[0];
×
UNCOV
53
            Dataverse dataverse = new Dataverse();
×
UNCOV
54
            dataverse.setDataverseType(Dataverse.DataverseType.valueOf(categoryNameUppercase));
×
UNCOV
55
            String categoryNameFriendly = dataverse.getFriendlyCategoryName();
×
UNCOV
56
            long categoryCount = (long) arrayOfObjects[1];
×
UNCOV
57
            job.add(CATEGORY, categoryNameFriendly);
×
UNCOV
58
            job.add(COUNT, categoryCount);
×
UNCOV
59
            jab.add(job);
×
UNCOV
60
        }
×
UNCOV
61
        return jab;
×
62
    }
63

64
    public static JsonArrayBuilder dataversesBySubjectToJson(List<Object[]> listOfObjectArrays) {
UNCOV
65
        JsonArrayBuilder jab = Json.createArrayBuilder();
×
UNCOV
66
        for (Object[] objectArray : listOfObjectArrays) {
×
UNCOV
67
            JsonObjectBuilder job = Json.createObjectBuilder();
×
UNCOV
68
            String subject = (String) objectArray[0];
×
UNCOV
69
            long count = (long) objectArray[1];
×
UNCOV
70
            job.add(SUBJECT, subject);
×
UNCOV
71
            job.add(COUNT, count);
×
UNCOV
72
            jab.add(job);
×
UNCOV
73
        }
×
UNCOV
74
        return jab;
×
75
    }
76

77
    public static JsonArrayBuilder datasetsBySubjectToJson(List<Object[]> listOfObjectArrays) {
UNCOV
78
        JsonArrayBuilder jab = Json.createArrayBuilder();
×
UNCOV
79
        for (Object[] objectArray : listOfObjectArrays) {
×
UNCOV
80
            JsonObjectBuilder job = Json.createObjectBuilder();
×
UNCOV
81
            String subject = (String) objectArray[0];
×
UNCOV
82
            long count = (long) objectArray[1];
×
UNCOV
83
            job.add(SUBJECT, subject);
×
UNCOV
84
            job.add(COUNT, count);
×
UNCOV
85
            jab.add(job);
×
UNCOV
86
        }
×
UNCOV
87
        return jab;
×
88
    }
89
    
90
    public static JsonArray timeSeriesToJson(List<Object[]> results) {
UNCOV
91
        return timeSeriesToJson(results, false);
×
92
    }
93
    
94
    public static JsonArray timeSeriesToJson(List<Object[]> results, boolean isBigDecimal) {
UNCOV
95
        JsonArrayBuilder jab = Json.createArrayBuilder();
×
UNCOV
96
        long total = 0;
×
UNCOV
97
        String curDate = (String) results.get(0)[0];
×
98
        // Get a list of all the monthly dates from the start until now
99
        List<String> dates = getDatesFrom(curDate);
×
100
        int i = 0;
×
101
        // Create an entry for each date
102
        for (String date : dates) {
×
103
            JsonObjectBuilder job = Json.createObjectBuilder();
×
104
            
105
            // If there's a result for this date, add it's count to the total
106
            // and find the date of the next entry
UNCOV
107
            if (date.equals(curDate)) {
×
UNCOV
108
                if(isBigDecimal) {
×
UNCOV
109
                    total +=((BigDecimal) results.get(i)[1]).longValue();
×
110
                } else {
111
                    total += (long) results.get(i)[1];
×
112
                }
UNCOV
113
                i += 1;
×
114
                if (i < results.size()) {
×
UNCOV
115
                    curDate = (String) results.get(i)[0];
×
116
                }
117
            }
118
            /*Don't report dates prior to the first count
119
             * Probably generally useful but added specifically because some installations
120
             * with MDC did not get unique view info to start, so there are MDC downloads
121
             * starting from the first logging date but unique views/downloads only start
122
             * later and it is odd to see no unique counts for the prior months
123
             */
124

UNCOV
125
            if (total != 0) {
×
UNCOV
126
                job.add(MetricsUtil.DATE, date);
×
127
                // Then add the aggregate count
128
                job.add(MetricsUtil.COUNT, total);
×
129
                jab.add(job);
×
130
            }
131
        }
×
132
        return jab.build();
×
133
    }
134
    
135
    public static JsonArray timeSeriesByTypeToJson(List<Object[]> results) {
UNCOV
136
        JsonArrayBuilder jab = Json.createArrayBuilder();
×
UNCOV
137
        Map<String, Long> totals = new HashMap<String, Long>();
×
UNCOV
138
        Map<String, Long> sizes =  new HashMap<String, Long>();
×
139
        String curDate = (String) results.get(0)[0];
×
140
        // Get a list of all the monthly dates from the start until now
141
        List<String> dates = getDatesFrom(curDate);
×
142
        int i = 0;
×
143
        // Create an entry for each date
144
        for (String date : dates) {
×
145

146
            // If there's are results for this date, add their counts to the totals
147
            // and find the date of the next entry(ies)
UNCOV
148
            while (date.equals(curDate) && i < results.size()) {
×
UNCOV
149
                String type = (String) results.get(i)[1];
×
UNCOV
150
                totals.put(type,  (totals.containsKey(type) ? totals.get(type) : 0) + (long) results.get(i)[2]);
×
151
                sizes.put(type,  (sizes.containsKey(type) ? sizes.get(type) : 0) + ((BigDecimal) results.get(i)[3]).longValue());
×
152
                i += 1;
×
153
                if (i < results.size()) {
×
154
                    curDate = (String) results.get(i)[0];
×
155
                }
156
            }
×
157
            // Then add the aggregate count and size for all types
UNCOV
158
            for(String type: totals.keySet()) {
×
159
                JsonObjectBuilder job = Json.createObjectBuilder();
×
UNCOV
160
                job.add(MetricsUtil.DATE, date);
×
161
                job.add(CONTENTTYPE, type);
×
162
                job.add(COUNT, totals.get(type));
×
163
                job.add(SIZE, sizes.get(type));
×
164
                jab.add(job);
×
165
            }
×
166
        }
×
167
        return jab.build();
×
168
    }
169
    
170
    public static JsonArray timeSeriesByPIDToJson(List<Object[]> results) {
UNCOV
171
        JsonArrayBuilder jab = Json.createArrayBuilder();
×
UNCOV
172
        Map<String, Long> totals = new HashMap<String, Long>();
×
UNCOV
173
        String curDate = (String) results.get(0)[0];
×
174
        // Get a list of all the monthly dates from the start until now
175
        List<String> dates = getDatesFrom(curDate);
×
176
        int i = 0;
×
177
        // Create an entry for each date
178
        for (String date : dates) {
×
179
            // If there's are results for this date, add their counts to the totals
180
            // and find the date of the next entry(ies)
181
            while (date.equals(curDate) && i < results.size()) {
×
UNCOV
182
                String pid = (String) results.get(i)[1];
×
UNCOV
183
                totals.put(pid,  (totals.containsKey(pid) ? totals.get(pid) : 0) + (long) results.get(i)[2]);
×
184
                i += 1;
×
185
                if (i < results.size()) {
×
186
                    curDate = (String) results.get(i)[0];
×
187
                }
188
            }
×
189
            // Then add the aggregate count and size for all types
UNCOV
190
            for(String type: totals.keySet()) {
×
191
                JsonObjectBuilder job = Json.createObjectBuilder();
×
UNCOV
192
                job.add(MetricsUtil.DATE, date);
×
193
                job.add(PID, type);
×
194
                job.add(COUNT, totals.get(type));
×
195
                jab.add(job);
×
196
            }
×
197
        }
×
198
        return jab.build();
×
199
    }
200
    
201
    public static JsonArray timeSeriesByIDAndPIDToJson(List<Object[]> results) {
UNCOV
202
        JsonArrayBuilder jab = Json.createArrayBuilder();
×
UNCOV
203
        Map<Integer, Long> totals = new HashMap<Integer, Long>();
×
UNCOV
204
        Map<Integer, String> pids = new HashMap<Integer, String>();
×
205
        String curDate = (String) results.get(0)[0];
×
206
        // Get a list of all the monthly dates from the start until now
207
        List<String> dates = getDatesFrom(curDate);
×
208
        int i = 0;
×
209
        // Create an entry for each date
210
        for (String date : dates) {
×
211
            // If there's are results for this date, add their counts to the totals
212
            // and find the date of the next entry(ies)
213
            while (date.equals(curDate) && i < results.size()) {
×
UNCOV
214
                Integer id = (Integer) results.get(i)[1];
×
UNCOV
215
                String pid = (String) results.get(i)[2];
×
216
                totals.put(id,  (totals.containsKey(id) ? totals.get(id) : 0) + (long) results.get(i)[3]);
×
217
                pids.put(id,  pid);
×
218
                i += 1;
×
219
                if (i < results.size()) {
×
220
                    curDate = (String) results.get(i)[0];
×
221
                }
222
            }
×
223
            // Then add the aggregate count and size for all types
UNCOV
224
            for(Integer id: totals.keySet()) {
×
225
                JsonObjectBuilder job = Json.createObjectBuilder();
×
UNCOV
226
                job.add(MetricsUtil.DATE, date);
×
227
                job.add(ID, id);
×
228
                if(pids.get(id)!=null) {
×
229
                    job.add(PID, pids.get(id));
×
230
                }
231
                job.add(COUNT, totals.get(id));
×
232
                jab.add(job);
×
UNCOV
233
            }
×
234
        }
×
235
        return jab.build();
×
236
    }
237
    
238

239
    /**
240
     *
241
     * @param userInput A year and month in YYYY-MM format.
242
     * @return A year and month in YYYY-M     
243
     * Note that along with sanitization, this checks that the requested month is
244
     * not after the current one. This will need to be made more robust if we
245
     * start writing metrics for farther in the future (e.g. the current year) the current year)
246
     */
247
    public static String sanitizeYearMonthUserInput(String userInput) throws BadRequestException {
UNCOV
248
        logger.fine("string from user to sanitize (hopefully YYYY-MM format): " + userInput);
×
UNCOV
249
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YEAR_AND_MONTH_PATTERN);
×
UNCOV
250
        LocalDate inputLocalDate = null;
×
251
        try {
UNCOV
252
            inputLocalDate = YearMonth.parse(userInput, dateTimeFormatter).atDay(1);
×
UNCOV
253
        } catch (DateTimeParseException ex) {
×
UNCOV
254
            throw new BadRequestException("The expected format is YYYY-MM but an exception was thrown: " + ex.getLocalizedMessage());
×
UNCOV
255
        }
×
256

UNCOV
257
        LocalDate currentDate = LocalDate.now();
×
258

UNCOV
259
        if (inputLocalDate.isAfter(currentDate)) {
×
UNCOV
260
            throw new BadRequestException("The requested date is set past the current month.");
×
261
        }
262

UNCOV
263
        String sanitized = inputLocalDate.format(dateTimeFormatter);
×
UNCOV
264
        return sanitized;
×
265
    }
266

267
    public static String validateDataLocationStringType(String dataLocation) throws BadRequestException {
268
        if (null == dataLocation || "".equals(dataLocation)) {
1✔
269
            dataLocation = DATA_LOCATION_LOCAL;
1✔
270
        }
271
        if (!(DATA_LOCATION_LOCAL.equals(dataLocation) || DATA_LOCATION_REMOTE.equals(dataLocation) || DATA_LOCATION_ALL.equals(dataLocation))) {
1✔
272
            throw new BadRequestException("Data location must be 'local', 'remote', or 'all'");
1✔
273
        }
274

275
        return dataLocation;
1✔
276
    }
277

278
    public static String getCurrentMonth() {
UNCOV
279
        return LocalDate.now().format(DateTimeFormatter.ofPattern(MetricsUtil.YEAR_AND_MONTH_PATTERN));
×
280
    }
281

282
    public static JsonObject stringToJsonObject(String str) {
UNCOV
283
        if (str == null) {
×
UNCOV
284
            return null;
×
285
        }
UNCOV
286
        JsonReader jsonReader = Json.createReader(new StringReader(str));
×
UNCOV
287
        JsonObject jo = jsonReader.readObject();
×
UNCOV
288
        jsonReader.close();
×
289

UNCOV
290
        return jo;
×
291
    }
292

293
    public static JsonArray stringToJsonArray(String str) {
UNCOV
294
        if (str == null) {
×
UNCOV
295
            return null;
×
296
        }
UNCOV
297
        JsonReader jsonReader = Json.createReader(new StringReader(str));
×
UNCOV
298
        JsonArray ja = jsonReader.readArray();
×
UNCOV
299
        jsonReader.close();
×
300

UNCOV
301
        return ja;
×
302
    }
303

304
    public static List<String> getDatesFrom(String startMonth) {
UNCOV
305
        List<String> dates = new ArrayList<String>();
×
UNCOV
306
        LocalDate next = LocalDate.parse(startMonth+ "-01").plusMonths(1);
×
UNCOV
307
        dates.add(startMonth);
×
UNCOV
308
        DateTimeFormatter monthFormat = DateTimeFormatter.ofPattern(YEAR_AND_MONTH_PATTERN);
×
UNCOV
309
        while (next.isBefore(LocalDate.now())) {
×
UNCOV
310
            dates.add(next.format(monthFormat));
×
UNCOV
311
            next = next.plusMonths(1);
×
312
        }
UNCOV
313
        return dates;
×
314
    }
315
}
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

© 2025 Coveralls, Inc