Skip to content

Commit 9a6e2fe

Browse files
[2.43] fix: prevent NPE in event report table-layout download when dimensions/items metadata entries are missing (#23939)
* fix: prevent NPE in event report table-layout download when dimensions/items metadata entries are missing (#23686)
1 parent b66ca83 commit 9a6e2fe

2 files changed

Lines changed: 85 additions & 2 deletions

File tree

dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/EventAggregateService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ private void addEventReportDimensionalItems(
493493
(List<String>)
494494
((Map<String, Object>) grid.getMetaData().get(DIMENSIONS.getKey())).get(dimension);
495495

496-
if (legendOptions.isEmpty()) {
496+
if (legendOptions == null || legendOptions.isEmpty()) {
497497
List<Legend> legends = eventDimensionalItemObject.getLegendSet().getSortedLegends();
498498
addLegends(dimensionalItems, parentUid, legends);
499499
} else {
@@ -604,7 +604,7 @@ private Grid generateOutputGrid(
604604
MetadataItem metadataItem =
605605
(MetadataItem) ((Map<String, Object>) grid.getMetaData().get(ITEMS.getKey())).get(row);
606606

607-
String name = defaultIfEmpty(metadataItem.getName(), row);
607+
String name = metadataItem == null ? row : defaultIfEmpty(metadataItem.getName(), row);
608608
String col = defaultIfEmpty(COLUMN_NAMES.get(row), row);
609609

610610
outputGrid.addHeader(new GridHeader(name, col, TEXT, false, true));

dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAggregateServiceTest.java

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,32 @@
3232
import static org.hisp.dhis.analytics.DataQueryParams.VALUE_ID;
3333
import static org.hisp.dhis.common.DimensionConstants.PERIOD_DIM_ID;
3434
import static org.hisp.dhis.common.DimensionType.PERIOD;
35+
import static org.hisp.dhis.test.TestBase.createDataElement;
36+
import static org.hisp.dhis.test.TestBase.createLegend;
37+
import static org.hisp.dhis.test.TestBase.createLegendSet;
3538
import static org.hisp.dhis.test.TestBase.createOrganisationUnit;
3639
import static org.junit.jupiter.api.Assertions.assertEquals;
40+
import static org.junit.jupiter.api.Assertions.assertFalse;
3741

3842
import java.lang.reflect.Method;
43+
import java.util.ArrayList;
44+
import java.util.HashMap;
3945
import java.util.LinkedHashMap;
4046
import java.util.List;
4147
import java.util.Map;
4248
import org.hisp.dhis.analytics.AnalyticsMetaDataKey;
49+
import org.hisp.dhis.analytics.EventAnalyticsDimensionalItem;
4350
import org.hisp.dhis.analytics.common.ColumnHeader;
4451
import org.hisp.dhis.analytics.event.EventQueryParams;
4552
import org.hisp.dhis.common.BaseDimensionalObject;
4653
import org.hisp.dhis.common.DimensionalItemObject;
4754
import org.hisp.dhis.common.Grid;
4855
import org.hisp.dhis.common.GridHeader;
56+
import org.hisp.dhis.common.ValueType;
57+
import org.hisp.dhis.common.ValueTypedDimensionalItemObject;
58+
import org.hisp.dhis.dataelement.DataElement;
59+
import org.hisp.dhis.legend.Legend;
60+
import org.hisp.dhis.legend.LegendSet;
4961
import org.hisp.dhis.period.PeriodDimension;
5062
import org.hisp.dhis.program.Program;
5163
import org.hisp.dhis.system.grid.ListGrid;
@@ -123,6 +135,39 @@ void shouldRemoveRawPeMetadataWhenNoDefaultAggregatePeriodIsVisible() throws Exc
123135
assertEquals(List.of("scheduleddate"), dimensions.keySet().stream().toList());
124136
}
125137

138+
@Test
139+
void shouldFallBackToAllLegendsWhenDimensionsMetadataOmitsLegendSetDataElement()
140+
throws Exception {
141+
Legend legendA = createLegend('A', 0.0, 2.0);
142+
Legend legendB = createLegend('B', 2.0, 4.0);
143+
LegendSet legendSet = createLegendSet('A', legendA, legendB);
144+
145+
DataElement dataElement = createDataElement('A');
146+
dataElement.setValueType(ValueType.NUMBER);
147+
dataElement.setLegendSets(List.of(legendSet));
148+
149+
Grid grid = new ListGrid();
150+
grid.getMetaData().put(AnalyticsMetaDataKey.DIMENSIONS.getKey(), new HashMap<String, Object>());
151+
152+
List<EventAnalyticsDimensionalItem> dimensionalItems = new ArrayList<>();
153+
154+
invokeAddEventReportDimensionalItems(dataElement, dimensionalItems, grid, dataElement.getUid());
155+
156+
assertFalse(dimensionalItems.isEmpty());
157+
}
158+
159+
@Test
160+
void shouldNotNpeWhenItemsMetadataOmitsRowDimension() throws Exception {
161+
String missingDimensionUid = "deUidAAAAA";
162+
163+
Grid grid = new ListGrid();
164+
grid.getMetaData().put(AnalyticsMetaDataKey.ITEMS.getKey(), new HashMap<String, Object>());
165+
166+
EventQueryParams params = new EventQueryParams.Builder().build();
167+
168+
invokeGenerateOutputGrid(grid, params, List.of(), List.of(), List.of(missingDimensionUid));
169+
}
170+
126171
@Test
127172
void shouldKeepValueAndEnrollmentOuHeadersUnchanged() throws Exception {
128173
EventQueryParams params =
@@ -157,6 +202,44 @@ private void invokePrivate(
157202
method.invoke(service, arg0, arg1);
158203
}
159204

205+
private void invokeAddEventReportDimensionalItems(
206+
ValueTypedDimensionalItemObject item,
207+
List<EventAnalyticsDimensionalItem> dimensionalItems,
208+
Grid grid,
209+
String dimension)
210+
throws Exception {
211+
Method method =
212+
EventAggregateService.class.getDeclaredMethod(
213+
"addEventReportDimensionalItems",
214+
ValueTypedDimensionalItemObject.class,
215+
List.class,
216+
Grid.class,
217+
String.class);
218+
method.setAccessible(true);
219+
method.invoke(service, item, dimensionalItems, grid, dimension);
220+
}
221+
222+
private Grid invokeGenerateOutputGrid(
223+
Grid grid,
224+
EventQueryParams params,
225+
List<Map<String, EventAnalyticsDimensionalItem>> rowPermutations,
226+
List<Map<String, EventAnalyticsDimensionalItem>> columnPermutations,
227+
List<String> rowDimensions)
228+
throws Exception {
229+
230+
Method method =
231+
EventAggregateService.class.getDeclaredMethod(
232+
"generateOutputGrid",
233+
Grid.class,
234+
EventQueryParams.class,
235+
List.class,
236+
List.class,
237+
List.class);
238+
method.setAccessible(true);
239+
return (Grid)
240+
method.invoke(service, grid, params, rowPermutations, columnPermutations, rowDimensions);
241+
}
242+
160243
private EventQueryParams singleDateFieldParams(String dateField, Program program) {
161244
PeriodDimension period = PeriodDimension.of("2021").setDateField(dateField);
162245
BaseDimensionalObject periodDimension =

0 commit comments

Comments
 (0)