From 5ff07ff662aea5b354414e1c27b7ee0a57d894ae Mon Sep 17 00:00:00 2001 From: Ioannis Rosuochatzakis Date: Thu, 26 Mar 2026 15:45:39 +0100 Subject: [PATCH 1/8] pom: Bump version to 1.7.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 90bb10f..551f822 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ eu.europa.ted.eforms eforms-core-java - 1.6.0 + 1.7.0-SNAPSHOT eForms Core Library API and tools for eForms applications. From 09242d045b1bc5abb395df086511e24eacd367c3 Mon Sep 17 00:00:00 2001 From: Ioannis Rosuochatzakis Date: Thu, 9 Apr 2026 19:18:37 +0200 Subject: [PATCH 2/8] fix: SdkFieldV1 maps "measure" to "duration" (TEDEFO-5013) --- .../eu/europa/ted/eforms/sdk/entity/v1/SdkFieldV1.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/eu/europa/ted/eforms/sdk/entity/v1/SdkFieldV1.java b/src/main/java/eu/europa/ted/eforms/sdk/entity/v1/SdkFieldV1.java index 0a7457b..940454a 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/entity/v1/SdkFieldV1.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/entity/v1/SdkFieldV1.java @@ -34,6 +34,16 @@ public SdkFieldV1( getRepeatable(repeatable)); } + // In SDK 1.x, "measure" semantically means "duration" (there was no "duration" type yet). + @Override + public String getType() { + String type = super.getType(); + if ("measure".equals(type)) { + return "duration"; + } + return type; + } + protected static String getCodelistId(Map> codelist) { if (codelist == null) { return null; From c6f9159f75cb5a120e5dc5f284f1efa23b0374da Mon Sep 17 00:00:00 2001 From: Ioannis Rosuochatzakis Date: Tue, 28 Apr 2026 16:02:38 +0200 Subject: [PATCH 3/8] perf: Replace Reflections with ClassGraph and share scan across factories (TEDEFO-5033) --- pom.xml | 12 +- .../sdk/component/SdkComponentFactory.java | 116 +++++++++--------- 2 files changed, 63 insertions(+), 65 deletions(-) diff --git a/pom.xml b/pom.xml index 551f822..873fc67 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ 3.8.6 11.1.3 7.1.1 - 0.10.2 + 4.8.179 1.8.2 3.1.0 2.0.3 @@ -76,9 +76,9 @@ - org.reflections - reflections - ${version.reflections} + io.github.classgraph + classgraph + ${version.classgraph} @@ -228,8 +228,8 @@ - org.reflections - reflections + io.github.classgraph + classgraph diff --git a/src/main/java/eu/europa/ted/eforms/sdk/component/SdkComponentFactory.java b/src/main/java/eu/europa/ted/eforms/sdk/component/SdkComponentFactory.java index 80a3482..2cc9f5e 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/component/SdkComponentFactory.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/component/SdkComponentFactory.java @@ -9,11 +9,9 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; -import java.util.stream.Stream; import eu.europa.ted.eforms.sdk.SdkVersion; -import org.reflections.Reflections; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ScanResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,6 +21,26 @@ public abstract class SdkComponentFactory { private static final Logger logger = LoggerFactory.getLogger(SdkComponentFactory.class); + /** + * Lazy-init holder for the JVM-wide classpath scan. Triggered the first time any + * {@link SdkComponentFactory} subclass is constructed; the resulting list is shared + * by all subclasses so that the (potentially expensive) classpath walk runs only once + * per JVM rather than once per factory subclass. + */ + private static final class AnnotatedClassesHolder { + static final List> CLASSES = scan(); + + private static List> scan() { + logger.debug("Scanning the classpath for types annotated with {}", SdkComponent.class); + try (ScanResult result = new ClassGraph() + .enableAnnotationInfo() + .ignoreClassVisibility() + .scan()) { + return result.getClassesWithAnnotation(SdkComponent.class).loadClasses(); + } + } + } + private Map>> componentsMap; class ComponentSelector { @@ -65,67 +83,47 @@ protected SdkComponentFactory() { private void populateComponents() { Class annotationType = SdkComponent.class; - logger.debug("Looking in the classpath for types annotated with {}", annotationType); - if (componentsMap == null) { componentsMap = new HashMap<>(); } - // Get a list of all the packages loaded by the available classloaders. - // This can be a bit expensive in some situations, so this method factory should - // be ensured to run as less as possible (ideally only once). - String[] availablePackages = Arrays - .stream(ClasspathHelper.classLoaders()) - .map(ClassLoader::getDefinedPackages) - .flatMap(Stream::of) - .map(Package::getName) - .toArray(String[]::new); + AnnotatedClassesHolder.CLASSES.forEach((Class clazz) -> { + logger.trace("Processing type [{}]", clazz); - if (logger.isTraceEnabled()) { - final List packages = Arrays.asList(availablePackages); - packages.stream().sorted() - .forEach(p -> logger.trace(p)); - } + SdkComponent annotation = clazz.getAnnotation(annotationType); + + String[] supportedSdkVersions = annotation.versions(); + SdkComponentType componentType = annotation.componentType(); + String qualifier = annotation.qualifier(); + ComponentSelector selector = new ComponentSelector(componentType, qualifier); + + logger.trace("Class [{}] has a component type of [{}] and supports SDK versions [{}]", + clazz, componentType, supportedSdkVersions); + + Arrays.asList(supportedSdkVersions).forEach((String sdkVersion) -> { + SdkComponentDescriptor component = + new SdkComponentDescriptor<>(sdkVersion, componentType, clazz); + + Map> components = + componentsMap.get(sdkVersion); + + if (components != null) { + SdkComponentDescriptor existingComponent = components.get(selector); + + if (existingComponent != null && !existingComponent.equals(component)) { + throw new IllegalArgumentException(MessageFormat.format( + "More than one components of type [{0}] have been found for SDK version [{1}]:\n\t- {2}\n\t- {3}", + componentType, sdkVersion, existingComponent.getImplType().getName(), + clazz.getName())); + } + } else { + components = new HashMap<>(); + componentsMap.put(sdkVersion, components); + } - new Reflections(ConfigurationBuilder.build().forPackages(availablePackages)) - .getTypesAnnotatedWith(annotationType).stream() - .forEach((Class clazz) -> { - logger.trace("Processing type [{}]", clazz); - - SdkComponent annotation = clazz.getAnnotation(annotationType); - - String[] supportedSdkVersions = annotation.versions(); - SdkComponentType componentType = annotation.componentType(); - String qualifier = annotation.qualifier(); - ComponentSelector selector = new ComponentSelector(componentType, qualifier); - - logger.trace("Class [{}] has a component type of [{}] and supports SDK versions [{}]", - clazz, componentType, supportedSdkVersions); - - Arrays.asList(supportedSdkVersions).forEach((String sdkVersion) -> { - SdkComponentDescriptor component = - new SdkComponentDescriptor<>(sdkVersion, componentType, clazz); - - Map> components = - componentsMap.get(sdkVersion); - - if (components != null) { - SdkComponentDescriptor existingComponent = components.get(selector); - - if (existingComponent != null && !existingComponent.equals(component)) { - throw new IllegalArgumentException(MessageFormat.format( - "More than one components of type [{0}] have been found for SDK version [{1}]:\n\t- {2}\n\t- {3}", - componentType, sdkVersion, existingComponent.getImplType().getName(), - clazz.getName())); - } - } else { - components = new HashMap<>(); - componentsMap.put(sdkVersion, components); - } - - components.put(selector, component); - }); - }); + components.put(selector, component); + }); + }); } protected T getComponentImpl(String sdkVersion, final SdkComponentType componentType, From 8fcb7d6355eeff30dc7d92f0ee9dba600b17501d Mon Sep 17 00:00:00 2001 From: ROUSSY Christophe Date: Fri, 10 Jul 2026 13:07:31 +0200 Subject: [PATCH 4/8] TEDEFO-4860 adding validation folder and rules.efx in enum, also adding fwd folder and other new files. --- .../europa/ted/eforms/sdk/SdkConstants.java | 70 +++++++++++++------ 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java b/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java index 25ecad1..707972f 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java @@ -19,50 +19,76 @@ public class SdkConstants { public static final String SDK_GROUP_ID = "eu.europa.ted.eforms"; public static final String SDK_ARTIFACT_ID = "eforms-sdk"; public static final String SDK_PACKAGING = "jar"; + + /** + * Forward folder of SDK2+, it can exist in some folders. + */ + public static final String FWD = "fwd"; private SdkConstants() {} public enum SdkResource implements PathResource { - CODELISTS(Path.of("codelists")), // - CODELISTS_JSON(Path.of("codelists", "codelists.json")), // + CODELISTS(Path.of("codelists")), + CODELISTS_JSON(Path.of("codelists", "codelists.json")), + + EFX_GRAMMAR(Path.of("efx-grammar")), + + FIELDS(Path.of("fields")), + FIELDS_JSON(Path.of("fields", "fields.json")), + + // FIELDS FWD FOLDER. + BUSINESS_ENTITIES_COMPOSITION(Path.of("fields", FWD, "business-entities-composition.json")), + BUSINESS_ENTITIES_HIERARCHY(Path.of("fields", FWD, "business-entities-hierarchies.json")), + BUSINESS_ENTITIES_PROPERTIES(Path.of("fields", FWD, "business-entities-properties.json")), + BUSINESS_TERMS(Path.of("fields", FWD, "business-terms.json")), + DATA_TYPES(Path.of("fields", FWD, "data-types.json")), + FIELDS_JSON_LIST(Path.of("fields", FWD, "fields.json")), + NODES_JSON_LIST(Path.of("fields", FWD, "nodes.json")), - EFX_GRAMMAR(Path.of("efx-grammar")), // - - FIELDS(Path.of("fields")), // - FIELDS_JSON(Path.of("fields", "fields.json")), // + /** + * Related to asset migration. + */ + MIGRATION(Path.of("migration")), + MIGRATION_JSON(Path.of("migration", "migration.json")), - NOTICE_TYPES(Path.of("notice-types")), // - NOTICE_TYPES_JSON(Path.of("notice-types", "notice-types.json")), // + NOTICE_TYPES(Path.of("notice-types")), + NOTICE_TYPES_JSON(Path.of("notice-types", "notice-types.json")), /** - * XSD files. + * Schema files. */ - SCHEMAS(Path.of("schemas")), // - SCHEMAS_COMMON(Path.of("schemas", "common")), // - SCHEMAS_MAINDOC(Path.of("schemas", "maindoc")), // + SCHEMAS(Path.of("schemas")), + SCHEMAS_JSON(Path.of("schemas", "schemas.json")), - SCHEMATRONS(Path.of("schematrons")), // - SCHEMATRONS_DYNAMIC(Path.of("schematrons", "dynamic")), // - SCHEMATRONS_STATIC(Path.of("schematrons", "static")), // + SCHEMAS_COMMON(Path.of("schemas", "common")), + SCHEMAS_MAINDOC(Path.of("schemas", "maindoc")), + + SCHEMATRONS(Path.of("schematrons")), + SCHEMATRONS_DYNAMIC(Path.of("schematrons", "dynamic")), + SCHEMATRONS_STATIC(Path.of("schematrons", "static")), /** * Internal usage, tedweb. */ - TED(Path.of(".ted")), // - TED_TEDWEB(Path.of(".ted", "tedweb")), // - TED_TEDWEB_REPORT_METADATA(Path.of(".ted", "tedweb", "report-metadata.json")), // - TED_TEDWEB_SEARCH_METADATA(Path.of(".ted", "tedweb", "search-metadata.json")), // + TED(Path.of(".ted")), + TED_TEDWEB(Path.of(".ted", "tedweb")), + TED_TEDWEB_REPORT_METADATA(Path.of(".ted", "tedweb", "report-metadata.json")), + TED_TEDWEB_SEARCH_METADATA(Path.of(".ted", "tedweb", "search-metadata.json")), /** * Internationalisation, labels. */ - TRANSLATIONS(Path.of("translations")), // + TRANSLATIONS(Path.of("translations")), + /** * The index file for translations, only present in SDK 1.10.0 and later. */ - TRANSLATIONS_JSON(Path.of("translations", "translations.json")), // + TRANSLATIONS_JSON(Path.of("translations", "translations.json")), + + VALIDATION(Path.of("validation")), + VALIDATION_RULES_EFX(Path.of("validation", "rules.efx")), - VIEW_TEMPLATES(Path.of("view-templates")), // + VIEW_TEMPLATES(Path.of("view-templates")), VIEW_TEMPLATES_JSON(Path.of("view-templates", "view-templates.json")); private Path path; From ebb56fac77a8ce049045f3c0bbbcd16ffde8598a Mon Sep 17 00:00:00 2001 From: ROUSSY Christophe Date: Mon, 13 Jul 2026 12:15:04 +0200 Subject: [PATCH 5/8] TEDEFO-4860 adding more constants and enum entries in SdkConstants --- .../europa/ted/eforms/sdk/SdkConstants.java | 111 +++++++++++++----- 1 file changed, 79 insertions(+), 32 deletions(-) diff --git a/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java b/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java index 707972f..c6ebd00 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java @@ -4,9 +4,29 @@ import eu.europa.ted.eforms.sdk.resource.PathResource; public class SdkConstants { + + public static final Path DEFAULT_SDK_ROOT = Path.of("eforms-sdk"); + + public static final String CODELISTS_DIR_NAME = "codelists"; + public static final String CODELISTS_JSON_FILE_NAME = "codelists.json"; + public static final String FIELDS_JSON_XML_STRUCTURE_KEY = "xmlStructure"; public static final String FIELDS_JSON_FIELDS_KEY = "fields"; + public static final String FIELDS_DIR_NAME = "fields"; + + public static final String NODES_JSON = "nodes.json"; + public static final String FIELDS_JSON_FILENAME = "fields.json"; + public static final String DATA_TYPES_JSON = "data-types.json"; + public static final String BUSINESS_TERMS_JSON = "business-terms.json"; + public static final String BUSINESS_ENTITIES_PROPERTIES_JSON = "business-entities-properties.json"; + public static final String BUSINESS_ENTITIES_HIERARCHIES_JSON = "business-entities-hierarchies.json"; + public static final String BUSINESS_ENTITIES_COMPOSITION_JSON = "business-entities-composition.json"; + + public static final String MIGRATION_DIR_NAME = "migration"; + public static final String MIGRATION_JSON_FILE_NAME = "migration.json"; + public static final String NOTICE_TYPES_DIR_NAME = "notice-types"; + public static final String NOTICE_TYPES_JSON_FILE_NAME = "notice-types.json"; public static final String NOTICE_TYPES_JSON_SUBTYPES_KEY = "noticeSubTypes"; public static final String NOTICE_TYPES_JSON_DOCUMENT_TYPES_KEY = "documentTypes"; public static final String NOTICE_TYPES_JSON_DOCUMENT_TYPE_KEY = "documentType"; @@ -14,58 +34,84 @@ public class SdkConstants { public static final String NOTICE_TYPES_JSON_ROOT_ELEMENT_KEY = "rootElement"; public static final String NOTICE_CUSTOMIZATION_ID_VERSION_PREFIX = "eforms-sdk-"; - public static final Path DEFAULT_SDK_ROOT = Path.of("eforms-sdk"); - public static final String SDK_GROUP_ID = "eu.europa.ted.eforms"; public static final String SDK_ARTIFACT_ID = "eforms-sdk"; public static final String SDK_PACKAGING = "jar"; + public static final String SCHEMAS_DIR_NAME = "schemas"; + public static final String SCHEMAS_JSON_FILE_NAME = "schemas.json"; + public static final String SCHEMATRONS_DIR_NAME = "schematrons"; + + public static final String TRANSLATIONS_DIR_NAME = "translations"; + public static final String TRANSLATIONS_JSON_FILE_NAME = "translations.json"; + public static final String VALIDATION_DIR_NAME = "validation"; + public static final String VALIDATION_RULES_EFX_FILE_NAME = "rules.efx"; + public static final String VALIDATION_DEPENDENCIES_JSON_FILE_NAME = "dependencies.json"; + + public static final String VIEW_TEMPLATES_DIR_NAME = "view-templates"; + public static final String VIEW_TEMPLATES_JSON_FILE_NAME = "view-templates.json"; + /** - * Forward folder of SDK2+, it can exist in some folders. + * Forward folder of SDK2+, it can exist in some folders. + * Files in that folder can be used to preview SDK2 features. */ public static final String FWD = "fwd"; private SdkConstants() {} public enum SdkResource implements PathResource { - CODELISTS(Path.of("codelists")), - CODELISTS_JSON(Path.of("codelists", "codelists.json")), + CODELISTS(Path.of(CODELISTS_DIR_NAME)), + CODELISTS_JSON(Path.of(CODELISTS_DIR_NAME, CODELISTS_JSON_FILE_NAME)), EFX_GRAMMAR(Path.of("efx-grammar")), - FIELDS(Path.of("fields")), - FIELDS_JSON(Path.of("fields", "fields.json")), + FIELDS(Path.of(FIELDS_DIR_NAME)), - // FIELDS FWD FOLDER. - BUSINESS_ENTITIES_COMPOSITION(Path.of("fields", FWD, "business-entities-composition.json")), - BUSINESS_ENTITIES_HIERARCHY(Path.of("fields", FWD, "business-entities-hierarchies.json")), - BUSINESS_ENTITIES_PROPERTIES(Path.of("fields", FWD, "business-entities-properties.json")), - BUSINESS_TERMS(Path.of("fields", FWD, "business-terms.json")), - DATA_TYPES(Path.of("fields", FWD, "data-types.json")), - FIELDS_JSON_LIST(Path.of("fields", FWD, "fields.json")), - NODES_JSON_LIST(Path.of("fields", FWD, "nodes.json")), + /** + * Fields and nodes. + */ + FIELDS_JSON(Path.of(FIELDS_DIR_NAME, FIELDS_JSON_FILENAME)), + + BUSINESS_ENTITIES_COMPOSITION(Path.of(FIELDS_DIR_NAME, FWD, BUSINESS_ENTITIES_COMPOSITION_JSON)), + BUSINESS_ENTITIES_HIERARCHY(Path.of(FIELDS_DIR_NAME, FWD, BUSINESS_ENTITIES_HIERARCHIES_JSON)), + BUSINESS_ENTITIES_PROPERTIES(Path.of(FIELDS_DIR_NAME, FWD, BUSINESS_ENTITIES_PROPERTIES_JSON)), + BUSINESS_TERMS(Path.of(FIELDS_DIR_NAME, FWD, BUSINESS_TERMS_JSON)), + DATA_TYPES(Path.of(FIELDS_DIR_NAME, FWD, DATA_TYPES_JSON)), + + /** + * JSON with array of fields. + */ + FIELDS_JSON_LIST(Path.of(FIELDS_DIR_NAME, FWD, FIELDS_JSON_FILENAME)), + + /** + * JSON with array of nodes. + */ + NODES_JSON_LIST(Path.of(FIELDS_DIR_NAME, FWD, NODES_JSON)), /** * Related to asset migration. */ - MIGRATION(Path.of("migration")), - MIGRATION_JSON(Path.of("migration", "migration.json")), + MIGRATION(Path.of(MIGRATION_DIR_NAME)), + MIGRATION_JSON(Path.of(MIGRATION_DIR_NAME, MIGRATION_JSON_FILE_NAME)), - NOTICE_TYPES(Path.of("notice-types")), - NOTICE_TYPES_JSON(Path.of("notice-types", "notice-types.json")), + /** + * Notice Types Definitions (NTD). + */ + NOTICE_TYPES(Path.of(NOTICE_TYPES_DIR_NAME)), + NOTICE_TYPES_JSON(Path.of(NOTICE_TYPES_DIR_NAME, NOTICE_TYPES_JSON_FILE_NAME)), /** * Schema files. */ - SCHEMAS(Path.of("schemas")), - SCHEMAS_JSON(Path.of("schemas", "schemas.json")), + SCHEMAS(Path.of(SCHEMAS_DIR_NAME)), + SCHEMAS_JSON(Path.of(SCHEMAS_DIR_NAME, SCHEMAS_JSON_FILE_NAME)), - SCHEMAS_COMMON(Path.of("schemas", "common")), - SCHEMAS_MAINDOC(Path.of("schemas", "maindoc")), + SCHEMAS_COMMON(Path.of(SCHEMAS_DIR_NAME, "common")), + SCHEMAS_MAINDOC(Path.of(SCHEMAS_DIR_NAME, "maindoc")), - SCHEMATRONS(Path.of("schematrons")), - SCHEMATRONS_DYNAMIC(Path.of("schematrons", "dynamic")), - SCHEMATRONS_STATIC(Path.of("schematrons", "static")), + SCHEMATRONS(Path.of(SCHEMATRONS_DIR_NAME)), + SCHEMATRONS_DYNAMIC(Path.of(SCHEMATRONS_DIR_NAME, "dynamic")), + SCHEMATRONS_STATIC(Path.of(SCHEMATRONS_DIR_NAME, "static")), /** * Internal usage, tedweb. @@ -78,18 +124,19 @@ public enum SdkResource implements PathResource { /** * Internationalisation, labels. */ - TRANSLATIONS(Path.of("translations")), + TRANSLATIONS(Path.of(TRANSLATIONS_DIR_NAME)), /** * The index file for translations, only present in SDK 1.10.0 and later. */ - TRANSLATIONS_JSON(Path.of("translations", "translations.json")), + TRANSLATIONS_JSON(Path.of(TRANSLATIONS_DIR_NAME, TRANSLATIONS_JSON_FILE_NAME)), - VALIDATION(Path.of("validation")), - VALIDATION_RULES_EFX(Path.of("validation", "rules.efx")), + VALIDATION(Path.of(VALIDATION_DIR_NAME)), + VALIDATION_RULES_EFX(Path.of(VALIDATION_DIR_NAME, VALIDATION_RULES_EFX_FILE_NAME)), + VALIDATION_DEPENDENCIES_JSON(Path.of(VALIDATION_DIR_NAME, VALIDATION_DEPENDENCIES_JSON_FILE_NAME)), - VIEW_TEMPLATES(Path.of("view-templates")), - VIEW_TEMPLATES_JSON(Path.of("view-templates", "view-templates.json")); + VIEW_TEMPLATES(Path.of(VIEW_TEMPLATES_DIR_NAME)), + VIEW_TEMPLATES_JSON(Path.of(VIEW_TEMPLATES_DIR_NAME, VIEW_TEMPLATES_JSON_FILE_NAME)); private Path path; From c98f79ff00154a8924ea8d9b9b549e2470bcc8f5 Mon Sep 17 00:00:00 2001 From: Ioannis Rosuochatzakis Date: Fri, 17 Jul 2026 06:38:01 +0200 Subject: [PATCH 6/8] docs: Update changelog for 1.7.0 release --- CHANGELOG.md | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5eabc2..73e65f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,38 +1,20 @@ -# eForms Core Library 1.6.0 Release Notes +# eForms Core Library 1.7.0 Release Notes The eForms Core Library is a collection of utilities used by the EFX Toolkit for Java Developers and other eForms applications. ## In this release -### SDK entity improvements +### SDK constants and resources -- Versioned SDK entity classes (`SdkFieldV1`, `SdkFieldV2`, `SdkNodeV1`, `SdkNodeV2`, etc.) have been moved from the EFX Toolkit into the core library, consolidating version-specific implementations in a single location. -- `SdkNode` now supports parent node references and ancestor chain traversal via `getAncestry()`. -- `SdkField` now exposes repeatability information, parent node references, and parsed XPath metadata via `getXpathInfo()`. -- Repository classes (`SdkNodeRepository`, `SdkFieldRepository`) now use two-pass loading to wire parent-child relationships during initialization. +- Added new SDK path, filename, and resource constants, including support for the validation folder and the `fwd` forward folder used by SDK 2. -### Privacy and data type support +### Performance -- Added `PrivacySettings` to `SdkField`, providing access to privacy code, justification, publication date, and related field references. -- Introduced `SdkDataType` entity and `SdkDataTypeRepository` for field type-level metadata including privacy masking values. -- Separated `duration` as a distinct data type from `measure`. +- Replaced Reflections with ClassGraph for component scanning and share a single classpath scan across factories, reducing startup cost (`SdkComponentFactory`). -### Notice subtype management +### Fixes -- Added `SdkNoticeSubtype` entity with intelligent ID parsing (prefix/number/suffix decomposition) and correct sorting order. -- Added `SdkNoticeTypeRepository` to load and manage notice subtypes. - -### Utilities - -- Moved `NoticeDocument` and `SafeDocumentBuilder` from the eforms-notice-viewer into the core library. `NoticeDocument` provides secure XML parsing with accessors for notice subtype, SDK version, and language detection. `SafeDocumentBuilder` implements XXE prevention following OWASP guidelines. - -### Component registry - -- Added component types for dependency extraction (`EFX_COMPUTE_DEPENDENCY_EXTRACTOR`, `EFX_VALIDATION_DEPENDENCY_EXTRACTOR`) and EFX rules translation (`EFX_RULES_TRANSLATOR`). - -### Dependencies - -- Updated versions of various dependencies. +- `SdkFieldV1` now maps the `measure` type to `duration`, consistent with the `duration`/`measure` split introduced in 1.6.0. ## Download From f3880c4d03a742d56a5ced276cdabe60d94d0965 Mon Sep 17 00:00:00 2001 From: Ioannis Rosuochatzakis Date: Fri, 17 Jul 2026 06:40:29 +0200 Subject: [PATCH 7/8] pom: Set version to 1.7.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 873fc67..435c7e1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ eu.europa.ted.eforms eforms-core-java - 1.7.0-SNAPSHOT + 1.7.0 eForms Core Library API and tools for eForms applications. @@ -33,7 +33,7 @@ - 2025-07-30T08:40:55Z + 2026-07-17T04:40:22Z UTF-8 From 1e8697445c10d9f11a5b15e3699bf0d9eafcfe13 Mon Sep 17 00:00:00 2001 From: Ioannis Rosuochatzakis Date: Fri, 17 Jul 2026 07:34:44 +0200 Subject: [PATCH 8/8] refactor: Standardize SdkConstants naming conventions --- .../europa/ted/eforms/sdk/SdkConstants.java | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java b/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java index c6ebd00..d3c9d77 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/SdkConstants.java @@ -4,9 +4,9 @@ import eu.europa.ted.eforms.sdk.resource.PathResource; public class SdkConstants { - + public static final Path DEFAULT_SDK_ROOT = Path.of("eforms-sdk"); - + public static final String CODELISTS_DIR_NAME = "codelists"; public static final String CODELISTS_JSON_FILE_NAME = "codelists.json"; @@ -14,13 +14,13 @@ public class SdkConstants { public static final String FIELDS_JSON_FIELDS_KEY = "fields"; public static final String FIELDS_DIR_NAME = "fields"; - public static final String NODES_JSON = "nodes.json"; - public static final String FIELDS_JSON_FILENAME = "fields.json"; - public static final String DATA_TYPES_JSON = "data-types.json"; - public static final String BUSINESS_TERMS_JSON = "business-terms.json"; - public static final String BUSINESS_ENTITIES_PROPERTIES_JSON = "business-entities-properties.json"; - public static final String BUSINESS_ENTITIES_HIERARCHIES_JSON = "business-entities-hierarchies.json"; - public static final String BUSINESS_ENTITIES_COMPOSITION_JSON = "business-entities-composition.json"; + public static final String NODES_JSON_FILE_NAME = "nodes.json"; + public static final String FIELDS_JSON_FILE_NAME = "fields.json"; + public static final String DATA_TYPES_JSON_FILE_NAME = "data-types.json"; + public static final String BUSINESS_TERMS_JSON_FILE_NAME = "business-terms.json"; + public static final String BUSINESS_ENTITIES_PROPERTIES_JSON_FILE_NAME = "business-entities-properties.json"; + public static final String BUSINESS_ENTITIES_HIERARCHIES_JSON_FILE_NAME = "business-entities-hierarchies.json"; + public static final String BUSINESS_ENTITIES_COMPOSITION_JSON_FILE_NAME = "business-entities-composition.json"; public static final String MIGRATION_DIR_NAME = "migration"; public static final String MIGRATION_JSON_FILE_NAME = "migration.json"; @@ -37,11 +37,11 @@ public class SdkConstants { public static final String SDK_GROUP_ID = "eu.europa.ted.eforms"; public static final String SDK_ARTIFACT_ID = "eforms-sdk"; public static final String SDK_PACKAGING = "jar"; - + public static final String SCHEMAS_DIR_NAME = "schemas"; public static final String SCHEMAS_JSON_FILE_NAME = "schemas.json"; public static final String SCHEMATRONS_DIR_NAME = "schematrons"; - + public static final String TRANSLATIONS_DIR_NAME = "translations"; public static final String TRANSLATIONS_JSON_FILE_NAME = "translations.json"; public static final String VALIDATION_DIR_NAME = "validation"; @@ -52,10 +52,10 @@ public class SdkConstants { public static final String VIEW_TEMPLATES_JSON_FILE_NAME = "view-templates.json"; /** - * Forward folder of SDK2+, it can exist in some folders. + * Forward folder of SDK2+, it can exist in some folders. * Files in that folder can be used to preview SDK2 features. */ - public static final String FWD = "fwd"; + public static final String FWD_DIR_NAME = "fwd"; private SdkConstants() {} @@ -66,27 +66,28 @@ public enum SdkResource implements PathResource { EFX_GRAMMAR(Path.of("efx-grammar")), FIELDS(Path.of(FIELDS_DIR_NAME)), - + FIELDS_FWD(Path.of(FIELDS_DIR_NAME, FWD_DIR_NAME)), + /** * Fields and nodes. */ - FIELDS_JSON(Path.of(FIELDS_DIR_NAME, FIELDS_JSON_FILENAME)), - - BUSINESS_ENTITIES_COMPOSITION(Path.of(FIELDS_DIR_NAME, FWD, BUSINESS_ENTITIES_COMPOSITION_JSON)), - BUSINESS_ENTITIES_HIERARCHY(Path.of(FIELDS_DIR_NAME, FWD, BUSINESS_ENTITIES_HIERARCHIES_JSON)), - BUSINESS_ENTITIES_PROPERTIES(Path.of(FIELDS_DIR_NAME, FWD, BUSINESS_ENTITIES_PROPERTIES_JSON)), - BUSINESS_TERMS(Path.of(FIELDS_DIR_NAME, FWD, BUSINESS_TERMS_JSON)), - DATA_TYPES(Path.of(FIELDS_DIR_NAME, FWD, DATA_TYPES_JSON)), - + FIELDS_JSON(Path.of(FIELDS_DIR_NAME, FIELDS_JSON_FILE_NAME)), + + FIELDS_FWD_BUSINESS_ENTITIES_COMPOSITION(Path.of(FIELDS_DIR_NAME, FWD_DIR_NAME, BUSINESS_ENTITIES_COMPOSITION_JSON_FILE_NAME)), + FIELDS_FWD_BUSINESS_ENTITIES_HIERARCHIES(Path.of(FIELDS_DIR_NAME, FWD_DIR_NAME, BUSINESS_ENTITIES_HIERARCHIES_JSON_FILE_NAME)), + FIELDS_FWD_BUSINESS_ENTITIES_PROPERTIES(Path.of(FIELDS_DIR_NAME, FWD_DIR_NAME, BUSINESS_ENTITIES_PROPERTIES_JSON_FILE_NAME)), + FIELDS_FWD_BUSINESS_TERMS(Path.of(FIELDS_DIR_NAME, FWD_DIR_NAME, BUSINESS_TERMS_JSON_FILE_NAME)), + FIELDS_FWD_DATA_TYPES(Path.of(FIELDS_DIR_NAME, FWD_DIR_NAME, DATA_TYPES_JSON_FILE_NAME)), + /** - * JSON with array of fields. + * JSON with array of fields (forward folder). */ - FIELDS_JSON_LIST(Path.of(FIELDS_DIR_NAME, FWD, FIELDS_JSON_FILENAME)), - + FIELDS_FWD_FIELDS_JSON(Path.of(FIELDS_DIR_NAME, FWD_DIR_NAME, FIELDS_JSON_FILE_NAME)), + /** - * JSON with array of nodes. + * JSON with array of nodes (forward folder). */ - NODES_JSON_LIST(Path.of(FIELDS_DIR_NAME, FWD, NODES_JSON)), + FIELDS_FWD_NODES_JSON(Path.of(FIELDS_DIR_NAME, FWD_DIR_NAME, NODES_JSON_FILE_NAME)), /** * Related to asset migration. @@ -125,7 +126,7 @@ public enum SdkResource implements PathResource { * Internationalisation, labels. */ TRANSLATIONS(Path.of(TRANSLATIONS_DIR_NAME)), - + /** * The index file for translations, only present in SDK 1.10.0 and later. */