From a4e913d6df89ffa3f50c836091905c032470573c Mon Sep 17 00:00:00 2001 From: marikomedlock Date: Fri, 13 Sep 2024 08:52:03 -0400 Subject: [PATCH 01/12] Attribute with repeated data type. (#991) * Attribute isRepeated flag. ValidateDataTypes indexing job. * CreateEntityMainn indexing job. * WriteEntityLevelDisplayHints indexing job. * WriteTextSearchField indexing job. * Select repeated attr field. Result parsing test list query. * Fetch string-only hints. Result parsing test hint query. * Group by repeated attribute field. Sql building and results parsing tests count query. * Filter on repeated attribute field. Sql building test list query. * Only use FLATTENED alias for repeated attribute field. * OpenAPI repeated type in ValueDisplay. Bug in returning hint query results. * Remove variant config files. * Regenerate docs. * Check actual data rows in result parsing hint & count query tests. * Fix overlapping conditional in eldh indexing job. * Always populate repeatedValue property of ValueDisplay in OpenAPI. --------- Co-authored-by: Dexter Amundsen --- docs/generated/UNDERLAY_CONFIG.md | 7 + .../job/bigquery/CreateEntityMain.java | 4 + .../job/bigquery/ValidateDataTypes.java | 12 ++ .../WriteEntityLevelDisplayHints.java | 198 ++++++++++++++---- .../job/bigquery/WriteTextSearchField.java | 19 +- .../app/controller/objmapping/ToApiUtils.java | 17 +- .../main/resources/api/service_openapi.yaml | 6 + ui/src/tanagra-underlay/underlayConfig.ts | 1 + .../tanagra/api/filter/AttributeFilter.java | 16 ++ .../tanagra/api/shared/ValueDisplay.java | 26 ++- .../tanagra/query/bigquery/BQQueryRunner.java | 29 ++- .../tanagra/query/bigquery/BQRowResult.java | 17 +- .../bigquery/translator/BQApiTranslator.java | 23 ++ .../field/BQAttributeFieldTranslator.java | 68 ++++-- .../filter/BQAttributeFilterTranslator.java | 29 ++- .../terra/tanagra/query/sql/SqlRowResult.java | 4 + .../query/sql/translator/ApiTranslator.java | 7 + .../terra/tanagra/underlay/ColumnSchema.java | 18 +- .../bio/terra/tanagra/underlay/Underlay.java | 1 + .../underlay/entitymodel/Attribute.java | 9 + .../underlay/indextable/ITEntityMain.java | 8 +- .../underlay/serialization/SZAttribute.java | 7 + .../sourcetable/STEntityAttributes.java | 4 +- .../BQCountQueryResultsTest.java | 114 +++++++++- .../resultparsing/BQHintQueryResultsTest.java | 48 ++++- .../resultparsing/BQListQueryResultsTest.java | 34 ++- .../sqlbuilding/BQCountQueryTest.java | 60 +++++- .../bigquery/sqlbuilding/BQFieldTest.java | 2 + .../filter/BQAttributeFilterTest.java | 59 +++++- ...repeatedAttributeFilterBinaryNotEquals.sql | 12 ++ .../repeatedAttributeFilterNaryIn.sql | 12 ++ .../groupByRepeatedAttribute.sql | 12 ++ 32 files changed, 776 insertions(+), 107 deletions(-) create mode 100644 underlay/src/test/resources/sql/BQAttributeFilterTest/repeatedAttributeFilterBinaryNotEquals.sql create mode 100644 underlay/src/test/resources/sql/BQAttributeFilterTest/repeatedAttributeFilterNaryIn.sql create mode 100644 underlay/src/test/resources/sql/BQCountQueryTest/groupByRepeatedAttribute.sql diff --git a/docs/generated/UNDERLAY_CONFIG.md b/docs/generated/UNDERLAY_CONFIG.md index 2c48725ae..908f9daae 100644 --- a/docs/generated/UNDERLAY_CONFIG.md +++ b/docs/generated/UNDERLAY_CONFIG.md @@ -73,6 +73,13 @@ When set to true, an indexing job will try to compute a display hint for this at *Default value:* `false` +### SZAttribute.isDataTypeRepeated +**optional** boolean + +True if the data type is repeated (e.g. an array of ints). + +*Default value:* `false` + ### SZAttribute.isSuppressedForExport **optional** boolean diff --git a/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/CreateEntityMain.java b/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/CreateEntityMain.java index 642d5b167..90bfb1c51 100644 --- a/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/CreateEntityMain.java +++ b/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/CreateEntityMain.java @@ -47,6 +47,10 @@ public void run(boolean isDryRun) { Field.newBuilder( columnSchema.getColumnName(), BigQueryBeamUtils.fromDataType(columnSchema.getDataType())) + .setMode( + columnSchema.isDataTypeRepeated() + ? Field.Mode.REPEATED + : Field.Mode.NULLABLE) .build()) .collect(Collectors.toList()); diff --git a/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/ValidateDataTypes.java b/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/ValidateDataTypes.java index 4c96777d4..ebd9642fc 100644 --- a/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/ValidateDataTypes.java +++ b/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/ValidateDataTypes.java @@ -92,6 +92,18 @@ public void run(boolean isDryRun) { .collect(Collectors.joining(",", "[", "]")), sourceQueryField.getType()); } + + // Check that the schema repeated flags match those of the index table columns. + boolean sourceQueryFieldIsRepeated = sourceQueryField.getMode().equals(Field.Mode.REPEATED); + boolean isRepeatedFlagsMatch = attribute.isDataTypeRepeated() == sourceQueryFieldIsRepeated; + if (!isRepeatedFlagsMatch) { + foundError = true; + LOGGER.info( + "Data type repeated mismatch found for attribute {}: entity declared {}, SQL schema returns {}", + attribute.getName(), + attribute.isDataTypeRepeated(), + sourceQueryField.getMode()); + } } if (foundError) { throw new InvalidConfigException("Data type mismatch found for entity: " + entity.getName()); diff --git a/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/WriteEntityLevelDisplayHints.java b/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/WriteEntityLevelDisplayHints.java index 92ba8862a..2f810b7c0 100644 --- a/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/WriteEntityLevelDisplayHints.java +++ b/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/WriteEntityLevelDisplayHints.java @@ -113,23 +113,53 @@ public void run(boolean isDryRun) { attribute.getName(), minMax.getKey(), minMax.getValue()); - } else if (isEnumHint(attribute)) { - List> enumCounts = computeEnumHint(attribute, isDryRun); + } else if (isEnumHintForValueDisplay(attribute)) { + List> enumCounts = + computeEnumHintForValueDisplay(attribute, isDryRun); + enumCounts.forEach( + enumCount -> { + Literal int64Field = + attribute.isValueDisplay() + ? enumCount.getKey().getValue() + : Literal.forInt64(null); + Literal stringField = + attribute.isValueDisplay() + ? Literal.forString(enumCount.getKey().getDisplay()) + : enumCount.getKey().getValue(); + + List rowOfLiterals = new ArrayList<>(); + rowOfLiterals.add(Literal.forString(attribute.getName())); + rowOfLiterals.add(Literal.forDouble(null)); + rowOfLiterals.add(Literal.forDouble(null)); + rowOfLiterals.add(int64Field); + rowOfLiterals.add(stringField); + rowOfLiterals.add(Literal.forInt64(enumCount.getValue())); + insertRows.add(rowOfLiterals); + LOGGER.info( + "Enum value-display or simple-string hint: {}, {}, {}, {}", + attribute.getName(), + int64Field, + stringField, + enumCount.getValue()); + }); + } else if (isEnumHintForRepeatedStringValue(attribute)) { + List> enumCounts = + computeEnumHintForRepeatedStringValue(attribute, isDryRun); enumCounts.forEach( enumCount -> { List rowOfLiterals = new ArrayList<>(); rowOfLiterals.add(Literal.forString(attribute.getName())); rowOfLiterals.add(Literal.forDouble(null)); rowOfLiterals.add(Literal.forDouble(null)); - rowOfLiterals.add(enumCount.getKey().getValue()); - rowOfLiterals.add(Literal.forString(enumCount.getKey().getDisplay())); + rowOfLiterals.add(Literal.forInt64(null)); + rowOfLiterals.add(enumCount.getKey()); rowOfLiterals.add(Literal.forInt64(enumCount.getValue())); insertRows.add(rowOfLiterals); LOGGER.info( - "Enum hint: {}, {}, {}, {}", + "Enum repeated-string hint: {}, {}, {}, {}", attribute.getName(), - enumCount.getKey().getValue(), - enumCount.getKey().getDisplay(), + null, + enumCount.getKey(), enumCount.getValue()); }); } else { @@ -205,8 +235,18 @@ public void run(boolean isDryRun) { } } - private static boolean isEnumHint(Attribute attribute) { - return attribute.isValueDisplay() && DataType.INT64.equals(attribute.getRuntimeDataType()); + private static boolean isEnumHintForValueDisplay(Attribute attribute) { + return (attribute.isValueDisplay() && DataType.INT64.equals(attribute.getRuntimeDataType())) + || (attribute.isSimple() + && !attribute.isDataTypeRepeated() + && DataType.STRING.equals(attribute.getRuntimeDataType())); + } + + private static boolean isEnumHintForRepeatedStringValue(Attribute attribute) { + // TODO: Support not-repeated string simple attributes & repeated integer attributes. + return attribute.isSimple() + && attribute.isDataTypeRepeated() + && (DataType.STRING.equals(attribute.getDataType())); } private static boolean isRangeHint(Attribute attribute) { @@ -214,7 +254,7 @@ private static boolean isRangeHint(Attribute attribute) { return false; } return switch (attribute.getRuntimeDataType()) { - case DOUBLE, INT64 -> true; + case DOUBLE, INT64 -> !attribute.isDataTypeRepeated(); default -> false; }; } @@ -275,29 +315,36 @@ private Pair computeRangeHint(Attribute attribute, boolean isD } } - private List> computeEnumHint(Attribute attribute, boolean isDryRun) { + private List> computeEnumHintForValueDisplay( + Attribute attribute, boolean isDryRun) { // Build the query. - // SELECT attrVal AS enumVal, attrDisp AS enumDisp, COUNT(*) AS enumCount FROM indextable GROUP - // BY enumVal, enumDisp + // SELECT attrVal AS enumVal[, attrDisp AS enumDisp], COUNT(*) AS enumCount FROM indextable + // GROUP BY enumVal[, enumDisp] SqlField attrValField = indexAttributesTable.getAttributeValueField(attribute.getName()); - SqlField attrDispField = indexAttributesTable.getAttributeDisplayField(attribute.getName()); + SqlField attrDispField = + attribute.isValueDisplay() + ? indexAttributesTable.getAttributeDisplayField(attribute.getName()) + : null; final String enumValAlias = "enumVal"; final String enumDispAlias = "enumDisp"; final String enumCountAlias = "enumCount"; String selectEnumCountSql = - "SELECT " - + SqlQueryField.of(attrValField, enumValAlias).renderForSelect() - + ", " - + SqlQueryField.of(attrDispField, enumDispAlias).renderForSelect() - + ", COUNT(*) AS " + "SELECT " + SqlQueryField.of(attrValField, enumValAlias).renderForSelect(); + if (attribute.isValueDisplay()) { + selectEnumCountSql += ", " + SqlQueryField.of(attrDispField, enumDispAlias).renderForSelect(); + } + selectEnumCountSql += + ", COUNT(*) AS " + enumCountAlias + " FROM " + indexAttributesTable.getTablePointer().render() + " GROUP BY " - + SqlQueryField.of(attrValField, enumValAlias).renderForGroupBy(null, true) - + ", " - + SqlQueryField.of(attrDispField, enumDispAlias).renderForGroupBy(null, true); + + SqlQueryField.of(attrValField, enumValAlias).renderForGroupBy(null, true); + if (attribute.isValueDisplay()) { + selectEnumCountSql += + ", " + SqlQueryField.of(attrDispField, enumDispAlias).renderForGroupBy(null, true); + } LOGGER.info("SQL enum count: {}", selectEnumCountSql); // Execute the query. @@ -315,16 +362,26 @@ private List> computeEnumHint(Attribute attribute, bool // Parse the result rows. for (FieldValueList rowResult : tableResult.getValues()) { FieldValue enumValFieldValue = rowResult.get(enumValAlias); - Literal enumVal = - Literal.forInt64(enumValFieldValue.isNull() ? null : enumValFieldValue.getLongValue()); - FieldValue enumDispFieldValue = rowResult.get(enumDispAlias); - String enumDisp = enumDispFieldValue.isNull() ? null : enumDispFieldValue.getStringValue(); + Literal enumVal; + String enumDisp; + if (attribute.isValueDisplay()) { + enumVal = + Literal.forInt64( + enumValFieldValue.isNull() ? null : enumValFieldValue.getLongValue()); + FieldValue enumDispFieldValue = rowResult.get(enumDispAlias); + enumDisp = enumDispFieldValue.isNull() ? null : enumDispFieldValue.getStringValue(); + } else { + enumVal = + Literal.forString( + enumValFieldValue.isNull() ? null : enumValFieldValue.getStringValue()); + enumDisp = null; + } FieldValue enumCountFieldValue = rowResult.get(enumCountAlias); long enumCount = enumCountFieldValue.getLongValue(); enumCounts.add(Pair.of(new ValueDisplay(enumVal, enumDisp), enumCount)); if (enumCounts.size() > MAX_ENUM_VALS_FOR_DISPLAY_HINT) { - // if there are more than the max number of values, then skip the display hint + // If there are more than the max number of values, then skip the display hint. LOGGER.info( "Skipping enum values display hint because there are >{} possible values: {}", MAX_ENUM_VALS_FOR_DISPLAY_HINT, @@ -334,17 +391,82 @@ private List> computeEnumHint(Attribute attribute, bool } } - // Check that there is exactly one display per value. - Map valDisplay = new HashMap<>(); - enumCounts.forEach( - enumCount -> { - if (valDisplay.containsKey(enumCount.getKey().getValue())) { - throw new InvalidConfigException( - "Found >1 possible display for the enum value " + enumCount.getKey().getValue()); - } else { - valDisplay.put(enumCount.getKey().getValue(), enumCount.getKey().getDisplay()); - } - }); + if (attribute.isValueDisplay()) { + // Check that there is exactly one display per value. + Map valDisplay = new HashMap<>(); + enumCounts.forEach( + enumCount -> { + if (valDisplay.containsKey(enumCount.getKey().getValue())) { + throw new InvalidConfigException( + "Found >1 possible display for the enum value " + enumCount.getKey().getValue()); + } else { + valDisplay.put(enumCount.getKey().getValue(), enumCount.getKey().getDisplay()); + } + }); + } + return enumCounts; + } + + private List> computeEnumHintForRepeatedStringValue( + Attribute attribute, boolean isDryRun) { + // TODO: Consolidate the logic here with the ValueDisplay enum hint method. + // Build the query. + // SELECT flattenedAttrVal AS enumVal, COUNT(*) AS enumCount FROM indextable + // CROSS JOIN UNNEST(indextable.attrVal) AS flattenedAttrVal + // GROUP BY enumVal + SqlField attrValField = indexAttributesTable.getAttributeValueField(attribute.getName()); + final String enumValAlias = "enumVal"; + final String enumCountAlias = "enumCount"; + final String flattenedAttrValAlias = "flattenedAttrVal"; + SqlField flattenedAttrValField = SqlField.of(flattenedAttrValAlias); + + String selectEnumCountSql = + "SELECT " + + SqlQueryField.of(flattenedAttrValField, enumValAlias).renderForSelect() + + ", COUNT(*) AS " + + enumCountAlias + + " FROM " + + indexAttributesTable.getTablePointer().render() + + " CROSS JOIN UNNEST(" + + SqlQueryField.of(attrValField).renderForSelect() + + ") AS " + + flattenedAttrValAlias + + " GROUP BY " + + SqlQueryField.of(attrValField, enumValAlias).renderForGroupBy(null, true); + LOGGER.info("SQL enum count: {}", selectEnumCountSql); + + // Execute the query. + List> enumCounts = new ArrayList<>(); + if (isDryRun) { + if (getOutputTable().isEmpty()) { + LOGGER.info("Skipping query dry run because output table does not exist yet."); + } else { + googleBigQuery.dryRunQuery(selectEnumCountSql); + } + enumCounts.add(Pair.of(Literal.forString(""), 0L)); + } else { + TableResult tableResult = googleBigQuery.runQueryLongTimeout(selectEnumCountSql); + + // Parse the result rows. + for (FieldValueList rowResult : tableResult.getValues()) { + FieldValue enumValFieldValue = rowResult.get(enumValAlias); + Literal enumVal = + Literal.forString( + enumValFieldValue.isNull() ? null : enumValFieldValue.getStringValue()); + FieldValue enumCountFieldValue = rowResult.get(enumCountAlias); + long enumCount = enumCountFieldValue.getLongValue(); + enumCounts.add(Pair.of(enumVal, enumCount)); + + if (enumCounts.size() > MAX_ENUM_VALS_FOR_DISPLAY_HINT) { + // if there are more than the max number of values, then skip the display hint + LOGGER.info( + "Skipping enum values display hint because there are >{} possible values: {}", + MAX_ENUM_VALS_FOR_DISPLAY_HINT, + attribute.getName()); + return List.of(); + } + } + } return enumCounts; } } diff --git a/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/WriteTextSearchField.java b/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/WriteTextSearchField.java index ec14e6e6f..53ce03bcb 100644 --- a/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/WriteTextSearchField.java +++ b/indexer/src/main/java/bio/terra/tanagra/indexing/job/bigquery/WriteTextSearchField.java @@ -69,13 +69,22 @@ public void run(boolean isDryRun) { SqlField attributeTextField; if (attribute.isValueDisplay()) { attributeTextField = indexTable.getAttributeDisplayField(attribute.getName()); - } else if (!attribute.getDataType().equals(DataType.STRING)) { - attributeTextField = - indexTable - .getAttributeValueField(attribute.getName()) - .cloneWithFunctionWrapper("CAST(${fieldSql} AS STRING)"); } else { + String functionWrapper = null; + if (!attribute.getDataType().equals(DataType.STRING)) { + functionWrapper = "CAST(${fieldSql} AS STRING)"; + } + if (attribute.isDataTypeRepeated()) { + functionWrapper = + "ARRAY_TO_STRING(" + + (functionWrapper == null ? "${fieldSql}" : functionWrapper) + + ", \" \")"; + } + attributeTextField = indexTable.getAttributeValueField(attribute.getName()); + if (functionWrapper != null) { + attributeTextField = attributeTextField.cloneWithFunctionWrapper(functionWrapper); + } } String idTextSql = diff --git a/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/ToApiUtils.java b/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/ToApiUtils.java index bfbbd0efb..eb572056e 100644 --- a/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/ToApiUtils.java +++ b/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/ToApiUtils.java @@ -42,10 +42,21 @@ public static ApiAttribute toApiObject(Attribute attribute) { public static ApiValueDisplay toApiObject(ValueDisplay valueDisplay) { ApiValueDisplay apiObject = new ApiValueDisplay(); - if (valueDisplay != null) { - apiObject.value(toApiObject(valueDisplay.getValue())).display(valueDisplay.getDisplay()); + if (valueDisplay == null) { + return apiObject; + } else if (valueDisplay.isRepeatedValue()) { + return apiObject + .isRepeatedValue(true) + .repeatedValue( + valueDisplay.getRepeatedValue().stream().map(ToApiUtils::toApiObject).toList()); + } else { + ApiLiteral apiValue = toApiObject(valueDisplay.getValue()); + return apiObject + .value(apiValue) + .display(valueDisplay.getDisplay()) + .isRepeatedValue(false) + .repeatedValue(List.of(apiValue)); } - return apiObject; } public static ApiLiteral toApiObject(Literal literal) { diff --git a/service/src/main/resources/api/service_openapi.yaml b/service/src/main/resources/api/service_openapi.yaml index 15d4674b7..b9654cd69 100644 --- a/service/src/main/resources/api/service_openapi.yaml +++ b/service/src/main/resources/api/service_openapi.yaml @@ -1432,6 +1432,12 @@ components: type: string description: Optional display string nullable: true + repeatedValue: + type: array + items: + $ref: "#/components/schemas/Literal" + isRepeatedValue: + type: boolean Literal: type: object diff --git a/ui/src/tanagra-underlay/underlayConfig.ts b/ui/src/tanagra-underlay/underlayConfig.ts index 58f688123..df1af9b50 100644 --- a/ui/src/tanagra-underlay/underlayConfig.ts +++ b/ui/src/tanagra-underlay/underlayConfig.ts @@ -4,6 +4,7 @@ export type SZAttribute = { displayHintRangeMax?: number; displayHintRangeMin?: number; isComputeDisplayHint?: boolean; + isDataTypeRepeated?: boolean; isSuppressedForExport?: boolean; name: string; runtimeDataType?: SZDataType; diff --git a/underlay/src/main/java/bio/terra/tanagra/api/filter/AttributeFilter.java b/underlay/src/main/java/bio/terra/tanagra/api/filter/AttributeFilter.java index ec5975772..134b6e08b 100644 --- a/underlay/src/main/java/bio/terra/tanagra/api/filter/AttributeFilter.java +++ b/underlay/src/main/java/bio/terra/tanagra/api/filter/AttributeFilter.java @@ -98,6 +98,22 @@ public boolean hasBinaryOperator() { return binaryOperator != null; } + public boolean hasNaryOperator() { + return naryOperator != null; + } + + public String getOperatorName() { + if (hasUnaryOperator()) { + return unaryOperator.name(); + } else if (hasBinaryOperator()) { + return binaryOperator.name(); + } else if (hasNaryOperator()) { + return naryOperator.name(); + } else { + return null; + } + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/underlay/src/main/java/bio/terra/tanagra/api/shared/ValueDisplay.java b/underlay/src/main/java/bio/terra/tanagra/api/shared/ValueDisplay.java index 8e99e5b4a..f637ae437 100644 --- a/underlay/src/main/java/bio/terra/tanagra/api/shared/ValueDisplay.java +++ b/underlay/src/main/java/bio/terra/tanagra/api/shared/ValueDisplay.java @@ -1,19 +1,29 @@ package bio.terra.tanagra.api.shared; -import java.util.Objects; +import com.google.common.collect.*; +import java.util.*; public class ValueDisplay { private final Literal value; private final String display; + private final ImmutableList repeatedValue; public ValueDisplay(Literal value) { this.value = value; this.display = null; + this.repeatedValue = null; } public ValueDisplay(Literal value, String display) { this.value = value; this.display = display; + this.repeatedValue = null; + } + + public ValueDisplay(List repeatedValue) { + this.value = null; + this.display = null; + this.repeatedValue = ImmutableList.copyOf(repeatedValue); } public Literal getValue() { @@ -24,6 +34,14 @@ public String getDisplay() { return display; } + public List getRepeatedValue() { + return repeatedValue; + } + + public boolean isRepeatedValue() { + return repeatedValue != null; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -33,11 +51,13 @@ public boolean equals(Object o) { return false; } ValueDisplay that = (ValueDisplay) o; - return value.equals(that.value) && Objects.equals(display, that.display); + return Objects.equals(value, that.value) + && Objects.equals(display, that.display) + && Objects.equals(repeatedValue, that.repeatedValue); } @Override public int hashCode() { - return Objects.hash(value, display); + return Objects.hash(value, display, repeatedValue); } } diff --git a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/BQQueryRunner.java b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/BQQueryRunner.java index 887142c85..eefe2d18f 100644 --- a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/BQQueryRunner.java +++ b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/BQQueryRunner.java @@ -271,8 +271,7 @@ public HintQueryResult run(HintQueryRequest hintQueryRequest) { .getHintedEntity() .getAttribute( sqlRowResult.get(attributeColName, DataType.STRING).getStringVal()); - if (attribute.isValueDisplay() - || attribute.getRuntimeDataType().equals(DataType.STRING)) { + if (attribute.isValueDisplay()) { // This is one (value,count) pair of an enum values hint. Literal enumVal = sqlRowResult.get(enumValColName, DataType.INT64); String enumDisplay = @@ -282,6 +281,13 @@ public HintQueryResult run(HintQueryRequest hintQueryRequest) { enumValues.containsKey(attribute) ? enumValues.get(attribute) : new HashMap<>(); enumValuesForAttr.put(new ValueDisplay(enumVal, enumDisplay), enumCount); enumValues.put(attribute, enumValuesForAttr); + } else if (attribute.getRuntimeDataType().equals(DataType.STRING)) { + Literal enumVal = sqlRowResult.get(enumDisplayColName, DataType.STRING); + Long enumCount = sqlRowResult.get(enumCountColName, DataType.INT64).getInt64Val(); + Map enumValuesForAttr = + enumValues.containsKey(attribute) ? enumValues.get(attribute) : new HashMap<>(); + enumValuesForAttr.put(new ValueDisplay(enumVal), enumCount); + enumValues.put(attribute, enumValuesForAttr); } else { // This is a range hint. Double min = sqlRowResult.get(minColName, DataType.DOUBLE).getDoubleVal(); @@ -383,15 +389,21 @@ private SqlQueryRequest buildQuerySqlAgainstIndexData( ITEntityMain entityMain = underlay.getIndexSchema().getEntityMain(singleEntity.getName()); List selectFieldSqls = new ArrayList<>(); + List joinTableSqls = new ArrayList<>(); selectFields.forEach( valueDisplayField -> { List sqlQueryFields; if (groupByFields.contains(valueDisplayField) && valueDisplayField instanceof AttributeField) { + BQAttributeFieldTranslator attributeFieldTranslator = + (BQAttributeFieldTranslator) bqTranslator.translator(valueDisplayField); sqlQueryFields = - ((BQAttributeFieldTranslator) bqTranslator.translator(valueDisplayField)) - .buildSqlFieldsForCountSelectAndGroupBy( - entityLevelHints.get(valueDisplayField.getEntity())); + attributeFieldTranslator.buildSqlFieldsForCountSelectAndGroupBy( + entityLevelHints.get(valueDisplayField.getEntity())); + String joinTableSql = attributeFieldTranslator.buildSqlJoinTableForCountQuery(); + if (joinTableSql != null) { + joinTableSqls.add(joinTableSql); + } } else { sqlQueryFields = bqTranslator.translator(valueDisplayField).buildSqlFieldsForListSelect(); @@ -401,12 +413,17 @@ private SqlQueryRequest buildQuerySqlAgainstIndexData( sqlQueryField -> selectFieldSqls.add(sqlQueryField.renderForSelect())); }); - // SELECT [select fields] FROM [entity main] + // SELECT [select fields] FROM [entity main] JOIN [join tables] sql.append("SELECT ") .append(String.join(", ", selectFieldSqls)) .append(" FROM ") .append(entityMain.getTablePointer().render()); + // JOIN [join tables] + if (!joinTableSqls.isEmpty()) { + sql.append(" ").append(String.join(" ", joinTableSqls)); + } + // WHERE [filter] EntityFilter singleEntityFilter = filters.get(singleEntity); if (singleEntityFilter != null) { diff --git a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/BQRowResult.java b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/BQRowResult.java index 5223d1e23..eb76ea3e8 100644 --- a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/BQRowResult.java +++ b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/BQRowResult.java @@ -2,11 +2,11 @@ import bio.terra.tanagra.api.shared.DataType; import bio.terra.tanagra.api.shared.Literal; -import bio.terra.tanagra.exception.InvalidQueryException; import bio.terra.tanagra.query.sql.SqlRowResult; import com.google.cloud.bigquery.FieldValue; import com.google.cloud.bigquery.FieldValueList; import java.sql.Timestamp; +import java.util.*; public class BQRowResult implements SqlRowResult { private final FieldValueList fieldValues; @@ -18,6 +18,18 @@ public BQRowResult(FieldValueList fieldValues) { @Override public Literal get(String columnName, DataType expectedDataType) { FieldValue fieldValue = fieldValues.get(columnName); + return toLiteral(fieldValue, expectedDataType); + } + + @Override + public List getRepeated(String columnName, DataType expectedDataType) { + List repeatedFieldValue = fieldValues.get(columnName).getRepeatedValue(); + return repeatedFieldValue.stream() + .map(fieldValue -> toLiteral(fieldValue, expectedDataType)) + .toList(); + } + + private static Literal toLiteral(FieldValue fieldValue, DataType expectedDataType) { return switch (expectedDataType) { case STRING -> Literal.forString(fieldValue.isNull() ? null : fieldValue.getStringValue()); case INT64 -> Literal.forInt64(fieldValue.isNull() ? null : fieldValue.getLongValue()); @@ -27,9 +39,6 @@ public Literal get(String columnName, DataType expectedDataType) { case TIMESTAMP -> Literal.forTimestamp( fieldValue.isNull() ? null : Timestamp.from(fieldValue.getTimestampInstant())); - default -> - throw new InvalidQueryException( - "Unsupported data type for BigQuery row result: " + expectedDataType); }; } diff --git a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/BQApiTranslator.java b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/BQApiTranslator.java index 30316d368..073ceeee9 100644 --- a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/BQApiTranslator.java +++ b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/BQApiTranslator.java @@ -9,6 +9,7 @@ import bio.terra.tanagra.api.field.RelatedEntityIdCountField; import bio.terra.tanagra.api.filter.*; import bio.terra.tanagra.api.filter.TextSearchFilter.TextSearchOperator; +import bio.terra.tanagra.api.shared.*; import bio.terra.tanagra.query.bigquery.translator.field.BQAttributeFieldTranslator; import bio.terra.tanagra.query.bigquery.translator.field.BQCountDistinctFieldTranslator; import bio.terra.tanagra.query.bigquery.translator.field.BQHierarchyIsMemberFieldTranslator; @@ -26,9 +27,12 @@ import bio.terra.tanagra.query.bigquery.translator.filter.BQRelationshipFilterTranslator; import bio.terra.tanagra.query.bigquery.translator.filter.BQTemporalPrimaryFilterTranslator; import bio.terra.tanagra.query.bigquery.translator.filter.BQTextSearchFilterTranslator; +import bio.terra.tanagra.query.sql.*; import bio.terra.tanagra.query.sql.translator.ApiFieldTranslator; import bio.terra.tanagra.query.sql.translator.ApiFilterTranslator; import bio.terra.tanagra.query.sql.translator.ApiTranslator; +import jakarta.annotation.*; +import java.util.*; public final class BQApiTranslator implements ApiTranslator { @Override @@ -116,6 +120,25 @@ public ApiFilterTranslator translator(TemporalPrimaryFilter temporalPrimaryFilte return new BQTemporalPrimaryFilterTranslator(this, temporalPrimaryFilter); } + @Override + public String naryFilterOnRepeatedFieldSql( + SqlField field, + NaryOperator naryOperator, + List values, + @Nullable String tableAlias, + SqlParams sqlParams) { + String functionTemplate = + "EXISTS (SELECT * FROM UNNEST(" + + FUNCTION_TEMPLATE_FIELD_VAR_BRACES + + ") AS flattened WHERE flattened " + + (NaryOperator.IN.equals(naryOperator) ? "IN" : "NOT IN") + + " (" + + FUNCTION_TEMPLATE_VALUES_VAR_BRACES + + "))"; + return functionWithCommaSeparatedArgsFilterSql( + field, functionTemplate, values, tableAlias, sqlParams); + } + @SuppressWarnings("PMD.TooFewBranchesForASwitchStatement") @Override public String textSearchOperatorTemplateSql(TextSearchFilter.TextSearchOperator operator) { diff --git a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/field/BQAttributeFieldTranslator.java b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/field/BQAttributeFieldTranslator.java index a6727ab7b..8e0718e94 100644 --- a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/field/BQAttributeFieldTranslator.java +++ b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/field/BQAttributeFieldTranslator.java @@ -12,6 +12,7 @@ import bio.terra.tanagra.query.sql.translator.ApiFieldTranslator; import bio.terra.tanagra.underlay.entitymodel.Attribute; import bio.terra.tanagra.underlay.indextable.ITEntityMain; +import jakarta.annotation.*; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -34,7 +35,7 @@ public BQAttributeFieldTranslator(AttributeField attributeField) { @Override public List buildSqlFieldsForListSelect() { - return buildSqlFields(true, true); + return buildSqlFields(true, true, false); } public List buildSqlFieldsForCountSelectAndGroupBy( @@ -42,21 +43,39 @@ public List buildSqlFieldsForCountSelectAndGroupBy( return buildSqlFields( true, entityLevelHints == null - || entityLevelHints.getHintInstance(attributeField.getAttribute()).isEmpty()); + || entityLevelHints.getHintInstance(attributeField.getAttribute()).isEmpty(), + true); + } + + public @Nullable String buildSqlJoinTableForCountQuery() { + Attribute attribute = attributeField.getAttribute(); + if (!attribute.isDataTypeRepeated() || attributeField.isAgainstSourceDataset()) { + return null; + } + + SqlField valueField = indexTable.getAttributeValueField(attribute.getName()); + if (attribute.hasRuntimeSqlFunctionWrapper()) { + valueField = valueField.cloneWithFunctionWrapper(attribute.getRuntimeSqlFunctionWrapper()); + } + SqlQueryField valueSqlQueryField = SqlQueryField.of(valueField); + return "CROSS JOIN UNNEST(" + + valueSqlQueryField.renderForSelect() + + ") AS " + + getValueFieldAlias(true); } @Override public List buildSqlFieldsForOrderBy() { - return buildSqlFields(false, true); + return buildSqlFields(false, true, false); } @Override public List buildSqlFieldsForGroupBy() { - return buildSqlFields(true, false); + return buildSqlFields(true, false, true); } private List buildSqlFields( - boolean includeValueField, boolean includeDisplayField) { + boolean includeValueField, boolean includeDisplayField, boolean flattenRepeatedValues) { Attribute attribute = attributeField.getAttribute(); SqlQueryField valueSqlQueryField; @@ -65,12 +84,15 @@ private List buildSqlFields( SqlField valueField = SqlField.of(attribute.getSourceQuery().getValueFieldName()); valueSqlQueryField = SqlQueryField.of(valueField); hasDisplayField = attribute.getSourceQuery().hasDisplayField(); + } else if (attribute.isDataTypeRepeated() && flattenRepeatedValues) { + valueSqlQueryField = SqlQueryField.of(SqlField.of(getValueFieldAlias(true))); + hasDisplayField = false; } else { SqlField valueField = indexTable.getAttributeValueField(attribute.getName()); if (attribute.hasRuntimeSqlFunctionWrapper()) { valueField = valueField.cloneWithFunctionWrapper(attribute.getRuntimeSqlFunctionWrapper()); } - valueSqlQueryField = SqlQueryField.of(valueField, getValueFieldAlias()); + valueSqlQueryField = SqlQueryField.of(valueField, getValueFieldAlias(false)); hasDisplayField = !attribute.isSimple(); } if (!hasDisplayField || attributeField.isExcludeDisplay()) { @@ -92,10 +114,12 @@ private List buildSqlFields( return sqlQueryFields; } - private String getValueFieldAlias() { - return indexTable - .getAttributeValueField(attributeField.getAttribute().getName()) - .getColumnName(); + private String getValueFieldAlias(boolean flattenRepeatedValues) { + String alias = + indexTable.getAttributeValueField(attributeField.getAttribute().getName()).getColumnName(); + return attributeField.getAttribute().isDataTypeRepeated() && flattenRepeatedValues + ? ("FLATTENED_" + alias) + : alias; } private String getDisplayFieldAlias() { @@ -106,21 +130,29 @@ private String getDisplayFieldAlias() { @Override public ValueDisplay parseValueDisplayFromResult(SqlRowResult sqlRowResult) { - Literal valueField = - sqlRowResult.get(getValueFieldAlias(), attributeField.getAttribute().getRuntimeDataType()); - - if (attributeField.getAttribute().isSimple() || attributeField.isExcludeDisplay()) { - return new ValueDisplay(valueField); + if (attributeField.getAttribute().isDataTypeRepeated()) { + List repeatedValueField = + sqlRowResult.getRepeated( + getValueFieldAlias(false), attributeField.getAttribute().getRuntimeDataType()); + return new ValueDisplay(repeatedValueField); } else { - Literal displayField = sqlRowResult.get(getDisplayFieldAlias(), DataType.STRING); - return new ValueDisplay(valueField, displayField.getStringVal()); + Literal valueField = + sqlRowResult.get( + getValueFieldAlias(false), attributeField.getAttribute().getRuntimeDataType()); + if (attributeField.getAttribute().isSimple() || attributeField.isExcludeDisplay()) { + return new ValueDisplay(valueField); + } else { + Literal displayField = sqlRowResult.get(getDisplayFieldAlias(), DataType.STRING); + return new ValueDisplay(valueField, displayField.getStringVal()); + } } } public ValueDisplay parseValueDisplayFromCountResult( SqlRowResult sqlRowResult, HintQueryResult entityLevelHints) { Literal valueField = - sqlRowResult.get(getValueFieldAlias(), attributeField.getAttribute().getRuntimeDataType()); + sqlRowResult.get( + getValueFieldAlias(true), attributeField.getAttribute().getRuntimeDataType()); if (attributeField.getAttribute().isSimple() || attributeField.isExcludeDisplay()) { if (attributeField.isExcludeDisplay()) { diff --git a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/filter/BQAttributeFilterTranslator.java b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/filter/BQAttributeFilterTranslator.java index 033b73e36..2ca11b39f 100644 --- a/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/filter/BQAttributeFilterTranslator.java +++ b/underlay/src/main/java/bio/terra/tanagra/query/bigquery/translator/filter/BQAttributeFilterTranslator.java @@ -1,12 +1,15 @@ package bio.terra.tanagra.query.bigquery.translator.filter; import bio.terra.tanagra.api.filter.AttributeFilter; +import bio.terra.tanagra.api.shared.*; +import bio.terra.tanagra.exception.*; import bio.terra.tanagra.query.sql.SqlField; import bio.terra.tanagra.query.sql.SqlParams; import bio.terra.tanagra.query.sql.translator.ApiFilterTranslator; import bio.terra.tanagra.query.sql.translator.ApiTranslator; import bio.terra.tanagra.underlay.entitymodel.Attribute; import bio.terra.tanagra.underlay.indextable.ITEntityMain; +import jakarta.annotation.*; public class BQAttributeFilterTranslator extends ApiFilterTranslator { private final AttributeFilter attributeFilter; @@ -33,7 +36,31 @@ public String buildSql(SqlParams sqlParams, String tableAlias) { valueField = valueField.cloneWithFunctionWrapper(attribute.getRuntimeSqlFunctionWrapper()); } - if (attributeFilter.hasUnaryOperator()) { + if (attribute.isDataTypeRepeated()) { + boolean naryOperatorIn = + (attributeFilter.hasBinaryOperator() + && BinaryOperator.EQUALS.equals(attributeFilter.getBinaryOperator())) + || (attributeFilter.hasNaryOperator() + && NaryOperator.IN.equals(attributeFilter.getNaryOperator())); + boolean naryOperatorNotIn = + (attributeFilter.hasBinaryOperator() + && BinaryOperator.NOT_EQUALS.equals(attributeFilter.getBinaryOperator())) + || (attributeFilter.hasNaryOperator() + && NaryOperator.NOT_IN.equals(attributeFilter.getNaryOperator())); + if (!naryOperatorIn && !naryOperatorNotIn) { + throw new InvalidQueryException( + "Operator not supported for repeated data type attributes: " + + attributeFilter.getOperatorName() + + ", " + + attribute.getName()); + } + return apiTranslator.naryFilterOnRepeatedFieldSql( + valueField, + naryOperatorIn ? NaryOperator.IN : NaryOperator.NOT_IN, + attributeFilter.getValues(), + tableAlias, + sqlParams); + } else if (attributeFilter.hasUnaryOperator()) { return apiTranslator.unaryFilterSql( valueField, attributeFilter.getUnaryOperator(), tableAlias, sqlParams); } else if (attributeFilter.hasBinaryOperator()) { diff --git a/underlay/src/main/java/bio/terra/tanagra/query/sql/SqlRowResult.java b/underlay/src/main/java/bio/terra/tanagra/query/sql/SqlRowResult.java index 35dd392b2..a9c124e6f 100644 --- a/underlay/src/main/java/bio/terra/tanagra/query/sql/SqlRowResult.java +++ b/underlay/src/main/java/bio/terra/tanagra/query/sql/SqlRowResult.java @@ -2,11 +2,15 @@ import bio.terra.tanagra.api.shared.DataType; import bio.terra.tanagra.api.shared.Literal; +import java.util.*; public interface SqlRowResult { /** Get literal value for the column in this row. */ Literal get(String columnName, DataType expectedDataType); + /** Get literal values for the repeated column in this row. */ + List getRepeated(String columnName, DataType expectedDataType); + /** Return the number of {@link bio.terra.tanagra.api.shared.Literal}s in this row. */ int size(); } diff --git a/underlay/src/main/java/bio/terra/tanagra/query/sql/translator/ApiTranslator.java b/underlay/src/main/java/bio/terra/tanagra/query/sql/translator/ApiTranslator.java index 699937d76..7a0503bd0 100644 --- a/underlay/src/main/java/bio/terra/tanagra/query/sql/translator/ApiTranslator.java +++ b/underlay/src/main/java/bio/terra/tanagra/query/sql/translator/ApiTranslator.java @@ -135,6 +135,13 @@ default String naryFilterSql( } } + String naryFilterOnRepeatedFieldSql( + SqlField field, + NaryOperator naryOperator, + List values, + @Nullable String tableAlias, + SqlParams sqlParams); + default String functionWithCommaSeparatedArgsFilterSql( SqlField field, String functionTemplate, diff --git a/underlay/src/main/java/bio/terra/tanagra/underlay/ColumnSchema.java b/underlay/src/main/java/bio/terra/tanagra/underlay/ColumnSchema.java index 350cb9e22..c950fea02 100644 --- a/underlay/src/main/java/bio/terra/tanagra/underlay/ColumnSchema.java +++ b/underlay/src/main/java/bio/terra/tanagra/underlay/ColumnSchema.java @@ -7,15 +7,22 @@ public class ColumnSchema implements Serializable { private final String columnName; private final DataType dataType; + private final boolean isDataTypeRepeated; private final boolean isRequired; public ColumnSchema(String columnName, DataType dataType) { - this(columnName, dataType, false); + this(columnName, dataType, false, false); } public ColumnSchema(String columnName, DataType dataType, boolean isRequired) { + this(columnName, dataType, false, isRequired); + } + + public ColumnSchema( + String columnName, DataType dataType, boolean isDataTypeRepeated, boolean isRequired) { this.columnName = columnName; this.dataType = dataType; + this.isDataTypeRepeated = isDataTypeRepeated; this.isRequired = isRequired; } @@ -27,6 +34,10 @@ public DataType getDataType() { return dataType; } + public boolean isDataTypeRepeated() { + return isDataTypeRepeated; + } + public boolean isRequired() { return isRequired; } @@ -42,11 +53,12 @@ public boolean equals(Object o) { ColumnSchema that = (ColumnSchema) o; return isRequired == that.isRequired && columnName.equals(that.columnName) - && dataType == that.dataType; + && dataType == that.dataType + && isDataTypeRepeated == that.isDataTypeRepeated; } @Override public int hashCode() { - return Objects.hash(columnName, dataType, isRequired); + return Objects.hash(columnName, dataType, isDataTypeRepeated, isRequired); } } diff --git a/underlay/src/main/java/bio/terra/tanagra/underlay/Underlay.java b/underlay/src/main/java/bio/terra/tanagra/underlay/Underlay.java index 9c0212ef1..2d14ea65f 100644 --- a/underlay/src/main/java/bio/terra/tanagra/underlay/Underlay.java +++ b/underlay/src/main/java/bio/terra/tanagra/underlay/Underlay.java @@ -372,6 +372,7 @@ public static Entity fromConfigEntity(SZEntity szEntity, String primaryEntityNam return new Attribute( szAttribute.name, ConfigReader.deserializeDataType(szAttribute.dataType), + szAttribute.isDataTypeRepeated, szAttribute.displayFieldName != null, szAttribute.name.equals(szEntity.idAttribute), szAttribute.runtimeSqlFunctionWrapper, diff --git a/underlay/src/main/java/bio/terra/tanagra/underlay/entitymodel/Attribute.java b/underlay/src/main/java/bio/terra/tanagra/underlay/entitymodel/Attribute.java index e5cf9ec15..f698fe80a 100644 --- a/underlay/src/main/java/bio/terra/tanagra/underlay/entitymodel/Attribute.java +++ b/underlay/src/main/java/bio/terra/tanagra/underlay/entitymodel/Attribute.java @@ -6,6 +6,7 @@ public final class Attribute { private final String name; private final DataType dataType; + private final boolean isDataTypeRepeated; private final boolean isValueDisplay; private final boolean isId; private final String runtimeSqlFunctionWrapper; @@ -20,6 +21,7 @@ public final class Attribute { public Attribute( String name, DataType dataType, + boolean isDataTypeRepeated, boolean isValueDisplay, boolean isId, String runtimeSqlFunctionWrapper, @@ -31,6 +33,7 @@ public Attribute( SourceQuery sourceQuery) { this.name = name; this.dataType = dataType; + this.isDataTypeRepeated = isDataTypeRepeated; this.isValueDisplay = isValueDisplay; this.isId = isId; this.runtimeSqlFunctionWrapper = runtimeSqlFunctionWrapper; @@ -50,6 +53,10 @@ public DataType getDataType() { return dataType; } + public boolean isDataTypeRepeated() { + return isDataTypeRepeated; + } + public boolean isSimple() { return !isValueDisplay; } @@ -111,6 +118,7 @@ public boolean equals(Object o) { && isVisitIdForTemporalQuery == attribute.isVisitIdForTemporalQuery && name.equals(attribute.name) && dataType == attribute.dataType + && isDataTypeRepeated == attribute.isDataTypeRepeated && Objects.equals(runtimeSqlFunctionWrapper, attribute.runtimeSqlFunctionWrapper) && runtimeDataType == attribute.runtimeDataType && Objects.equals(sourceQuery, attribute.sourceQuery); @@ -121,6 +129,7 @@ public int hashCode() { return Objects.hash( name, dataType, + isDataTypeRepeated, isValueDisplay, isId, runtimeSqlFunctionWrapper, diff --git a/underlay/src/main/java/bio/terra/tanagra/underlay/indextable/ITEntityMain.java b/underlay/src/main/java/bio/terra/tanagra/underlay/indextable/ITEntityMain.java index 9572f4e9a..bb4edef91 100644 --- a/underlay/src/main/java/bio/terra/tanagra/underlay/indextable/ITEntityMain.java +++ b/underlay/src/main/java/bio/terra/tanagra/underlay/indextable/ITEntityMain.java @@ -38,7 +38,10 @@ public ITEntityMain( szAttribute -> { columnSchemasBuilder.add( new ColumnSchema( - szAttribute.name, ConfigReader.deserializeDataType(szAttribute.dataType))); + szAttribute.name, + ConfigReader.deserializeDataType(szAttribute.dataType), + szAttribute.isDataTypeRepeated, + false)); if (szAttribute.displayFieldName != null) { columnSchemasBuilder.add( new ColumnSchema( @@ -107,7 +110,8 @@ public SqlField getAttributeValueField(String attribute) { } public ColumnSchema getAttributeValueColumnSchema(Attribute attribute) { - return new ColumnSchema(attribute.getName(), attribute.getDataType()); + return new ColumnSchema( + attribute.getName(), attribute.getDataType(), attribute.isDataTypeRepeated(), false); } public SqlField getAttributeDisplayField(String attribute) { diff --git a/underlay/src/main/java/bio/terra/tanagra/underlay/serialization/SZAttribute.java b/underlay/src/main/java/bio/terra/tanagra/underlay/serialization/SZAttribute.java index 19aa404fa..54748d802 100644 --- a/underlay/src/main/java/bio/terra/tanagra/underlay/serialization/SZAttribute.java +++ b/underlay/src/main/java/bio/terra/tanagra/underlay/serialization/SZAttribute.java @@ -23,6 +23,13 @@ public class SZAttribute { @AnnotatedField(name = "SZAttribute.dataType", markdown = "Data type of the attribute.") public SZDataType dataType; + @AnnotatedField( + name = "SZAttribute.isDataTypeRepeated", + markdown = "True if the data type is repeated (e.g. an array of ints).", + optional = true, + defaultValue = "false") + public boolean isDataTypeRepeated; + @AnnotatedField( name = "SZAttribute.valueFieldName", markdown = diff --git a/underlay/src/main/java/bio/terra/tanagra/underlay/sourcetable/STEntityAttributes.java b/underlay/src/main/java/bio/terra/tanagra/underlay/sourcetable/STEntityAttributes.java index 0a0635e74..5ea61742c 100644 --- a/underlay/src/main/java/bio/terra/tanagra/underlay/sourcetable/STEntityAttributes.java +++ b/underlay/src/main/java/bio/terra/tanagra/underlay/sourcetable/STEntityAttributes.java @@ -32,7 +32,9 @@ public STEntityAttributes(BQTable bqTable, String entity, List szAt szAttribute.valueFieldName == null ? szAttribute.name : szAttribute.valueFieldName, - ConfigReader.deserializeDataType(szAttribute.dataType))); + ConfigReader.deserializeDataType(szAttribute.dataType), + szAttribute.isDataTypeRepeated, + false)); if (szAttribute.displayFieldName != null) { attributeDisplayColumnSchemasBuilder.put( szAttribute.name, new ColumnSchema(szAttribute.displayFieldName, DataType.STRING)); diff --git a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQCountQueryResultsTest.java b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQCountQueryResultsTest.java index 286eaf8ae..dc1690923 100644 --- a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQCountQueryResultsTest.java +++ b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQCountQueryResultsTest.java @@ -13,8 +13,7 @@ import bio.terra.tanagra.api.field.HierarchyPathField; import bio.terra.tanagra.api.field.RelatedEntityIdCountField; import bio.terra.tanagra.api.field.ValueDisplayField; -import bio.terra.tanagra.api.query.count.CountQueryRequest; -import bio.terra.tanagra.api.query.count.CountQueryResult; +import bio.terra.tanagra.api.query.count.*; import bio.terra.tanagra.api.query.hint.HintInstance; import bio.terra.tanagra.api.query.hint.HintQueryResult; import bio.terra.tanagra.api.shared.DataType; @@ -22,11 +21,9 @@ import bio.terra.tanagra.api.shared.OrderByDirection; import bio.terra.tanagra.api.shared.ValueDisplay; import bio.terra.tanagra.query.bigquery.BQRunnerTest; -import bio.terra.tanagra.underlay.entitymodel.Entity; -import bio.terra.tanagra.underlay.entitymodel.Hierarchy; +import bio.terra.tanagra.underlay.entitymodel.*; import bio.terra.tanagra.underlay.entitymodel.entitygroup.EntityGroup; -import java.util.List; -import java.util.Map; +import java.util.*; import org.junit.jupiter.api.Test; public class BQCountQueryResultsTest extends BQRunnerTest { @@ -115,6 +112,111 @@ void attributeField() { }); } + @Test + void repeatedAttributeField() { + Entity entity = underlay.getEntity("condition"); + + // We don't have an example of an attribute with a repeated data type, yet. + // So create an artificial attribute just for this test. + AttributeField repeatedStringAttribute = + new AttributeField( + underlay, + entity, + new Attribute( + "vocabulary", + DataType.STRING, + true, + false, + false, + "['foo', 'bar', 'baz', ${fieldSql}]", + DataType.STRING, + entity.getAttribute("vocabulary").isComputeDisplayHint(), + entity.getAttribute("vocabulary").isSuppressedForExport(), + entity.getAttribute("vocabulary").isVisitDateForTemporalQuery(), + entity.getAttribute("vocabulary").isVisitIdForTemporalQuery(), + entity.getAttribute("vocabulary").getSourceQuery()), + false); + + List groupBys = List.of(repeatedStringAttribute); + HintQueryResult entityLevelHints = + new HintQueryResult( + "", + List.of( + new HintInstance( + entity.getAttribute("vocabulary"), + Map.of( + new ValueDisplay(Literal.forString("foo")), + 25L, + new ValueDisplay(Literal.forString("bar")), + 140L, + new ValueDisplay(Literal.forString("baz")), + 85L)))); + CountQueryResult countQueryResult = + bqQueryRunner.run( + new CountQueryRequest( + underlay, + entity, + null, + groupBys, + null, + OrderByDirection.DESCENDING, + null, + null, + null, + entityLevelHints, + false)); + + // Check each of the group by fields. + countQueryResult.getCountInstances().stream() + .map(countInstance -> countInstance.getEntityFieldValue(repeatedStringAttribute)) + .forEach( + vocabulary -> { + assertNotNull(vocabulary); + assertTrue( + vocabulary.getValue().isNull() + || DataType.STRING.equals(vocabulary.getValue().getDataType())); + assertFalse(vocabulary.isRepeatedValue()); + assertNotNull(vocabulary.getValue().getStringVal()); + assertNull(vocabulary.getDisplay()); + }); + + // Condition entity should have an enum string-value hint with 4 + 3 values for vocabulary. The + // three fake ones should all have matching counts. + assertEquals(7, countQueryResult.getCountInstances().size()); + Optional fooCount = + countQueryResult.getCountInstances().stream() + .filter( + countInstance -> + countInstance + .getEntityFieldValue(repeatedStringAttribute) + .getValue() + .equals(Literal.forString("foo"))) + .findAny(); + assertTrue(fooCount.isPresent()); + Optional barCount = + countQueryResult.getCountInstances().stream() + .filter( + countInstance -> + countInstance + .getEntityFieldValue(repeatedStringAttribute) + .getValue() + .equals(Literal.forString("bar"))) + .findAny(); + assertTrue(barCount.isPresent()); + Optional bazCount = + countQueryResult.getCountInstances().stream() + .filter( + countInstance -> + countInstance + .getEntityFieldValue(repeatedStringAttribute) + .getValue() + .equals(Literal.forString("baz"))) + .findAny(); + assertTrue(bazCount.isPresent()); + assertTrue(fooCount.get().getCount() == barCount.get().getCount()); + assertTrue(barCount.get().getCount() == bazCount.get().getCount()); + } + @Test void hierarchyFields() { Entity entity = underlay.getEntity("condition"); diff --git a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQHintQueryResultsTest.java b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQHintQueryResultsTest.java index b557f9e2a..74f98ed15 100644 --- a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQHintQueryResultsTest.java +++ b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQHintQueryResultsTest.java @@ -3,8 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import bio.terra.tanagra.api.query.hint.HintQueryRequest; -import bio.terra.tanagra.api.query.hint.HintQueryResult; +import bio.terra.tanagra.api.query.hint.*; import bio.terra.tanagra.api.shared.DataType; import bio.terra.tanagra.api.shared.Literal; import bio.terra.tanagra.query.bigquery.BQRunnerTest; @@ -21,8 +20,42 @@ protected String getServiceConfigName() { } @Test - void entityLevelHint() { - Entity hintedEntity = underlay.getPrimaryEntity(); + void entityLevelHints() { + // Person entity should have range hints for year_of_birth and age (runtime calculated), and an + // enum value-display hint with 3 values for gender. + List hintInstances = checkEntityLevelHints(underlay.getPrimaryEntity()); + assertTrue( + hintInstances.stream() + .anyMatch( + hintInstance -> + hintInstance.getAttribute().getName().equals("year_of_birth") + && hintInstance.isRangeHint())); + assertTrue( + hintInstances.stream() + .anyMatch( + hintInstance -> + hintInstance.getAttribute().getName().equals("age") + && hintInstance.isRangeHint())); + assertTrue( + hintInstances.stream() + .anyMatch( + hintInstance -> + hintInstance.getAttribute().getName().equals("gender") + && hintInstance.isEnumHint() + && hintInstance.getEnumValueCounts().size() == 3)); + + // Brand entity should have an enum string-value hint with 2 values for vocabulary. + hintInstances = checkEntityLevelHints(underlay.getEntity("brand")); + assertTrue( + hintInstances.stream() + .anyMatch( + hintInstance -> + hintInstance.getAttribute().getName().equals("vocabulary") + && hintInstance.isEnumHint() + && hintInstance.getEnumValueCounts().size() == 2)); + } + + private List checkEntityLevelHints(Entity hintedEntity) { HintQueryResult hintQueryResult = bqQueryRunner.run(new HintQueryRequest(underlay, hintedEntity, null, null, null, false)); @@ -43,8 +76,10 @@ void entityLevelHint() { assertTrue(hintInstance.getMin() <= hintInstance.getMax()); } else { // isEnumHint assertTrue( - attribute.isValueDisplay() - || attribute.getRuntimeDataType().equals(DataType.STRING)); + (attribute.isValueDisplay() + && DataType.INT64.equals(attribute.getRuntimeDataType())) + || (attribute.isSimple() + && DataType.STRING.equals(attribute.getRuntimeDataType()))); assertFalse(hintInstance.getEnumValueCounts().isEmpty()); hintInstance .getEnumValueCounts() @@ -58,6 +93,7 @@ void entityLevelHint() { .equals(enumValue.getValue().getDataType()))); } }); + return hintQueryResult.getHintInstances(); } @Test diff --git a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQListQueryResultsTest.java b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQListQueryResultsTest.java index a49b528c3..7d49fe244 100644 --- a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQListQueryResultsTest.java +++ b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/resultparsing/BQListQueryResultsTest.java @@ -20,8 +20,7 @@ import bio.terra.tanagra.api.shared.OrderByDirection; import bio.terra.tanagra.api.shared.ValueDisplay; import bio.terra.tanagra.query.bigquery.BQRunnerTest; -import bio.terra.tanagra.underlay.entitymodel.Entity; -import bio.terra.tanagra.underlay.entitymodel.Hierarchy; +import bio.terra.tanagra.underlay.entitymodel.*; import bio.terra.tanagra.underlay.entitymodel.entitygroup.EntityGroup; import java.util.List; import org.junit.jupiter.api.Test; @@ -41,12 +40,34 @@ void attributeField() { AttributeField idAttribute = new AttributeField(underlay, entity, entity.getIdAttribute(), false); + // We don't have an example of an attribute with a repeated data type, yet. + // So create an artificial attribute just for this test. + AttributeField repeatedStringAttribute = + new AttributeField( + underlay, + entity, + new Attribute( + "person_source_value", + DataType.STRING, + true, + false, + false, + "['foo', 'bar', 'baz', ${fieldSql}]", + DataType.STRING, + entity.getIdAttribute().isComputeDisplayHint(), + entity.getIdAttribute().isSuppressedForExport(), + entity.getIdAttribute().isVisitDateForTemporalQuery(), + entity.getIdAttribute().isVisitIdForTemporalQuery(), + entity.getIdAttribute().getSourceQuery()), + false); + List selectAttributes = List.of( simpleAttribute, valueDisplayAttribute, valueDisplayAttributeWithoutDisplay, - runtimeCalculatedAttribute); + runtimeCalculatedAttribute, + repeatedStringAttribute); List orderBys = List.of(new OrderBy(idAttribute, OrderByDirection.DESCENDING)); int limit = 5; ListQueryResult listQueryResult = @@ -92,6 +113,13 @@ void attributeField() { age.getValue().isNull() || DataType.INT64.equals(age.getValue().getDataType())); assertNotNull(age.getValue().getInt64Val()); assertNull(age.getDisplay()); + + ValueDisplay repeatedString = + listInstance.getEntityFieldValue(repeatedStringAttribute); + assertNotNull(repeatedString); + assertTrue(repeatedString.isRepeatedValue()); + assertNotNull(repeatedString.getRepeatedValue()); + assertEquals(4, repeatedString.getRepeatedValue().size()); }); } diff --git a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/BQCountQueryTest.java b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/BQCountQueryTest.java index 2c30166ab..88ed46ece 100644 --- a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/BQCountQueryTest.java +++ b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/BQCountQueryTest.java @@ -6,10 +6,7 @@ import bio.terra.tanagra.api.query.count.CountQueryResult; import bio.terra.tanagra.api.query.hint.HintInstance; import bio.terra.tanagra.api.query.hint.HintQueryResult; -import bio.terra.tanagra.api.shared.BinaryOperator; -import bio.terra.tanagra.api.shared.Literal; -import bio.terra.tanagra.api.shared.OrderByDirection; -import bio.terra.tanagra.api.shared.ValueDisplay; +import bio.terra.tanagra.api.shared.*; import bio.terra.tanagra.query.bigquery.BQRunnerTest; import bio.terra.tanagra.query.bigquery.BQTable; import bio.terra.tanagra.underlay.entitymodel.Attribute; @@ -156,6 +153,61 @@ void groupByValueDisplayAttribute() throws IOException { "groupByValueDisplayField", countQueryResult.getSql(), entityMainTable); } + @Test + void groupByRepeatedAttribute() throws IOException { + Entity entity = underlay.getEntity("condition"); + + // We don't have an example of an attribute with a repeated data type, yet. + // So create an artificial attribute just for this test. + Attribute groupByAttribute = + new Attribute( + "vocabulary", + DataType.STRING, + true, + false, + false, + "['foo', 'bar', 'baz', ${fieldSql}]", + DataType.STRING, + entity.getAttribute("vocabulary").isComputeDisplayHint(), + entity.getAttribute("vocabulary").isSuppressedForExport(), + entity.getAttribute("vocabulary").isVisitDateForTemporalQuery(), + entity.getAttribute("vocabulary").isVisitIdForTemporalQuery(), + entity.getAttribute("vocabulary").getSourceQuery()); + AttributeField groupByAttributeField = + new AttributeField(underlay, entity, groupByAttribute, false); + HintQueryResult hintQueryResult = + new HintQueryResult( + "", + List.of( + new HintInstance( + groupByAttribute, + Map.of( + new ValueDisplay(Literal.forString("foo")), + 25L, + new ValueDisplay(Literal.forString("bar")), + 140L, + new ValueDisplay(Literal.forString("baz")), + 85L)))); + CountQueryResult countQueryResult = + bqQueryRunner.run( + new CountQueryRequest( + underlay, + entity, + null, + List.of(groupByAttributeField), + null, + OrderByDirection.DESCENDING, + null, + null, + null, + hintQueryResult, + true)); + BQTable entityMainTable = + underlay.getIndexSchema().getEntityMain(entity.getName()).getTablePointer(); + assertSqlMatchesWithTableNameOnly( + "groupByRepeatedAttribute", countQueryResult.getSql(), entityMainTable); + } + @Test void countDistinctAttributeNotId() throws IOException { Entity entity = underlay.getEntity("conditionOccurrence"); diff --git a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/BQFieldTest.java b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/BQFieldTest.java index fc3b0462a..12ba89b06 100644 --- a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/BQFieldTest.java +++ b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/BQFieldTest.java @@ -88,6 +88,7 @@ void attributeFieldAgainstSourceData() throws IOException { new Attribute( "ethnicityNoDisplayJoin", ethnicityAttribute.getDataType(), + ethnicityAttribute.isDataTypeRepeated(), ethnicityAttribute.isValueDisplay(), ethnicityAttribute.isId(), ethnicityAttribute.getRuntimeSqlFunctionWrapper(), @@ -110,6 +111,7 @@ void attributeFieldAgainstSourceData() throws IOException { new Attribute( "genderSuppressed", genderAttribute.getDataType(), + genderAttribute.isDataTypeRepeated(), genderAttribute.isValueDisplay(), genderAttribute.isId(), genderAttribute.getRuntimeSqlFunctionWrapper(), diff --git a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/filter/BQAttributeFilterTest.java b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/filter/BQAttributeFilterTest.java index 8b58e250e..70bf325c9 100644 --- a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/filter/BQAttributeFilterTest.java +++ b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/filter/BQAttributeFilterTest.java @@ -4,10 +4,7 @@ import bio.terra.tanagra.api.filter.AttributeFilter; import bio.terra.tanagra.api.query.list.ListQueryRequest; import bio.terra.tanagra.api.query.list.ListQueryResult; -import bio.terra.tanagra.api.shared.BinaryOperator; -import bio.terra.tanagra.api.shared.Literal; -import bio.terra.tanagra.api.shared.NaryOperator; -import bio.terra.tanagra.api.shared.UnaryOperator; +import bio.terra.tanagra.api.shared.*; import bio.terra.tanagra.query.bigquery.BQRunnerTest; import bio.terra.tanagra.query.bigquery.BQTable; import bio.terra.tanagra.underlay.entitymodel.Attribute; @@ -75,4 +72,58 @@ void attributeFilter() throws IOException { assertSqlMatchesWithTableNameOnly( "attributeFilterNaryBetween", listQueryResult.getSql(), table); } + + @Test + void repeatedAttributeFilter() throws IOException { + Entity entity = underlay.getEntity("condition"); + + // We don't have an example of an attribute with a repeated data type, yet. + // So create an artificial attribute just for this test. + Attribute attribute = + new Attribute( + "vocabulary", + DataType.STRING, + true, + false, + false, + "['foo', 'bar', 'baz', ${fieldSql}]", + DataType.STRING, + entity.getAttribute("vocabulary").isComputeDisplayHint(), + entity.getAttribute("vocabulary").isSuppressedForExport(), + entity.getAttribute("vocabulary").isVisitDateForTemporalQuery(), + entity.getAttribute("vocabulary").isVisitIdForTemporalQuery(), + entity.getAttribute("vocabulary").getSourceQuery()); + + // Filter with binary operator NOT_EQUALS. + AttributeFilter attributeFilter = + new AttributeFilter( + underlay, entity, attribute, BinaryOperator.NOT_EQUALS, Literal.forString("SNOMED")); + AttributeField simpleAttribute = + new AttributeField(underlay, entity, entity.getAttribute("name"), false); + ListQueryResult listQueryResult = + bqQueryRunner.run( + ListQueryRequest.dryRunAgainstIndexData( + underlay, entity, List.of(simpleAttribute), attributeFilter, null, null)); + BQTable table = underlay.getIndexSchema().getEntityMain(entity.getName()).getTablePointer(); + assertSqlMatchesWithTableNameOnly( + "repeatedAttributeFilterBinaryNotEquals", listQueryResult.getSql(), table); + + // Filter with n-ary operator IN. + attributeFilter = + new AttributeFilter( + underlay, + entity, + attribute, + NaryOperator.IN, + List.of( + Literal.forString("bar"), + Literal.forString("ICD9CM"), + Literal.forString("SNOMED"))); + listQueryResult = + bqQueryRunner.run( + ListQueryRequest.dryRunAgainstIndexData( + underlay, entity, List.of(simpleAttribute), attributeFilter, null, null)); + assertSqlMatchesWithTableNameOnly( + "repeatedAttributeFilterNaryIn", listQueryResult.getSql(), table); + } } diff --git a/underlay/src/test/resources/sql/BQAttributeFilterTest/repeatedAttributeFilterBinaryNotEquals.sql b/underlay/src/test/resources/sql/BQAttributeFilterTest/repeatedAttributeFilterBinaryNotEquals.sql new file mode 100644 index 000000000..31b9e744c --- /dev/null +++ b/underlay/src/test/resources/sql/BQAttributeFilterTest/repeatedAttributeFilterBinaryNotEquals.sql @@ -0,0 +1,12 @@ + + SELECT + name + FROM + ${ENT_condition} + WHERE + EXISTS (SELECT + * + FROM + UNNEST(['foo', 'bar', 'baz', vocabulary]) AS flattened + WHERE + flattened NOT IN (@val0)) diff --git a/underlay/src/test/resources/sql/BQAttributeFilterTest/repeatedAttributeFilterNaryIn.sql b/underlay/src/test/resources/sql/BQAttributeFilterTest/repeatedAttributeFilterNaryIn.sql new file mode 100644 index 000000000..741e11d17 --- /dev/null +++ b/underlay/src/test/resources/sql/BQAttributeFilterTest/repeatedAttributeFilterNaryIn.sql @@ -0,0 +1,12 @@ + + SELECT + name + FROM + ${ENT_condition} + WHERE + EXISTS (SELECT + * + FROM + UNNEST(['foo', 'bar', 'baz', vocabulary]) AS flattened + WHERE + flattened IN (@val0, @val1, @val2)) diff --git a/underlay/src/test/resources/sql/BQCountQueryTest/groupByRepeatedAttribute.sql b/underlay/src/test/resources/sql/BQCountQueryTest/groupByRepeatedAttribute.sql new file mode 100644 index 000000000..b28a02293 --- /dev/null +++ b/underlay/src/test/resources/sql/BQCountQueryTest/groupByRepeatedAttribute.sql @@ -0,0 +1,12 @@ + + SELECT + COUNT(id) AS T_CTDT, + FLATTENED_vocabulary + FROM + ${ENT_condition} + CROSS JOIN + UNNEST(['foo', 'bar', 'baz', vocabulary]) AS FLATTENED_vocabulary + GROUP BY + FLATTENED_vocabulary + ORDER BY + T_CTDT DESC From 6401fc07f5cd238fdafcdde57f25e0e33ef7fb5b Mon Sep 17 00:00:00 2001 From: bumptagbot Date: Fri, 13 Sep 2024 12:52:22 +0000 Subject: [PATCH 02/12] bump 0.0.609 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 24a9f7e6f..dfe5606c6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,4 @@ gradle.ext { } // This line needs to match the VERSION_LINE_MATCH regex in the bump-tag-publish GHA. -gradle.ext.tanagraVersion = "0.0.608-SNAPSHOT" +gradle.ext.tanagraVersion = "0.0.609-SNAPSHOT" From 3b9ed7ae9d12d0dba3ad1d0f5655cfd168e2f420 Mon Sep 17 00:00:00 2001 From: marikomedlock Date: Fri, 13 Sep 2024 09:17:29 -0400 Subject: [PATCH 03/12] Variant search config. (#995) * Attribute isRepeated flag. ValidateDataTypes indexing job. * CreateEntityMainn indexing job. * WriteEntityLevelDisplayHints indexing job. * WriteTextSearchField indexing job. * Select repeated attr field. Result parsing test list query. * Fetch string-only hints. Result parsing test hint query. * Group by repeated attribute field. Sql building and results parsing tests count query. * Filter on repeated attribute field. Sql building test list query. * Only use FLATTENED alias for repeated attribute field. * OpenAPI repeated type in ValueDisplay. Bug in returning hint query results. * Remove variant config files. * Regenerate docs. * Check actual data rows in result parsing hint & count query tests. * Fix overlapping conditional in eldh indexing job. * Variant search config -- first pass. * Use t_item_count in criteria selector. * Put back rest of underlay. * Add multi-select for variant entity. * Revert whitespace changes. * Always populate repeatedValue property of ValueDisplay in OpenAPI. * Move variant config to testonly version of aouSC underlay. * Move variant config files into separate directories. --------- Co-authored-by: Dexter Amundsen --- .../criteriaselector/variant/selector.json | 15 ++ .../criteriaselector/variant/variant.json | 55 +++++ .../aouCT_testonly/entity/variant/all.sql | 12 ++ .../aouCT_testonly/entity/variant/entity.json | 22 ++ .../variantPerson/entityGroup.json | 8 + .../entitygroup/variantPerson/idPairs.sql | 6 + .../config/indexer/aouSC2023Q3R2_verily.json | 2 +- .../config/service/aouSC2023Q3R2_verily.json | 2 +- .../underlay/aouSC2023Q3R2_testonly/ui.json | 164 +++++++++++++++ .../aouSC2023Q3R2_testonly/underlay.json | 191 ++++++++++++++++++ 10 files changed, 475 insertions(+), 2 deletions(-) create mode 100644 underlay/src/main/resources/config/criteria/aouSC2023Q3R2_testonly/criteriaselector/variant/selector.json create mode 100644 underlay/src/main/resources/config/criteria/aouSC2023Q3R2_testonly/criteriaselector/variant/variant.json create mode 100644 underlay/src/main/resources/config/datamapping/aouCT_testonly/entity/variant/all.sql create mode 100644 underlay/src/main/resources/config/datamapping/aouCT_testonly/entity/variant/entity.json create mode 100644 underlay/src/main/resources/config/datamapping/aouCT_testonly/entitygroup/variantPerson/entityGroup.json create mode 100644 underlay/src/main/resources/config/datamapping/aouCT_testonly/entitygroup/variantPerson/idPairs.sql create mode 100644 underlay/src/main/resources/config/underlay/aouSC2023Q3R2_testonly/ui.json create mode 100644 underlay/src/main/resources/config/underlay/aouSC2023Q3R2_testonly/underlay.json diff --git a/underlay/src/main/resources/config/criteria/aouSC2023Q3R2_testonly/criteriaselector/variant/selector.json b/underlay/src/main/resources/config/criteria/aouSC2023Q3R2_testonly/criteriaselector/variant/selector.json new file mode 100644 index 000000000..902c96261 --- /dev/null +++ b/underlay/src/main/resources/config/criteria/aouSC2023Q3R2_testonly/criteriaselector/variant/selector.json @@ -0,0 +1,15 @@ +{ + "name": "tanagra-variant", + "displayName": "SNP/Indel Variant", + "isEnabledForCohorts": true, + "isEnabledForDataFeatureSets": false, + "display": { + "category": "Genomics", + "tags": null + }, + "filterBuilder": "core.EntityGroupFilterBuilder", + "plugin": "entityGroup", + "pluginConfig": null, + "pluginConfigFile": "variant.json", + "modifiers": null +} \ No newline at end of file diff --git a/underlay/src/main/resources/config/criteria/aouSC2023Q3R2_testonly/criteriaselector/variant/variant.json b/underlay/src/main/resources/config/criteria/aouSC2023Q3R2_testonly/criteriaselector/variant/variant.json new file mode 100644 index 000000000..5b7f13a58 --- /dev/null +++ b/underlay/src/main/resources/config/criteria/aouSC2023Q3R2_testonly/criteriaselector/variant/variant.json @@ -0,0 +1,55 @@ +{ + "columns": [ + { + "key": "variant_id", + "widthString": "20%", + "title": "Variant id" + }, + { + "key": "gene", + "widthDouble": 100, + "title": "Gene" + }, + { + "key": "rs_number", + "widthDouble": 100, + "title": "RS Number" + }, + { + "key": "genomic_location", + "widthDouble": 100, + "title": "Genomic Location" + }, + { + "key": "protein_change", + "widthDouble": 100, + "title": "Protein Change" + }, + { + "key": "allele_count", + "widthDouble": 100, + "title": "Allele Count" + }, + { + "key": "allele_number", + "widthDouble": 100, + "title": "Allele Number" + }, + { + "key": "allele_frequency", + "widthDouble": 100, + "title": "Allele Frequency" + }, + { + "key": "t_item_count", + "widthDouble": 150, + "title": "Participant count" + } + ], + "classificationEntityGroups": [ + { + "id": "variantPerson" + } + ], + "multiSelect": true +} \ No newline at end of file diff --git a/underlay/src/main/resources/config/datamapping/aouCT_testonly/entity/variant/all.sql b/underlay/src/main/resources/config/datamapping/aouCT_testonly/entity/variant/all.sql new file mode 100644 index 000000000..1040eecf5 --- /dev/null +++ b/underlay/src/main/resources/config/datamapping/aouCT_testonly/entity/variant/all.sql @@ -0,0 +1,12 @@ +SELECT ROW_NUMBER() OVER (ORDER BY vid) AS row_num, + vid, + gene_symbol, + dbsnp_rsid, + genomic_location, + consequence, + aa_change, + clinvar_classification, + gvs_all_ac, + gvs_all_an, + gvs_all_af +FROM `${omopDataset}.prep_vat` diff --git a/underlay/src/main/resources/config/datamapping/aouCT_testonly/entity/variant/entity.json b/underlay/src/main/resources/config/datamapping/aouCT_testonly/entity/variant/entity.json new file mode 100644 index 000000000..0792992cb --- /dev/null +++ b/underlay/src/main/resources/config/datamapping/aouCT_testonly/entity/variant/entity.json @@ -0,0 +1,22 @@ +{ + "name": "variant", + "allInstancesSqlFile": "all.sql", + "attributes": [ + { "name": "id", "dataType": "INT64", "valueFieldName": "row_num" }, + { "name": "variant_id", "dataType": "STRING", "valueFieldName": "vid" }, + { "name": "gene", "dataType": "STRING", "valueFieldName": "gene_symbol", "isComputeDisplayHint": true }, + { "name": "rs_number", "dataType": "STRING", "isDataTypeRepeated": true, "valueFieldName": "dbsnp_rsid" }, + { "name": "genomic_location", "dataType": "STRING" }, + { "name": "consequence", "dataType": "STRING", "isDataTypeRepeated": true, "isComputeDisplayHint": true }, + { "name": "protein_change", "dataType": "STRING", "valueFieldName": "aa_change" }, + { "name": "clinvar_significance", "dataType": "STRING", "isDataTypeRepeated": true, "valueFieldName": "clinvar_classification", "isComputeDisplayHint": true }, + { "name": "allele_count", "dataType": "INT64", "valueFieldName": "gvs_all_ac", "isComputeDisplayHint": true }, + { "name": "allele_number", "dataType": "INT64", "valueFieldName": "gvs_all_an", "isComputeDisplayHint": true }, + { "name": "allele_frequency", "dataType": "DOUBLE", "valueFieldName": "gvs_all_af", "isComputeDisplayHint": true } + ], + "idAttribute": "id", + "textSearch": { + "attributes": [ "variant_id", "gene", "rs_number", "genomic_location" ] + }, + "optimizeGroupByAttributes": [ "variant_id" ] +} \ No newline at end of file diff --git a/underlay/src/main/resources/config/datamapping/aouCT_testonly/entitygroup/variantPerson/entityGroup.json b/underlay/src/main/resources/config/datamapping/aouCT_testonly/entitygroup/variantPerson/entityGroup.json new file mode 100644 index 000000000..232dab05d --- /dev/null +++ b/underlay/src/main/resources/config/datamapping/aouCT_testonly/entitygroup/variantPerson/entityGroup.json @@ -0,0 +1,8 @@ +{ + "name": "variantPerson", + "groupEntity": "variant", + "itemsEntity": "person", + "idPairsSqlFile": "idPairs.sql", + "groupEntityIdFieldName": "variant_row_num", + "itemsEntityIdFieldName": "flattened_person_id" +} diff --git a/underlay/src/main/resources/config/datamapping/aouCT_testonly/entitygroup/variantPerson/idPairs.sql b/underlay/src/main/resources/config/datamapping/aouCT_testonly/entitygroup/variantPerson/idPairs.sql new file mode 100644 index 000000000..418cfc020 --- /dev/null +++ b/underlay/src/main/resources/config/datamapping/aouCT_testonly/entitygroup/variantPerson/idPairs.sql @@ -0,0 +1,6 @@ +SELECT v.variant_row_num, flattened_person_id +FROM `${omopDataset}.variant_to_person` AS vtop +JOIN + (SELECT ROW_NUMBER() OVER (ORDER BY vid) AS variant_row_num, vid FROM `${omopDataset}.prep_vat`) + AS v ON v.vid = vtop.vid +CROSS JOIN UNNEST(vtop.person_ids) AS flattened_person_id diff --git a/underlay/src/main/resources/config/indexer/aouSC2023Q3R2_verily.json b/underlay/src/main/resources/config/indexer/aouSC2023Q3R2_verily.json index bed2c6930..d1b822423 100644 --- a/underlay/src/main/resources/config/indexer/aouSC2023Q3R2_verily.json +++ b/underlay/src/main/resources/config/indexer/aouSC2023Q3R2_verily.json @@ -1,5 +1,5 @@ { - "underlay": "aouSC2023Q3R2", + "underlay": "aouSC2023Q3R2_testonly", "bigQuery": { "sourceData": { "projectId": "verily-tanagra-dev", diff --git a/underlay/src/main/resources/config/service/aouSC2023Q3R2_verily.json b/underlay/src/main/resources/config/service/aouSC2023Q3R2_verily.json index c74b5e517..e1b4108b1 100644 --- a/underlay/src/main/resources/config/service/aouSC2023Q3R2_verily.json +++ b/underlay/src/main/resources/config/service/aouSC2023Q3R2_verily.json @@ -1,5 +1,5 @@ { - "underlay": "aouSC2023Q3R2", + "underlay": "aouSC2023Q3R2_testonly", "bigQuery": { "sourceData": { "projectId": "verily-tanagra-dev", diff --git a/underlay/src/main/resources/config/underlay/aouSC2023Q3R2_testonly/ui.json b/underlay/src/main/resources/config/underlay/aouSC2023Q3R2_testonly/ui.json new file mode 100644 index 000000000..a69a340ed --- /dev/null +++ b/underlay/src/main/resources/config/underlay/aouSC2023Q3R2_testonly/ui.json @@ -0,0 +1,164 @@ +{ + "featureConfig": { + "overrideExportButton": true + }, + "demographicChartConfigs": { + "groupByAttributes": ["gender", "race", "age"], + "chartConfigs": [ + { + "title": "Gender identity", + "primaryProperties": [{ "key": "gender" }] + }, + { + "title": "Gender identity, Current age, Race", + "primaryProperties": [ + { "key": "gender" }, + { + "key": "age", + "buckets": [ + { + "min": 18, + "max": 45, + "displayName": "18-44" + }, + { + "min": 45, + "max": 65, + "displayName": "45-64" + }, + { + "min": 65, + "displayName": "65+" + } + ] + } + ], + "stackedProperty": { "key": "race" } + } + ] + }, + "criteriaSearchConfig": { + "criteriaTypeWidth": 120, + "columns": [ + { "key": "name", "width": "100%", "title": "Name" }, + { "key": "vocabulary_t_value", "width": 120, "title": "Vocab" }, + { "key": "concept_code", "width": 120, "title": "Code" }, + { "key": "t_rollup_count", "width": 150, "title": "Roll-up Count" } + ] + }, + "cohortReviewConfig": { + "participantsListColumns": [ + { "key": "id", "width": 35, "title": "Id" }, + { "key": "age", "width": 25, "title": "Age" }, + { "key": "gender", "width": 30, "title": "Gender" }, + { "key": "sex_at_birth", "width": 40, "title": "Sex at Birth" }, + { "key": "race", "width": 60, "title": "Race" }, + { "key": "ethnicity", "width": 60, "title": "Ethnicity" } + ], + "attributes": [ + { + "title": "Gender", + "key": "gender" + }, + { + "title": "Sex at Birth", + "key": "sex_at_birth" + }, + { + "title": "Age", + "key": "age" + }, + { + "title": "Race", + "key": "race" + }, + { + "title": "Ethnicity", + "key": "ethnicity" + } + ], + "pages": [ + { + "type": "entityTable", + "id": "condition", + "title": "Conditions", + "plugin": { + "entity": "conditionOccurrence", + "columns": [ + { "key": "condition_start_datetime", "width": "10%", "title": "Start date", "sortable": true }, + { "key": "standard_concept_code", "width": "15%", "title": "Standard Code", "sortable": true, "filterable": true }, + { "key": "standard_vocabulary", "width": "15%", "title": "Standard Vocabulary", "sortable": true, "filterable": true }, + { "key": "standard_concept_name", "width": "30%", "title": "Condition name", "sortable": true, "filterable": true }, + { "key": "age_at_occurrence", "width": "15%", "title": "Age at Occurrence", "sortable": true }, + { "key": "visit_type", "width": "15%", "title": "Visit Type", "sortable": true } + ] + } + }, + { + "type": "entityTable", + "id": "procedure", + "title": "Procedures", + "plugin": { + "entity": "procedureOccurrence", + "columns": [ + { "key": "procedure_datetime", "width": "10%", "title": "Date", "sortable": true, "filterable": true }, + { "key": "standard_concept_code", "width": "15%", "title": "Standard Code", "sortable": true, "filterable": true }, + { "key": "standard_vocabulary", "width": "15%", "title": "Standard Vocabulary", "sortable": true, "filterable": true }, + { "key": "standard_concept_name", "width": "30%", "title": "Procedure Name", "sortable": true, "filterable": true }, + { "key": "age_at_occurrence", "width": "15%", "title": "Age at Occurrence", "sortable": true, "filterable": true }, + { "key": "visit_type", "width": "15%", "title": "Visit Type", "sortable": true, "filterable": true } + ] + } + }, + { + "type": "entityTable", + "id": "observation", + "title": "Observations", + "plugin": { + "entity": "observationOccurrence", + "columns": [ + { "key": "observation_datetime", "width": "10%", "title": "Date", "sortable": true, "filterable": true }, + { "key": "standard_concept_code", "width": "15%", "title": "Standard Code", "sortable": true, "filterable": true }, + { "key": "standard_vocabulary", "width": "15%", "title": "Standard Vocabulary", "sortable": true, "filterable": true }, + { "key": "standard_concept_name", "width": "30%", "title": "Observation Name", "sortable": true, "filterable": true }, + { "key": "age_at_occurrence", "width": "15%", "title": "Age at Occurrence", "sortable": true, "filterable": true }, + { "key": "visit_type", "width": "15%", "title": "Visit Type", "sortable": true, "filterable": true } + ] + } + }, + { + "type": "entityTable", + "id": "ingredient", + "title": "Drugs", + "plugin": { + "entity": "ingredientOccurrence", + "columns": [ + { "key": "drug_exposure_start_datetime", "width": "10%", "title": "Date", "sortable": true, "filterable": true }, + { "key": "standard_concept_code", "width": "15%", "title": "Standard Code", "sortable": true, "filterable": true }, + { "key": "standard_vocabulary", "width": "15%", "title": "Standard Vocabulary", "sortable": true, "filterable": true }, + { "key": "standard_concept_name", "width": "30%", "title": "Drug Name", "sortable": true, "filterable": true }, + { "key": "age_at_occurrence", "width": "15%", "title": "Age at Occurrence", "sortable": true, "filterable": true }, + { "key": "visit_type", "width": "15%", "title": "Visit Type", "sortable": true, "filterable": true } + ] + } + }, + { + "type": "entityTable", + "id": "measurements", + "title": "Labs and measurements", + "plugin": { + "entity": "measurementOccurrence", + "columns": [ + { "key": "measurement_datetime", "width": "10%", "title": "Date", "sortable": true, "filterable": true }, + { "key": "standard_concept_name", "width": "25%", "title": "Lab/measurement Name", "sortable": true, "filterable": true }, + { "key": "value_enum", "width": "15%", "title": "Categorical value", "sortable": true, "filterable": true }, + { "key": "value_numeric", "width": "15%", "title": "Numeric value", "sortable": true, "filterable": true }, + { "key": "unit_concept_name", "width": "10%", "title": "Unit", "sortable": true, "filterable": true }, + { "key": "age_at_occurrence", "width": "10%", "title": "Age at Occurrence", "sortable": true, "filterable": true }, + { "key": "visit_type", "width": "15%", "title": "Visit Type", "sortable": true, "filterable": true } + ] + } + } + ] + } +} diff --git a/underlay/src/main/resources/config/underlay/aouSC2023Q3R2_testonly/underlay.json b/underlay/src/main/resources/config/underlay/aouSC2023Q3R2_testonly/underlay.json new file mode 100644 index 000000000..7a5645bad --- /dev/null +++ b/underlay/src/main/resources/config/underlay/aouSC2023Q3R2_testonly/underlay.json @@ -0,0 +1,191 @@ +{ + "name": "aouSC2023Q3R2_testonly", + "primaryEntity": "person", + "entities": [ + "aouCT/person", + + "aouRT/conditionConcept", + "aouRT/conditionOccurrence", + "aouRT/conditionNonHierarchyConcept", + "aouRT/procedureConcept", + "aouRT/procedureOccurrence", + "aouRT/procedureNonHierarchyConcept", + + "aouRT/brandConcept", + "aouRT/ingredientConcept", + "aouRT/ingredientOccurrence", + "aouRT/ingredientNonHierarchyConcept", + + "aouRT/measurementSnomedConcept", + "aouRT/measurementLoincConcept", + "aouRT/measurementNonHierarchyConcept", + "aouRT/measurementOccurrence", + + "aouRT/observationConcept", + "aouRT/observationOccurrence", + "aouRT/deviceConcept", + "aouRT/deviceOccurrence", + "aouRT/visitConcept", + "aouRT/visitOccurrence", + + "aouRT/cpt4Concept", + "aouRT/icd9cmConcept", + "aouRT/icd9procConcept", + "aouRT/icd10cmConcept", + "aouRT/icd10pcsConcept", + + "aouRT/activitySummary", + "aouRT/heartRateLevel", + "aouRT/heartRateSummary", + "aouRT/sleepDailySummary", + "aouRT/sleepLevel", + "aouRT/stepsIntraday", + "aouCT/zipcodeSocioeconomic", + + "aouRT/bloodPressure", + "aouRT/heartRate", + "aouRT/height", + "aouRT/weight", + "aouRT/bmi", + "aouRT/waistCircumference", + "aouRT/hipCircumference", + + "aouRT/surveyBasics", + "aouRT/surveyLifestyle", + "aouRT/surveyOverallHealth", + "aouRT/surveyPersonalAndFamilyHealth", + "aouRT/surveyHealthCareAccess", + "aouRT/surveySocialDeterminantsOfHealth", + "aouRT/surveyOccurrence", + + "aouCT_testonly/variant" + ], + "groupItemsEntityGroups": [ + "aouRT/brandIngredientConcept", + + "aouRT/activitySummaryPerson", + "aouRT/heartRateLevelPerson", + "aouRT/heartRateSummaryPerson", + "aouRT/sleepDailySummaryPerson", + "aouRT/sleepLevelPerson", + "aouRT/stepsIntradayPerson", + "aouCT/zipcodeSocioeconomicPerson", + + "aouRT/bloodPressurePerson", + "aouRT/heartRatePerson", + "aouRT/heightPerson", + "aouRT/weightPerson", + "aouRT/bmiPerson", + "aouRT/waistCircumferencePerson", + "aouRT/hipCircumferencePerson", + + "aouCT_testonly/variantPerson" + ], + "criteriaOccurrenceEntityGroups": [ + "aouRT/conditionPerson", + "aouRT/conditionNonHierarchyPerson", + + "aouRT/procedurePerson", + + "aouRT/ingredientPerson", + "aouRT/ingredientNonHierarchyPerson", + + "aouRT/measurementSnomedPerson", + "aouRT/measurementLoincPerson", + "aouRT/measurementNonHierarchyPerson", + "aouRT/procedureNonHierarchyPerson", + + "aouRT/observationPerson", + "aouRT/devicePerson", + "aouRT/visitPerson", + + "aouRT/cpt4Person", + "aouRT/icd9cmPerson", + "aouRT/icd9procPerson", + "aouRT/icd10cmPerson", + "aouRT/icd10pcsPerson", + + "aouRT/surveyBasicsPerson", + "aouRT/surveyLifestylePerson", + "aouRT/surveyOverallHealthPerson", + "aouRT/surveyPersonalAndFamilyHealthPerson", + "aouRT/surveyHealthCareAccessPerson", + "aouRT/surveySocialDeterminantsOfHealthPerson" + ], + "criteriaSelectors": [ + "aouSR2023Q3R2/conditions", + "aouSR2023Q3R2/procedures", + "aouSR2023Q3R2/observations", + "aouSR2023Q3R2/drugs", + "aouSR2023Q3R2/measurement", + "aouSR2023Q3R2/visits", + "aouSR2023Q3R2/devices", + "aouSR2023Q3R2/hasEHRData", + "aouSR2023Q3R2/cpt4", + "aouSR2023Q3R2/icd9CM", + "aouSR2023Q3R2/icd9Proc", + "aouSR2023Q3R2/icd10CM", + "aouSR2023Q3R2/icd10PCS", + "aouSR2023Q3R2/age", + "aouSR2023Q3R2/isDeceased", + "aouSR2023Q3R2/ethnicity", + "aouSR2023Q3R2/gender", + "aouSR2023Q3R2/race", + "aouSR2023Q3R2/sexAtBirth", + "aouSR2023Q3R2/fitbit", + "aouSR2023Q3R2/fitbitActivitySummary", + "aouSR2023Q3R2/fitbitStepsIntraday", + "aouSR2023Q3R2/fitbitHeartRateLevel", + "aouSR2023Q3R2/fitbitHeartRateSummary", + "aouSR2023Q3R2/fitbitSleepDailySummary", + "aouSR2023Q3R2/fitbitSleepLevel", + "aouSR2023Q3R2/wearConsent", + "aouSC2023Q3R2/shortReadWGS", + "aouSC2023Q3R2/longReadWGS", + "aouSC2023Q3R2/globalDiversityArray", + "aouSC2023Q3R2/structuralVariants", + "aouSC2023Q3R2_testonly/variant", + "aouSR2023Q3R2/bloodPressure", + "aouSR2023Q3R2/heartRate", + "aouSR2023Q3R2/height", + "aouSR2023Q3R2/weight", + "aouSR2023Q3R2/bmi", + "aouSR2023Q3R2/waistCircumference", + "aouSR2023Q3R2/hipCircumference", + "aouSR2023Q3R2/outputUnfiltered", + "aouSR2023Q3R2/surveyBasics", + "aouSR2023Q3R2/surveyLifestyle", + "aouSR2023Q3R2/surveyOverallHealth", + "aouSR2023Q3R2/surveyPersonalAndFamilyHealth", + "aouSR2023Q3R2/surveyHealthCareAccess", + "aouSR2023Q3R2/surveySocialDeterminantsOfHealth" + ], + "prepackagedDataFeatures": [ + "aouSR2023Q3R2/_demographics", + "aouSR2023Q3R2/_fitbit_actvity_summary_id", + "aouSR2023Q3R2/_fitbit_steps_intraday_id", + "aouSR2023Q3R2/_fitbit_heart_rate_summary_id", + "aouSR2023Q3R2/_fitbit_heart_rate_level_id", + "aouSR2023Q3R2/_fitbit_sleep_daily_summary_id", + "aouSR2023Q3R2/_fitbit_sleep_level_id", + "aouSC2023Q3R2/_zipcode_socioeconomic_id" + ], + "visualizations": [ + "omop/genderAndAge", + "omop/raceAndAge", + "aou/sexAtBirthAndAge", + "omop/age", + "omop/race", + "omop/gender", + "aou/sexAtBirth", + "omop/topConditions", + "omop/topProcedures", + "omop/topIngredients", + "omop/topMeasurements" + ], + "metadata": { + "displayName": "All Of Us Synthetic Dataset Controlled Tier", + "description": "SC2023Q3R2" + }, + "uiConfigFile": "ui.json" +} From 4b66bb5070bd18bd4c5b4ec9f38ce129f5c1dc3f Mon Sep 17 00:00:00 2001 From: bumptagbot Date: Fri, 13 Sep 2024 13:17:52 +0000 Subject: [PATCH 04/12] bump 0.0.610 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index dfe5606c6..f1d7b0220 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,4 @@ gradle.ext { } // This line needs to match the VERSION_LINE_MATCH regex in the bump-tag-publish GHA. -gradle.ext.tanagraVersion = "0.0.609-SNAPSHOT" +gradle.ext.tanagraVersion = "0.0.610-SNAPSHOT" From c29f1ebdd08d0479d6c360fe7f43908dda704fd6 Mon Sep 17 00:00:00 2001 From: marikomedlock Date: Fri, 13 Sep 2024 12:48:03 -0400 Subject: [PATCH 05/12] Boolean not filter missing parentheses. (#1003) --- .../query/sql/translator/ApiTranslator.java | 2 +- .../filter/BQBooleanLogicFilterTest.java | 33 +++++++++++++++++++ .../tanagra/query/sql/ApiTranslatorTest.java | 2 +- .../booleanNotFilter.sql | 2 +- ...eanNotFilterWithNestedBooleanAndFilter.sql | 8 +++++ .../booleanNotFilterWithSwapFields.sql | 4 +-- 6 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilterWithNestedBooleanAndFilter.sql diff --git a/underlay/src/main/java/bio/terra/tanagra/query/sql/translator/ApiTranslator.java b/underlay/src/main/java/bio/terra/tanagra/query/sql/translator/ApiTranslator.java index 7a0503bd0..6c824e30d 100644 --- a/underlay/src/main/java/bio/terra/tanagra/query/sql/translator/ApiTranslator.java +++ b/underlay/src/main/java/bio/terra/tanagra/query/sql/translator/ApiTranslator.java @@ -228,7 +228,7 @@ default String booleanAndOrFilterSql( } default String booleanNotFilterSql(String subFilterSql) { - return "NOT " + subFilterSql; + return "NOT (" + subFilterSql + ")"; } default String logicalOperatorSql(BooleanAndOrFilter.LogicalOperator operator) { diff --git a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/filter/BQBooleanLogicFilterTest.java b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/filter/BQBooleanLogicFilterTest.java index 54c5f5bea..a30b5cda5 100644 --- a/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/filter/BQBooleanLogicFilterTest.java +++ b/underlay/src/test/java/bio/terra/tanagra/query/bigquery/sqlbuilding/filter/BQBooleanLogicFilterTest.java @@ -63,6 +63,39 @@ void booleanNotFilter() throws IOException { assertSqlMatchesWithTableNameOnly("booleanNotFilter", listQueryResult.getSql(), table); } + @Test + void booleanNotFilterWithNestedBooleanAndFilter() throws IOException { + Entity entity = underlay.getPrimaryEntity(); + AttributeFilter attributeFilter1 = + new AttributeFilter( + underlay, + entity, + entity.getAttribute("year_of_birth"), + BinaryOperator.NOT_EQUALS, + Literal.forInt64(1_956L)); + AttributeFilter attributeFilter2 = + new AttributeFilter( + underlay, + entity, + entity.getAttribute("gender"), + BinaryOperator.EQUALS, + Literal.forInt64(8_532L)); + BooleanNotFilter booleanNotFilter = + new BooleanNotFilter( + new BooleanAndOrFilter( + BooleanAndOrFilter.LogicalOperator.AND, + List.of(attributeFilter1, attributeFilter2))); + AttributeField simpleAttribute = + new AttributeField(underlay, entity, entity.getAttribute("year_of_birth"), false); + ListQueryResult listQueryResult = + bqQueryRunner.run( + ListQueryRequest.dryRunAgainstIndexData( + underlay, entity, List.of(simpleAttribute), booleanNotFilter, null, null)); + BQTable table = underlay.getIndexSchema().getEntityMain(entity.getName()).getTablePointer(); + assertSqlMatchesWithTableNameOnly( + "booleanNotFilterWithNestedBooleanAndFilter", listQueryResult.getSql(), table); + } + @Test void booleanAndOrFilterWithSwapFields() throws IOException { // e.g. SELECT occurrence BOOLEAN LOGIC FILTER ON condition (foreign key is on the occurrence diff --git a/underlay/src/test/java/bio/terra/tanagra/query/sql/ApiTranslatorTest.java b/underlay/src/test/java/bio/terra/tanagra/query/sql/ApiTranslatorTest.java index 41b5e369d..724a25609 100644 --- a/underlay/src/test/java/bio/terra/tanagra/query/sql/ApiTranslatorTest.java +++ b/underlay/src/test/java/bio/terra/tanagra/query/sql/ApiTranslatorTest.java @@ -259,7 +259,7 @@ void booleanNotFilter() { apiTranslator.binaryFilterSql( field, BinaryOperator.LESS_THAN_OR_EQUAL, val, tableAlias, sqlParams); String sql = apiTranslator.booleanNotFilterSql(subFilterSql); - assertEquals("NOT tableAlias.columnName <= @val0", sql); + assertEquals("NOT (tableAlias.columnName <= @val0)", sql); assertEquals(ImmutableMap.of("val0", val), sqlParams.getParams()); } diff --git a/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilter.sql b/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilter.sql index d43c03989..3bc73235c 100644 --- a/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilter.sql +++ b/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilter.sql @@ -4,4 +4,4 @@ FROM ${ENT_person} WHERE - NOT year_of_birth != @val0 + NOT (year_of_birth != @val0) diff --git a/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilterWithNestedBooleanAndFilter.sql b/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilterWithNestedBooleanAndFilter.sql new file mode 100644 index 000000000..82b40f1bb --- /dev/null +++ b/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilterWithNestedBooleanAndFilter.sql @@ -0,0 +1,8 @@ + + SELECT + year_of_birth + FROM + ${ENT_person} + WHERE + NOT ((year_of_birth != @val0) + AND (gender = @val1)) diff --git a/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilterWithSwapFields.sql b/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilterWithSwapFields.sql index d75c35bba..21afc1c31 100644 --- a/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilterWithSwapFields.sql +++ b/underlay/src/test/resources/sql/BQBooleanLogicFilterTest/booleanNotFilterWithSwapFields.sql @@ -4,7 +4,7 @@ FROM ${ENT_conditionOccurrence} WHERE - NOT condition IN (SELECT + NOT (condition IN (SELECT descendant FROM ${HAD_condition_default} @@ -12,4 +12,4 @@ ancestor = @val0 UNION ALL SELECT - @val1) + @val1)) From 0d04504921fffabde47c2a37c5c6441257a77588 Mon Sep 17 00:00:00 2001 From: bumptagbot Date: Fri, 13 Sep 2024 16:48:21 +0000 Subject: [PATCH 06/12] bump 0.0.611 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index f1d7b0220..eaedefddd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,4 @@ gradle.ext { } // This line needs to match the VERSION_LINE_MATCH regex in the bump-tag-publish GHA. -gradle.ext.tanagraVersion = "0.0.610-SNAPSHOT" +gradle.ext.tanagraVersion = "0.0.611-SNAPSHOT" From 675653f895b2659bfca005ca96aa29e0f449e312 Mon Sep 17 00:00:00 2001 From: Dexter Amundsen Date: Fri, 13 Sep 2024 10:21:41 -0700 Subject: [PATCH 07/12] More ui package bumps to address snyk vuln (#1004) --- ui/package-lock.json | 125 +++++++++++++++++++++++++++---------------- ui/package.json | 5 +- 2 files changed, 82 insertions(+), 48 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index 5363185cf..afc737083 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -6796,9 +6796,9 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -6808,7 +6808,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -6848,11 +6848,11 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/body-parser/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -10257,36 +10257,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -10318,22 +10318,30 @@ "node": ">= 0.8" } }, + "node_modules/express/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/express/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -10629,12 +10637,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -10653,6 +10661,14 @@ "ms": "2.0.0" } }, + "node_modules/finalhandler/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -15293,9 +15309,12 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -19104,9 +19123,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -19223,19 +19242,27 @@ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -19299,13 +19326,17 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" diff --git a/ui/package.json b/ui/package.json index 556f7a021..5c5e5407c 100644 --- a/ui/package.json +++ b/ui/package.json @@ -49,10 +49,11 @@ }, "overrides": { "async": "^2.6.4", + "body-parser": "^1.20.3", "braces": "^3.0.3", "decode-uri-component": "^0.2.2", "ejs": "^3.1.10", - "express": "^4.19.2", + "express": "^4.21.0", "ip": "^1.1.9", "json5": "^2.2.2", "loader-utils": "^2.0.4", @@ -63,6 +64,8 @@ "postcss": "^8.4.31", "randombytes": "^2.1.0", "semver": "^7.5.2", + "send": "^0.19.0", + "serve-static": "^1.16.0", "serialize-javascript": "^6.0.2", "terser": "^5.14.2", "tough-cookie": "^4.1.3", From d2380c5b1754650e4475c8bb770be120a4da6632 Mon Sep 17 00:00:00 2001 From: bumptagbot Date: Fri, 13 Sep 2024 17:21:59 +0000 Subject: [PATCH 08/12] bump 0.0.612 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index eaedefddd..05964a02e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,4 @@ gradle.ext { } // This line needs to match the VERSION_LINE_MATCH regex in the bump-tag-publish GHA. -gradle.ext.tanagraVersion = "0.0.611-SNAPSHOT" +gradle.ext.tanagraVersion = "0.0.612-SNAPSHOT" From 596611df7a2e84b49ae9e420f849a4356233ac79 Mon Sep 17 00:00:00 2001 From: Dexter Amundsen Date: Fri, 13 Sep 2024 10:39:10 -0700 Subject: [PATCH 09/12] Bump spring and lib versions (#1002) --- annotationProcessor/build.gradle | 8 +- annotationProcessor/gradle.lockfile | 129 +++++++++++---------- build.gradle | 7 +- cli/gradle.lockfile | 10 +- client/build.gradle | 10 +- indexer/gradle.lockfile | 21 ++-- service/build.gradle | 18 +-- service/gradle.lockfile | 166 ++++++++++++++-------------- underlay/gradle.lockfile | 10 +- 9 files changed, 195 insertions(+), 184 deletions(-) diff --git a/annotationProcessor/build.gradle b/annotationProcessor/build.gradle index cfe92fd24..93b77c56b 100644 --- a/annotationProcessor/build.gradle +++ b/annotationProcessor/build.gradle @@ -3,7 +3,7 @@ plugins { // These plugins are needed to resolve versions of spring dependencies // transitively added by terra-common-lib - id 'org.springframework.boot' version '3.3.1' + id 'org.springframework.boot' version '3.3.3' id 'io.spring.dependency-management' version '1.1.5' } @@ -53,8 +53,10 @@ dependencies { implementation project(path: ':service') // explicity declare libs and version to address synk warnings - implementation 'org.springframework:spring-web:6.1.12' - testFixturesImplementation 'org.springframework:spring-web:6.1.12' + implementation "org.springframework:spring-web:${gradle.vSpringWeb}" + implementation "org.springframework:spring-webmvc:${gradle.vSpringWeb}" + testFixturesImplementation "org.springframework:spring-web:${gradle.vSpringWeb}" + testFixturesImplementation "org.springframework:spring-webmvc:${gradle.vSpringWeb}" // Static analysis pmd "net.sourceforge.pmd:pmd-ant:${gradle.vPmd}" diff --git a/annotationProcessor/gradle.lockfile b/annotationProcessor/gradle.lockfile index 69c7168d2..fe89d3dd0 100644 --- a/annotationProcessor/gradle.lockfile +++ b/annotationProcessor/gradle.lockfile @@ -8,23 +8,23 @@ bio.terra:terra-common-lib:1.1.16-SNAPSHOT=compileClasspath,productionRuntimeCla ch.qos.logback.contrib:logback-jackson:0.1.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath ch.qos.logback.contrib:logback-json-classic:0.1.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath ch.qos.logback.contrib:logback-json-core:0.1.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -ch.qos.logback:logback-classic:1.5.6=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -ch.qos.logback:logback-core:1.5.6=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.5.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-core:1.5.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.amazonaws:aws-java-sdk-core:1.12.652=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.amazonaws:aws-java-sdk-sts:1.12.652=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.amazonaws:jmespath-java:1.12.652=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-guava:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.17.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-guava:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.fasterxml:classmate:1.7.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.github.ben-manes.caffeine:caffeine:3.1.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.github.jnr:jffi:1.3.13=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -152,11 +152,11 @@ io.gsonfire:gson-fire:1.9.0=productionRuntimeClasspath,runtimeClasspath,testFixt io.kubernetes:client-java-api:20.0.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath io.kubernetes:client-java-proto:20.0.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath io.kubernetes:client-java:20.0.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -io.micrometer:micrometer-commons:1.13.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -io.micrometer:micrometer-observation:1.13.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +io.micrometer:micrometer-commons:1.13.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +io.micrometer:micrometer-observation:1.13.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath io.netty:netty-bom:4.1.111.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -io.netty:netty-buffer:4.1.111.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -io.netty:netty-common:4.1.111.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +io.netty:netty-buffer:4.1.112.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +io.netty:netty-common:4.1.112.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath io.opencensus:opencensus-api:0.31.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath io.opencensus:opencensus-contrib-http-util:0.31.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath io.opencensus:opencensus-proto:0.2.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -185,7 +185,7 @@ javax.annotation:javax.annotation-api:1.3.2=productionRuntimeClasspath,runtimeCl javax.xml.bind:jaxb-api:2.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath jaxen:jaxen:2.0.0=spotbugs joda-time:joda-time:2.8.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy:1.14.17=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy:1.14.19=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath net.java.dev.jna:jna-platform:5.13.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath net.java.dev.jna:jna:5.13.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath net.minidev:accessors-smart:2.5.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -210,8 +210,8 @@ org.apache.commons:commons-text:1.10.0=spotbugs org.apache.commons:commons-text:1.12.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.3.1=checkstyle,pmd,spotbugs -org.apache.httpcomponents.core5:httpcore5-h2:5.2.4=checkstyle,pmd,spotbugs -org.apache.httpcomponents.core5:httpcore5:5.2.4=checkstyle,pmd,spotbugs +org.apache.httpcomponents.core5:httpcore5-h2:5.2.5=checkstyle,pmd,spotbugs +org.apache.httpcomponents.core5:httpcore5:5.2.5=checkstyle,pmd,spotbugs org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpclient:4.5.14=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.16=checkstyle,productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -224,9 +224,9 @@ org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:1.0.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.apache.oltu.oauth2:org.apache.oltu.oauth2.common:1.0.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-core:10.1.25=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-el:10.1.25=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-websocket:10.1.25=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:10.1.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:10.1.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:10.1.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.apache.xbean:xbean-reflect:3.7=checkstyle org.bitbucket.b_c:jose4j:0.9.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.bouncycastle:bcpkix-jdk18on:1.77=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -256,13 +256,13 @@ org.glassfish.hk2:osgi-resource-locator:1.0.3=productionRuntimeClasspath,runtime org.glassfish.jaxb:jaxb-core:4.0.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.glassfish.jaxb:jaxb-runtime:4.0.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.glassfish.jaxb:txw2:4.0.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.connectors:jersey-jdk-connector:3.1.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.core:jersey-client:3.1.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.core:jersey-common:3.1.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.ext:jersey-entity-filtering:3.1.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.inject:jersey-hk2:3.1.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.media:jersey-media-json-jackson:3.1.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.media:jersey-media-multipart:3.1.7=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.connectors:jersey-jdk-connector:3.1.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.core:jersey-client:3.1.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.core:jersey-common:3.1.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.ext:jersey-entity-filtering:3.1.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.inject:jersey-hk2:3.1.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.media:jersey-media-json-jackson:3.1.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.media:jersey-media-multipart:3.1.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.hashids:hashids:1.0.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.hibernate.common:hibernate-commons-annotations:6.0.6.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.hibernate.orm:hibernate-core:6.5.2.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -273,10 +273,10 @@ org.jacoco:org.jacoco.report:0.8.12=jacocoAnt org.javassist:javassist:3.28.0-GA=checkstyle org.javassist:javassist:3.30.2-GA=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.jboss.logging:jboss-logging:3.5.3.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.9.24=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.24=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.24=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.9.24=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-common:1.9.25=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.25=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.25=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib:1.9.25=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.jetbrains:annotations:13.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.json:json:20240303=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.jvnet.mimepull:mimepull:1.9.15=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -297,37 +297,36 @@ org.pcollections:pcollections:3.2.0=pmd org.postgresql:postgresql:42.7.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.reflections:reflections:0.10.2=checkstyle org.scala-lang:scala-library:2.13.10=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.slf4j:jcl-over-slf4j:2.0.13=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.slf4j:jul-to-slf4j:2.0.13=pmd,productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.13=spotbugs,spotbugsSlf4j,testFixturesRuntimeClasspath -org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:jcl-over-slf4j:2.0.16=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:2.0.16=pmd,productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,spotbugs,spotbugsSlf4j,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.slf4j:slf4j-simple:2.0.0=spotbugsSlf4j -org.slf4j:slf4j-simple:2.0.13=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-autoconfigure:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-data-jdbc:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-jdbc:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-json:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-logging:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-tomcat:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-web:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.data:spring-data-commons:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.data:spring-data-jdbc:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.data:spring-data-relational:3.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.retry:spring-retry:2.0.6=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.security:spring-security-core:6.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.security:spring-security-crypto:6.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-aop:6.1.10=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-beans:6.1.10=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-context:6.1.10=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-core:6.1.10=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-expression:6.1.10=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-jcl:6.1.10=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-jdbc:6.1.10=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-tx:6.1.10=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-web:6.1.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-webmvc:6.1.10=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.slf4j:slf4j-simple:2.0.16=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-data-jdbc:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-jdbc:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.data:spring-data-commons:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.data:spring-data-jdbc:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.data:spring-data-relational:3.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.retry:spring-retry:2.0.8=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.security:spring-security-core:6.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.security:spring-security-crypto:6.3.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-aop:6.1.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-beans:6.1.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-context:6.1.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-core:6.1.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-expression:6.1.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-jcl:6.1.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-jdbc:6.1.12=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-tx:6.1.12=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-web:6.1.13=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-webmvc:6.1.13=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.threeten:threeten-extra:1.8.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.threeten:threetenbp:1.6.9=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath org.vumc.vda.tanagra:admin-client:0.0.113-SNAPSHOT=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath diff --git a/build.gradle b/build.gradle index 895137a42..2eca95989 100644 --- a/build.gradle +++ b/build.gradle @@ -6,14 +6,15 @@ buildscript { } gradle.ext { - vSpringBoot = '3.3.1' + vSpringBoot = '3.3.3' + vSpringWeb = '6.1.13' vPmd = '7.1.0' vTerraCommonLib = '1.1.16-SNAPSHOT' vApacheCommonsText = '1.12.0' vSlf4jApi = '2.0.16' vSpotBugs = '4.8.5' - vJackson = '2.17.1' - vJersey3 = '3.1.7' // Java 17 compatible + vJackson = '2.17.2' + vJersey = '3.1.8' // Java 17 compatible vSwaggerAnnotations = '2.2.22' vSwaggerCodegen = '3.0.57' vPicocliVersion = '4.7.6' diff --git a/cli/gradle.lockfile b/cli/gradle.lockfile index df37d74d7..bb79176a6 100644 --- a/cli/gradle.lockfile +++ b/cli/gradle.lockfile @@ -3,11 +3,11 @@ # This file is expected to be part of source control. ch.qos.logback:logback-classic:1.5.6=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath ch.qos.logback:logback-core:1.5.6=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.spotbugs:spotbugs-annotations:4.8.5=compileClasspath,spotbugs,testCompileClasspath com.github.spotbugs:spotbugs:4.8.5=spotbugs diff --git a/client/build.gradle b/client/build.gradle index 62772f22c..66f6cc08d 100644 --- a/client/build.gradle +++ b/client/build.gradle @@ -7,7 +7,7 @@ plugins { id 'com.jfrog.artifactory' version '5.2.2' id 'io.spring.dependency-management' version '1.1.5' id 'org.hidetake.swagger.generator' version '2.19.2' - id 'org.springframework.boot' version '3.3.1' + id 'org.springframework.boot' version '3.3.3' } repositories { @@ -53,10 +53,10 @@ dependencies { implementation "com.fasterxml.jackson.core:jackson-core:${gradle.vJackson}" implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${gradle.vJackson}" - implementation "org.glassfish.jersey.core:jersey-client:${gradle.vJersey3}" - implementation "org.glassfish.jersey.media:jersey-media-json-jackson:${gradle.vJersey3}" - implementation "org.glassfish.jersey.media:jersey-media-multipart:${gradle.vJersey3}" - implementation "org.glassfish.jersey.connectors:jersey-jdk-connector:${gradle.vJersey3}" + implementation "org.glassfish.jersey.core:jersey-client:${gradle.vJersey}" + implementation "org.glassfish.jersey.media:jersey-media-json-jackson:${gradle.vJersey}" + implementation "org.glassfish.jersey.media:jersey-media-multipart:${gradle.vJersey}" + implementation "org.glassfish.jersey.connectors:jersey-jdk-connector:${gradle.vJersey}" } bootJar { diff --git a/indexer/gradle.lockfile b/indexer/gradle.lockfile index 7ad7013cd..71863c23e 100644 --- a/indexer/gradle.lockfile +++ b/indexer/gradle.lockfile @@ -6,13 +6,20 @@ ch.qos.logback:logback-classic:1.5.6=runtimeClasspath,testFixturesRuntimeClasspa ch.qos.logback:logback-core:1.5.6=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.charleskorn.kaml:kaml-jvm:0.60.0=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.charleskorn.kaml:kaml:0.60.0=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-joda:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.17.1=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.1=compileClasspath,testCompileClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.17.1=compileClasspath,testCompileClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.1=compileClasspath,testCompileClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.1=compileClasspath,testCompileClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.2=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-joda:2.17.1=compileClasspath,testCompileClasspath +com.fasterxml.jackson.datatype:jackson-datatype-joda:2.17.2=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1=compileClasspath,testCompileClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.17.1=compileClasspath,testCompileClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.fasterxml:classmate:1.5.1=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.spotbugs:spotbugs-annotations:4.8.5=compileClasspath,spotbugs,testCompileClasspath diff --git a/service/build.gradle b/service/build.gradle index 8ab11694e..c3e8941f0 100644 --- a/service/build.gradle +++ b/service/build.gradle @@ -5,7 +5,7 @@ plugins { id 'com.google.cloud.tools.jib' version '3.1.2' id 'org.hidetake.swagger.generator' version '2.19.2' - id 'org.springframework.boot' version '3.3.1' + id 'org.springframework.boot' version '3.3.3' id 'io.spring.dependency-management' version '1.1.5' id 'org.barfuin.gradle.taskinfo' version '2.2.0' id 'net.linguica.maven-settings' version '0.5' @@ -94,8 +94,10 @@ dependencies { implementation 'org.springframework.security:spring-security-core' // explicity declare libs and version to address synk warnings - implementation 'org.springframework:spring-web:6.1.12' - testFixturesImplementation 'org.springframework:spring-web:6.1.12' + implementation "org.springframework:spring-web:${gradle.vSpringWeb}" + implementation "org.springframework:spring-webmvc:${gradle.vSpringWeb}" + testFixturesImplementation "org.springframework:spring-web:${gradle.vSpringWeb}" + testFixturesImplementation "org.springframework:spring-webmvc:${gradle.vSpringWeb}" // [Application DB] MySQL/MariaDB implementation 'org.mariadb.jdbc:mariadb-java-client:3.4.0' @@ -124,11 +126,11 @@ dependencies { // [Access control]: VUMC admin service // Changed form javax->jakarta, so using jersey3 - implementation "org.glassfish.jersey.core:jersey-common:${gradle.vJersey3}" - implementation "org.glassfish.jersey.core:jersey-client:${gradle.vJersey3}" - implementation "org.glassfish.jersey.inject:jersey-hk2:${gradle.vJersey3}" - implementation "org.glassfish.jersey.media:jersey-media-multipart:${gradle.vJersey3}" - implementation "org.glassfish.jersey.media:jersey-media-json-jackson:${gradle.vJersey3}" + implementation "org.glassfish.jersey.core:jersey-common:${gradle.vJersey}" + implementation "org.glassfish.jersey.core:jersey-client:${gradle.vJersey}" + implementation "org.glassfish.jersey.inject:jersey-hk2:${gradle.vJersey}" + implementation "org.glassfish.jersey.media:jersey-media-multipart:${gradle.vJersey}" + implementation "org.glassfish.jersey.media:jersey-media-json-jackson:${gradle.vJersey}" implementation 'org.vumc.vda.tanagra:admin-client:0.0.113-SNAPSHOT' diff --git a/service/gradle.lockfile b/service/gradle.lockfile index 9cc6fafc4..c1e8c1fc2 100644 --- a/service/gradle.lockfile +++ b/service/gradle.lockfile @@ -8,23 +8,23 @@ bio.terra:terra-common-lib:1.1.16-SNAPSHOT=compileClasspath,compileProtoPath,pro ch.qos.logback.contrib:logback-jackson:0.1.5=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath ch.qos.logback.contrib:logback-json-classic:0.1.5=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath ch.qos.logback.contrib:logback-json-core:0.1.5=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -ch.qos.logback:logback-classic:1.5.6=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -ch.qos.logback:logback-core:1.5.6=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.5.7=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-core:1.5.7=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath com.amazonaws:aws-java-sdk-core:1.12.652=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath com.amazonaws:aws-java-sdk-sts:1.12.652=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath com.amazonaws:jmespath-java:1.12.652=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.17.1=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-guava:2.17.1=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.17.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.17.2=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-guava:2.17.2=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath com.fasterxml:classmate:1.7.0=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath com.github.jnr:jffi:1.3.13=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -155,11 +155,11 @@ io.gsonfire:gson-fire:1.9.0=compileProtoPath,productionRuntimeClasspath,runtimeC io.kubernetes:client-java-api:20.0.1=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath io.kubernetes:client-java-proto:20.0.1=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath io.kubernetes:client-java:20.0.1=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -io.micrometer:micrometer-commons:1.13.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -io.micrometer:micrometer-observation:1.13.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +io.micrometer:micrometer-commons:1.13.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +io.micrometer:micrometer-observation:1.13.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath io.netty:netty-bom:4.1.111.Final=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -io.netty:netty-buffer:4.1.111.Final=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -io.netty:netty-common:4.1.111.Final=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +io.netty:netty-buffer:4.1.112.Final=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +io.netty:netty-common:4.1.112.Final=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath io.opencensus:opencensus-api:0.31.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath io.opencensus:opencensus-contrib-http-util:0.31.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath io.opencensus:opencensus-proto:0.2.0=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -191,8 +191,8 @@ javax.xml.bind:jaxb-api:2.3.1=compileProtoPath,productionRuntimeClasspath,runtim jaxen:jaxen:2.0.0=spotbugs joda-time:joda-time:2.8.1=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath junit:junit:4.13.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -net.bytebuddy:byte-buddy-agent:1.14.17=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -net.bytebuddy:byte-buddy:1.14.17=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy-agent:1.14.19=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +net.bytebuddy:byte-buddy:1.14.19=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath net.java.dev.jna:jna-platform:5.13.0=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath net.java.dev.jna:jna:5.13.0=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath net.minidev:accessors-smart:2.5.1=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -217,8 +217,8 @@ org.apache.commons:commons-text:1.10.0=spotbugs org.apache.commons:commons-text:1.12.0=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.3.1=checkstyle,pmd,spotbugs -org.apache.httpcomponents.core5:httpcore5-h2:5.2.4=checkstyle,pmd,spotbugs -org.apache.httpcomponents.core5:httpcore5:5.2.4=checkstyle,pmd,spotbugs +org.apache.httpcomponents.core5:httpcore5-h2:5.2.5=checkstyle,pmd,spotbugs +org.apache.httpcomponents.core5:httpcore5:5.2.5=checkstyle,pmd,spotbugs org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.16=checkstyle,compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -231,13 +231,13 @@ org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:1.0.2=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.apache.oltu.oauth2:org.apache.oltu.oauth2.common:1.0.2=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-core:10.1.25=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-el:10.1.25=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-websocket:10.1.25=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:10.1.28=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:10.1.28=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:10.1.28=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath org.assertj:assertj-core:3.25.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.awaitility:awaitility:4.2.1=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.awaitility:awaitility:4.2.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath org.bitbucket.b_c:jose4j:0.9.4=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.bouncycastle:bcpkix-jdk18on:1.77=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.bouncycastle:bcprov-jdk18on:1.78=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -266,13 +266,13 @@ org.glassfish.hk2:osgi-resource-locator:1.0.3=compileClasspath,compileProtoPath, org.glassfish.jaxb:jaxb-core:4.0.5=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.glassfish.jaxb:jaxb-runtime:4.0.5=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.glassfish.jaxb:txw2:4.0.5=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.connectors:jersey-jdk-connector:3.1.7=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.core:jersey-client:3.1.7=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.core:jersey-common:3.1.7=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.ext:jersey-entity-filtering:3.1.7=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.inject:jersey-hk2:3.1.7=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.media:jersey-media-json-jackson:3.1.7=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.glassfish.jersey.media:jersey-media-multipart:3.1.7=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.connectors:jersey-jdk-connector:3.1.8=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.core:jersey-client:3.1.8=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.core:jersey-common:3.1.8=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.ext:jersey-entity-filtering:3.1.8=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.inject:jersey-hk2:3.1.8=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.media:jersey-media-json-jackson:3.1.8=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.glassfish.jersey.media:jersey-media-multipart:3.1.8=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath org.hamcrest:hamcrest:2.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath org.hashids:hashids:1.0.3=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath @@ -285,23 +285,23 @@ org.jacoco:org.jacoco.report:0.8.12=jacocoAnt org.javassist:javassist:3.28.0-GA=checkstyle org.javassist:javassist:3.30.2-GA=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.jboss.logging:jboss-logging:3.5.3.Final=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:1.9.24=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.24=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.24=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:1.9.24=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-common:1.9.25=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.25=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.25=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib:1.9.25=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.jetbrains:annotations:13.0=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.json:json:20240303=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-api:5.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-engine:5.10.2=testCompileProtoPath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-params:5.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter:5.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.junit.platform:junit-platform-commons:1.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.junit.platform:junit-platform-engine:1.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.junit.platform:junit-platform-launcher:1.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.junit.platform:junit-platform-runner:1.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.junit.platform:junit-platform-suite-api:1.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.junit.platform:junit-platform-suite-commons:1.10.2=testCompileProtoPath,testRuntimeClasspath -org.junit:junit-bom:5.10.2=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.10.3=testCompileProtoPath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.platform:junit-platform-commons:1.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.platform:junit-platform-engine:1.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.platform:junit-platform-runner:1.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.10.3=testCompileProtoPath,testRuntimeClasspath +org.junit:junit-bom:5.10.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath org.jvnet.mimepull:mimepull:1.9.15=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.liquibase:liquibase-core:4.27.0=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.mariadb.jdbc:mariadb-java-client:3.3.3=testFixturesCompileProtoPath,testFixturesRuntimeClasspath @@ -326,42 +326,42 @@ org.pcollections:pcollections:3.2.0=pmd org.postgresql:postgresql:42.7.3=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.reflections:reflections:0.10.2=checkstyle org.scala-lang:scala-library:2.13.10=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.skyscreamer:jsonassert:1.5.1=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.slf4j:jcl-over-slf4j:2.0.13=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.slf4j:jul-to-slf4j:2.0.13=compileClasspath,compileProtoPath,pmd,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.13=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,spotbugs,spotbugsSlf4j,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.slf4j:jcl-over-slf4j:2.0.16=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,compileProtoPath,pmd,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:2.0.16=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,spotbugs,spotbugsSlf4j,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.slf4j:slf4j-simple:2.0.0=spotbugsSlf4j -org.slf4j:slf4j-simple:2.0.13=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-autoconfigure:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-configuration-processor:3.3.1=annotationProcessor -org.springframework.boot:spring-boot-starter-data-jdbc:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-jdbc:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-json:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-logging:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-test:3.3.1=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-tomcat:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-web:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-test-autoconfigure:3.3.1=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.springframework.boot:spring-boot-test:3.3.1=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.springframework.boot:spring-boot:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.data:spring-data-commons:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.data:spring-data-jdbc:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.data:spring-data-relational:3.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.retry:spring-retry:2.0.6=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.security:spring-security-core:6.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework.security:spring-security-crypto:6.3.1=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-aop:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-beans:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-context:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-core:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-expression:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-jcl:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-jdbc:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-test:6.1.10=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath -org.springframework:spring-tx:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-web:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -org.springframework:spring-webmvc:6.1.10=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.slf4j:slf4j-simple:2.0.16=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-configuration-processor:3.3.3=annotationProcessor +org.springframework.boot:spring-boot-starter-data-jdbc:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-jdbc:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:3.3.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:3.3.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.springframework.boot:spring-boot-test:3.3.3=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.springframework.boot:spring-boot:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.data:spring-data-commons:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.data:spring-data-jdbc:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.data:spring-data-relational:3.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.retry:spring-retry:2.0.8=compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.security:spring-security-core:6.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework.security:spring-security-crypto:6.3.3=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-aop:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-beans:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-context:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-core:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-expression:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-jcl:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-jdbc:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-test:6.1.12=testCompileClasspath,testCompileProtoPath,testRuntimeClasspath +org.springframework:spring-tx:6.1.12=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-web:6.1.13=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-webmvc:6.1.13=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileClasspath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.threeten:threeten-extra:1.8.0=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.threeten:threetenbp:1.6.9=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath org.vumc.vda.tanagra:admin-client:0.0.113-SNAPSHOT=compileClasspath,compileProtoPath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath diff --git a/underlay/gradle.lockfile b/underlay/gradle.lockfile index ad2ac5599..12899e72d 100644 --- a/underlay/gradle.lockfile +++ b/underlay/gradle.lockfile @@ -1,11 +1,11 @@ # This is a Gradle generated file for dependency locking. # Manual edits can break the build and are not advised. # This file is expected to be part of source control. -com.fasterxml.jackson.core:jackson-annotations:2.17.1=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.17.1=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.17.1=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.17.1=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=compileClasspath,compileProtoPath,runtimeClasspath,testCompileClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath com.fasterxml:classmate:1.5.1=compileProtoPath,runtimeClasspath,testCompileProtoPath,testFixturesCompileProtoPath,testFixturesRuntimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.spotbugs:spotbugs-annotations:4.8.5=compileClasspath,compileProtoPath,spotbugs,testCompileClasspath,testCompileProtoPath From 6a3ee727f3887f212e225a532cdd332282061b62 Mon Sep 17 00:00:00 2001 From: bumptagbot Date: Fri, 13 Sep 2024 17:39:33 +0000 Subject: [PATCH 10/12] bump 0.0.613 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 05964a02e..829f50f67 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,4 @@ gradle.ext { } // This line needs to match the VERSION_LINE_MATCH regex in the bump-tag-publish GHA. -gradle.ext.tanagraVersion = "0.0.612-SNAPSHOT" +gradle.ext.tanagraVersion = "0.0.613-SNAPSHOT" From 41a32d754f0884a1e793f9fdbdc05b3c490aeb2c Mon Sep 17 00:00:00 2001 From: Dexter Amundsen Date: Fri, 13 Sep 2024 10:48:10 -0700 Subject: [PATCH 11/12] Util to generateId, remove extra userEmail args (#999) --- .github/workflows/regression-test.yaml | 2 +- .../regression-test-downstream-repo.yaml | 2 +- .../terra/tanagra/indexing/JobSequencer.java | 13 +-- .../app/controller/CohortsApiController.java | 80 ++++++++-------- .../app/controller/ReviewsApiController.java | 5 +- .../controller/objmapping/FromApiUtils.java | 19 ++-- .../app/controller/objmapping/ToApiUtils.java | 48 +++++----- .../java/bio/terra/tanagra/db/CohortDao.java | 3 - .../terra/tanagra/service/ServiceUtils.java | 11 +++ .../tanagra/service/UnderlayService.java | 11 +-- .../accesscontrol/AccessControlService.java | 91 +++++++------------ .../service/accesscontrol/ResourceId.java | 40 +++----- .../service/artifact/CohortService.java | 14 ++- .../service/artifact/FeatureSetService.java | 4 +- .../service/artifact/ReviewService.java | 7 +- .../service/artifact/StudyService.java | 2 +- .../artifact/model/ActivityLogResource.java | 16 ++-- .../service/artifact/model/AnnotationKey.java | 4 +- .../service/artifact/model/Cohort.java | 11 ++- .../artifact/model/CohortRevision.java | 15 +-- .../service/artifact/model/Criteria.java | 4 +- .../service/artifact/model/FeatureSet.java | 7 +- .../service/artifact/model/Review.java | 7 +- .../tanagra/service/artifact/model/Study.java | 13 ++- .../reviewquery/AnnotationFilter.java | 27 +++--- .../service/export/DataExportHelper.java | 4 +- .../regression/QueryCountRegressionTest.java | 4 +- .../service/ActivityLogServiceTest.java | 6 +- .../service/AnnotationServiceTest.java | 8 +- .../tanagra/service/CohortServiceTest.java | 35 +++---- .../service/DataExportServiceTest.java | 12 ++- .../tanagra/service/ReviewInstanceTest.java | 4 +- .../tanagra/service/ReviewPaginationTest.java | 3 +- .../tanagra/service/ReviewSampleSizeTest.java | 4 +- .../tanagra/service/ReviewServiceTest.java | 8 +- .../accesscontrol/BaseAccessControlTest.java | 83 +++++++---------- .../impl/core/EntityGroupFilterBuilder.java | 6 +- .../core/EntityGroupFilterBuilderBase.java | 12 +-- .../impl/core/SurveyFilterBuilder.java | 6 +- 39 files changed, 291 insertions(+), 360 deletions(-) create mode 100644 service/src/main/java/bio/terra/tanagra/service/ServiceUtils.java diff --git a/.github/workflows/regression-test.yaml b/.github/workflows/regression-test.yaml index 8b75b9889..a3969261a 100644 --- a/.github/workflows/regression-test.yaml +++ b/.github/workflows/regression-test.yaml @@ -64,7 +64,7 @@ jobs: env: TEST_PROJECT_SA_KEY: ${{ secrets.TEST_PROJECT_SA_KEY }} - name: Gradle Run Regression Tests Only - run: ./gradlew service:regressionTests -PregressionTestUnderlays=cmssynpuf,aouSR2019q4r4 --info --scan + run: ./gradlew service:regressionTests -PregressionTestUnderlays=cmssynpuf,aouSR2019q4r4 --scan env: DBMS: postgresql GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflowsForDownstreamRepo/regression-test-downstream-repo.yaml b/.github/workflowsForDownstreamRepo/regression-test-downstream-repo.yaml index d6cf99666..99b572730 100644 --- a/.github/workflowsForDownstreamRepo/regression-test-downstream-repo.yaml +++ b/.github/workflowsForDownstreamRepo/regression-test-downstream-repo.yaml @@ -53,7 +53,7 @@ jobs: mkdir -p rendered/ echo "$GHA_SA_KEY" > rendered/gha_sa_key.json export GOOGLE_APPLICATION_CREDENTIALS=$PWD/rendered/gha_sa_key.json - ./tanagra/gradlew -p tanagra service:regressionTests -PregressionTestUnderlays="${UNDERLAYS:-$DEFAULT_UNDERLAYS}" --info --scan + ./tanagra/gradlew -p tanagra service:regressionTests -PregressionTestUnderlays="${UNDERLAYS:-$DEFAULT_UNDERLAYS}" --scan env: DBMS: postgresql GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/indexer/src/main/java/bio/terra/tanagra/indexing/JobSequencer.java b/indexer/src/main/java/bio/terra/tanagra/indexing/JobSequencer.java index 8eeb304a5..0617498ef 100644 --- a/indexer/src/main/java/bio/terra/tanagra/indexing/JobSequencer.java +++ b/indexer/src/main/java/bio/terra/tanagra/indexing/JobSequencer.java @@ -497,14 +497,11 @@ public enum JobExecutor { public JobRunner getRunner( List jobSets, boolean isDryRun, IndexingJob.RunType runType) { - switch (this) { - case SERIAL: - return new SerialRunner(jobSets, isDryRun, runType); - case PARALLEL: - return new ParallelRunner(jobSets, isDryRun, runType); - default: - throw new IllegalArgumentException("Unknown JobExecution enum type: " + this); - } + return switch (this) { + case SERIAL -> new SerialRunner(jobSets, isDryRun, runType); + case PARALLEL -> new ParallelRunner(jobSets, isDryRun, runType); + default -> throw new IllegalArgumentException("Unknown JobExecution enum type: " + this); + }; } } } diff --git a/service/src/main/java/bio/terra/tanagra/app/controller/CohortsApiController.java b/service/src/main/java/bio/terra/tanagra/app/controller/CohortsApiController.java index 0b74a2791..b4904dbca 100644 --- a/service/src/main/java/bio/terra/tanagra/app/controller/CohortsApiController.java +++ b/service/src/main/java/bio/terra/tanagra/app/controller/CohortsApiController.java @@ -67,8 +67,8 @@ public ResponseEntity createCohort(String studyId, ApiCohortCreateInf Cohort.builder() .displayName(body.getDisplayName()) .description(body.getDescription()) - .underlay(body.getUnderlayName()), - SpringAuthentication.getCurrentUser().getEmail()); + .underlay(body.getUnderlayName()) + .createdBy(SpringAuthentication.getCurrentUser().getEmail())); return ResponseEntity.ok(ToApiUtils.toApiObject(createdCohort)); } @@ -195,36 +195,36 @@ public ResponseEntity queryCohortCounts( private static CohortRevision.CriteriaGroupSection fromApiObject(ApiCriteriaGroupSection apiObj) { BooleanAndOrFilter.LogicalOperator operator; - 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()); - } + 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()); + }; return CohortRevision.CriteriaGroupSection.builder() .id(apiObj.getId()) @@ -258,15 +258,11 @@ private static CohortRevision.CriteriaGroup fromApiObject(ApiCriteriaGroup apiOb } private static ReducingOperator fromApiObject(ApiReducingOperator apiObj) { - switch (apiObj) { - case ANY: - return null; - case FIRST_MENTION_OF: - return ReducingOperator.FIRST_MENTION_OF; - case LAST_MENTION_OF: - return ReducingOperator.LAST_MENTION_OF; - default: - throw new IllegalArgumentException("Unknown reducing operator: " + apiObj); - } + return switch (apiObj) { + case ANY -> null; + case FIRST_MENTION_OF -> ReducingOperator.FIRST_MENTION_OF; + case LAST_MENTION_OF -> ReducingOperator.LAST_MENTION_OF; + default -> throw new IllegalArgumentException("Unknown reducing operator: " + apiObj); + }; } } diff --git a/service/src/main/java/bio/terra/tanagra/app/controller/ReviewsApiController.java b/service/src/main/java/bio/terra/tanagra/app/controller/ReviewsApiController.java index 193222486..9497a19ad 100644 --- a/service/src/main/java/bio/terra/tanagra/app/controller/ReviewsApiController.java +++ b/service/src/main/java/bio/terra/tanagra/app/controller/ReviewsApiController.java @@ -147,11 +147,10 @@ public ResponseEntity listReviews( offset, limit); ApiReviewList apiReviews = new ApiReviewList(); + Cohort cohort = cohortService.getCohort(studyId, cohortId); reviewService .listReviews(authorizedReviewIds, offset, limit) - .forEach( - review -> - apiReviews.add(toApiObject(review, cohortService.getCohort(studyId, cohortId)))); + .forEach(review -> apiReviews.add(toApiObject(review, cohort))); return ResponseEntity.ok(apiReviews); } diff --git a/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/FromApiUtils.java b/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/FromApiUtils.java index ccc8d03a8..110ee17aa 100644 --- a/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/FromApiUtils.java +++ b/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/FromApiUtils.java @@ -481,18 +481,13 @@ private static ValueDisplayField buildRelationshipField( } public static Literal fromApiObject(ApiLiteral apiLiteral) { - switch (apiLiteral.getDataType()) { - case INT64: - return Literal.forInt64(apiLiteral.getValueUnion().getInt64Val()); - case STRING: - return Literal.forString(apiLiteral.getValueUnion().getStringVal()); - case BOOLEAN: - return Literal.forBoolean(apiLiteral.getValueUnion().isBoolVal()); - case DATE: - return Literal.forDate(apiLiteral.getValueUnion().getDateVal()); - default: - throw new SystemException("Unknown API data type: " + apiLiteral.getDataType()); - } + return switch (apiLiteral.getDataType()) { + case INT64 -> Literal.forInt64(apiLiteral.getValueUnion().getInt64Val()); + case STRING -> Literal.forString(apiLiteral.getValueUnion().getStringVal()); + case BOOLEAN -> Literal.forBoolean(apiLiteral.getValueUnion().isBoolVal()); + case DATE -> Literal.forDate(apiLiteral.getValueUnion().getDateVal()); + default -> throw new SystemException("Unknown API data type: " + apiLiteral.getDataType()); + }; } public static BinaryOperator fromApiObject(ApiBinaryOperator apiOperator) { diff --git a/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/ToApiUtils.java b/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/ToApiUtils.java index eb572056e..0e892822b 100644 --- a/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/ToApiUtils.java +++ b/service/src/main/java/bio/terra/tanagra/app/controller/objmapping/ToApiUtils.java @@ -67,29 +67,28 @@ public static ApiLiteral toApiObject(Literal literal) { ApiLiteral apiLiteral = new ApiLiteral().dataType(ApiDataType.fromValue(literal.getDataType().name())); - switch (literal.getDataType()) { - case INT64: - return apiLiteral.valueUnion(new ApiLiteralValueUnion().int64Val(literal.getInt64Val())); - case STRING: - return apiLiteral.valueUnion(new ApiLiteralValueUnion().stringVal(literal.getStringVal())); - case BOOLEAN: - return apiLiteral.valueUnion(new ApiLiteralValueUnion().boolVal(literal.getBooleanVal())); - case DATE: - return apiLiteral.valueUnion( - new ApiLiteralValueUnion() - .dateVal(literal.getDateVal() == null ? null : literal.getDateVal().toString())); - case TIMESTAMP: - return apiLiteral.valueUnion( - new ApiLiteralValueUnion() - .timestampVal( - literal.getTimestampVal() == null - ? null - : literal.getTimestampVal().toString())); - case DOUBLE: - return apiLiteral.valueUnion(new ApiLiteralValueUnion().doubleVal(literal.getDoubleVal())); - default: - throw new SystemException("Unknown data type: " + literal.getDataType()); - } + return switch (literal.getDataType()) { + case INT64 -> + apiLiteral.valueUnion(new ApiLiteralValueUnion().int64Val(literal.getInt64Val())); + case STRING -> + apiLiteral.valueUnion(new ApiLiteralValueUnion().stringVal(literal.getStringVal())); + case BOOLEAN -> + apiLiteral.valueUnion(new ApiLiteralValueUnion().boolVal(literal.getBooleanVal())); + case DATE -> + apiLiteral.valueUnion( + new ApiLiteralValueUnion() + .dateVal(literal.getDateVal() == null ? null : literal.getDateVal().toString())); + case TIMESTAMP -> + apiLiteral.valueUnion( + new ApiLiteralValueUnion() + .timestampVal( + literal.getTimestampVal() == null + ? null + : literal.getTimestampVal().toString())); + case DOUBLE -> + apiLiteral.valueUnion(new ApiLiteralValueUnion().doubleVal(literal.getDoubleVal())); + default -> throw new SystemException("Unknown data type: " + literal.getDataType()); + }; } public static ApiCohort toApiObject(Cohort cohort) { @@ -215,8 +214,7 @@ private static ApiInstance toApiObject(ListInstance listInstance) { hierarchyFieldSets, ((HierarchyIsMemberField) field).getHierarchy().getName()) .setIsMember(value.getValue().getBooleanVal()); - } else if (field instanceof RelatedEntityIdCountField) { - RelatedEntityIdCountField countField = (RelatedEntityIdCountField) field; + } else if (field instanceof RelatedEntityIdCountField countField) { relationshipFieldSets.add( new ApiInstanceRelationshipFields() .relatedEntity(countField.getCountedEntity().getName()) diff --git a/service/src/main/java/bio/terra/tanagra/db/CohortDao.java b/service/src/main/java/bio/terra/tanagra/db/CohortDao.java index 9bd3031a5..544f180c5 100644 --- a/service/src/main/java/bio/terra/tanagra/db/CohortDao.java +++ b/service/src/main/java/bio/terra/tanagra/db/CohortDao.java @@ -327,10 +327,7 @@ public String createNextRevision( .setIsMostRecent(true) .version(cohort.getMostRecentRevision().getVersion() + 1) .createdBy(userEmail) - .lastModifiedBy(userEmail) .id(null) // Builder will generate a new id. - .created(null) - .lastModified(null) .recordsCount(null) // Only store the records count for frozen revisions. .build(); createRevision(cohortId, nextRevision); diff --git a/service/src/main/java/bio/terra/tanagra/service/ServiceUtils.java b/service/src/main/java/bio/terra/tanagra/service/ServiceUtils.java new file mode 100644 index 000000000..3a8380ffc --- /dev/null +++ b/service/src/main/java/bio/terra/tanagra/service/ServiceUtils.java @@ -0,0 +1,11 @@ +package bio.terra.tanagra.service; + +import org.apache.commons.lang3.RandomStringUtils; + +public class ServiceUtils { + private ServiceUtils() {} + + public static String newArtifactId() { + return RandomStringUtils.randomAlphanumeric(10); + } +} diff --git a/service/src/main/java/bio/terra/tanagra/service/UnderlayService.java b/service/src/main/java/bio/terra/tanagra/service/UnderlayService.java index 3dbf6d9ec..b09a2cae4 100644 --- a/service/src/main/java/bio/terra/tanagra/service/UnderlayService.java +++ b/service/src/main/java/bio/terra/tanagra/service/UnderlayService.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -65,9 +64,7 @@ public UnderlayService( public List listUnderlays(ResourceCollection authorizedIds) { if (authorizedIds.isAllResources()) { - return underlayCache.values().stream() - .map(CachedUnderlay::getUnderlay) - .collect(Collectors.toUnmodifiableList()); + return underlayCache.values().stream().map(CachedUnderlay::getUnderlay).toList(); } else { // If the incoming list is empty, the caller does not have permission to see any // underlays, so we return an empty list. @@ -75,13 +72,11 @@ public List listUnderlays(ResourceCollection authorizedIds) { return Collections.emptyList(); } List authorizedNames = - authorizedIds.getResources().stream() - .map(ResourceId::getUnderlay) - .collect(Collectors.toList()); + authorizedIds.getResources().stream().map(ResourceId::getUnderlay).toList(); return underlayCache.values().stream() .map(CachedUnderlay::getUnderlay) .filter(underlay -> authorizedNames.contains(underlay.getName())) - .collect(Collectors.toUnmodifiableList()); + .toList(); } } diff --git a/service/src/main/java/bio/terra/tanagra/service/accesscontrol/AccessControlService.java b/service/src/main/java/bio/terra/tanagra/service/accesscontrol/AccessControlService.java index 3dc9e8e0f..4dbab7d49 100644 --- a/service/src/main/java/bio/terra/tanagra/service/accesscontrol/AccessControlService.java +++ b/service/src/main/java/bio/terra/tanagra/service/accesscontrol/AccessControlService.java @@ -114,49 +114,30 @@ public boolean isAuthorized(UserId user, Permissions permissions, ResourceId res + ", " + resource.getType()); } - Permissions resourcePermissions; - switch (resource.getType()) { - case UNDERLAY: - resourcePermissions = accessControlImpl.getUnderlay(user, resource); - break; - case STUDY: - resourcePermissions = accessControlImpl.getStudy(user, resource); - break; - case COHORT: - resourcePermissions = accessControlImpl.getCohort(user, resource); - break; - case FEATURE_SET: - resourcePermissions = accessControlImpl.getDataFeatureSet(user, resource); - break; - case REVIEW: - resourcePermissions = accessControlImpl.getReview(user, resource); - break; - case ANNOTATION_KEY: - resourcePermissions = accessControlImpl.getAnnotation(user, resource); - break; - case ACTIVITY_LOG: - resourcePermissions = accessControlImpl.getActivityLog(user); - break; - default: - throw new SystemException("Unsupported resource type: " + resource.getType()); - } + Permissions resourcePermissions = + switch (resource.getType()) { + case UNDERLAY -> accessControlImpl.getUnderlay(user, resource); + case STUDY -> accessControlImpl.getStudy(user, resource); + case COHORT -> accessControlImpl.getCohort(user, resource); + case FEATURE_SET -> accessControlImpl.getDataFeatureSet(user, resource); + case REVIEW -> accessControlImpl.getReview(user, resource); + case ANNOTATION_KEY -> accessControlImpl.getAnnotation(user, resource); + case ACTIVITY_LOG -> accessControlImpl.getActivityLog(user); + default -> throw new SystemException("Unsupported resource type: " + resource.getType()); + }; return resourcePermissions.contains(permissions); } public ResourceCollection listAuthorizedResources( UserId user, Permissions permissions, int offset, int limit) { - ResourceCollection allResources; - switch (permissions.getType()) { - case UNDERLAY: - allResources = accessControlImpl.listUnderlays(user, offset, limit); - break; - case STUDY: - allResources = accessControlImpl.listStudies(user, offset, limit); - break; - default: - throw new SystemException( - "Listing " + permissions.getType() + " resources requires a parent resource id"); - } + ResourceCollection allResources = + switch (permissions.getType()) { + case UNDERLAY -> accessControlImpl.listUnderlays(user, offset, limit); + case STUDY -> accessControlImpl.listStudies(user, offset, limit); + default -> + throw new SystemException( + "Listing " + permissions.getType() + " resources requires a parent resource id"); + }; return allResources.filter(permissions); } @@ -173,26 +154,20 @@ public ResourceCollection listAuthorizedResources( + " is unexpected for child resource type " + permissions.getType()); } - ResourceCollection allResources; - switch (permissions.getType()) { - case COHORT: - allResources = accessControlImpl.listCohorts(user, parentResource, offset, limit); - break; - case FEATURE_SET: - allResources = accessControlImpl.listDataFeatureSets(user, parentResource, offset, limit); - break; - case REVIEW: - allResources = accessControlImpl.listReviews(user, parentResource, offset, limit); - break; - case ANNOTATION_KEY: - allResources = accessControlImpl.listAnnotations(user, parentResource, offset, limit); - break; - default: - throw new SystemException( - "Listing " - + permissions.getType() - + " resources does not require a parent resource id"); - } + ResourceCollection allResources = + switch (permissions.getType()) { + case COHORT -> accessControlImpl.listCohorts(user, parentResource, offset, limit); + case FEATURE_SET -> + accessControlImpl.listDataFeatureSets(user, parentResource, offset, limit); + case REVIEW -> accessControlImpl.listReviews(user, parentResource, offset, limit); + case ANNOTATION_KEY -> + accessControlImpl.listAnnotations(user, parentResource, offset, limit); + default -> + throw new SystemException( + "Listing " + + permissions.getType() + + " resources does not require a parent resource id"); + }; return allResources.filter(permissions); } } diff --git a/service/src/main/java/bio/terra/tanagra/service/accesscontrol/ResourceId.java b/service/src/main/java/bio/terra/tanagra/service/accesscontrol/ResourceId.java index ff6d96c5a..a518cacd7 100644 --- a/service/src/main/java/bio/terra/tanagra/service/accesscontrol/ResourceId.java +++ b/service/src/main/java/bio/terra/tanagra/service/accesscontrol/ResourceId.java @@ -76,16 +76,11 @@ public boolean isNull() { } public ResourceId getParent() { - switch (type) { - case COHORT: - case FEATURE_SET: - return forStudy(study); - case REVIEW: - case ANNOTATION_KEY: - return forCohort(study, cohort); - default: - return null; - } + return switch (type) { + case COHORT, FEATURE_SET -> forStudy(study); + case REVIEW, ANNOTATION_KEY -> forCohort(study, cohort); + default -> null; + }; } public ResourceId getStudyResourceId() { @@ -96,22 +91,15 @@ public String getId() { if (isNull) { return "NULL_" + type; } - switch (type) { - case UNDERLAY: - return underlay; - case STUDY: - return study; - case COHORT: - return buildCompositeId(List.of(study, cohort)); - case FEATURE_SET: - return buildCompositeId(List.of(study, featureSet)); - case REVIEW: - return buildCompositeId(List.of(study, cohort, review)); - case ANNOTATION_KEY: - return buildCompositeId(List.of(study, cohort, annotationKey)); - default: - throw new IllegalArgumentException("Unknown resource type: " + type); - } + return switch (type) { + case UNDERLAY -> underlay; + case STUDY -> study; + case COHORT -> buildCompositeId(List.of(study, cohort)); + case FEATURE_SET -> buildCompositeId(List.of(study, featureSet)); + case REVIEW -> buildCompositeId(List.of(study, cohort, review)); + case ANNOTATION_KEY -> buildCompositeId(List.of(study, cohort, annotationKey)); + default -> throw new IllegalArgumentException("Unknown resource type: " + type); + }; } private static String buildCompositeId(List ids) { diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/CohortService.java b/service/src/main/java/bio/terra/tanagra/service/artifact/CohortService.java index 78abc94e8..43fffdaeb 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/CohortService.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/CohortService.java @@ -51,15 +51,14 @@ public CohortService( } /** Create a cohort and its first revision without any criteria. */ - public Cohort createCohort(String studyId, Cohort.Builder cohortBuilder, String userEmail) { - return createCohort(studyId, cohortBuilder, userEmail, Collections.emptyList()); + public Cohort createCohort(String studyId, Cohort.Builder cohortBuilder) { + return createCohort(studyId, cohortBuilder, Collections.emptyList()); } /** Create a cohort and its first revision. */ public Cohort createCohort( String studyId, Cohort.Builder cohortBuilder, - String userEmail, List sections) { // Make sure underlay name and study id are valid. underlayService.getUnderlay(cohortBuilder.getUnderlay()); @@ -71,15 +70,14 @@ public Cohort createCohort( .sections(sections) .setIsMostRecent(true) .setIsEditable(true) - .createdBy(userEmail) - .lastModifiedBy(userEmail) + .createdBy(cohortBuilder.getCreatedBy()) .build(); cohortBuilder.addRevision(firstRevision); - cohortDao.createCohort( - studyId, cohortBuilder.createdBy(userEmail).lastModifiedBy(userEmail).build()); + cohortDao.createCohort(studyId, cohortBuilder.build()); Cohort cohort = cohortDao.getCohort(cohortBuilder.getId()); - activityLogService.logCohort(ActivityLog.Type.CREATE_COHORT, userEmail, studyId, cohort); + activityLogService.logCohort( + ActivityLog.Type.CREATE_COHORT, cohort.getCreatedBy(), studyId, cohort); return cohort; } diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/FeatureSetService.java b/service/src/main/java/bio/terra/tanagra/service/artifact/FeatureSetService.java index dc931ff86..fc544826d 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/FeatureSetService.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/FeatureSetService.java @@ -45,8 +45,7 @@ public FeatureSet createFeatureSet( // }); // } - featureSetDao.createFeatureSet( - studyId, featureSetBuilder.createdBy(userEmail).lastModifiedBy(userEmail).build()); + featureSetDao.createFeatureSet(studyId, featureSetBuilder.createdBy(userEmail).build()); return featureSetDao.getFeatureSet(featureSetBuilder.getId()); } @@ -135,7 +134,6 @@ public FeatureSet cloneFeatureSet( .displayName(newDisplayName) .description(newDescription) .createdBy(userEmail) - .lastModifiedBy(userEmail) // Shallow copy criteria and attributes: they are written to DB and fetched for return // Any ids are used in conjunction with concept_set_id as primary key .criteria(original.getCriteria()) diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/ReviewService.java b/service/src/main/java/bio/terra/tanagra/service/artifact/ReviewService.java index 6b3616b5d..4c655b53a 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/ReviewService.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/ReviewService.java @@ -112,10 +112,7 @@ public Review createReviewHelper( throw new IllegalArgumentException("Cannot create a review with an empty query result"); } reviewDao.createReview( - cohortId, - reviewBuilder.createdBy(userEmail).lastModifiedBy(userEmail).build(), - primaryEntityIds, - cohortRecordsCount); + cohortId, reviewBuilder.createdBy(userEmail).build(), primaryEntityIds, cohortRecordsCount); Review review = reviewDao.getReview(reviewBuilder.getId()); activityLogService.logReview( ActivityLog.Type.CREATE_REVIEW, userEmail, studyId, cohortId, review); @@ -455,7 +452,7 @@ public CountQueryResult countReviewInstances( /* limit= */ Integer.MAX_VALUE) .stream() .sorted(Comparator.comparing(AnnotationKey::getDisplayName)) - .collect(Collectors.toList()); + .toList(); annotationKeys.forEach( annotation -> columnHeaders.append( diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/StudyService.java b/service/src/main/java/bio/terra/tanagra/service/artifact/StudyService.java index 6425149e3..65fc8dba3 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/StudyService.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/StudyService.java @@ -28,7 +28,7 @@ public StudyService(StudyDao studyDao, ActivityLogService activityLogService) { /** Create a new study. */ public Study createStudy(Study.Builder studyBuilder, String userEmail) { - studyDao.createStudy(studyBuilder.createdBy(userEmail).lastModifiedBy(userEmail).build()); + studyDao.createStudy(studyBuilder.createdBy(userEmail).build()); Study study = studyDao.getStudy(studyBuilder.getId()); activityLogService.logStudy(ActivityLog.Type.CREATE_STUDY, userEmail, study); return study; diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/model/ActivityLogResource.java b/service/src/main/java/bio/terra/tanagra/service/artifact/model/ActivityLogResource.java index ced749f72..e9d8daf2f 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/model/ActivityLogResource.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/model/ActivityLogResource.java @@ -71,16 +71,12 @@ public String getReviewDisplayName() { } public String getLogStr() { - switch (type) { - case STUDY: - return "study-" + studyId; - case COHORT: - return "cohort-" + cohortId; - case REVIEW: - return "review-" + reviewId; - default: - return "unknown type " + type; - } + return switch (type) { + case STUDY -> "study-" + studyId; + case COHORT -> "cohort-" + cohortId; + case REVIEW -> "review-" + reviewId; + default -> "unknown type " + type; + }; } public static Builder builder() { diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/model/AnnotationKey.java b/service/src/main/java/bio/terra/tanagra/service/artifact/model/AnnotationKey.java index 25323df08..4f949e86d 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/model/AnnotationKey.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/model/AnnotationKey.java @@ -6,10 +6,10 @@ import bio.terra.tanagra.api.shared.DataType; import bio.terra.tanagra.api.shared.Literal; import bio.terra.tanagra.exception.SystemException; +import bio.terra.tanagra.service.ServiceUtils; import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.List; -import org.apache.commons.lang3.RandomStringUtils; public final class AnnotationKey { private final String id; @@ -142,7 +142,7 @@ public void addEnumVal(String enumVal) { public AnnotationKey build() { if (id == null) { - id = RandomStringUtils.randomAlphanumeric(10); + id = ServiceUtils.newArtifactId(); } if (displayName == null) { throw new BadRequestException("Annotation key requires a display name"); diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/model/Cohort.java b/service/src/main/java/bio/terra/tanagra/service/artifact/model/Cohort.java index ae810bb8f..8a5b652a0 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/model/Cohort.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/model/Cohort.java @@ -4,6 +4,7 @@ import bio.terra.common.exception.*; import bio.terra.tanagra.exception.SystemException; +import bio.terra.tanagra.service.ServiceUtils; import jakarta.annotation.Nullable; import java.time.OffsetDateTime; import java.util.ArrayList; @@ -11,7 +12,6 @@ import java.util.Comparator; import java.util.List; import java.util.Optional; -import org.apache.commons.lang3.RandomStringUtils; public final class Cohort { private final String id; @@ -155,12 +155,15 @@ public Builder isDeleted(boolean isDeleted) { public Cohort build() { if (id == null) { - id = RandomStringUtils.randomAlphanumeric(10); + id = ServiceUtils.newArtifactId(); } if (displayName != null && displayName.length() > MAX_DISPLAY_NAME_LENGTH) { throw new BadRequestException( "Cohort name cannot be greater than " + MAX_DISPLAY_NAME_LENGTH + " characters"); } + if (lastModifiedBy == null) { + lastModifiedBy = createdBy; + } revisions = new ArrayList<>(revisions); revisions.sort(Comparator.comparing(CohortRevision::getVersion)); return new Cohort(this); @@ -174,6 +177,10 @@ public String getUnderlay() { return underlay; } + public String getCreatedBy() { + return createdBy; + } + public void addRevision(CohortRevision cohortRevision) { if (revisions == null) { revisions = new ArrayList<>(); diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/model/CohortRevision.java b/service/src/main/java/bio/terra/tanagra/service/artifact/model/CohortRevision.java index 8c37456a2..dd1cb8204 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/model/CohortRevision.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/model/CohortRevision.java @@ -3,6 +3,7 @@ import bio.terra.common.exception.NotFoundException; import bio.terra.tanagra.api.filter.BooleanAndOrFilter; import bio.terra.tanagra.api.shared.*; +import bio.terra.tanagra.service.ServiceUtils; import jakarta.annotation.Nullable; import java.time.OffsetDateTime; import java.util.ArrayList; @@ -10,7 +11,6 @@ import java.util.List; import java.util.Objects; import java.util.stream.*; -import org.apache.commons.lang3.RandomStringUtils; @SuppressWarnings("PMD.ExcessivePublicCount") public final class CohortRevision { @@ -167,7 +167,10 @@ public Builder recordsCount(Long recordsCount) { public CohortRevision build() { if (id == null) { - id = RandomStringUtils.randomAlphanumeric(10); + id = ServiceUtils.newArtifactId(); + } + if (lastModifiedBy == null) { + lastModifiedBy = createdBy; } return new CohortRevision(this); } @@ -240,7 +243,7 @@ private CriteriaGroupSection( List secondConditionCriteriaGroups, BooleanAndOrFilter.LogicalOperator operator, ReducingOperator firstConditionReducingOperator, - ReducingOperator secondConditionRedcuingOperator, + ReducingOperator secondConditionReducingOperator, JoinOperator joinOperator, Integer joinOperatorValue, boolean isExcluded) { @@ -250,7 +253,7 @@ private CriteriaGroupSection( this.secondConditionCriteriaGroups = secondConditionCriteriaGroups; this.operator = operator; this.firstConditionReducingOperator = firstConditionReducingOperator; - this.secondConditionRedcuingOperator = secondConditionRedcuingOperator; + this.secondConditionRedcuingOperator = secondConditionReducingOperator; this.joinOperator = joinOperator; this.joinOperatorValue = joinOperatorValue; this.isExcluded = isExcluded; @@ -374,7 +377,7 @@ public Builder setIsExcluded(boolean excluded) { public CriteriaGroupSection build() { if (id == null) { - id = RandomStringUtils.randomAlphanumeric(10); + id = ServiceUtils.newArtifactId(); } return new CriteriaGroupSection( id, @@ -488,7 +491,7 @@ public Builder criteria(List criteria) { public CriteriaGroup build() { if (id == null) { - id = RandomStringUtils.randomAlphanumeric(10); + id = ServiceUtils.newArtifactId(); } return new CriteriaGroup(id, displayName, criteria); } diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/model/Criteria.java b/service/src/main/java/bio/terra/tanagra/service/artifact/model/Criteria.java index 565d41384..cd939d500 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/model/Criteria.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/model/Criteria.java @@ -1,9 +1,9 @@ package bio.terra.tanagra.service.artifact.model; +import bio.terra.tanagra.service.ServiceUtils; import java.util.HashMap; import java.util.Map; import java.util.Objects; -import org.apache.commons.lang3.RandomStringUtils; public final class Criteria { private final String id; @@ -136,7 +136,7 @@ public Builder tags(Map tags) { public Criteria build() { if (id == null) { - id = RandomStringUtils.randomAlphanumeric(10); + id = ServiceUtils.newArtifactId(); } return new Criteria( id, diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/model/FeatureSet.java b/service/src/main/java/bio/terra/tanagra/service/artifact/model/FeatureSet.java index 590733c43..c89fbf605 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/model/FeatureSet.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/model/FeatureSet.java @@ -3,6 +3,7 @@ import static bio.terra.tanagra.service.artifact.model.Study.MAX_DISPLAY_NAME_LENGTH; import bio.terra.common.exception.*; +import bio.terra.tanagra.service.ServiceUtils; import bio.terra.tanagra.underlay.entitymodel.Entity; import jakarta.annotation.Nullable; import java.time.OffsetDateTime; @@ -14,7 +15,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.stream.Collectors; -import org.apache.commons.lang3.RandomStringUtils; public final class FeatureSet { private final String id; @@ -183,7 +183,7 @@ public Builder isDeleted(boolean isDeleted) { public FeatureSet build() { if (id == null) { - id = RandomStringUtils.randomAlphanumeric(10); + id = ServiceUtils.newArtifactId(); } if (displayName != null && displayName.length() > MAX_DISPLAY_NAME_LENGTH) { throw new BadRequestException( @@ -191,6 +191,9 @@ public FeatureSet build() { + MAX_DISPLAY_NAME_LENGTH + " characters"); } + if (lastModifiedBy == null) { + lastModifiedBy = createdBy; + } criteria = new ArrayList<>(criteria); criteria.sort(Comparator.comparing(Criteria::getId)); excludeOutputAttributesPerEntity = diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/model/Review.java b/service/src/main/java/bio/terra/tanagra/service/artifact/model/Review.java index 9cd1a1c97..c6eb66eb8 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/model/Review.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/model/Review.java @@ -3,9 +3,9 @@ import static bio.terra.tanagra.service.artifact.model.Study.MAX_DISPLAY_NAME_LENGTH; import bio.terra.common.exception.*; +import bio.terra.tanagra.service.ServiceUtils; import jakarta.annotation.Nullable; import java.time.OffsetDateTime; -import org.apache.commons.lang3.RandomStringUtils; public final class Review { private final String id; @@ -140,12 +140,15 @@ public Builder isDeleted(boolean isDeleted) { public Review build() { if (id == null) { - id = RandomStringUtils.randomAlphanumeric(10); + id = ServiceUtils.newArtifactId(); } if (displayName != null && displayName.length() > MAX_DISPLAY_NAME_LENGTH) { throw new BadRequestException( "Review name cannot be greater than " + MAX_DISPLAY_NAME_LENGTH + " characters"); } + if (lastModifiedBy == null) { + lastModifiedBy = createdBy; + } return new Review(this); } diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/model/Study.java b/service/src/main/java/bio/terra/tanagra/service/artifact/model/Study.java index 261e21170..8cfe298c4 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/model/Study.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/model/Study.java @@ -1,6 +1,7 @@ package bio.terra.tanagra.service.artifact.model; import bio.terra.common.exception.*; +import bio.terra.tanagra.service.ServiceUtils; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import jakarta.annotation.Nullable; @@ -8,7 +9,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -192,18 +192,21 @@ public Builder isDeleted(boolean isDeleted) { } public Study build() { + // true if the id is empty or null + if (StringUtils.isEmpty(id)) { + id = ServiceUtils.newArtifactId(); + } // Always have a map, even if it is empty if (properties == null) { properties = new HashMap<>(); } - // true if the id is empty or null - if (StringUtils.isEmpty(id)) { - id = RandomStringUtils.randomAlphanumeric(10); - } if (displayName != null && displayName.length() > MAX_DISPLAY_NAME_LENGTH) { throw new BadRequestException( "Study name cannot be greater than " + MAX_DISPLAY_NAME_LENGTH + " characters"); } + if (lastModifiedBy == null) { + lastModifiedBy = createdBy; + } return new Study(this); } diff --git a/service/src/main/java/bio/terra/tanagra/service/artifact/reviewquery/AnnotationFilter.java b/service/src/main/java/bio/terra/tanagra/service/artifact/reviewquery/AnnotationFilter.java index 68a4fda6a..00d4e28ac 100644 --- a/service/src/main/java/bio/terra/tanagra/service/artifact/reviewquery/AnnotationFilter.java +++ b/service/src/main/java/bio/terra/tanagra/service/artifact/reviewquery/AnnotationFilter.java @@ -26,22 +26,17 @@ public boolean isMatch(List annotationValues) { return false; } int comparison = av.getLiteral().compareTo(value); - switch (operator) { - case EQUALS: - return comparison == 0; - case NOT_EQUALS: - return comparison != 0; - case LESS_THAN: - return comparison == -1; - case GREATER_THAN: - return comparison == 1; - case LESS_THAN_OR_EQUAL: - return comparison <= 0; - case GREATER_THAN_OR_EQUAL: - return comparison >= 0; - default: - throw new SystemException("Unsupported annotation filter operator: " + operator); - } + return switch (operator) { + case EQUALS -> comparison == 0; + case NOT_EQUALS -> comparison != 0; + case LESS_THAN -> comparison == -1; + case GREATER_THAN -> comparison == 1; + case LESS_THAN_OR_EQUAL -> comparison <= 0; + case GREATER_THAN_OR_EQUAL -> comparison >= 0; + default -> + throw new SystemException( + "Unsupported annotation filter operator: " + operator); + }; }); } } diff --git a/service/src/main/java/bio/terra/tanagra/service/export/DataExportHelper.java b/service/src/main/java/bio/terra/tanagra/service/export/DataExportHelper.java index 9a77a53c7..379b0ed68 100644 --- a/service/src/main/java/bio/terra/tanagra/service/export/DataExportHelper.java +++ b/service/src/main/java/bio/terra/tanagra/service/export/DataExportHelper.java @@ -174,7 +174,7 @@ public Map getTotalNumRowsOfEntityData() { null, 1); }) - .collect(Collectors.toList()); + .toList(); Map totalNumRows = new HashMap<>(); if (maxChildThreads == null || maxChildThreads > 1) { @@ -297,7 +297,7 @@ public List writeEntityDataToGcs(String fileNameTemplate) { substitutedFilename, true); }) - .collect(Collectors.toList()); + .toList(); List exportFileResults = new ArrayList<>(); if (maxChildThreads == null || maxChildThreads > 1) { diff --git a/service/src/test/java/bio/terra/tanagra/regression/QueryCountRegressionTest.java b/service/src/test/java/bio/terra/tanagra/regression/QueryCountRegressionTest.java index ad5a5c8c6..4c225b51e 100644 --- a/service/src/test/java/bio/terra/tanagra/regression/QueryCountRegressionTest.java +++ b/service/src/test/java/bio/terra/tanagra/regression/QueryCountRegressionTest.java @@ -103,8 +103,8 @@ void countsMatch(Path filePath) throws IOException { rtCohort .getDisplayName() .substring(0, Math.min(rtCohort.getDisplayName().length(), 50))) - .description(rtCohort.getDisplayName()), - USER_EMAIL_1, + .description(rtCohort.getDisplayName()) + .createdBy(USER_EMAIL_1), rtCohort.getCriteriaGroupSectionsList().stream() .map(QueryCountRegressionTest::fromRegressionTestObj) .collect(Collectors.toList())); diff --git a/service/src/test/java/bio/terra/tanagra/service/ActivityLogServiceTest.java b/service/src/test/java/bio/terra/tanagra/service/ActivityLogServiceTest.java index f651a43a3..f42e28a51 100644 --- a/service/src/test/java/bio/terra/tanagra/service/ActivityLogServiceTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/ActivityLogServiceTest.java @@ -128,8 +128,7 @@ void createLogs() throws InterruptedException { Cohort cohort1 = cohortService.createCohort( study1.getId(), - Cohort.builder().underlay(UNDERLAY_NAME), - USER_EMAIL_1, + Cohort.builder().underlay(UNDERLAY_NAME).createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_GENDER)); assertNotNull(cohort1); LOGGER.info("Created cohort {} at {}", cohort1.getId(), cohort1.getCreated()); @@ -332,8 +331,7 @@ void filterList() throws InterruptedException { Cohort cohort1 = cohortService.createCohort( study1.getId(), - Cohort.builder().underlay(UNDERLAY_NAME), - USER_EMAIL_1, + Cohort.builder().underlay(UNDERLAY_NAME).createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_DEMOGRAPHICS)); assertNotNull(cohort1); LOGGER.info("Created cohort {} at {}", cohort1.getId(), cohort1.getCreated()); diff --git a/service/src/test/java/bio/terra/tanagra/service/AnnotationServiceTest.java b/service/src/test/java/bio/terra/tanagra/service/AnnotationServiceTest.java index 6a1dbee6d..6db30b75d 100644 --- a/service/src/test/java/bio/terra/tanagra/service/AnnotationServiceTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/AnnotationServiceTest.java @@ -78,8 +78,8 @@ void createCohortsAndReviews() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 2") - .description("first cohort"), - USER_EMAIL_1, + .description("first cohort") + .createdBy(USER_EMAIL_1), List.of( CRITERIA_GROUP_SECTION_DEMOGRAPHICS_AND_CONDITION, CRITERIA_GROUP_SECTION_PROCEDURE)); @@ -93,8 +93,8 @@ void createCohortsAndReviews() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 2") - .description("second cohort"), - USER_EMAIL_1, + .description("second cohort") + .createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_PROCEDURE)); assertNotNull(cohort2); LOGGER.info("Created cohort {} at {}", cohort2.getId(), cohort2.getCreated()); diff --git a/service/src/test/java/bio/terra/tanagra/service/CohortServiceTest.java b/service/src/test/java/bio/terra/tanagra/service/CohortServiceTest.java index 8d1dcd16f..252d68cc7 100644 --- a/service/src/test/java/bio/terra/tanagra/service/CohortServiceTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/CohortServiceTest.java @@ -93,8 +93,8 @@ void createUpdateDelete() throws InterruptedException { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName(displayName) - .description(description), - createdByEmail); + .description(description) + .createdBy(createdByEmail)); assertNotNull(createdCohort); LOGGER.info("Created cohort {} at {}", createdCohort.getId(), createdCohort.getCreated()); assertEquals(UNDERLAY_NAME, createdCohort.getUnderlay()); @@ -147,8 +147,8 @@ void listAllOrSelected() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 1") - .description("first cohort"), - USER_EMAIL_1); + .description("first cohort") + .createdBy(USER_EMAIL_1)); assertNotNull(cohort1); LOGGER.info("Created cohort {} at {}", cohort1.getId(), cohort1.getCreated()); @@ -159,8 +159,8 @@ void listAllOrSelected() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 2") - .description("second cohort"), - USER_EMAIL_1); + .description("second cohort") + .createdBy(USER_EMAIL_1)); assertNotNull(cohort2); LOGGER.info("Created cohort {} at {}", cohort2.getId(), cohort2.getCreated()); Cohort cohort3 = @@ -169,8 +169,8 @@ void listAllOrSelected() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 3") - .description("third cohort"), - USER_EMAIL_1); + .description("third cohort") + .createdBy(USER_EMAIL_1)); assertNotNull(cohort3); LOGGER.info("Created cohort {} at {}", cohort3.getId(), cohort3.getCreated()); @@ -230,7 +230,8 @@ void invalid() { NotFoundException.class, () -> cohortService.createCohort( - study1.getId(), Cohort.builder().underlay("invalid_underlay"), USER_EMAIL_1)); + study1.getId(), + Cohort.builder().underlay("invalid_underlay").createdBy(USER_EMAIL_1))); // Display name length exceeds maximum. assertThrows( @@ -240,8 +241,8 @@ void invalid() { study1.getId(), Cohort.builder() .underlay(UNDERLAY_NAME) - .displayName("123456789012345678901234567890123456789012345678901"), - USER_EMAIL_1)); + .displayName("123456789012345678901234567890123456789012345678901") + .createdBy(USER_EMAIL_1))); } @Test @@ -253,8 +254,8 @@ void withCriteria() throws InterruptedException { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 1") - .description("first cohort"), - USER_EMAIL_1); + .description("first cohort") + .createdBy(USER_EMAIL_1)); assertNotNull(cohort1); LOGGER.info("Created cohort {} at {}", cohort1.getId(), cohort1.getCreated()); @@ -287,8 +288,8 @@ void withCriteria() throws InterruptedException { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 2") - .description("second cohort"), - USER_EMAIL_1, + .description("second cohort") + .createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_PROCEDURE)); assertNotNull(cohort2); LOGGER.info("Created cohort {} at {}", cohort2.getId(), cohort2.getCreated()); @@ -322,8 +323,8 @@ void withCriteria() throws InterruptedException { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 3") - .description("third cohort"), - USER_EMAIL_1, + .description("third cohort") + .createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_TEMPORAL_WITHIN_NUM_DAYS)); assertNotNull(cohort3); LOGGER.info("Created cohort {} at {}", cohort3.getId(), cohort3.getCreated()); diff --git a/service/src/test/java/bio/terra/tanagra/service/DataExportServiceTest.java b/service/src/test/java/bio/terra/tanagra/service/DataExportServiceTest.java index 742150d2d..a34f04dd5 100644 --- a/service/src/test/java/bio/terra/tanagra/service/DataExportServiceTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/DataExportServiceTest.java @@ -125,8 +125,10 @@ void createAnnotationValues() { cohort1 = cohortService.createCohort( study1.getId(), - Cohort.builder().underlay(UNDERLAY_NAME).displayName("First Cohort"), - USER_EMAIL_1, + Cohort.builder() + .underlay(UNDERLAY_NAME) + .displayName("First Cohort") + .createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_GENDER)); assertNotNull(cohort1); LOGGER.info("Created cohort {} at {}", cohort1.getId(), cohort1.getCreated()); @@ -134,8 +136,10 @@ void createAnnotationValues() { cohort2 = cohortService.createCohort( study1.getId(), - Cohort.builder().underlay(UNDERLAY_NAME).displayName("Second Cohort"), - USER_EMAIL_1, + Cohort.builder() + .underlay(UNDERLAY_NAME) + .displayName("Second Cohort") + .createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_GENDER, CRITERIA_GROUP_SECTION_AGE)); assertNotNull(cohort2); LOGGER.info("Created cohort {} at {}", cohort2.getId(), cohort2.getCreated()); diff --git a/service/src/test/java/bio/terra/tanagra/service/ReviewInstanceTest.java b/service/src/test/java/bio/terra/tanagra/service/ReviewInstanceTest.java index 0812c53de..c0a39e1b1 100644 --- a/service/src/test/java/bio/terra/tanagra/service/ReviewInstanceTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/ReviewInstanceTest.java @@ -86,8 +86,8 @@ void createReviewsAndAnnotations() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 2") - .description("first cohort"), - USER_EMAIL_1, + .description("first cohort") + .createdBy(USER_EMAIL_1), List.of( CRITERIA_GROUP_SECTION_DEMOGRAPHICS_AND_CONDITION, CRITERIA_GROUP_SECTION_PROCEDURE)); diff --git a/service/src/test/java/bio/terra/tanagra/service/ReviewPaginationTest.java b/service/src/test/java/bio/terra/tanagra/service/ReviewPaginationTest.java index 636eb3724..ca569989a 100644 --- a/service/src/test/java/bio/terra/tanagra/service/ReviewPaginationTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/ReviewPaginationTest.java @@ -63,8 +63,7 @@ void createReview() { cohort1 = cohortService.createCohort( study1.getId(), - Cohort.builder().underlay(UNDERLAY_NAME), - USER_EMAIL_1, + Cohort.builder().underlay(UNDERLAY_NAME).createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_GENDER)); assertNotNull(cohort1); LOGGER.info("Created cohort {} at {}", cohort1.getId(), cohort1.getCreated()); diff --git a/service/src/test/java/bio/terra/tanagra/service/ReviewSampleSizeTest.java b/service/src/test/java/bio/terra/tanagra/service/ReviewSampleSizeTest.java index 70ad61548..ef04e61d0 100644 --- a/service/src/test/java/bio/terra/tanagra/service/ReviewSampleSizeTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/ReviewSampleSizeTest.java @@ -72,8 +72,8 @@ void createStudyAndCohort() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 2") - .description("first cohort"), - USER_EMAIL_1, + .description("first cohort") + .createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_GENDER)); assertNotNull(cohort1); LOGGER.info("Created cohort1 {} at {}", cohort1.getId(), cohort1.getCreated()); diff --git a/service/src/test/java/bio/terra/tanagra/service/ReviewServiceTest.java b/service/src/test/java/bio/terra/tanagra/service/ReviewServiceTest.java index 4b3828622..e98e39f14 100644 --- a/service/src/test/java/bio/terra/tanagra/service/ReviewServiceTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/ReviewServiceTest.java @@ -67,8 +67,8 @@ void createTwoCohorts() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 2") - .description("first cohort"), - USER_EMAIL_1, + .description("first cohort") + .createdBy(USER_EMAIL_1), List.of( CRITERIA_GROUP_SECTION_DEMOGRAPHICS_AND_CONDITION, CRITERIA_GROUP_SECTION_PROCEDURE)); @@ -82,8 +82,8 @@ void createTwoCohorts() { Cohort.builder() .underlay(UNDERLAY_NAME) .displayName("cohort 2") - .description("second cohort"), - USER_EMAIL_1, + .description("second cohort") + .createdBy(USER_EMAIL_1), List.of(CRITERIA_GROUP_SECTION_PROCEDURE)); assertNotNull(cohort2); LOGGER.info("Created cohort {} at {}", cohort2.getId(), cohort2.getCreated()); diff --git a/service/src/test/java/bio/terra/tanagra/service/accesscontrol/BaseAccessControlTest.java b/service/src/test/java/bio/terra/tanagra/service/accesscontrol/BaseAccessControlTest.java index b4076a645..e420f4704 100644 --- a/service/src/test/java/bio/terra/tanagra/service/accesscontrol/BaseAccessControlTest.java +++ b/service/src/test/java/bio/terra/tanagra/service/accesscontrol/BaseAccessControlTest.java @@ -93,8 +93,8 @@ protected void createArtifacts() { Cohort.builder() .underlay(CMS_SYNPUF) .displayName("cohort 2") - .description("first cohort"), - USER_3.getEmail(), + .description("first cohort") + .createdBy(USER_3.getEmail()), List.of( CRITERIA_GROUP_SECTION_DEMOGRAPHICS_AND_CONDITION, CRITERIA_GROUP_SECTION_PROCEDURE)); @@ -107,8 +107,8 @@ protected void createArtifacts() { Cohort.builder() .underlay(CMS_SYNPUF) .displayName("cohort 2") - .description("second cohort"), - USER_4.getEmail(), + .description("second cohort") + .createdBy(USER_4.getEmail()), List.of(CRITERIA_GROUP_SECTION_PROCEDURE)); assertNotNull(cohort2); LOGGER.info("Created cohort {} at {}", cohort2.getId(), cohort2.getCreated()); @@ -256,50 +256,37 @@ protected void assertServiceListWithReadPermission( user, Permissions.forActions(type, Action.READ), parent, 0, Integer.MAX_VALUE); assertEquals(isAllResources, resources.isAllResources()); - Set actual; - switch (type) { - case UNDERLAY: - actual = - underlayService.listUnderlays(resources).stream() - .map(u -> ResourceId.forUnderlay(u.getName())) - .collect(Collectors.toSet()); - break; - case STUDY: - actual = - studyService.listStudies(resources, 0, Integer.MAX_VALUE).stream() - .map(s -> ResourceId.forStudy(s.getId())) - .collect(Collectors.toSet()); - break; - case COHORT: - actual = - cohortService.listCohorts(resources, 0, Integer.MAX_VALUE).stream() - .map(c -> ResourceId.forCohort(parent.getStudy(), c.getId())) - .collect(Collectors.toSet()); - break; - case FEATURE_SET: - actual = - featureSetService.listFeatureSets(resources, 0, Integer.MAX_VALUE).stream() - .map(c -> ResourceId.forFeatureSet(parent.getStudy(), c.getId())) - .collect(Collectors.toSet()); - break; - case REVIEW: - actual = - reviewService.listReviews(resources, 0, Integer.MAX_VALUE).stream() - .map(r -> ResourceId.forReview(parent.getStudy(), parent.getCohort(), r.getId())) - .collect(Collectors.toSet()); - break; - case ANNOTATION_KEY: - actual = - annotationService.listAnnotationKeys(resources, 0, Integer.MAX_VALUE).stream() - .map( - a -> - ResourceId.forAnnotationKey( - parent.getStudy(), parent.getCohort(), a.getId())) - .collect(Collectors.toSet()); - break; - default: - throw new IllegalArgumentException("Unknown resource type: " + type); - } + Set actual = + switch (type) { + case UNDERLAY -> + underlayService.listUnderlays(resources).stream() + .map(u -> ResourceId.forUnderlay(u.getName())) + .collect(Collectors.toSet()); + case STUDY -> + studyService.listStudies(resources, 0, Integer.MAX_VALUE).stream() + .map(s -> ResourceId.forStudy(s.getId())) + .collect(Collectors.toSet()); + case COHORT -> + cohortService.listCohorts(resources, 0, Integer.MAX_VALUE).stream() + .map(c -> ResourceId.forCohort(parent.getStudy(), c.getId())) + .collect(Collectors.toSet()); + case FEATURE_SET -> + featureSetService.listFeatureSets(resources, 0, Integer.MAX_VALUE).stream() + .map(c -> ResourceId.forFeatureSet(parent.getStudy(), c.getId())) + .collect(Collectors.toSet()); + case REVIEW -> + reviewService.listReviews(resources, 0, Integer.MAX_VALUE).stream() + .map(r -> ResourceId.forReview(parent.getStudy(), parent.getCohort(), r.getId())) + .collect(Collectors.toSet()); + case ANNOTATION_KEY -> + annotationService.listAnnotationKeys(resources, 0, Integer.MAX_VALUE).stream() + .map( + a -> + ResourceId.forAnnotationKey( + parent.getStudy(), parent.getCohort(), a.getId())) + .collect(Collectors.toSet()); + default -> throw new IllegalArgumentException("Unknown resource type: " + type); + }; List expected = Arrays.asList(expectedResources); assertEquals(expected.size(), actual.size()); actual.forEach(r -> assertTrue(expected.contains(r))); diff --git a/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/EntityGroupFilterBuilder.java b/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/EntityGroupFilterBuilder.java index 8af225c53..73660b3df 100644 --- a/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/EntityGroupFilterBuilder.java +++ b/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/EntityGroupFilterBuilder.java @@ -5,6 +5,7 @@ import bio.terra.tanagra.api.shared.Literal; import bio.terra.tanagra.proto.criteriaselector.ValueDataOuterClass; import bio.terra.tanagra.proto.criteriaselector.configschema.CFEntityGroup; +import bio.terra.tanagra.proto.criteriaselector.configschema.CFEntityGroup.EntityGroup.EntityGroupConfig; import bio.terra.tanagra.proto.criteriaselector.dataschema.DTEntityGroup; import bio.terra.tanagra.underlay.uiplugin.CriteriaSelector; import java.util.HashMap; @@ -35,10 +36,7 @@ public DTEntityGroup.EntityGroup deserializeData(String serialized) { @Override protected List entityGroupIds() { return deserializeConfig().getClassificationEntityGroupsList().stream() - .map( - classificationEntityGroup -> { - return classificationEntityGroup.getId(); - }) + .map(EntityGroupConfig::getId) .collect(Collectors.toList()); } diff --git a/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/EntityGroupFilterBuilderBase.java b/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/EntityGroupFilterBuilderBase.java index f6af31f19..9dfdbd4f2 100644 --- a/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/EntityGroupFilterBuilderBase.java +++ b/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/EntityGroupFilterBuilderBase.java @@ -235,10 +235,7 @@ private Map> selectedIdsPerEntityGroup( // Sort selected IDs so they're consistent for tests rather than returning them in the original // selection order. - selectedIdsPerEntityGroup.forEach( - (entityGroup, selectedIds) -> { - Collections.sort(selectedIds); - }); + selectedIdsPerEntityGroup.forEach((entityGroup, selectedIds) -> Collections.sort(selectedIds)); return selectedIdsPerEntityGroup; } @@ -251,12 +248,7 @@ private List selectedEntityGroups( selectedEntityGroups = new ArrayList<>(selectedIdsPerEntityGroup.keySet()); } else { selectedEntityGroups = - entityGroupIds().stream() - .map( - entityGroupId -> { - return underlay.getEntityGroup(entityGroupId); - }) - .collect(Collectors.toList()); + entityGroupIds().stream().map(underlay::getEntityGroup).collect(Collectors.toList()); } return selectedEntityGroups.stream() diff --git a/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/SurveyFilterBuilder.java b/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/SurveyFilterBuilder.java index b7788cd5f..17d983d10 100644 --- a/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/SurveyFilterBuilder.java +++ b/underlay/src/main/java/bio/terra/tanagra/filterbuilder/impl/core/SurveyFilterBuilder.java @@ -5,6 +5,7 @@ import bio.terra.tanagra.api.shared.Literal; import bio.terra.tanagra.proto.criteriaselector.ValueDataOuterClass; import bio.terra.tanagra.proto.criteriaselector.configschema.CFSurvey; +import bio.terra.tanagra.proto.criteriaselector.configschema.CFSurvey.Survey.EntityGroupConfig; import bio.terra.tanagra.proto.criteriaselector.dataschema.DTSurvey; import bio.terra.tanagra.underlay.uiplugin.CriteriaSelector; import java.util.HashMap; @@ -34,10 +35,7 @@ public DTSurvey.Survey deserializeData(String serialized) { @Override protected List entityGroupIds() { return deserializeConfig().getEntityGroupsList().stream() - .map( - entityGroup -> { - return entityGroup.getId(); - }) + .map(EntityGroupConfig::getId) .collect(Collectors.toList()); } From 9442c998349ec61f2048606d13c942d408e037a4 Mon Sep 17 00:00:00 2001 From: bumptagbot Date: Fri, 13 Sep 2024 17:48:28 +0000 Subject: [PATCH 12/12] bump 0.0.614 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 829f50f67..123516548 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,4 @@ gradle.ext { } // This line needs to match the VERSION_LINE_MATCH regex in the bump-tag-publish GHA. -gradle.ext.tanagraVersion = "0.0.613-SNAPSHOT" +gradle.ext.tanagraVersion = "0.0.614-SNAPSHOT"