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 a6fa4c7..45b67ae 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 @@ -1,5 +1,8 @@ package eu.europa.ted.eforms.sdk.entity; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Objects; import com.fasterxml.jackson.databind.JsonNode; import eu.europa.ted.eforms.xpath.XPathInfo; @@ -15,7 +18,12 @@ public abstract class SdkField implements Comparable { private final boolean repeatable; private final String privacyCode; private final PrivacySettings privacySettings; + private final List attributes; + private final String attributeOf; + private final String attributeName; private SdkNode parentNode; + private List attributeFields; + private SdkField attributeOfField; private XPathInfo xpathInfo; /** @@ -111,6 +119,9 @@ protected SdkField(final String id, final String type, final String parentNodeId this.repeatable = repeatable; this.privacyCode = null; this.privacySettings = null; + this.attributes = Collections.emptyList(); + this.attributeOf = null; + this.attributeName = null; } protected SdkField(final JsonNode fieldNode) { @@ -124,6 +135,21 @@ protected SdkField(final JsonNode fieldNode) { final JsonNode privacyNode = fieldNode.get("privacy"); this.privacyCode = privacyNode != null ? privacyNode.get("code").asText(null) : null; this.privacySettings = extractPrivacy(privacyNode); + this.attributes = extractAttributes(fieldNode); + this.attributeOf = fieldNode.has("attributeOf") ? fieldNode.get("attributeOf").asText(null) : null; + this.attributeName = fieldNode.has("attributeName") ? fieldNode.get("attributeName").asText(null) : null; + } + + protected List extractAttributes(final JsonNode fieldNode) { + final JsonNode attributesNode = fieldNode.get("attributes"); + if (attributesNode == null || !attributesNode.isArray()) { + return Collections.emptyList(); + } + List result = new ArrayList<>(); + for (JsonNode attr : attributesNode) { + result.add(attr.asText()); + } + return Collections.unmodifiableList(result); } protected String extractCodelistId(final JsonNode fieldNode) { @@ -193,6 +219,50 @@ public String getCodelistId() { return this.codelistId; } + public List getAttributes() { + return this.attributes; + } + + public String getAttributeOf() { + return this.attributeOf; + } + + public String getAttributeName() { + return this.attributeName; + } + + public List getAttributeFields() { + return this.attributeFields; + } + + public void setAttributeFields(List attributeFields) { + this.attributeFields = Collections.unmodifiableList(attributeFields); + } + + public SdkField getAttributeOfField() { + return this.attributeOfField; + } + + public void setAttributeOfField(SdkField attributeOfField) { + this.attributeOfField = attributeOfField; + } + + /** + * Returns the attribute field with the given XML attribute name (e.g. "unitCode", "listName"), + * or null if this field has no such attribute. + */ + public SdkField getAttributeField(String attrName) { + if (this.attributeFields == null) { + return null; + } + for (SdkField attrField : this.attributeFields) { + if (attrName.equals(attrField.getAttributeName())) { + return attrField; + } + } + return null; + } + public boolean isRepeatable() { return this.repeatable; } 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 index 5f379c4..27cd9bd 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkDataTypeRepository.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/repository/SdkDataTypeRepository.java @@ -50,6 +50,7 @@ public static SdkDataTypeRepository createDefault() { repository.addType("number", "-1"); repository.addType("amount", "-1"); repository.addType("measure", "-1"); + repository.addType("duration", "-1"); return repository; } 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 6edebfd..a06f6aa 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 @@ -1,6 +1,8 @@ package eu.europa.ted.eforms.sdk.repository; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import eu.europa.ted.eforms.sdk.SdkConstants; @@ -43,7 +45,7 @@ protected void populateMap(final JsonNode json, final Object... context) } } - // Second pass: resolve privacy field references + // Second pass: resolve cross-field references for (final SdkField sdkField : this.values()) { if (sdkField.getPrivacySettings() != null) { SdkField.PrivacySettings privacy = sdkField.getPrivacySettings(); @@ -62,6 +64,21 @@ protected void populateMap(final JsonNode json, final Object... context) privacy.setPublicationDateField(this.get(privacy.getPublicationDateFieldId())); } } + + if (!sdkField.getAttributes().isEmpty()) { + List attrFields = new ArrayList<>(); + for (String attrFieldId : sdkField.getAttributes()) { + SdkField attrField = this.get(attrFieldId); + if (attrField != null) { + attrFields.add(attrField); + } + } + sdkField.setAttributeFields(attrFields); + } + + if (sdkField.getAttributeOf() != null) { + sdkField.setAttributeOfField(this.get(sdkField.getAttributeOf())); + } } } }