Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/main/java/eu/europa/ted/eforms/sdk/SdkSymbolResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import eu.europa.ted.efx.exceptions.ConsistencyCheckException;
import eu.europa.ted.efx.exceptions.TranslatorConfigurationException;
import eu.europa.ted.efx.exceptions.SdkInconsistencyException;
import eu.europa.ted.efx.exceptions.SymbolResolutionException;

Expand Down Expand Up @@ -304,6 +304,17 @@ public String getTypeOfField(String fieldId) {
if (sdkField == null) {
throw SymbolResolutionException.unknownSymbol(fieldId);
}

// Temporary: the SDK does not yet distinguish duration from measure.
// Both are "measure" in the SDK, but durations use the "duration-unit" codelist.
// Remove this when the SDK adds "duration" as a proper data type.
if (FieldTypes.MEASURE.getName().equals(sdkField.getType())) {
SdkField unitCodeField = sdkField.getAttributeField("unitCode");
if (unitCodeField != null && "duration-unit".equals(unitCodeField.getCodelistId())) {
return FieldTypes.DURATION.getName();
}
}

return sdkField.getType();
}

Expand Down Expand Up @@ -662,7 +673,7 @@ public String getPrivacySettingOfField(final String fieldId, final PrivacySettin
case JUSTIFICATION_DESCRIPTION_FIELD:
return privacy.getJustificationDescriptionFieldId();
default:
throw ConsistencyCheckException.unhandledPrivacySetting(privacyField);
throw TranslatorConfigurationException.unhandledPrivacySetting(privacyField);
}
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2025 European Union
*
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European
* Commission – subsequent versions of the EUPL (the "Licence"); You may not use this work except in
* compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/software/page/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence
* is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence for the specific language governing permissions and limitations under
* the Licence.
*/
package eu.europa.ted.efx.exceptions;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.ParseCancellationException;

/**
* Abstract base class for all EFX compilation exceptions that represent user errors in EFX code.
* Extends ParseCancellationException to properly stop ANTLR4 parsing and bypass error recovery
* mechanisms.
*
* Provides a shared utility for formatting source position information from ANTLR tokens.
*/
@SuppressWarnings("squid:MaximumInheritanceDepth")
public abstract class EfxCompilationException extends ParseCancellationException {

protected EfxCompilationException(String template, Object... args) {
super(args.length > 0 ? String.format(template, args) : template);
}

protected EfxCompilationException(ParserRuleContext ctx, String template, Object... args) {
super(formatMessage(ctx, template, args));
}

/**
* Formats a complete error message with source position prefix.
*
* @param ctx the ANTLR parser rule context indicating the source position of the error
* @param template the message template (as used by {@link String#format})
* @param args the arguments to substitute into the template
* @return the formatted message prefixed with "line X:Y "
*/
protected static String formatMessage(ParserRuleContext ctx, String template, Object... args) {
Token token = ctx.getStart();
return String.format("line %d:%d ", token.getLine(), token.getCharPositionInLine())
+ String.format(template, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,15 @@
*/
package eu.europa.ted.efx.exceptions;

import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.v4.runtime.ParserRuleContext;

import eu.europa.ted.efx.model.expressions.TypedExpression;
import eu.europa.ted.efx.model.variables.Parametrised;

/**
* Exception thrown when invalid arguments are detected in EFX templates.
* Extends ParseCancellationException to properly stop ANTLR4 parsing
* and bypass error recovery mechanisms.
*/
@SuppressWarnings("squid:MaximumInheritanceDepth") // Necessary to integrate with ANTLR4 parser cancellation
public class InvalidArgumentException extends ParseCancellationException {
public class InvalidArgumentException extends EfxCompilationException {

public enum ErrorCode {
ARGUMENT_NUMBER_MISMATCH,
Expand All @@ -40,19 +37,24 @@ public enum ErrorCode {

private final ErrorCode errorCode;

private InvalidArgumentException(ErrorCode errorCode, String message) {
super(message);
private InvalidArgumentException(ErrorCode errorCode, String template, Object... args) {
super(template, args);
this.errorCode = errorCode;
}

private InvalidArgumentException(ErrorCode errorCode, ParserRuleContext ctx, String template, Object... args) {
super(ctx, template, args);
this.errorCode = errorCode;
}

public ErrorCode getErrorCode() {
return errorCode;
return this.errorCode;
}

public static InvalidArgumentException argumentNumberMismatch(Parametrised identifier, int expectedNumber, int actualNumber) {
return new InvalidArgumentException(ErrorCode.ARGUMENT_NUMBER_MISMATCH,
String.format(ARGUMENT_NUMBER_MISMATCH, identifier.getClass().getSimpleName().toLowerCase(),
identifier.name, expectedNumber, actualNumber));
ARGUMENT_NUMBER_MISMATCH, identifier.getClass().getSimpleName().toLowerCase(),
identifier.name, expectedNumber, actualNumber);
}

public static InvalidArgumentException argumentNumberMismatch(Parametrised identifier, int expectedNumber) {
Expand All @@ -62,16 +64,16 @@ public static InvalidArgumentException argumentNumberMismatch(Parametrised ident
public static InvalidArgumentException argumentTypeMismatch(int position, Parametrised identifier,
Class<? extends TypedExpression> expectedType, Class<? extends TypedExpression> actualType) {
return new InvalidArgumentException(ErrorCode.ARGUMENT_TYPE_MISMATCH,
String.format(ARGUMENT_TYPE_MISMATCH, position + 1, identifier.getClass().getSimpleName().toLowerCase(),
identifier.name, TypedExpression.getEfxDataType(expectedType).getSimpleName(),
TypedExpression.getEfxDataType(actualType).getSimpleName()));
ARGUMENT_TYPE_MISMATCH, position + 1, identifier.getClass().getSimpleName().toLowerCase(),
identifier.name, TypedExpression.getEfxDataType(expectedType).getSimpleName(),
TypedExpression.getEfxDataType(actualType).getSimpleName());
}

public static InvalidArgumentException unsupportedSequenceType(String type, String functionName) {
return new InvalidArgumentException(ErrorCode.UNSUPPORTED_SEQUENCE_TYPE, String.format(UNSUPPORTED_SEQUENCE_TYPE, type, functionName));
public static InvalidArgumentException unsupportedSequenceType(ParserRuleContext ctx, String type, String functionName) {
return new InvalidArgumentException(ErrorCode.UNSUPPORTED_SEQUENCE_TYPE, ctx, UNSUPPORTED_SEQUENCE_TYPE, type, functionName);
}

public static InvalidArgumentException missingArgument(String parameterName) {
return new InvalidArgumentException(ErrorCode.MISSING_ARGUMENT, String.format(MISSING_ARGUMENT, parameterName));
public static InvalidArgumentException missingArgument(ParserRuleContext ctx, String parameterName) {
return new InvalidArgumentException(ErrorCode.MISSING_ARGUMENT, ctx, MISSING_ARGUMENT, parameterName);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@
*/
package eu.europa.ted.efx.exceptions;

import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.v4.runtime.ParserRuleContext;

/**
* Exception thrown when identifier-related errors occur during EFX template processing.
* This includes undeclared identifiers, duplicate declarations, and scope violations.
* Extends ParseCancellationException to properly stop ANTLR4 parsing
* and bypass error recovery mechanisms.
*/
@SuppressWarnings("squid:MaximumInheritanceDepth") // Necessary to integrate with ANTLR4 parser cancellation
public class InvalidIdentifierException extends ParseCancellationException {
public class InvalidIdentifierException extends EfxCompilationException {

public enum ErrorCode {
UNDECLARED_IDENTIFIER,
Expand All @@ -36,24 +33,29 @@ public enum ErrorCode {

private final ErrorCode errorCode;

private InvalidIdentifierException(ErrorCode errorCode, String message) {
super(message);
private InvalidIdentifierException(ErrorCode errorCode, String template, Object... args) {
super(template, args);
this.errorCode = errorCode;
}

private InvalidIdentifierException(ErrorCode errorCode, ParserRuleContext ctx, String template, Object... args) {
super(ctx, template, args);
this.errorCode = errorCode;
}

public ErrorCode getErrorCode() {
return errorCode;
return this.errorCode;
}

public static InvalidIdentifierException undeclaredIdentifier(String identifierName) {
return new InvalidIdentifierException(ErrorCode.UNDECLARED_IDENTIFIER, String.format(UNDECLARED_IDENTIFIER, identifierName));
return new InvalidIdentifierException(ErrorCode.UNDECLARED_IDENTIFIER, UNDECLARED_IDENTIFIER, identifierName);
}

public static InvalidIdentifierException alreadyDeclared(String identifierName) {
return new InvalidIdentifierException(ErrorCode.IDENTIFIER_ALREADY_DECLARED, String.format(IDENTIFIER_ALREADY_DECLARED, identifierName));
return new InvalidIdentifierException(ErrorCode.IDENTIFIER_ALREADY_DECLARED, IDENTIFIER_ALREADY_DECLARED, identifierName);
}

public static InvalidIdentifierException notAContextVariable(String variableName) {
return new InvalidIdentifierException(ErrorCode.NOT_A_CONTEXT_VARIABLE, String.format(NOT_A_CONTEXT_VARIABLE, variableName));
public static InvalidIdentifierException notAContextVariable(ParserRuleContext ctx, String variableName) {
return new InvalidIdentifierException(ErrorCode.NOT_A_CONTEXT_VARIABLE, ctx, NOT_A_CONTEXT_VARIABLE, variableName);
}
}
}
Loading