diff --git a/README.md b/README.md index 504623f2..e02cd8e0 100644 --- a/README.md +++ b/README.md @@ -300,15 +300,32 @@ DataValueSetResponse response = dhis2.saveDataValueSet(file, options); This section explains operations for the analytics engine. +### Get analytics data + +To retrieve analytics data: + +```java +AnalyticsQuery query = AnalyticsQuery.instance() + .addDataDimension(List.of("fbfJHSPpUQD", "cYeuwXTCPkU", "Jtf34kNZhzP")) + .addPeriodDimension(List.of("202501", "202502", "202503")) + .addDimension("fMZEcRHuamy", List.of("qkPbeWaFsnU", "wbrDrL2aYEc")) + .addOrgUnitFilter(List.of("ImspTQPwCqd")) + .setIncludeMetadataDetails(true); + +AnalyticsData data = dhis2.getAnalyticsData(query); +``` + ### Get analytics data value set To retrieve analytics data in the data value set format: ```java -DataValueSet dvs = dhis2.getAnalyticsDataValueSet(AnalyticsQuery.instance() +AnalyticsQuery query = AnalyticsQuery.instance() .addDimension(Dimension.DIMENSION_DX, "cYeuwXTCPkU", "Jtf34kNZhzP") .addDimension(Dimension.DIMENSION_OU, "O6uvpzGd5pu", "fdc6uOvgoji") - .addDimension(Dimension.DIMENSION_PE, "202007", "202008")); + .addDimension(Dimension.DIMENSION_PE, "202007", "202008"); + +DataValueSet dvs = dhis2.getAnalyticsDataValueSet(query); ``` ### Write analytics data value set to file @@ -322,7 +339,7 @@ AnalyticsQuery query = AnalyticsQuery.instance() .addDimension(Dimension.DIMENSION_PE, "202007", "202008"); File file = new File("/tmp/data-value-set.json"); - + dhis2.writeAnalyticsDataValueSet(query, file); ``` diff --git a/src/main/java/org/hisp/dhis/BaseDhis2.java b/src/main/java/org/hisp/dhis/BaseDhis2.java index 9d0cbd3c..061ac3d8 100644 --- a/src/main/java/org/hisp/dhis/BaseDhis2.java +++ b/src/main/java/org/hisp/dhis/BaseDhis2.java @@ -439,8 +439,13 @@ protected URI getAnalyticsQuery(URIBuilder uriBuilder, AnalyticsQuery query) { addParameter(uriBuilder, "skipData", query.getSkipData()); addParameter(uriBuilder, "skipRounding", query.getSkipRounding()); addParameter(uriBuilder, "ignoreLimit", query.getIgnoreLimit()); - addParameter(uriBuilder, "inputIdScheme", query.getInputIdScheme()); + addParameter(uriBuilder, "showHierarchy", query.getShowHierarchy()); + addParameter(uriBuilder, "includeNumDen", query.getIncludeNumDen()); + addParameter(uriBuilder, "includeMetadataDetails", query.getIncludeMetadataDetails()); addParameter(uriBuilder, "outputIdScheme", query.getOutputIdScheme()); + addParameter(uriBuilder, "outputOrgUnitIdScheme", query.getOutputOrgUnitIdScheme()); + addParameter(uriBuilder, "outputDataElementIdScheme", query.getOutputDataElementIdScheme()); + addParameter(uriBuilder, "inputIdScheme", query.getInputIdScheme()); return HttpUtils.build(uriBuilder); } @@ -939,7 +944,7 @@ private void handleErrorsForGet(CloseableHttpResponse response, String url) * @param content the JSON content. * @param type the object type. * @return an object. - * @throws IOException + * @throws IOException if reading failed. */ protected T readValue(String content, Class type) throws IOException { return objectMapper.readValue(content, type); diff --git a/src/main/java/org/hisp/dhis/Dhis2.java b/src/main/java/org/hisp/dhis/Dhis2.java index 5a1a928f..f9f9bc04 100644 --- a/src/main/java/org/hisp/dhis/Dhis2.java +++ b/src/main/java/org/hisp/dhis/Dhis2.java @@ -85,6 +85,7 @@ import org.hisp.dhis.model.SystemSettings; import org.hisp.dhis.model.TableHook; import org.hisp.dhis.model.Visualization; +import org.hisp.dhis.model.analytics.AnalyticsData; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistration; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistrationImportOptions; import org.hisp.dhis.model.dashboard.Dashboard; @@ -2318,6 +2319,21 @@ public String getDataValueFile(DataValueQuery query) { config.getResolvedUriBuilder().appendPath("dataValues/files"), query); } + // ------------------------------------------------------------------------- + // Analytics data + // ------------------------------------------------------------------------- + + /** + * Retrieves a {@link AnalyticsData}. + * + * @param query the {@link AnalyticsQuery}. + * @return {@link AnalyticsData}. + */ + public AnalyticsData getAnalyticsData(AnalyticsQuery query) { + return getAnalyticsResponse( + config.getResolvedUriBuilder().appendPath("analytics"), query, AnalyticsData.class); + } + // ------------------------------------------------------------------------- // Analytics data value set // ------------------------------------------------------------------------- diff --git a/src/main/java/org/hisp/dhis/model/analytics/AnalyticsData.java b/src/main/java/org/hisp/dhis/model/analytics/AnalyticsData.java new file mode 100644 index 00000000..1380ca58 --- /dev/null +++ b/src/main/java/org/hisp/dhis/model/analytics/AnalyticsData.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.model.analytics; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class AnalyticsData { + @JsonProperty private List headers; + + @JsonProperty private AnalyticsMetaData metaData; + + @JsonProperty private List> rows; + + @JsonProperty private Integer height; + + @JsonProperty private Integer width; + + @JsonProperty private Integer headerWidth; +} diff --git a/src/main/java/org/hisp/dhis/model/analytics/AnalyticsHeader.java b/src/main/java/org/hisp/dhis/model/analytics/AnalyticsHeader.java new file mode 100644 index 00000000..5c0418fa --- /dev/null +++ b/src/main/java/org/hisp/dhis/model/analytics/AnalyticsHeader.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.model.analytics; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import org.hisp.dhis.model.ValueType; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class AnalyticsHeader { + @JsonProperty private String name; + + @JsonProperty private String column; + + @JsonProperty private ValueType valueType; + + @JsonProperty private Boolean hidden; + + @JsonProperty private Boolean meta; +} diff --git a/src/main/java/org/hisp/dhis/model/analytics/AnalyticsMetaData.java b/src/main/java/org/hisp/dhis/model/analytics/AnalyticsMetaData.java new file mode 100644 index 00000000..1e2cb18c --- /dev/null +++ b/src/main/java/org/hisp/dhis/model/analytics/AnalyticsMetaData.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.model.analytics; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Map; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class AnalyticsMetaData { + @JsonProperty private Map items; + + @JsonProperty private Map> dimensions; +} diff --git a/src/main/java/org/hisp/dhis/model/analytics/MetaDataItem.java b/src/main/java/org/hisp/dhis/model/analytics/MetaDataItem.java new file mode 100644 index 00000000..5c1c4917 --- /dev/null +++ b/src/main/java/org/hisp/dhis/model/analytics/MetaDataItem.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.model.analytics; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class MetaDataItem { + @JsonProperty private String uid; + + @JsonProperty private String name; + + @JsonProperty private String dimensionType; + + @JsonProperty private String code; + + @JsonProperty private String dimensionItemType; + + @JsonProperty private String valueType; + + @JsonProperty private String totalAggregationType; + + @JsonProperty private String startDate; + + @JsonProperty private String endDate; + + @JsonProperty private String legendSet; + + @JsonProperty private String aggregationType; +} diff --git a/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java b/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java index 9d3964d4..9e7faa54 100644 --- a/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java +++ b/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java @@ -58,8 +58,18 @@ public class AnalyticsQuery { private Boolean ignoreLimit; + private Boolean showHierarchy; + + private Boolean includeNumDen; + + private Boolean includeMetadataDetails; + private IdScheme outputIdScheme; + private IdScheme outputOrgUnitIdScheme; + + private IdScheme outputDataElementIdScheme; + private IdScheme inputIdScheme; private AnalyticsQuery() {} @@ -95,6 +105,36 @@ public AnalyticsQuery addDimension(String dimension, List items) { return addDimension(new Dimension(dimension, items)); } + /** + * Adds a data dimension and items to this query. + * + * @param items the list of dimension items. + * @return this {@link AnalyticsQuery}. + */ + public AnalyticsQuery addDataDimension(List items) { + return addDimension(Dimension.DIMENSION_DX, items); + } + + /** + * Adds a period dimension and items to this query. + * + * @param items the list of dimension items. + * @return this {@link AnalyticsQuery}. + */ + public AnalyticsQuery addPeriodDimension(List items) { + return addDimension(Dimension.DIMENSION_PE, items); + } + + /** + * Adds an org unit dimension and items to this query. + * + * @param items the list of dimension items. + * @return this {@link AnalyticsQuery}. + */ + public AnalyticsQuery addOrgUnitDimension(List items) { + return addDimension(Dimension.DIMENSION_OU, items); + } + /** * Adds a filter to this query. * @@ -105,4 +145,45 @@ public AnalyticsQuery addFilter(Dimension filter) { this.filters.add(filter); return this; } + + /** + * Adds a filter and items to this query. + * + * @param filter the filter identifier. + * @param items the filter items. + * @return this {@link AnalyticsQuery}. + */ + public AnalyticsQuery addFilter(String filter, List items) { + return addFilter(new Dimension(filter, items)); + } + + /** + * Adds a data filter and items to this query. + * + * @param items the filter items. + * @return this {@link AnalyticsQuery}. + */ + public AnalyticsQuery addDataFilter(List items) { + return addFilter(new Dimension(Dimension.DIMENSION_DX, items)); + } + + /** + * Adds a period filter and items to this query. + * + * @param items the filter items. + * @return this {@link AnalyticsQuery}. + */ + public AnalyticsQuery addPeriodFilter(List items) { + return addFilter(new Dimension(Dimension.DIMENSION_PE, items)); + } + + /** + * Adds an org unit filter and items to this query. + * + * @param items the filter items. + * @return this {@link AnalyticsQuery}. + */ + public AnalyticsQuery addOrgUnitFilter(List items) { + return addFilter(new Dimension(Dimension.DIMENSION_OU, items)); + } } diff --git a/src/main/java/org/hisp/dhis/util/CollectionUtils.java b/src/main/java/org/hisp/dhis/util/CollectionUtils.java index 691ee7ec..d0b27023 100644 --- a/src/main/java/org/hisp/dhis/util/CollectionUtils.java +++ b/src/main/java/org/hisp/dhis/util/CollectionUtils.java @@ -109,9 +109,9 @@ public static List mutableList(T... items) { * * @param type. * @param type. - * @param objects the objects of type . + * @param objects the objects of U. * @param mapper the mapping function. - * @return a list of objects of type . + * @return a list of objects of type T. */ public static List mapToList(List objects, Function mapper) { return objects.stream().map(mapper).toList(); diff --git a/src/test/java/org/hisp/dhis/Dhis2Test.java b/src/test/java/org/hisp/dhis/Dhis2Test.java index 02ba2a8a..53b7c007 100644 --- a/src/test/java/org/hisp/dhis/Dhis2Test.java +++ b/src/test/java/org/hisp/dhis/Dhis2Test.java @@ -75,8 +75,11 @@ void testGetObjectQueryA() { URI uri = dhis2.getObjectQuery(uriBuilder, query); String expected = - "https://dhis2.org/api/dataElements?" - + "filter=name%3Alike%3AImmunization&filter=valueType%3Aeq%3ANUMBER&page=2&pageSize=100&order=code%3Adesc"; + """ + https://dhis2.org/api/dataElements\ + ?filter=name%3Alike%3AImmunization\ + &filter=valueType%3Aeq%3ANUMBER\ + &page=2&pageSize=100&order=code%3Adesc"""; assertEquals(expected, uri.toString()); } @@ -99,8 +102,10 @@ void testGetObjectQueryB() { URI uri = dhis2.getObjectQuery(uriBuilder, query); String expected = - "https://dhis2.org/api/indicators?" - + "filter=name%3Alike%3AANC&page=4&pageSize=50&order=name%3Aasc%2Cuid%3Adesc"; + """ + https://dhis2.org/api/indicators\ + ?filter=name%3Alike%3AANC\ + &page=4&pageSize=50&order=name%3Aasc%2Cuid%3Adesc"""; assertEquals(expected, uri.toString()); } @@ -170,8 +175,12 @@ void testGetAnalyticsQuery() { URI uri = dhis2.getAnalyticsQuery(uriBuilder, query); String expected = - "https://dhis2.org/api/analytics?" - + "aggregationType=AVERAGE&ignoreLimit=true&inputIdScheme=code&outputIdScheme=uid"; + """ + https://dhis2.org/api/analytics?\ + aggregationType=AVERAGE\ + &ignoreLimit=true\ + &outputIdScheme=uid\ + &inputIdScheme=code"""; assertEquals(expected, uri.toString()); } diff --git a/src/test/java/org/hisp/dhis/TestFixture.java b/src/test/java/org/hisp/dhis/TestFixture.java index 3086de9b..43e3ebf6 100644 --- a/src/test/java/org/hisp/dhis/TestFixture.java +++ b/src/test/java/org/hisp/dhis/TestFixture.java @@ -36,7 +36,7 @@ public final class TestFixture { public static final String V41_URL = "https://play.im.dhis2.org/stable-2-41-3-1"; - public static final String LOCAL_URL = "https://localhost/dhis"; + public static final String LOCAL_URL = "http://localhost/dhis"; public static final String DEFAULT_URL = V41_URL; diff --git a/src/test/java/org/hisp/dhis/analytics/AnalyticsDataApiTest.java b/src/test/java/org/hisp/dhis/analytics/AnalyticsDataApiTest.java new file mode 100644 index 00000000..f4515924 --- /dev/null +++ b/src/test/java/org/hisp/dhis/analytics/AnalyticsDataApiTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.analytics; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.hisp.dhis.Dhis2; +import org.hisp.dhis.TestFixture; +import org.hisp.dhis.model.ValueType; +import org.hisp.dhis.model.analytics.AnalyticsData; +import org.hisp.dhis.model.analytics.AnalyticsHeader; +import org.hisp.dhis.model.analytics.AnalyticsMetaData; +import org.hisp.dhis.model.analytics.MetaDataItem; +import org.hisp.dhis.query.analytics.AnalyticsQuery; +import org.hisp.dhis.support.TestTags; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +@Slf4j +@Tag(TestTags.INTEGRATION) +class AnalyticsDataApiTest { + @Test + @Disabled("Using local environment") + void testGetAnalyticsData() { + Dhis2 dhis2 = new Dhis2(TestFixture.LOCAL_CONFIG); + + AnalyticsQuery query = + AnalyticsQuery.instance() + .addDataDimension(List.of("fbfJHSPpUQD", "cYeuwXTCPkU", "Jtf34kNZhzP")) + .addPeriodDimension(List.of("202501", "202502", "202503")) + .addOrgUnitFilter(List.of("ImspTQPwCqd")) + .setSkipData(false) + .setSkipMeta(false) + .setIncludeMetadataDetails(true); + + AnalyticsData data = dhis2.getAnalyticsData(query); + + log.info(data.toString()); + + assertNotNull(data); + assertEquals(3, data.getWidth()); + assertEquals(3, data.getHeaderWidth()); + assertTrue(data.getHeight() > 0, String.valueOf(data.getHeight())); + + List headers = data.getHeaders(); + + assertNotNull(headers); + assertEquals(3, headers.size()); + + AnalyticsHeader firstHeader = headers.get(0); + + assertNotNull(firstHeader); + assertEquals("dx", firstHeader.getName()); + assertEquals("Data", firstHeader.getColumn()); + assertEquals(ValueType.TEXT, firstHeader.getValueType()); + + AnalyticsMetaData metaData = data.getMetaData(); + + Map items = metaData.getItems(); + + assertNotNull(items); + assertFalse(items.keySet().isEmpty()); + + MetaDataItem dxItem = items.get("dx"); + + assertNotNull(dxItem); + assertEquals("dx", dxItem.getUid()); + assertEquals("Data", dxItem.getName()); + + Map> dimensions = metaData.getDimensions(); + + assertNotNull(dimensions); + assertTrue(dimensions.containsKey("dx")); + assertTrue(dimensions.containsKey("pe")); + assertTrue(dimensions.containsKey("ou")); + + assertNotNull(metaData); + + List firstRow = data.getRows().get(0); + + assertNotNull(firstRow); + assertEquals(3, firstRow.size()); + } +}