From 335b2627ed9c23b739ab65ba8ae516a5afe7063a Mon Sep 17 00:00:00 2001 From: Ioannis Rousochatzakis Date: Thu, 16 Nov 2023 12:00:18 +0100 Subject: [PATCH] Added workaround for generating labels from a sequence of asset-ids in EFX 1. --- .../ted/efx/sdk1/EfxTemplateTranslatorV1.java | 65 ++++++++++++++++++- .../efx/sdk1/EfxTemplateTranslatorV1Test.java | 7 ++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/europa/ted/efx/sdk1/EfxTemplateTranslatorV1.java b/src/main/java/eu/europa/ted/efx/sdk1/EfxTemplateTranslatorV1.java index 73d1ff9..9880486 100644 --- a/src/main/java/eu/europa/ted/efx/sdk1/EfxTemplateTranslatorV1.java +++ b/src/main/java/eu/europa/ted/efx/sdk1/EfxTemplateTranslatorV1.java @@ -246,8 +246,36 @@ public void exitExpressionTemplate(ExpressionTemplateContext ctx) { @Override public void exitStandardLabelReference(StandardLabelReferenceContext ctx) { - StringExpression assetId = ctx.assetId() != null ? this.stack.pop(StringExpression.class) - : this.script.getStringLiteralFromUnquotedString(""); + if (!this.stack.empty() && StringSequenceExpression.class.isAssignableFrom(this.stack.peek().getClass()) && ctx.assetId() != null) { + + // This is a workaround that allows EFX 1 to render a sequence of labels without a special + // syntax. When a standard label reference is processed, the template translator checks if + // the assetId is provided with a SequenceExpression. If this is the case, then the + // translator generates the appropriate code to render a sequence of labels. + // + // For example, this will render a sequence of labels for a label reference of the form + // #{assetType|labelType|${for text:$t in ('assetId1','assetId2') return $t}}:} + // The only restriction is that the assetType and labelType must be the same for all labels in the sequence. + + StringSequenceExpression assetIdSequence = this.stack.pop(StringSequenceExpression.class); + this.exitStandardLabelReference(ctx, assetIdSequence); + } else { + + // Standard implementation as originally intended by EFX 1 + + StringExpression assetId = ctx.assetId() != null ? this.stack.pop(StringExpression.class) + : this.script.getStringLiteralFromUnquotedString(""); + this.exitStandardLabelReference(ctx, assetId); + } + } + + /** + * Renders a single label from a standard label reference. + * + * @param ctx The ParserRuleContext of the standard label reference. + * @param assetId The assetId of the label to render. + */ + private void exitStandardLabelReference(StandardLabelReferenceContext ctx, StringExpression assetId) { StringExpression labelType = ctx.labelType() != null ? this.stack.pop(StringExpression.class) : this.script.getStringLiteralFromUnquotedString(""); StringExpression assetType = ctx.assetType() != null ? this.stack.pop(StringExpression.class) @@ -258,6 +286,39 @@ public void exitStandardLabelReference(StandardLabelReferenceContext ctx) { this.script.getStringLiteralFromUnquotedString("|"), assetId)))); } + /** + * Renders a sequence of labels from a standard label reference. + * + * @param ctx The ParserRuleContext of the standard label reference. + * @param assetIdSequence The sequence of assetIds for the labels to render. + */ + private void exitStandardLabelReference(StandardLabelReferenceContext ctx, StringSequenceExpression assetIdSequence) { + StringExpression labelType = ctx.labelType() != null ? this.stack.pop(StringExpression.class) + : this.script.getStringLiteralFromUnquotedString(""); + StringExpression assetType = ctx.assetType() != null ? this.stack.pop(StringExpression.class) + : this.script.getStringLiteralFromUnquotedString(""); + + Variable loopVariable = new Variable("item", + this.script.composeVariableDeclaration("item", StringExpression.class), StringExpression.empty(), + this.script.composeVariableReference("item", StringExpression.class)); + + this.stack.push(this.markup.renderLabelFromExpression( + this.script.composeDistinctValuesFunction( + this.script.composeForExpression( + this.script.composeIteratorList( + List.of( + this.script.composeIteratorExpression(loopVariable.declarationExpression, assetIdSequence))), + this.script.composeStringConcatenation(List.of( + assetType, + this.script.getStringLiteralFromUnquotedString("|"), + labelType, + this.script.getStringLiteralFromUnquotedString("|"), + new StringExpression(loopVariable.referenceExpression.getScript()))), + StringSequenceExpression.class), + StringSequenceExpression.class))); + } + + @Override public void exitShorthandBtLabelReference(ShorthandBtLabelReferenceContext ctx) { StringExpression assetId = this.script.getStringLiteralFromUnquotedString(ctx.BtId().getText()); diff --git a/src/test/java/eu/europa/ted/efx/sdk1/EfxTemplateTranslatorV1Test.java b/src/test/java/eu/europa/ted/efx/sdk1/EfxTemplateTranslatorV1Test.java index f002a9c..4e2c45e 100644 --- a/src/test/java/eu/europa/ted/efx/sdk1/EfxTemplateTranslatorV1Test.java +++ b/src/test/java/eu/europa/ted/efx/sdk1/EfxTemplateTranslatorV1Test.java @@ -180,6 +180,13 @@ void testStandardLabelReference_UsingLabelTypeAsAssetId() { translateTemplate("{BT-00-Text} #{auxiliary|text|value}")); } + @Test + void testStandardLabelReference_WithAssetIdIterator() { + assertEquals( + "let block01() -> { label(distinct-values(for $item in for $t in ./normalize-space(text()) return $t return concat('field', '|', 'name', '|', $item))) }\nfor-each(/*/PathNode/TextField).call(block01())", + translateTemplate("{BT-00-Text} #{field|name|${for text:$t in BT-00-Text return $t}}")); + } + @Test void testShorthandBtLabelReference() { assertEquals(