Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor dao classes to extract param build, row insert #1001

Merged
merged 13 commits into from
Sep 17, 2024
1 change: 1 addition & 0 deletions gradle/config/checkstyle/suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<suppress checks="JavadocStyle"/>
<suppress checks="JavadocType"/>
<suppress checks="JavaNCSS"/>
<suppress checks="ParameterNumber"/>
<!-- Spotless is canonical for line length. -->
<suppress checks="LineLength"/>
<suppress checks="MethodLength"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,36 +195,36 @@ public ResponseEntity<ApiInstanceCountList> queryCohortCounts(

private static CohortRevision.CriteriaGroupSection fromApiObject(ApiCriteriaGroupSection apiObj) {
BooleanAndOrFilter.LogicalOperator operator;
JoinOperator joinOperator =
switch (apiObj.getOperator()) {
case OR -> {
operator = BooleanAndOrFilter.LogicalOperator.OR;
yield null;
}
case AND -> {
operator = BooleanAndOrFilter.LogicalOperator.AND;
yield null;
}
case DURING_SAME_ENCOUNTER -> {
operator = BooleanAndOrFilter.LogicalOperator.OR;
yield JoinOperator.DURING_SAME_ENCOUNTER;
}
case WITHIN_NUM_DAYS -> {
operator = BooleanAndOrFilter.LogicalOperator.OR;
yield JoinOperator.WITHIN_NUM_DAYS;
}
case NUM_DAYS_BEFORE -> {
operator = BooleanAndOrFilter.LogicalOperator.OR;
yield JoinOperator.NUM_DAYS_BEFORE;
}
case NUM_DAYS_AFTER -> {
operator = BooleanAndOrFilter.LogicalOperator.OR;
yield JoinOperator.NUM_DAYS_AFTER;
}
default ->
throw new IllegalArgumentException(
"Unknown criteria group section operator: " + apiObj.getOperator());
};
JoinOperator joinOperator;
switch (apiObj.getOperator()) {
case OR:
operator = BooleanAndOrFilter.LogicalOperator.OR;
joinOperator = null;
break;
case AND:
operator = BooleanAndOrFilter.LogicalOperator.AND;
joinOperator = null;
break;
case DURING_SAME_ENCOUNTER:
operator = BooleanAndOrFilter.LogicalOperator.OR;
joinOperator = JoinOperator.DURING_SAME_ENCOUNTER;
break;
case WITHIN_NUM_DAYS:
operator = BooleanAndOrFilter.LogicalOperator.OR;
joinOperator = JoinOperator.WITHIN_NUM_DAYS;
break;
case NUM_DAYS_BEFORE:
operator = BooleanAndOrFilter.LogicalOperator.OR;
joinOperator = JoinOperator.NUM_DAYS_BEFORE;
break;
case NUM_DAYS_AFTER:
operator = BooleanAndOrFilter.LogicalOperator.OR;
joinOperator = JoinOperator.NUM_DAYS_AFTER;
break;
default:
throw new IllegalArgumentException(
"Unknown criteria group section operator: " + apiObj.getOperator());
}

return CohortRevision.CriteriaGroupSection.builder()
.id(apiObj.getId())
Expand Down
177 changes: 112 additions & 65 deletions service/src/main/java/bio/terra/tanagra/db/AnnotationDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import bio.terra.tanagra.service.artifact.model.AnnotationKey;
import bio.terra.tanagra.service.artifact.model.AnnotationValue;
import jakarta.annotation.Nullable;
import java.sql.Date;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -78,37 +79,21 @@ public AnnotationDao(NamedParameterJdbcTemplate jdbcTemplate) {

@WriteTransaction
public void createAnnotationKey(String cohortId, AnnotationKey annotationKey) {
String sql =
"INSERT INTO annotation_key (cohort_id, id, display_name, description, data_type) "
+ "VALUES (:cohort_id, :id, :display_name, :description, :data_type)";
LOGGER.debug("CREATE annotation key: {}", sql);
MapSqlParameterSource params =
new MapSqlParameterSource()
.addValue("cohort_id", cohortId)
.addValue("id", annotationKey.getId())
.addValue("display_name", annotationKey.getDisplayName())
.addValue("description", annotationKey.getDescription())
.addValue("data_type", annotationKey.getDataType().name());
int rowsAffected = jdbcTemplate.update(sql, params);
LOGGER.debug("CREATE annotation key rowsAffected = {}", rowsAffected);
MapSqlParameterSource keyParamSets =
Copy link
Contributor Author

@dexamundsen dexamundsen Sep 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

general pattern: build param, then insert rows

buildKeyParam(
cohortId,
annotationKey.getId(),
annotationKey.getDisplayName(),
annotationKey.getDescription(),
annotationKey.getDataType().name());
insertKeyRows(List.of(keyParamSets));

if (!annotationKey.getEnumVals().isEmpty()) {
sql =
"INSERT INTO annotation_key_enum_value (cohort_id, annotation_key_id, enum) "
+ "VALUES (:cohort_id, :annotation_key_id, :enum)";
LOGGER.debug("CREATE annotation key enum value: {}", sql);
MapSqlParameterSource[] enumParamSets =
List<MapSqlParameterSource> enumValueParamSets =
annotationKey.getEnumVals().stream()
.map(
ev ->
new MapSqlParameterSource()
.addValue("cohort_id", cohortId)
.addValue("annotation_key_id", annotationKey.getId())
.addValue("enum", ev))
.toList()
.toArray(new MapSqlParameterSource[0]);
rowsAffected = Arrays.stream(jdbcTemplate.batchUpdate(sql, enumParamSets)).sum();
LOGGER.debug("CREATE annotation key enum value rowsAffected = {}", rowsAffected);
.map(val -> buildEnumValueParam(cohortId, annotationKey.getId(), val))
.toList();
insertEnumValueRows(enumValueParamSets);
}
}

Expand Down Expand Up @@ -189,36 +174,29 @@ private List<AnnotationKey> getAnnotationKeysHelper(
return Collections.emptyList();
}

// Fetch enum vals. (annotation key id -> enum)
String sql =
ANNOTATION_KEY_ENUM_VALUE_SELECT_SQL + " WHERE annotation_key_id IN (:annotation_key_ids)";
MapSqlParameterSource params =
new MapSqlParameterSource()
.addValue(
"annotation_key_ids",
annotationKeys.stream()
.map(AnnotationKey.Builder::getId)
.collect(Collectors.toSet()));
List<Pair<String, String>> enumVals =
jdbcTemplate.query(sql, params, ANNOTATION_KEY_ENUM_VALUE_ROW_MAPPER);

// Put enum vals into their respective annotation keys.
Map<String, AnnotationKey.Builder> annotationKeysMap =
annotationKeys.stream()
.collect(Collectors.toMap(AnnotationKey.Builder::getId, Function.identity()));
enumVals.forEach(
pair -> {
String annotationKeyId = pair.getKey();
String enumVal = pair.getValue();
annotationKeysMap.get(annotationKeyId).addEnumVal(enumVal);
});

// Fetch enum vals. (annotation key id -> enum)
List<Pair<String, String>> enumVals = getEnumValuesMatchingList(annotationKeysMap.keySet());
enumVals.forEach(pair -> annotationKeysMap.get(pair.getKey()).addEnumVal(pair.getValue()));

// Preserve the order returned by the original query.
return annotationKeys.stream()
.map(a -> annotationKeysMap.get(a.getId()).build())
.collect(Collectors.toList());
}

public List<Pair<String, String>> getEnumValuesMatchingList(Set<String> keyIds) {
String sql =
ANNOTATION_KEY_ENUM_VALUE_SELECT_SQL + " WHERE annotation_key_id IN (:annotation_key_ids)";
MapSqlParameterSource params =
new MapSqlParameterSource().addValue("annotation_key_ids", keyIds);
return jdbcTemplate.query(sql, params, ANNOTATION_KEY_ENUM_VALUE_ROW_MAPPER);
}

@WriteTransaction
@SuppressWarnings("PMD.UseObjectForClearerAPI")
public void updateAnnotationKey(
Expand Down Expand Up @@ -268,27 +246,21 @@ public void updateAnnotationValues(
LOGGER.debug("DELETE annotation values rowsAffected = {}", rowsAffected);

// Write the annotation values.
sql =
"INSERT INTO annotation_value (cohort_id, annotation_key_id, review_id, primary_entity_instance_id, bool_val, int64_val, string_val, date_val) "
+ "VALUES (:cohort_id, :annotation_key_id, :review_id, :primary_entity_instance_id, :bool_val, :int64_val, :string_val, :date_val)";
LOGGER.debug("CREATE annotation values: {}", sql);
MapSqlParameterSource[] valueParamSets =
List<MapSqlParameterSource> valueParamSets =
annotationValues.stream()
.map(
av ->
new MapSqlParameterSource()
.addValue("cohort_id", cohortId)
.addValue("annotation_key_id", annotationKeyId)
.addValue("review_id", reviewId)
.addValue("primary_entity_instance_id", instanceId)
.addValue("bool_val", av.getBooleanVal())
.addValue("int64_val", av.getInt64Val())
.addValue("string_val", av.getStringVal())
.addValue("date_val", av.getDateVal()))
.toList()
.toArray(new MapSqlParameterSource[0]);
rowsAffected = Arrays.stream(jdbcTemplate.batchUpdate(sql, valueParamSets)).sum();
LOGGER.debug("CREATE annotation values rowsAffected = {}", rowsAffected);
buildValueParam(
cohortId,
annotationKeyId,
reviewId,
instanceId,
av.getBooleanVal(),
av.getInt64Val(),
av.getStringVal(),
av.getDateVal()))
.toList();
insertValueRows(valueParamSets);
}

@ReadTransaction
Expand All @@ -298,4 +270,79 @@ public List<AnnotationValue.Builder> getAllAnnotationValues(String cohortId) {
MapSqlParameterSource params = new MapSqlParameterSource().addValue("cohort_id", cohortId);
return jdbcTemplate.query(sql, params, ANNOTATION_VALUE_ROW_MAPPER);
}

void insertKeyRows(List<MapSqlParameterSource> keyParamSets) {
String sql =
"INSERT INTO annotation_key (cohort_id, id, display_name, description, data_type) "
+ "VALUES (:cohort_id, :id, :display_name, :description, :data_type)";
LOGGER.debug("CREATE annotation key: {}", sql);
int rowsAffected =
Arrays.stream(
jdbcTemplate.batchUpdate(sql, keyParamSets.toArray(new MapSqlParameterSource[0])))
.sum();
LOGGER.debug("CREATE annotation key rowsAffected = {}", rowsAffected);
}

void insertEnumValueRows(List<MapSqlParameterSource> enumValueParamSets) {
String sql =
"INSERT INTO annotation_key_enum_value (cohort_id, annotation_key_id, enum) "
+ "VALUES (:cohort_id, :annotation_key_id, :enum)";
LOGGER.debug("CREATE annotation key enum value: {}", sql);
int rowsAffected =
Arrays.stream(
jdbcTemplate.batchUpdate(
sql, enumValueParamSets.toArray(new MapSqlParameterSource[0])))
.sum();
LOGGER.debug("CREATE annotation key enum value rowsAffected = {}", rowsAffected);
}

void insertValueRows(List<MapSqlParameterSource> valueParamSets) {
// Write the annotation values.
String sql =
"INSERT INTO annotation_value (cohort_id, annotation_key_id, review_id, primary_entity_instance_id, bool_val, int64_val, string_val, date_val) "
+ "VALUES (:cohort_id, :annotation_key_id, :review_id, :primary_entity_instance_id, :bool_val, :int64_val, :string_val, :date_val)";
LOGGER.debug("CREATE annotation values: {}", sql);
int rowsAffected =
Arrays.stream(
jdbcTemplate.batchUpdate(sql, valueParamSets.toArray(new MapSqlParameterSource[0])))
.sum();
LOGGER.debug("CREATE annotation values rowsAffected = {}", rowsAffected);
}

MapSqlParameterSource buildKeyParam(
String cohortId, String id, String displayName, String description, String dataTypeName) {
return new MapSqlParameterSource()
.addValue("cohort_id", cohortId)
.addValue("id", id)
.addValue("display_name", displayName)
.addValue("description", description)
.addValue("data_type", dataTypeName);
}

MapSqlParameterSource buildEnumValueParam(String cohortId, String keyId, String enumValue) {
return new MapSqlParameterSource()
.addValue("cohort_id", cohortId)
.addValue("annotation_key_id", keyId)
.addValue("enum", enumValue);
}

MapSqlParameterSource buildValueParam(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made them package private to be callable from other dao classes

String cohortId,
String keyId,
String reviewId,
String instanceId,
Boolean booelanVal,
Long int64Val,
String stringVal,
Date dateVal) {
return new MapSqlParameterSource()
.addValue("cohort_id", cohortId)
.addValue("annotation_key_id", keyId)
.addValue("review_id", reviewId)
.addValue("primary_entity_instance_id", instanceId)
.addValue("bool_val", booelanVal)
.addValue("int64_val", int64Val)
.addValue("string_val", stringVal)
.addValue("date_val", dateVal);
}
}
Loading