diff --git a/src/main/java/eu/europa/ted/eforms/sdk/entity/SdkDataType.java b/src/main/java/eu/europa/ted/eforms/sdk/entity/SdkDataType.java new file mode 100644 index 0000000..396eb57 --- /dev/null +++ b/src/main/java/eu/europa/ted/eforms/sdk/entity/SdkDataType.java @@ -0,0 +1,68 @@ +/* + * Copyright 2026 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.eforms.sdk.entity; + +import java.util.Objects; + +/** + * Represents an eForms SDK data type. + * + * Each field in the SDK has a type (e.g., "text", "date", "amount"). This entity captures + * type-level metadata such as the privacy masking value. Currently hardcoded; will be loaded from + * data-types.json when it is added to the SDK. + */ +public class SdkDataType { + private final String id; + private final String privacyMask; + + @SuppressWarnings("unused") + private SdkDataType() { + throw new UnsupportedOperationException(); + } + + public SdkDataType(final String id, final String privacyMask) { + this.id = id; + this.privacyMask = privacyMask; + } + + public String getId() { + return this.id; + } + + public String getPrivacyMask() { + return this.privacyMask; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + SdkDataType other = (SdkDataType) obj; + return Objects.equals(this.id, other.id); + } + + @Override + public int hashCode() { + return Objects.hash(this.id); + } + + @Override + public String toString() { + return this.id; + } +} diff --git a/src/main/java/eu/europa/ted/eforms/sdk/entity/SdkField.java b/src/main/java/eu/europa/ted/eforms/sdk/entity/SdkField.java index 88c2613..a6fa4c7 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/entity/SdkField.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/entity/SdkField.java @@ -13,9 +13,82 @@ public abstract class SdkField implements Comparable { private final String type; private final String codelistId; private final boolean repeatable; + private final String privacyCode; + private final PrivacySettings privacySettings; private SdkNode parentNode; private XPathInfo xpathInfo; + /** + * Privacy settings for fields that can be withheld from publication. + */ + public static class PrivacySettings { + private final String privacyCodeFieldId; + private final String justificationCodeFieldId; + private final String justificationDescriptionFieldId; + private final String publicationDateFieldId; + private SdkField privacyCodeField; + private SdkField justificationCodeField; + private SdkField justificationDescriptionField; + private SdkField publicationDateField; + + public PrivacySettings(final String privacyCodeFieldId, + final String justificationCodeFieldId, final String justificationDescriptionFieldId, + final String publicationDateFieldId) { + this.privacyCodeFieldId = privacyCodeFieldId; + this.justificationCodeFieldId = justificationCodeFieldId; + this.justificationDescriptionFieldId = justificationDescriptionFieldId; + this.publicationDateFieldId = publicationDateFieldId; + } + + public String getPrivacyCodeFieldId() { + return this.privacyCodeFieldId; + } + + public String getJustificationCodeFieldId() { + return this.justificationCodeFieldId; + } + + public String getJustificationDescriptionFieldId() { + return this.justificationDescriptionFieldId; + } + + public String getPublicationDateFieldId() { + return this.publicationDateFieldId; + } + + public SdkField getPrivacyCodeField() { + return this.privacyCodeField; + } + + public void setPrivacyCodeField(SdkField privacyCodeField) { + this.privacyCodeField = privacyCodeField; + } + + public SdkField getJustificationCodeField() { + return this.justificationCodeField; + } + + public void setJustificationCodeField(SdkField justificationCodeField) { + this.justificationCodeField = justificationCodeField; + } + + public SdkField getJustificationDescriptionField() { + return this.justificationDescriptionField; + } + + public void setJustificationDescriptionField(SdkField justificationDescriptionField) { + this.justificationDescriptionField = justificationDescriptionField; + } + + public SdkField getPublicationDateField() { + return this.publicationDateField; + } + + public void setPublicationDateField(SdkField publicationDateField) { + this.publicationDateField = publicationDateField; + } + } + @SuppressWarnings("unused") private SdkField() { throw new UnsupportedOperationException(); @@ -36,6 +109,8 @@ protected SdkField(final String id, final String type, final String parentNodeId this.type = type; this.codelistId = codelistId; this.repeatable = repeatable; + this.privacyCode = null; + this.privacySettings = null; } protected SdkField(final JsonNode fieldNode) { @@ -46,6 +121,9 @@ protected SdkField(final JsonNode fieldNode) { this.type = fieldNode.get("type").asText(null); this.codelistId = extractCodelistId(fieldNode); this.repeatable = extractRepeatable(fieldNode); + final JsonNode privacyNode = fieldNode.get("privacy"); + this.privacyCode = privacyNode != null ? privacyNode.get("code").asText(null) : null; + this.privacySettings = extractPrivacy(privacyNode); } protected String extractCodelistId(final JsonNode fieldNode) { @@ -76,36 +154,59 @@ protected boolean extractRepeatable(final JsonNode fieldNode) { return valueNode.asBoolean(false); } + protected PrivacySettings extractPrivacy(final JsonNode privacyNode) { + if (privacyNode == null) { + return null; + } + + final String privacyCodeFieldId = privacyNode.get("unpublishedFieldId").asText(null); + final String justificationCodeFieldId = privacyNode.get("reasonCodeFieldId").asText(null); + final String justificationDescriptionFieldId = + privacyNode.get("reasonDescriptionFieldId").asText(null); + final String publicationDateFieldId = privacyNode.get("publicationDateFieldId").asText(null); + + return new PrivacySettings(privacyCodeFieldId, justificationCodeFieldId, + justificationDescriptionFieldId, publicationDateFieldId); + } + public String getId() { - return id; + return this.id; } public String getParentNodeId() { - return parentNodeId; + return this.parentNodeId; } public String getXpathAbsolute() { - return xpathAbsolute; + return this.xpathAbsolute; } public String getXpathRelative() { - return xpathRelative; + return this.xpathRelative; } public String getType() { - return type; + return this.type; } public String getCodelistId() { - return codelistId; + return this.codelistId; } public boolean isRepeatable() { - return repeatable; + return this.repeatable; + } + + public String getPrivacyCode() { + return this.privacyCode; + } + + public PrivacySettings getPrivacySettings() { + return this.privacySettings; } public SdkNode getParentNode() { - return parentNode; + return this.parentNode; } public void setParentNode(SdkNode parentNode) { @@ -144,16 +245,16 @@ public boolean equals(Object obj) { return false; } SdkField other = (SdkField) obj; - return Objects.equals(id, other.id); + return Objects.equals(this.id, other.id); } @Override public int hashCode() { - return Objects.hash(id); + return Objects.hash(this.id); } @Override public String toString() { - return id; + return this.id; } } diff --git a/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkDataTypeRepository.java b/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkDataTypeRepository.java new file mode 100644 index 0000000..5f379c4 --- /dev/null +++ b/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkDataTypeRepository.java @@ -0,0 +1,60 @@ +/* + * Copyright 2026 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.eforms.sdk.repository; + +import java.util.HashMap; +import eu.europa.ted.eforms.sdk.entity.SdkDataType; + +/** + * Repository of SDK data types. + * + * Currently uses hardcoded type definitions. When data-types.json is added to the SDK, this class + * will be updated to load type metadata from JSON. + */ +public class SdkDataTypeRepository extends HashMap { + private static final long serialVersionUID = 1L; + + /** + * Creates a repository with the default set of SDK data types and their privacy masks. This is a + * temporary approach until data-types.json is available in the SDK. + */ + public static SdkDataTypeRepository createDefault() { + SdkDataTypeRepository repository = new SdkDataTypeRepository(); + + repository.addType("text", "unpublished"); + repository.addType("text-multilingual", "unpublished"); + repository.addType("code", "unpublished"); + repository.addType("internal-code", "unpublished"); + repository.addType("id", "unpublished"); + repository.addType("id-ref", "unpublished"); + repository.addType("phone", "unpublished"); + repository.addType("email", "unpublished"); + repository.addType("url", "unpublished"); + repository.addType("date", "1970-01-01Z"); + repository.addType("zoned-date", "1970-01-01Z"); + repository.addType("time", "00:00:00Z"); + repository.addType("zoned-time", "00:00:00Z"); + repository.addType("indicator", "0"); + repository.addType("integer", "-1"); + repository.addType("number", "-1"); + repository.addType("amount", "-1"); + repository.addType("measure", "-1"); + + return repository; + } + + private void addType(String id, String privacyMask) { + this.put(id, new SdkDataType(id, privacyMask)); + } +} diff --git a/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkFieldRepository.java b/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkFieldRepository.java index 670bad5..6edebfd 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkFieldRepository.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkFieldRepository.java @@ -32,6 +32,8 @@ protected void populateMap(final JsonNode json, final Object... context) : null; final ArrayNode fields = (ArrayNode) json.get(SdkConstants.FIELDS_JSON_FIELDS_KEY); + + // First pass: create all field entities and add them to the map for (final JsonNode field : fields) { final SdkField sdkField = SdkEntityFactory.getSdkField(sdkVersion, field); put(sdkField.getId(), sdkField); @@ -40,5 +42,26 @@ protected void populateMap(final JsonNode json, final Object... context) sdkField.setParentNode(nodes.get(sdkField.getParentNodeId())); } } + + // Second pass: resolve privacy field references + for (final SdkField sdkField : this.values()) { + if (sdkField.getPrivacySettings() != null) { + SdkField.PrivacySettings privacy = sdkField.getPrivacySettings(); + + if (privacy.getPrivacyCodeFieldId() != null) { + privacy.setPrivacyCodeField(this.get(privacy.getPrivacyCodeFieldId())); + } + if (privacy.getJustificationCodeFieldId() != null) { + privacy.setJustificationCodeField(this.get(privacy.getJustificationCodeFieldId())); + } + if (privacy.getJustificationDescriptionFieldId() != null) { + privacy.setJustificationDescriptionField( + this.get(privacy.getJustificationDescriptionFieldId())); + } + if (privacy.getPublicationDateFieldId() != null) { + privacy.setPublicationDateField(this.get(privacy.getPublicationDateFieldId())); + } + } + } } }