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
51 changes: 51 additions & 0 deletions src/main/java/eu/europa/ted/eforms/sdk/entity/SdkField.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.Objects;
import com.fasterxml.jackson.databind.JsonNode;
import eu.europa.ted.eforms.xpath.XPathInfo;
import eu.europa.ted.eforms.xpath.XPathProcessor;

public abstract class SdkField implements Comparable<SdkField> {
private final String id;
Expand All @@ -10,6 +12,9 @@ public abstract class SdkField implements Comparable<SdkField> {
private final String parentNodeId;
private final String type;
private final String codelistId;
private final boolean repeatable;
private SdkNode parentNode;
private XPathInfo xpathInfo;

@SuppressWarnings("unused")
private SdkField() {
Expand All @@ -18,12 +23,19 @@ private SdkField() {

protected SdkField(final String id, final String type, final String parentNodeId,
final String xpathAbsolute, final String xpathRelative, final String codelistId) {
this(id, type, parentNodeId, xpathAbsolute, xpathRelative, codelistId, false);
}

protected SdkField(final String id, final String type, final String parentNodeId,
final String xpathAbsolute, final String xpathRelative, final String codelistId,
final boolean repeatable) {
this.id = id;
this.parentNodeId = parentNodeId;
this.xpathAbsolute = xpathAbsolute;
this.xpathRelative = xpathRelative;
this.type = type;
this.codelistId = codelistId;
this.repeatable = repeatable;
}

protected SdkField(final JsonNode fieldNode) {
Expand All @@ -33,6 +45,7 @@ protected SdkField(final JsonNode fieldNode) {
this.xpathRelative = fieldNode.get("xpathRelative").asText(null);
this.type = fieldNode.get("type").asText(null);
this.codelistId = extractCodelistId(fieldNode);
this.repeatable = extractRepeatable(fieldNode);
}

protected String extractCodelistId(final JsonNode fieldNode) {
Expand All @@ -49,6 +62,20 @@ protected String extractCodelistId(final JsonNode fieldNode) {
return valueNode.get("id").asText(null);
}

protected boolean extractRepeatable(final JsonNode fieldNode) {
final JsonNode repeatableNode = fieldNode.get("repeatable");
if (repeatableNode == null) {
return false;
}

final JsonNode valueNode = repeatableNode.get("value");
if (valueNode == null) {
return false;
}

return valueNode.asBoolean(false);
}

public String getId() {
return id;
}
Expand All @@ -73,6 +100,30 @@ public String getCodelistId() {
return codelistId;
}

public boolean isRepeatable() {
return repeatable;
}

public SdkNode getParentNode() {
return parentNode;
}

public void setParentNode(SdkNode parentNode) {
this.parentNode = parentNode;
}

/**
* Returns parsed XPath information for this field.
* Provides access to attribute info, path decomposition, and predicate checks.
* Lazily initialized on first access.
*/
public XPathInfo getXpathInfo() {
if (this.xpathInfo == null) {
this.xpathInfo = XPathProcessor.parse(this.xpathAbsolute);
}
return this.xpathInfo;
}

/**
* Helps with hash maps collisions. Should be consistent with equals.
*/
Expand Down
44 changes: 43 additions & 1 deletion src/main/java/eu/europa/ted/eforms/sdk/entity/SdkNode.java
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -12,6 +15,8 @@ public abstract class SdkNode implements Comparable<SdkNode> {
private final String xpathRelative;
private final String parentId;
private final boolean repeatable;
private SdkNode parent;
private List<String> cachedAncestry;

protected SdkNode(final String id, final String parentId, final String xpathAbsolute,
final String xpathRelative, final boolean repeatable) {
Expand Down Expand Up @@ -51,9 +56,46 @@ public boolean isRepeatable() {
return repeatable;
}

public SdkNode getParent() {
return parent;
}

/**
* Sets the parent node and invalidates the cached ancestry.
* Should only be called during SDK initialization (two-pass loading).
*
* @param parent the parent node
*/
public void setParent(SdkNode parent) {
this.parent = parent;
this.cachedAncestry = null;
}

/**
* Returns the ancestry chain from this node to the root.
* The list includes this node as the first element, followed by its parent,
* grandparent, and so on up to the root node.
*
* The result is cached and recomputed only when the parent changes.
*
* @return unmodifiable list of node IDs ordered from child (this node) to root
*/
public List<String> getAncestry() {
if (cachedAncestry == null) {
List<String> ancestry = new ArrayList<>();
SdkNode current = this;
while (current != null) {
ancestry.add(current.getId());
current = current.getParent();
}
cachedAncestry = Collections.unmodifiableList(ancestry);
}
return cachedAncestry;
}

@Override
public int compareTo(SdkNode o) {
return o.getId().compareTo(o.getId());
return this.getId().compareTo(o.getId());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package eu.europa.ted.eforms.sdk.entity.v1;

import java.util.List;
import java.util.Optional;
import eu.europa.ted.eforms.sdk.component.SdkComponent;
import eu.europa.ted.eforms.sdk.component.SdkComponentType;
import eu.europa.ted.eforms.sdk.entity.SdkCodelist;

/**
* Representation of an SdkCodelist for usage in the symbols map.
*
* @author rouschr
*/
@SdkComponent(versions = {"1"}, componentType = SdkComponentType.CODELIST)
public class SdkCodelistV1 extends SdkCodelist {

public SdkCodelistV1(final String codelistId, final String codelistVersion,
final List<String> codes, final Optional<String> parentId) {
super(codelistId, codelistVersion, codes, parentId);
}
}
65 changes: 65 additions & 0 deletions src/main/java/eu/europa/ted/eforms/sdk/entity/v1/SdkFieldV1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package eu.europa.ted.eforms.sdk.entity.v1;

import java.util.Map;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import eu.europa.ted.eforms.sdk.component.SdkComponent;
import eu.europa.ted.eforms.sdk.component.SdkComponentType;
import eu.europa.ted.eforms.sdk.entity.SdkField;

@SdkComponent(versions = {"1"}, componentType = SdkComponentType.FIELD)
public class SdkFieldV1 extends SdkField {

public SdkFieldV1(final String id, final String type, final String parentNodeId,
final String xpathAbsolute, final String xpathRelative, final String codelistId,
final boolean repeatable) {
super(id, type, parentNodeId, xpathAbsolute, xpathRelative, codelistId, repeatable);
}

public SdkFieldV1(final JsonNode field) {
super(field);
}

@JsonCreator
public SdkFieldV1(
@JsonProperty("id") final String id,
@JsonProperty("type") final String type,
@JsonProperty("parentNodeId") final String parentNodeId,
@JsonProperty("xpathAbsolute") final String xpathAbsolute,
@JsonProperty("xpathRelative") final String xpathRelative,
@JsonProperty("codeList") final Map<String, Map<String, String>> codelist,
@JsonProperty("repeatable") final Map<String, Object> repeatable) {
this(id, type, parentNodeId, xpathAbsolute, xpathRelative, getCodelistId(codelist),
getRepeatable(repeatable));
}

protected static String getCodelistId(Map<String, Map<String, String>> codelist) {
if (codelist == null) {
return null;
}

Map<String, String> value = codelist.get("value");
if (value == null) {
return null;
}

return value.get("id");
}

protected static boolean getRepeatable(Map<String, Object> repeatable) {
if (repeatable == null) {
return false;
}

// If there are constraints, the field may repeat conditionally - treat as repeatable
Object constraints = repeatable.get("constraints");
if (constraints != null) {
return true;
}

// Otherwise check the default value
Object value = repeatable.get("value");
return Boolean.TRUE.equals(value);
}
}
29 changes: 29 additions & 0 deletions src/main/java/eu/europa/ted/eforms/sdk/entity/v1/SdkNodeV1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package eu.europa.ted.eforms.sdk.entity.v1;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import eu.europa.ted.eforms.sdk.component.SdkComponent;
import eu.europa.ted.eforms.sdk.component.SdkComponentType;
import eu.europa.ted.eforms.sdk.entity.SdkNode;

/**
* A node is something like a section. Nodes can be parents of other nodes or parents of fields.
*/
@SdkComponent(versions = {"1"}, componentType = SdkComponentType.NODE)
public class SdkNodeV1 extends SdkNode {

@JsonCreator
public SdkNodeV1(
@JsonProperty("id") String id,
@JsonProperty("parentId") String parentId,
@JsonProperty("xpathAbsolute") String xpathAbsolute,
@JsonProperty("xpathRelative") String xpathRelative,
@JsonProperty("repeatable") boolean repeatable) {
super(id, parentId, xpathAbsolute, xpathRelative, repeatable);
}

public SdkNodeV1(JsonNode node) {
super(node);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package eu.europa.ted.eforms.sdk.entity.v1;

import com.fasterxml.jackson.databind.JsonNode;
import eu.europa.ted.eforms.sdk.component.SdkComponent;
import eu.europa.ted.eforms.sdk.component.SdkComponentType;
import eu.europa.ted.eforms.sdk.entity.SdkNoticeSubtype;

/**
* Represents a notice subtype from the SDK's notice-types.json file.
*/
@SdkComponent(versions = {"1"}, componentType = SdkComponentType.NOTICE_TYPE)
public class SdkNoticeSubtypeV1 extends SdkNoticeSubtype {

public SdkNoticeSubtypeV1(String subTypeId, String documentType, String type) {
super(subTypeId, documentType, type);
}

public SdkNoticeSubtypeV1(JsonNode json) {
super(json);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package eu.europa.ted.eforms.sdk.entity.v2;

import java.util.List;
import java.util.Optional;
import eu.europa.ted.eforms.sdk.component.SdkComponent;
import eu.europa.ted.eforms.sdk.component.SdkComponentType;
import eu.europa.ted.eforms.sdk.entity.v1.SdkCodelistV1;

/**
* Representation of an SdkCodelist for usage in the symbols map.
*
* @author rouschr
*/
@SdkComponent(versions = {"2"}, componentType = SdkComponentType.CODELIST)
public class SdkCodelistV2 extends SdkCodelistV1 {

public SdkCodelistV2(final String codelistId, final String codelistVersion,
final List<String> codes, final Optional<String> parentId) {
super(codelistId, codelistVersion, codes, parentId);
}
}
43 changes: 43 additions & 0 deletions src/main/java/eu/europa/ted/eforms/sdk/entity/v2/SdkFieldV2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package eu.europa.ted.eforms.sdk.entity.v2;

import java.util.Map;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import eu.europa.ted.eforms.sdk.component.SdkComponent;
import eu.europa.ted.eforms.sdk.component.SdkComponentType;
import eu.europa.ted.eforms.sdk.entity.v1.SdkFieldV1;

@SdkComponent(versions = {"2"}, componentType = SdkComponentType.FIELD)
public class SdkFieldV2 extends SdkFieldV1 {
private final String alias;

public SdkFieldV2(String id, String type, String parentNodeId, String xpathAbsolute,
String xpathRelative, String rootCodelistId, boolean repeatable, String alias) {
super(id, type, parentNodeId, xpathAbsolute, xpathRelative, rootCodelistId, repeatable);
this.alias = alias;
}

public SdkFieldV2(JsonNode fieldNode) {
super(fieldNode);
this.alias = fieldNode.has("alias") ? fieldNode.get("alias").asText(null) : null;
}

@JsonCreator
public SdkFieldV2(
@JsonProperty("id") final String id,
@JsonProperty("type") final String type,
@JsonProperty("parentNodeId") final String parentNodeId,
@JsonProperty("xpathAbsolute") final String xpathAbsolute,
@JsonProperty("xpathRelative") final String xpathRelative,
@JsonProperty("codeList") final Map<String, Map<String, String>> codelist,
@JsonProperty("repeatable") final Map<String, Object> repeatable,
@JsonProperty("alias") final String alias) {
this(id, type, parentNodeId, xpathAbsolute, xpathRelative, getCodelistId(codelist),
getRepeatable(repeatable), alias);
}

public String getAlias() {
return alias;
}
}
Loading