From b65a3df4178d408df16b7168768d50c61cd40d8c Mon Sep 17 00:00:00 2001 From: teleivo Date: Fri, 17 Jan 2025 14:29:56 +0100 Subject: [PATCH] chore: remove more interfaces --- .../trackedentity/aggregates/AclStore.java | 95 +++++++++- .../aggregates/DefaultAclStore.java | 132 -------------- .../aggregates/DefaultEnrollmentStore.java | 121 ------------ .../aggregates/DefaultEventStore.java | 172 ------------------ .../aggregates/EnrollmentStore.java | 112 ++++++++---- .../trackedentity/aggregates/EventStore.java | 160 ++++++++++++---- .../aggregates/TrackedEntityStore.java | 10 +- 7 files changed, 301 insertions(+), 501 deletions(-) delete mode 100644 dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultAclStore.java delete mode 100644 dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultEnrollmentStore.java delete mode 100644 dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultEventStore.java diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/AclStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/AclStore.java index 8c37e05eed18..9dbd006ea521 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/AclStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/AclStore.java @@ -28,16 +28,101 @@ package org.hisp.dhis.tracker.export.trackedentity.aggregates; import java.util.List; +import org.hisp.dhis.common.collection.CollectionUtils; +import org.hisp.dhis.hibernate.jsonb.type.JsonbFunctions; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; /** * @author Luciano Fiandesio */ -public interface AclStore { - List getAccessibleTrackedEntityTypes(String userUID, List userGroupUIDs); +@Repository("org.hisp.dhis.tracker.trackedentity.aggregates.AclStore") +class AclStore { + private final NamedParameterJdbcTemplate jdbcTemplate; - List getAccessiblePrograms(String userUID, List userGroupUIDs); + private static final String USER_SQL_PARAM_NAME = "userId"; - List getAccessibleProgramStages(String userUID, List userGroupUIDs); + private static final String USER_GROUP_SQL_PARAM_NAME = "userGroupUIDs"; - List getAccessibleRelationshipTypes(String userUID, List userGroupUIDs); + private static final String PUBLIC_ACCESS_CONDITION = + "sharing->>'public' LIKE '__r%' OR sharing->>'public' IS NULL"; + + private static final String USERACCESS_CONDITION = + "sharing->'users'->:" + USER_SQL_PARAM_NAME + "->>'access' LIKE '__r%'"; + + private static final String USERGROUPACCESS_CONDITION = + JsonbFunctions.HAS_USER_GROUP_IDS + + "( sharing, :" + + USER_GROUP_SQL_PARAM_NAME + + ") = true " + + "and " + + JsonbFunctions.CHECK_USER_GROUPS_ACCESS + + "(sharing, '__r%', :" + + USER_GROUP_SQL_PARAM_NAME + + ") = true"; + + private static final String GET_TE_TYPE_ACL = + "SELECT trackedentitytypeid FROM trackedentitytype " + + " WHERE " + + PUBLIC_ACCESS_CONDITION + + " OR " + + USERACCESS_CONDITION; + + static final String GET_PROGRAM_ACL = + "SELECT p.programid FROM program p " + + " WHERE " + + PUBLIC_ACCESS_CONDITION + + " OR " + + USERACCESS_CONDITION; + + static final String GET_PROGRAMSTAGE_ACL = + "SELECT ps.programstageid FROM programstage ps " + + " WHERE " + + PUBLIC_ACCESS_CONDITION + + " OR " + + USERACCESS_CONDITION; + + private static final String GET_RELATIONSHIPTYPE_ACL = + "SELECT rs.relationshiptypeid " + + "FROM relationshiptype rs" + + " WHERE " + + PUBLIC_ACCESS_CONDITION + + " OR " + + USERACCESS_CONDITION; + + AclStore(@Qualifier("readOnlyJdbcTemplate") JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate); + } + + List getAccessibleTrackedEntityTypes(String userUID, List userGroupUIDs) { + return executeAclQuery(userUID, userGroupUIDs, GET_TE_TYPE_ACL, "trackedentitytypeid"); + } + + List getAccessiblePrograms(String userUID, List userGroupUIDs) { + return executeAclQuery(userUID, userGroupUIDs, GET_PROGRAM_ACL, "programid"); + } + + List getAccessibleProgramStages(String userUID, List userGroupUIDs) { + return executeAclQuery(userUID, userGroupUIDs, GET_PROGRAMSTAGE_ACL, "programstageid"); + } + + List getAccessibleRelationshipTypes(String userUID, List userGroupUIDs) { + return executeAclQuery(userUID, userGroupUIDs, GET_RELATIONSHIPTYPE_ACL, "relationshiptypeid"); + } + + private List executeAclQuery( + String userUID, List userGroupUIDs, String sql, String primaryKey) { + MapSqlParameterSource parameterMap = new MapSqlParameterSource(); + parameterMap.addValue(USER_SQL_PARAM_NAME, userUID); + + if (!CollectionUtils.isEmpty(userGroupUIDs)) { + sql += " OR " + USERGROUPACCESS_CONDITION; + parameterMap.addValue(USER_GROUP_SQL_PARAM_NAME, "{" + String.join(",", userGroupUIDs) + "}"); + } + + return jdbcTemplate.query(sql, parameterMap, (rs, i) -> rs.getLong(primaryKey)); + } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultAclStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultAclStore.java deleted file mode 100644 index 60e9a753c21b..000000000000 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultAclStore.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2004-2022, 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.tracker.export.trackedentity.aggregates; - -import java.util.List; -import org.hisp.dhis.common.collection.CollectionUtils; -import org.hisp.dhis.hibernate.jsonb.type.JsonbFunctions; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Repository; - -/** - * @author Luciano Fiandesio - */ -@Repository("org.hisp.dhis.tracker.trackedentity.aggregates.AclStore") -class DefaultAclStore implements AclStore { - private final NamedParameterJdbcTemplate jdbcTemplate; - - private static final String USER_SQL_PARAM_NAME = "userId"; - - private static final String USER_GROUP_SQL_PARAM_NAME = "userGroupUIDs"; - - private static final String PUBLIC_ACCESS_CONDITION = - "sharing->>'public' LIKE '__r%' OR sharing->>'public' IS NULL"; - - private static final String USERACCESS_CONDITION = - "sharing->'users'->:" + USER_SQL_PARAM_NAME + "->>'access' LIKE '__r%'"; - - private static final String USERGROUPACCESS_CONDITION = - JsonbFunctions.HAS_USER_GROUP_IDS - + "( sharing, :" - + USER_GROUP_SQL_PARAM_NAME - + ") = true " - + "and " - + JsonbFunctions.CHECK_USER_GROUPS_ACCESS - + "(sharing, '__r%', :" - + USER_GROUP_SQL_PARAM_NAME - + ") = true"; - - private static final String GET_TE_TYPE_ACL = - "SELECT trackedentitytypeid FROM trackedentitytype " - + " WHERE " - + PUBLIC_ACCESS_CONDITION - + " OR " - + USERACCESS_CONDITION; - - static final String GET_PROGRAM_ACL = - "SELECT p.programid FROM program p " - + " WHERE " - + PUBLIC_ACCESS_CONDITION - + " OR " - + USERACCESS_CONDITION; - - static final String GET_PROGRAMSTAGE_ACL = - "SELECT ps.programstageid FROM programstage ps " - + " WHERE " - + PUBLIC_ACCESS_CONDITION - + " OR " - + USERACCESS_CONDITION; - - private static final String GET_RELATIONSHIPTYPE_ACL = - "SELECT rs.relationshiptypeid " - + "FROM relationshiptype rs" - + " WHERE " - + PUBLIC_ACCESS_CONDITION - + " OR " - + USERACCESS_CONDITION; - - public DefaultAclStore(@Qualifier("readOnlyJdbcTemplate") JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate); - } - - @Override - public List getAccessibleTrackedEntityTypes(String userUID, List userGroupUIDs) { - return executeAclQuery(userUID, userGroupUIDs, GET_TE_TYPE_ACL, "trackedentitytypeid"); - } - - @Override - public List getAccessiblePrograms(String userUID, List userGroupUIDs) { - return executeAclQuery(userUID, userGroupUIDs, GET_PROGRAM_ACL, "programid"); - } - - @Override - public List getAccessibleProgramStages(String userUID, List userGroupUIDs) { - return executeAclQuery(userUID, userGroupUIDs, GET_PROGRAMSTAGE_ACL, "programstageid"); - } - - @Override - public List getAccessibleRelationshipTypes(String userUID, List userGroupUIDs) { - return executeAclQuery(userUID, userGroupUIDs, GET_RELATIONSHIPTYPE_ACL, "relationshiptypeid"); - } - - private List executeAclQuery( - String userUID, List userGroupUIDs, String sql, String primaryKey) { - MapSqlParameterSource parameterMap = new MapSqlParameterSource(); - parameterMap.addValue(USER_SQL_PARAM_NAME, userUID); - - if (!CollectionUtils.isEmpty(userGroupUIDs)) { - sql += " OR " + USERGROUPACCESS_CONDITION; - parameterMap.addValue(USER_GROUP_SQL_PARAM_NAME, "{" + String.join(",", userGroupUIDs) + "}"); - } - - return jdbcTemplate.query(sql, parameterMap, (rs, i) -> rs.getLong(primaryKey)); - } -} diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultEnrollmentStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultEnrollmentStore.java deleted file mode 100644 index 821316c0cabf..000000000000 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultEnrollmentStore.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2004-2022, 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.tracker.export.trackedentity.aggregates; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; -import java.util.List; -import org.hisp.dhis.note.Note; -import org.hisp.dhis.program.Enrollment; -import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.EnrollmentRowCallbackHandler; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.NoteRowCallbackHandler; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.ProgramAttributeRowCallbackHandler; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.query.EnrollmentQuery; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.query.ProgramAttributeQuery; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Repository; - -/** - * @author Luciano Fiandesio - */ -@Repository("org.hisp.dhis.tracker.trackedentity.aggregates.EnrollmentStore") -class DefaultEnrollmentStore extends AbstractStore implements EnrollmentStore { - private static final String GET_ENROLLMENT_SQL_BY_TE = EnrollmentQuery.getQuery(); - - private static final String GET_ATTRIBUTES = ProgramAttributeQuery.getQuery(); - - private static final String GET_NOTES_SQL = - "select en.uid as key, n.uid, n.notetext, " - + "n.creator, n.created " - + "from note n join enrollment_notes enn " - + "on n.noteid = enn.noteid " - + "join enrollment en on enn.enrollmentid = en.enrollmentid " - + "where enn.enrollmentid in (:ids)"; - - private static final String FILTER_OUT_DELETED_ENROLLMENTS = "en.deleted=false"; - - public DefaultEnrollmentStore(@Qualifier("readOnlyJdbcTemplate") JdbcTemplate jdbcTemplate) { - super(jdbcTemplate); - } - - @Override - public Multimap getEnrollmentsByTrackedEntityIds( - List ids, Context ctx) { - List> teIds = Lists.partition(ids, PARITITION_SIZE); - - Multimap enrollmentMultimap = ArrayListMultimap.create(); - - teIds.forEach( - partition -> - enrollmentMultimap.putAll(getEnrollmentsByTrackedEntityIdsPartitioned(partition, ctx))); - - return enrollmentMultimap; - } - - private Multimap getEnrollmentsByTrackedEntityIdsPartitioned( - List ids, Context ctx) { - EnrollmentRowCallbackHandler handler = new EnrollmentRowCallbackHandler(); - - jdbcTemplate.query( - getQuery( - GET_ENROLLMENT_SQL_BY_TE, - ctx, - " en.programid IN (:programIds)", - FILTER_OUT_DELETED_ENROLLMENTS), - createIdsParam(ids).addValue("programIds", ctx.getPrograms()), - handler); - - return handler.getItems(); - } - - @Override - public Multimap getNotes(List ids) { - return fetch(GET_NOTES_SQL, new NoteRowCallbackHandler(), ids); - } - - @Override - public Multimap getAttributes(List ids, Context ctx) { - ProgramAttributeRowCallbackHandler handler = new ProgramAttributeRowCallbackHandler(); - - jdbcTemplate.query( - getQuery( - GET_ATTRIBUTES, ctx, " pa.programid IN (:programIds)", FILTER_OUT_DELETED_ENROLLMENTS), - createIdsParam(ids).addValue("programIds", ctx.getPrograms()), - handler); - - return handler.getItems(); - } - - @Override - String getRelationshipEntityColumn() { - return "enrollmentid"; - } -} diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultEventStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultEventStore.java deleted file mode 100644 index ab75b9ff0745..000000000000 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/DefaultEventStore.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2004-2022, 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.tracker.export.trackedentity.aggregates; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.hisp.dhis.eventdatavalue.EventDataValue; -import org.hisp.dhis.note.Note; -import org.hisp.dhis.program.Event; -import org.hisp.dhis.query.JpaQueryUtils; -import org.hisp.dhis.security.acl.AclService; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.EventDataValueRowCallbackHandler; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.EventRowCallbackHandler; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.NoteRowCallbackHandler; -import org.hisp.dhis.tracker.export.trackedentity.aggregates.query.EventQuery; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Repository; - -/** - * @author Luciano Fiandesio - */ -@Repository("org.hisp.dhis.tracker.trackedentity.aggregates.EventStore") -class DefaultEventStore extends AbstractStore implements EventStore { - private static final String GET_EVENTS_SQL = EventQuery.getQuery(); - - private static final String GET_DATAVALUES_SQL = - "select ev.uid as key, " - + "ev.eventdatavalues " - + "from event ev " - + "where ev.eventid in (:ids)"; - - private static final String GET_NOTES_SQL = - "select ev.uid as key, n.uid, n.notetext, " - + "n.creator, n.created " - + "from note n " - + "join event_notes evn " - + "on n.noteid = evn.noteid " - + "join event ev on evn.eventid = ev.eventid " - + "where evn.eventid in (:ids)"; - - private static final String ACL_FILTER_SQL = - "CASE WHEN p.type = 'WITH_REGISTRATION' THEN " - + "p.trackedentitytypeid in (:trackedEntityTypeIds) else true END " - + "AND ev.programstageid in (:programStageIds) AND en.programid IN (:programIds)"; - - private static final String ACL_FILTER_SQL_NO_PROGRAM_STAGE = - "CASE WHEN p.type = 'WITH_REGISTRATION' THEN " - + "p.trackedentitytypeid in (:trackedEntityTypeIds) else true END " - + "AND en.programid IN (:programIds)"; - - private static final String FILTER_OUT_DELETED_EVENTS = "ev.deleted=false"; - - public DefaultEventStore(JdbcTemplate jdbcTemplate) { - super(jdbcTemplate); - } - - @Override - String getRelationshipEntityColumn() { - return "eventid"; - } - - @Override - public Multimap getEventsByEnrollmentIds(List enrollmentsId, Context ctx) { - List> enrollmentIdsPartitions = Lists.partition(enrollmentsId, PARITITION_SIZE); - - Multimap eventMultimap = ArrayListMultimap.create(); - - enrollmentIdsPartitions.forEach( - partition -> eventMultimap.putAll(getEventsByEnrollmentIdsPartitioned(partition, ctx))); - - return eventMultimap; - } - - private String getAttributeOptionComboClause(Context ctx) { - return " and ev.attributeoptioncomboid not in (" - + "select distinct(cocco.categoryoptioncomboid) " - + "from categoryoptioncombos_categoryoptions as cocco " - + - // Get inaccessible category options - "where cocco.categoryoptionid not in ( " - + "select co.categoryoptionid " - + "from categoryoption co " - + " where " - + JpaQueryUtils.generateSQlQueryForSharingCheck( - "co.sharing", ctx.getUserUid(), ctx.getUserGroups(), AclService.LIKE_READ_DATA) - + ") )"; - } - - private Multimap getEventsByEnrollmentIdsPartitioned( - List enrollmentsId, Context ctx) { - EventRowCallbackHandler handler = new EventRowCallbackHandler(); - - List programStages = ctx.getProgramStages(); - - String aocSql = ctx.isSuperUser() ? "" : getAttributeOptionComboClause(ctx); - - if (programStages.isEmpty()) { - jdbcTemplate.query( - getQuery( - GET_EVENTS_SQL, - ctx, - ACL_FILTER_SQL_NO_PROGRAM_STAGE + aocSql, - FILTER_OUT_DELETED_EVENTS), - createIdsParam(enrollmentsId) - .addValue("trackedEntityTypeIds", ctx.getTrackedEntityTypes()) - .addValue("programIds", ctx.getPrograms()), - handler); - } else { - jdbcTemplate.query( - getQuery(GET_EVENTS_SQL, ctx, ACL_FILTER_SQL + aocSql, FILTER_OUT_DELETED_EVENTS), - createIdsParam(enrollmentsId) - .addValue("trackedEntityTypeIds", ctx.getTrackedEntityTypes()) - .addValue("programStageIds", programStages) - .addValue("programIds", ctx.getPrograms()), - handler); - } - - return handler.getItems(); - } - - @Override - public Map> getDataValues(List eventIds) { - Map> dataValueListMultimap = new HashMap<>(); - - Lists.partition(eventIds, PARITITION_SIZE) - .forEach(partition -> dataValueListMultimap.putAll(getDataValuesPartitioned(partition))); - - return dataValueListMultimap; - } - - private Map> getDataValuesPartitioned(List eventIds) { - EventDataValueRowCallbackHandler handler = new EventDataValueRowCallbackHandler(); - - jdbcTemplate.query(GET_DATAVALUES_SQL, createIdsParam(eventIds), handler); - - return handler.getItems(); - } - - @Override - public Multimap getNotes(List eventIds) { - return fetch(GET_NOTES_SQL, new NoteRowCallbackHandler(), eventIds); - } -} diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/EnrollmentStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/EnrollmentStore.java index 1ebefba64aa4..c4171c88cb3a 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/EnrollmentStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/EnrollmentStore.java @@ -27,47 +27,91 @@ */ package org.hisp.dhis.tracker.export.trackedentity.aggregates; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import java.util.List; import org.hisp.dhis.note.Note; import org.hisp.dhis.program.Enrollment; -import org.hisp.dhis.relationship.RelationshipItem; import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.EnrollmentRowCallbackHandler; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.NoteRowCallbackHandler; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.ProgramAttributeRowCallbackHandler; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.query.EnrollmentQuery; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.query.ProgramAttributeQuery; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; /** * @author Luciano Fiandesio */ -public interface EnrollmentStore { - /** - * @param ids a list of {@see TrackedEntity} Primary Keys - * @return a MultiMap where key is a {@see TrackedEntity} uid and the key a List of {@see - * Enrollment} objects - */ - Multimap getEnrollmentsByTrackedEntityIds(List ids, Context ctx); - - /** - * @param ids a list of {@see Enrollment} Primary Keys - * @return a MultiMap where key is a {@see Enrollment} uid and the key a List of {@see Note} - * objects - */ - Multimap getNotes(List ids); - - /** - * Fetches all the relationships having the enrollment id specified in the arg as "left" or - * "right" relationship - * - * @param ids a list of {@see Enrollment} Primary Keys - * @return a MultiMap where key is a {@see Enrollment} uid and the key a List of {@see - * Relationship} objects - */ - Multimap getRelationships(List ids, Context ctx); - - /** - * Fetches all the attributes - * - * @param ids a list of enrollment ids - * @return a MultiMap where key is a {@see Enrollment} uid and the key a List of {@see Attribute} - * objects - */ - Multimap getAttributes(List ids, Context ctx); +@Repository("org.hisp.dhis.tracker.trackedentity.aggregates.EnrollmentStore") +class EnrollmentStore extends AbstractStore { + private static final String GET_ENROLLMENT_SQL_BY_TE = EnrollmentQuery.getQuery(); + + private static final String GET_ATTRIBUTES = ProgramAttributeQuery.getQuery(); + + private static final String GET_NOTES_SQL = + "select en.uid as key, n.uid, n.notetext, " + + "n.creator, n.created " + + "from note n join enrollment_notes enn " + + "on n.noteid = enn.noteid " + + "join enrollment en on enn.enrollmentid = en.enrollmentid " + + "where enn.enrollmentid in (:ids)"; + + private static final String FILTER_OUT_DELETED_ENROLLMENTS = "en.deleted=false"; + + EnrollmentStore(@Qualifier("readOnlyJdbcTemplate") JdbcTemplate jdbcTemplate) { + super(jdbcTemplate); + } + + Multimap getEnrollmentsByTrackedEntityIds(List ids, Context ctx) { + List> teIds = Lists.partition(ids, PARITITION_SIZE); + + Multimap enrollmentMultimap = ArrayListMultimap.create(); + + teIds.forEach( + partition -> + enrollmentMultimap.putAll(getEnrollmentsByTrackedEntityIdsPartitioned(partition, ctx))); + + return enrollmentMultimap; + } + + private Multimap getEnrollmentsByTrackedEntityIdsPartitioned( + List ids, Context ctx) { + EnrollmentRowCallbackHandler handler = new EnrollmentRowCallbackHandler(); + + jdbcTemplate.query( + getQuery( + GET_ENROLLMENT_SQL_BY_TE, + ctx, + " en.programid IN (:programIds)", + FILTER_OUT_DELETED_ENROLLMENTS), + createIdsParam(ids).addValue("programIds", ctx.getPrograms()), + handler); + + return handler.getItems(); + } + + Multimap getNotes(List ids) { + return fetch(GET_NOTES_SQL, new NoteRowCallbackHandler(), ids); + } + + Multimap getAttributes(List ids, Context ctx) { + ProgramAttributeRowCallbackHandler handler = new ProgramAttributeRowCallbackHandler(); + + jdbcTemplate.query( + getQuery( + GET_ATTRIBUTES, ctx, " pa.programid IN (:programIds)", FILTER_OUT_DELETED_ENROLLMENTS), + createIdsParam(ids).addValue("programIds", ctx.getPrograms()), + handler); + + return handler.getItems(); + } + + @Override + String getRelationshipEntityColumn() { + return "enrollmentid"; + } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/EventStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/EventStore.java index fbe20026c42d..925c3aa14067 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/EventStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/EventStore.java @@ -27,46 +27,142 @@ */ package org.hisp.dhis.tracker.export.trackedentity.aggregates; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; import com.google.common.collect.Multimap; +import java.util.HashMap; import java.util.List; import java.util.Map; import org.hisp.dhis.eventdatavalue.EventDataValue; import org.hisp.dhis.note.Note; import org.hisp.dhis.program.Event; -import org.hisp.dhis.relationship.RelationshipItem; +import org.hisp.dhis.query.JpaQueryUtils; +import org.hisp.dhis.security.acl.AclService; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.EventDataValueRowCallbackHandler; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.EventRowCallbackHandler; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.mapper.NoteRowCallbackHandler; +import org.hisp.dhis.tracker.export.trackedentity.aggregates.query.EventQuery; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; /** * @author Luciano Fiandesio */ -public interface EventStore { - /** - * Key: enrollment uid -> Value: Event - * - * @param enrollmentsId a List of Enrollment Primary Keys - * @param ctx the {@see Context} - * @return A Map, where the key is a Enrollment Primary Key, and the value is a List of {@see - * Event} - */ - Multimap getEventsByEnrollmentIds(List enrollmentsId, Context ctx); - - /** - * Key: event uid -> Value: List - * - * @param eventIds a List of event primary keys - * @return A Map, where the key is an event primary key, and the value is a List of {@see - * DataValue} - */ - Map> getDataValues(List eventIds); - - /** - * Fetches all the relationships having the event id specified in the arg as "left" or "right" - * relationship - * - * @param ids a list of {@see Enrollment} Primary Keys - * @return a MultiMap where key is a {@see Enrollment} uid and the value a List of {@see - * Relationship} objects - */ - Multimap getRelationships(List ids, Context ctx); - - Multimap getNotes(List eventIds); +@Repository("org.hisp.dhis.tracker.trackedentity.aggregates.EventStore") +class EventStore extends AbstractStore { + private static final String GET_EVENTS_SQL = EventQuery.getQuery(); + + private static final String GET_DATAVALUES_SQL = + "select ev.uid as key, " + + "ev.eventdatavalues " + + "from event ev " + + "where ev.eventid in (:ids)"; + + private static final String GET_NOTES_SQL = + "select ev.uid as key, n.uid, n.notetext, " + + "n.creator, n.created " + + "from note n " + + "join event_notes evn " + + "on n.noteid = evn.noteid " + + "join event ev on evn.eventid = ev.eventid " + + "where evn.eventid in (:ids)"; + + private static final String ACL_FILTER_SQL = + "CASE WHEN p.type = 'WITH_REGISTRATION' THEN " + + "p.trackedentitytypeid in (:trackedEntityTypeIds) else true END " + + "AND ev.programstageid in (:programStageIds) AND en.programid IN (:programIds)"; + + private static final String ACL_FILTER_SQL_NO_PROGRAM_STAGE = + "CASE WHEN p.type = 'WITH_REGISTRATION' THEN " + + "p.trackedentitytypeid in (:trackedEntityTypeIds) else true END " + + "AND en.programid IN (:programIds)"; + + private static final String FILTER_OUT_DELETED_EVENTS = "ev.deleted=false"; + + EventStore(JdbcTemplate jdbcTemplate) { + super(jdbcTemplate); + } + + String getRelationshipEntityColumn() { + return "eventid"; + } + + public Multimap getEventsByEnrollmentIds(List enrollmentsId, Context ctx) { + List> enrollmentIdsPartitions = Lists.partition(enrollmentsId, PARITITION_SIZE); + + Multimap eventMultimap = ArrayListMultimap.create(); + + enrollmentIdsPartitions.forEach( + partition -> eventMultimap.putAll(getEventsByEnrollmentIdsPartitioned(partition, ctx))); + + return eventMultimap; + } + + private String getAttributeOptionComboClause(Context ctx) { + return " and ev.attributeoptioncomboid not in (" + + "select distinct(cocco.categoryoptioncomboid) " + + "from categoryoptioncombos_categoryoptions as cocco " + + + // Get inaccessible category options + "where cocco.categoryoptionid not in ( " + + "select co.categoryoptionid " + + "from categoryoption co " + + " where " + + JpaQueryUtils.generateSQlQueryForSharingCheck( + "co.sharing", ctx.getUserUid(), ctx.getUserGroups(), AclService.LIKE_READ_DATA) + + ") )"; + } + + private Multimap getEventsByEnrollmentIdsPartitioned( + List enrollmentsId, Context ctx) { + EventRowCallbackHandler handler = new EventRowCallbackHandler(); + + List programStages = ctx.getProgramStages(); + + String aocSql = ctx.isSuperUser() ? "" : getAttributeOptionComboClause(ctx); + + if (programStages.isEmpty()) { + jdbcTemplate.query( + getQuery( + GET_EVENTS_SQL, + ctx, + ACL_FILTER_SQL_NO_PROGRAM_STAGE + aocSql, + FILTER_OUT_DELETED_EVENTS), + createIdsParam(enrollmentsId) + .addValue("trackedEntityTypeIds", ctx.getTrackedEntityTypes()) + .addValue("programIds", ctx.getPrograms()), + handler); + } else { + jdbcTemplate.query( + getQuery(GET_EVENTS_SQL, ctx, ACL_FILTER_SQL + aocSql, FILTER_OUT_DELETED_EVENTS), + createIdsParam(enrollmentsId) + .addValue("trackedEntityTypeIds", ctx.getTrackedEntityTypes()) + .addValue("programStageIds", programStages) + .addValue("programIds", ctx.getPrograms()), + handler); + } + + return handler.getItems(); + } + + Map> getDataValues(List eventIds) { + Map> dataValueListMultimap = new HashMap<>(); + + Lists.partition(eventIds, PARITITION_SIZE) + .forEach(partition -> dataValueListMultimap.putAll(getDataValuesPartitioned(partition))); + + return dataValueListMultimap; + } + + private Map> getDataValuesPartitioned(List eventIds) { + EventDataValueRowCallbackHandler handler = new EventDataValueRowCallbackHandler(); + + jdbcTemplate.query(GET_DATAVALUES_SQL, createIdsParam(eventIds), handler); + + return handler.getItems(); + } + + Multimap getNotes(List eventIds) { + return fetch(GET_NOTES_SQL, new NoteRowCallbackHandler(), eventIds); + } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/TrackedEntityStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/TrackedEntityStore.java index 57877cc04ee8..07f2a442b8a8 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/TrackedEntityStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/aggregates/TrackedEntityStore.java @@ -108,7 +108,7 @@ private String getTrackedEntitiesOwnershipSqlForSpecificProgram(boolean skipUser return sql; } - public TrackedEntityStore(@Qualifier("readOnlyJdbcTemplate") JdbcTemplate jdbcTemplate) { + TrackedEntityStore(@Qualifier("readOnlyJdbcTemplate") JdbcTemplate jdbcTemplate) { super(jdbcTemplate); } @@ -117,7 +117,7 @@ String getRelationshipEntityColumn() { return "trackedentityid"; } - public Map getTrackedEntities(List ids, Context ctx) { + Map getTrackedEntities(List ids, Context ctx) { List> idPartitions = Lists.partition(ids, PARITITION_SIZE); Map trackedEntityMap = new LinkedHashMap<>(); @@ -146,15 +146,15 @@ private Map getTrackedEntitiesPartitioned(List ids, return handler.getItems(); } - public Multimap getAttributes(List ids) { + Multimap getAttributes(List ids) { return fetch(GET_TE_ATTRIBUTES, new TrackedEntityAttributeRowCallbackHandler(), ids); } - public Multimap getProgramOwners(List ids) { + Multimap getProgramOwners(List ids) { return fetch(GET_PROGRAM_OWNERS, new ProgramOwnerRowCallbackHandler(), ids); } - public Multimap getOwnedTrackedEntities( + Multimap getOwnedTrackedEntities( List ids, Context ctx, boolean skipUserScopeValidation) { List> teds = Lists.partition(ids, PARITITION_SIZE);