Skip to content

Commit d2e06d5

Browse files
committed
Include native totals in VisualizationObject to AFM conversion
1 parent 9895019 commit d2e06d5

File tree

3 files changed

+137
-1
lines changed

3 files changed

+137
-1
lines changed

gooddata-java-model/src/main/java/com/gooddata/sdk/model/md/visualization/VisualizationConverter.java

+42-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.gooddata.sdk.model.executeafm.Execution;
1212
import com.gooddata.sdk.model.executeafm.afm.Afm;
1313
import com.gooddata.sdk.model.executeafm.afm.AttributeItem;
14+
import com.gooddata.sdk.model.executeafm.afm.NativeTotalItem;
1415
import com.gooddata.sdk.model.executeafm.afm.filter.CompatibilityFilter;
1516
import com.gooddata.sdk.model.executeafm.afm.filter.DateFilter;
1617
import com.gooddata.sdk.model.executeafm.afm.filter.ExtendedFilter;
@@ -25,6 +26,7 @@
2526
import com.gooddata.sdk.model.executeafm.resultspec.ResultSpec;
2627
import com.gooddata.sdk.model.executeafm.resultspec.SortItem;
2728
import com.gooddata.sdk.model.executeafm.resultspec.TotalItem;
29+
import com.gooddata.sdk.model.md.report.Total;
2830

2931
import java.util.ArrayList;
3032
import java.util.HashSet;
@@ -88,8 +90,9 @@ public static Afm convertToAfm(final VisualizationObject visualizationObject) {
8890
final List<AttributeItem> attributes = convertAttributes(visualizationObject.getAttributes());
8991
final List<CompatibilityFilter> filters = convertFilters(visualizationObject.getFilters());
9092
final List<MeasureItem> measures = convertMeasures(visualizationObject.getMeasures());
93+
final List<NativeTotalItem> totals = convertNativeTotals(visualizationObject);
9194

92-
return new Afm(attributes, filters, measures, null);
95+
return new Afm(attributes, filters, measures, totals);
9396
}
9497

9598
/**
@@ -322,4 +325,42 @@ private static <T> List<T> removeIrrelevantFilters(final List<T> filters) {
322325
})
323326
.collect(Collectors.toList());
324327
}
328+
329+
private static List<NativeTotalItem> convertNativeTotals(final VisualizationObject visualizationObject) {
330+
final List<Bucket> attributeBuckets = getAttributeBuckets(visualizationObject);
331+
final List<String> attributeIds = getIdsFromAttributeBuckets(attributeBuckets);
332+
return attributeBuckets.stream()
333+
.flatMap(bucket -> bucket.getTotals().stream())
334+
.filter(totalItem -> isNativeTotal(totalItem) && attributeIds.contains(totalItem.getAttributeIdentifier()))
335+
.map(totalItem -> convertToNativeTotalItem(totalItem, attributeIds))
336+
.collect(toList());
337+
}
338+
339+
private static NativeTotalItem convertToNativeTotalItem(TotalItem totalItem, List<String> attributeIds) {
340+
final int attributeIdx = attributeIds.indexOf(totalItem.getAttributeIdentifier());
341+
return new NativeTotalItem(
342+
totalItem.getMeasureIdentifier(),
343+
new ArrayList<>(attributeIds.subList(0, attributeIdx))
344+
);
345+
}
346+
347+
private static List<Bucket> getAttributeBuckets(final VisualizationObject visualizationObject) {
348+
return visualizationObject.getBuckets().stream()
349+
.filter(bucket -> bucket.getItems().stream().allMatch(AttributeItem.class::isInstance))
350+
.collect(toList());
351+
}
352+
353+
private static List<String> getIdsFromAttributeBuckets(final List<Bucket> attributeBuckets) {
354+
return attributeBuckets.stream()
355+
.flatMap(bucket ->
356+
bucket.getItems().stream()
357+
.map(AttributeItem.class::cast)
358+
.map(AttributeItem::getLocalIdentifier)
359+
)
360+
.collect(toList());
361+
}
362+
363+
private static boolean isNativeTotal(TotalItem totalItem) {
364+
return totalItem.getType() != null && Total.NAT.name().equals(totalItem.getType().toUpperCase());
365+
}
325366
}

gooddata-java-model/src/test/groovy/com/gooddata/sdk/model/md/visualization/VisualizationConverterTest.groovy

+10
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class VisualizationConverterTest extends Specification {
5050
private static final String STACKED_COLUMN_CHART = "md/visualization/stackedColumnChart.json"
5151
private static final String LINE_CHART = "md/visualization/lineChart.json"
5252
private static final String TABLE_WITH_TOTALS = "md/visualization/complexTableWithTotals.json"
53+
private static final String AFM_FROM_TABLE_WITH_TOTALS = "executeafm/afm/complextTableWithTotalsConvertedAfm.json"
5354

5455
@SuppressWarnings("GrDeprecatedAPIUsage")
5556
def "should convert complex"() {
@@ -93,6 +94,15 @@ class VisualizationConverterTest extends Specification {
9394
that converted, jsonEquals(expectedAfm)
9495
}
9596

97+
def "should convert AFM of complex pivot table with totals"() {
98+
given:
99+
Afm expectedAfm = readObjectFromResource("/$AFM_FROM_TABLE_WITH_TOTALS", Afm)
100+
VisualizationObject visualizationObject = readObjectFromResource("/$TABLE_WITH_TOTALS", VisualizationObject)
101+
Afm converted = convertToAfm(visualizationObject)
102+
103+
expect:
104+
that converted, jsonEquals(expectedAfm)
105+
}
96106

97107
@Unroll
98108
def "should generate result spec for table with default sorting from #name"() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
{
2+
"measures": [
3+
{
4+
"localIdentifier": "fd0164f14ec2444b9b5a7140ce059036",
5+
"definition": {
6+
"measureDefinition": {
7+
"filters": [],
8+
"item": {
9+
"uri": "/gdc/md/w3hub93g7fwmvx60pkt2v8cr56530t0l/obj/9211"
10+
}
11+
}
12+
},
13+
"alias": "_Close [BOP]"
14+
}
15+
],
16+
"attributes": [
17+
{
18+
"displayForm": {
19+
"uri": "/gdc/md/w3hub93g7fwmvx60pkt2v8cr56530t0l/obj/1024"
20+
},
21+
"localIdentifier": "e4bb25477bca4fb2a29a4b80d94568d4"
22+
},
23+
{
24+
"displayForm": {
25+
"uri": "/gdc/md/w3hub93g7fwmvx60pkt2v8cr56530t0l/obj/1028"
26+
},
27+
"localIdentifier": "9008f5d33b3e41279402a25e2f05d0c9"
28+
},
29+
{
30+
"displayForm": {
31+
"uri": "/gdc/md/w3hub93g7fwmvx60pkt2v8cr56530t0l/obj/1086"
32+
},
33+
"localIdentifier": "023641d306f84921be39d0aa1d6464db"
34+
},
35+
{
36+
"displayForm": {
37+
"uri": "/gdc/md/w3hub93g7fwmvx60pkt2v8cr56530t0l/obj/1805"
38+
},
39+
"localIdentifier": "a22843f5d77f48b4938ccfb460eb8be4"
40+
},
41+
{
42+
"displayForm": {
43+
"uri": "/gdc/md/w3hub93g7fwmvx60pkt2v8cr56530t0l/obj/1094"
44+
},
45+
"localIdentifier": "a77983fcc9574f6bad6be1d3cb08bf71"
46+
}
47+
],
48+
"nativeTotals": [
49+
{
50+
"measureIdentifier": "fd0164f14ec2444b9b5a7140ce059036",
51+
"attributeIdentifiers": []
52+
},
53+
{
54+
"measureIdentifier": "fd0164f14ec2444b9b5a7140ce059036",
55+
"attributeIdentifiers": [
56+
"e4bb25477bca4fb2a29a4b80d94568d4"
57+
]
58+
},
59+
{
60+
"measureIdentifier": "fd0164f14ec2444b9b5a7140ce059036",
61+
"attributeIdentifiers": [
62+
"e4bb25477bca4fb2a29a4b80d94568d4",
63+
"9008f5d33b3e41279402a25e2f05d0c9"
64+
]
65+
},
66+
{
67+
"measureIdentifier": "fd0164f14ec2444b9b5a7140ce059036",
68+
"attributeIdentifiers": [
69+
"e4bb25477bca4fb2a29a4b80d94568d4",
70+
"9008f5d33b3e41279402a25e2f05d0c9",
71+
"023641d306f84921be39d0aa1d6464db"
72+
]
73+
},
74+
{
75+
"measureIdentifier": "fd0164f14ec2444b9b5a7140ce059036",
76+
"attributeIdentifiers": [
77+
"e4bb25477bca4fb2a29a4b80d94568d4",
78+
"9008f5d33b3e41279402a25e2f05d0c9",
79+
"023641d306f84921be39d0aa1d6464db",
80+
"a22843f5d77f48b4938ccfb460eb8be4"
81+
]
82+
}
83+
],
84+
"filters":[]
85+
}

0 commit comments

Comments
 (0)