Skip to content

Commit

Permalink
fix: Exclude analytics geometry fields when no support [DHIS2-18417] (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
larshelge authored Jan 6, 2025
1 parent 52ca7f1 commit f0565d7
Show file tree
Hide file tree
Showing 28 changed files with 409 additions and 203 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hisp.dhis.analytics.AggregationType;
import org.hisp.dhis.analytics.AnalyticsMetaDataKey;
import org.hisp.dhis.analytics.EventOutputType;
Expand All @@ -52,8 +54,9 @@
import org.hisp.dhis.event.EventStatus;
import org.hisp.dhis.program.EnrollmentStatus;

@Builder
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor
public class EventDataQueryRequest {
private String program;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,10 @@ public interface EventDataQueryService {
* Returns the coordinate column field to use for the given coordinate field. Coordinate field
* must match EVENT, a data element identifier or an attribute identifier.
*
* @param program the program instance.
* @param coordinateField the coordinate field.
* @param fallbackCoordinateField the fallback coordinate field applied if coordinate field in
* result set is null.
* @param defaultCoordinateFallback flag for cascade fallback, first not null geometry (coalesce)
* will be applied.
* @return the coordinate column list.
* @param request the {@link EventDataQueryRequest}.
* @throws IllegalQueryException if one of the given coordinates is not valid.
*/
List<String> getCoordinateFields(
String program,
String coordinateField,
String fallbackCoordinateField,
boolean defaultCoordinateFallback);
List<String> getCoordinateFields(EventDataQueryRequest request);

/**
* Returns a {@link QueryItem}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1384,11 +1384,13 @@ protected String getCoalesce(List<String> fields, String defaultColumnName) {

String args =
fields.stream()
.filter(f -> f != null && !f.isBlank())
.filter(StringUtils::isNotBlank)
.map(f -> sqlBuilder.quoteAx(f))
.collect(Collectors.joining(","));

return args.isEmpty() ? defaultColumnName : "coalesce(" + args + ")";
String sql = String.format("coalesce(%s)", args);

return args.isEmpty() ? defaultColumnName : sql;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import lombok.RequiredArgsConstructor;
import org.hisp.dhis.common.IllegalQueryException;
import org.hisp.dhis.common.ValueType;
Expand Down Expand Up @@ -69,11 +68,11 @@ public class DefaultEventCoordinateService implements EventCoordinateService {
public static final List<String> COL_NAME_PROGRAM_NO_REGISTRATION_GEOMETRY_LIST =
List.of(COL_NAME_EVENT_GEOMETRY, COL_NAME_ENROLLMENT_GEOMETRY, COL_NAME_OU_GEOMETRY);

@Nonnull private final ProgramService programService;
private final ProgramService programService;

@Nonnull private final DataElementService dataElementService;
private final DataElementService dataElementService;

@Nonnull private final TrackedEntityAttributeService attributeService;
private final TrackedEntityAttributeService attributeService;

@Override
public boolean isFallbackCoordinateFieldValid(boolean isRegistration, String coordinateField) {
Expand Down Expand Up @@ -115,23 +114,21 @@ public List<String> getFallbackCoordinateFields(
}

fallbackCoordinateFields.add(fallbackCoordinateField);
} else {
if (defaultCoordinateFallback) {
List<String> items =
new ArrayList<>(
pr.isRegistration()
? COL_NAME_GEOMETRY_LIST
: COL_NAME_PROGRAM_NO_REGISTRATION_GEOMETRY_LIST);

fallbackCoordinateFields.addAll(items);
}
} else if (defaultCoordinateFallback) {
List<String> items =
new ArrayList<>(
pr.isRegistration()
? COL_NAME_GEOMETRY_LIST
: COL_NAME_PROGRAM_NO_REGISTRATION_GEOMETRY_LIST);

fallbackCoordinateFields.addAll(items);
}

return fallbackCoordinateFields;
}

@Override
public String getCoordinateField(ValueType valueType, String field, ErrorCode errorCode) {
public String validateCoordinateField(ValueType valueType, String field, ErrorCode errorCode) {
if (ValueType.COORDINATE != valueType && ValueType.ORGANISATION_UNIT != valueType) {
throwIllegalQueryEx(errorCode, field);
}
Expand All @@ -140,13 +137,13 @@ public String getCoordinateField(ValueType valueType, String field, ErrorCode er
}

@Override
public String getCoordinateField(String program, String coordinateField, ErrorCode errorCode) {
public String validateCoordinateField(String program, String field, ErrorCode errorCode) {
Program pr = programService.getProgram(program);

if (COL_NAME_TRACKED_ENTITY_GEOMETRY.equals(coordinateField) && !pr.isRegistration()) {
throwIllegalQueryEx(errorCode, coordinateField);
if (COL_NAME_TRACKED_ENTITY_GEOMETRY.equals(field) && !pr.isRegistration()) {
throwIllegalQueryEx(errorCode, field);
}

return coordinateField;
return field;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,7 @@ public EventQueryParams getFromRequest(EventDataQueryRequest request, boolean an
throwIllegalQueryEx(ErrorCode.E7130, request.getStage());
}

List<String> coordinateFields =
getCoordinateFields(
request.getProgram(),
request.getCoordinateField(),
request.getFallbackCoordinateField(),
request.isDefaultCoordinateFallback());
List<String> coordinateFields = getCoordinateFields(request);

addDimensionsToParams(params, request, userOrgUnits, pr, idScheme);

Expand Down Expand Up @@ -420,49 +415,48 @@ public EventQueryParams getFromAnalyticalObject(EventAnalyticalObject object) {
* @return the coordinate column list.
*/
@Override
public List<String> getCoordinateFields(
String program,
String coordinateField,
String fallbackCoordinateField,
boolean defaultCoordinateFallback) {
List<String> coordinateFields = new ArrayList<>();
public List<String> getCoordinateFields(EventDataQueryRequest request) {
final String program = request.getProgram();
// TODO Remove when all web apps stop using old names of coordinate fields
final String coordinateField = mapCoordinateField(request.getCoordinateField());
final boolean defaultCoordinateFallback = request.isDefaultCoordinateFallback();
final String fallbackCoordinateField = mapCoordinateField(request.getFallbackCoordinateField());

// TODO!!! remove when all fe apps stop using old names of coordinate fields
coordinateField = mapCoordinateField(coordinateField);
fallbackCoordinateField = mapCoordinateField(fallbackCoordinateField);
List<String> coordinateFields = new ArrayList<>();

if (coordinateField == null) {
coordinateFields.add(StringUtils.EMPTY);
} else if (COL_NAME_GEOMETRY_LIST.contains(coordinateField)) {
coordinateFields.add(
eventCoordinateService.getCoordinateField(program, coordinateField, ErrorCode.E7221));
eventCoordinateService.validateCoordinateField(
program, coordinateField, ErrorCode.E7221));
} else if (EventQueryParams.EVENT_COORDINATE_FIELD.equals(coordinateField)) {
coordinateFields.add(
eventCoordinateService.getCoordinateField(
eventCoordinateService.validateCoordinateField(
program, COL_NAME_EVENT_GEOMETRY, ErrorCode.E7221));
} else if (EventQueryParams.ENROLLMENT_COORDINATE_FIELD.equals(coordinateField)) {
coordinateFields.add(
eventCoordinateService.getCoordinateField(
eventCoordinateService.validateCoordinateField(
program, COL_NAME_ENROLLMENT_GEOMETRY, ErrorCode.E7221));
} else if (EventQueryParams.TRACKER_COORDINATE_FIELD.equals(coordinateField)) {
coordinateFields.add(
eventCoordinateService.getCoordinateField(
eventCoordinateService.validateCoordinateField(
program, COL_NAME_TRACKED_ENTITY_GEOMETRY, ErrorCode.E7221));
}

DataElement dataElement = dataElementService.getDataElement(coordinateField);

if (dataElement != null) {
coordinateFields.add(
eventCoordinateService.getCoordinateField(
eventCoordinateService.validateCoordinateField(
dataElement.getValueType(), coordinateField, ErrorCode.E7219));
}

TrackedEntityAttribute attribute = attributeService.getTrackedEntityAttribute(coordinateField);

if (attribute != null) {
coordinateFields.add(
eventCoordinateService.getCoordinateField(
eventCoordinateService.validateCoordinateField(
attribute.getValueType(), coordinateField, ErrorCode.E7220));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import org.hisp.dhis.common.DimensionItemKeywords.Keyword;
import org.hisp.dhis.common.Grid;
import org.hisp.dhis.common.GridHeader;
import org.hisp.dhis.db.sql.SqlBuilder;
import org.hisp.dhis.system.grid.ListGrid;
import org.hisp.dhis.util.Timer;
import org.springframework.stereotype.Service;
Expand All @@ -89,6 +90,8 @@ public class EnrollmentQueryService {

private final SchemeIdHandler schemeIdHandler;

private final SqlBuilder sqlBuilder;

/**
* Returns a list of enrollments matching the given query.
*
Expand Down Expand Up @@ -143,8 +146,9 @@ public Grid getEnrollments(EventQueryParams params) {
* @return the {@link Grid} with headers.
*/
private Grid createGridWithHeaders(EventQueryParams params) {
return new ListGrid()
.addHeader(
Grid grid = new ListGrid();

grid.addHeader(
new GridHeader(
ENROLLMENT.getItem(),
getEnrollmentLabel(params.getProgram(), ENROLLMENT.getName()),
Expand Down Expand Up @@ -183,11 +187,15 @@ private Grid createGridWithHeaders(EventQueryParams params) {
false,
true))
.addHeader(
new GridHeader(LAST_UPDATED.getItem(), LAST_UPDATED.getName(), DATETIME, false, true))
.addHeader(new GridHeader(GEOMETRY.getItem(), GEOMETRY.getName(), TEXT, false, true))
.addHeader(new GridHeader(LONGITUDE.getItem(), LONGITUDE.getName(), NUMBER, false, true))
.addHeader(new GridHeader(LATITUDE.getItem(), LATITUDE.getName(), NUMBER, false, true))
.addHeader(
new GridHeader(LAST_UPDATED.getItem(), LAST_UPDATED.getName(), DATETIME, false, true));

if (sqlBuilder.supportsGeospatialData()) {
grid.addHeader(new GridHeader(GEOMETRY.getItem(), GEOMETRY.getName(), TEXT, false, true))
.addHeader(new GridHeader(LONGITUDE.getItem(), LONGITUDE.getName(), NUMBER, false, true))
.addHeader(new GridHeader(LATITUDE.getItem(), LATITUDE.getName(), NUMBER, false, true));
}

grid.addHeader(
new GridHeader(
ORG_UNIT_NAME.getItem(),
getOrgUnitLabel(params.getProgram(), ORG_UNIT_NAME.getName()),
Expand All @@ -205,6 +213,8 @@ private Grid createGridWithHeaders(EventQueryParams params) {
new GridHeader(ORG_UNIT_CODE.getItem(), ORG_UNIT_CODE.getName(), TEXT, false, true))
.addHeader(
new GridHeader(PROGRAM_STATUS.getItem(), PROGRAM_STATUS.getName(), TEXT, false, true));

return grid;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,47 +39,47 @@ public interface EventCoordinateService {
/**
* Verifies the validity of fallback coordinate field.
*
* @param isRegistration true when underlying program is registration
* @param coordinateField the name of coordinate field (uid or name)
* @return returns true if valid.
* @throws IllegalQueryException
* @param isRegistration true when program is registration.
* @param coordinateField the name of coordinate field (identifier or name).
* @return true if valid.
* @throws IllegalQueryException if validation failed.
*/
boolean isFallbackCoordinateFieldValid(boolean isRegistration, String coordinateField)
throws IllegalQueryException;

/**
* Provides list of coordinate fields.
*
* @param program underlying program
* @param fallbackCoordinateField fallback
* @param defaultCoordinateFallback fallback cascade should be applied when true
* @return list of coordinate fields
* @throws IllegalQueryException
* @param program the program identifier.
* @param fallbackCoordinateField the fallback coordinate field.
* @param defaultCoordinateFallback fallback cascade should be applied when true.
* @return a list of coordinate fields.
* @throws IllegalQueryException if validation failed.
*/
List<String> getFallbackCoordinateFields(
String program, String fallbackCoordinateField, boolean defaultCoordinateFallback);

/**
* Provides verified geometry.
* Validates the given coordinate field.
*
* @param valueType value type
* @param field geometry
* @param valueType the {@link ValueType}.
* @param field the coordinate field.
* @param errorCode code for standard error message
* @return the coordinate field.
* @throws IllegalQueryException
* @throws IllegalQueryException if validation failed.
*/
String getCoordinateField(ValueType valueType, String field, ErrorCode errorCode)
String validateCoordinateField(ValueType valueType, String field, ErrorCode errorCode)
throws IllegalQueryException;

/**
* Provides verified geometry.
* Validates the given coordinate field.
*
* @param program underlying program
* @param coordinateField geometry
* @param errorCode code for standard error message
* @param program the program identifier.
* @param field the coordinate field.
* @param errorCode the {@link ErrorCode}.
* @return the coordinate field.
* @throws IllegalQueryException
* @throws IllegalQueryException if validation failed.
*/
public String getCoordinateField(String program, String coordinateField, ErrorCode errorCode)
public String validateCoordinateField(String program, String field, ErrorCode errorCode)
throws IllegalQueryException;
}
Loading

0 comments on commit f0565d7

Please sign in to comment.