From 5c1a2fc1427f5f42f6a1cae4a9b902b0a0cd1457 Mon Sep 17 00:00:00 2001 From: Sonia Zorba <sonia.zorba@inaf.it> Date: Sun, 13 Dec 2020 09:52:50 +0100 Subject: [PATCH] Workaround for fixing node type attribute issue --- .../datamodel/RemoveDuplicateTypeAdapter.java | 25 +++++++++++++++++++ .../ivoa/xml/vospace/v2/ContainerNode.java | 3 +++ .../java/net/ivoa/xml/vospace/v2/Node.java | 15 ++++++++++- .../net/ivoa/xml/vospace/v2/NodeTest.java | 4 +-- 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/main/java/it/inaf/oats/vospace/datamodel/RemoveDuplicateTypeAdapter.java diff --git a/src/main/java/it/inaf/oats/vospace/datamodel/RemoveDuplicateTypeAdapter.java b/src/main/java/it/inaf/oats/vospace/datamodel/RemoveDuplicateTypeAdapter.java new file mode 100644 index 0000000..7314707 --- /dev/null +++ b/src/main/java/it/inaf/oats/vospace/datamodel/RemoveDuplicateTypeAdapter.java @@ -0,0 +1,25 @@ +package it.inaf.oats.vospace.datamodel; + +import javax.xml.bind.annotation.adapters.XmlAdapter; +import net.ivoa.xml.vospace.v2.Node; + +/** + * JAXB automatically generates the xsi:type attribute, however it doesn't fill + * it for the root node (it seems that this is by design). Since we need it, we + * manually added it on the Node class, but this causes a duplication of the + * attribute in the children nodes. This adapter is applied to children nodes to + * avoid the duplication by setting the field to null. + */ +public class RemoveDuplicateTypeAdapter extends XmlAdapter<Node, Node> { + + @Override + public Node unmarshal(Node node) throws Exception { + return node; + } + + @Override + public Node marshal(Node node) throws Exception { + node.removeType(); + return node; + } +} diff --git a/src/main/java/net/ivoa/xml/vospace/v2/ContainerNode.java b/src/main/java/net/ivoa/xml/vospace/v2/ContainerNode.java index 03a7880..d25747a 100644 --- a/src/main/java/net/ivoa/xml/vospace/v2/ContainerNode.java +++ b/src/main/java/net/ivoa/xml/vospace/v2/ContainerNode.java @@ -6,6 +6,7 @@ // package net.ivoa.xml.vospace.v2; +import it.inaf.oats.vospace.datamodel.RemoveDuplicateTypeAdapter; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; @@ -14,6 +15,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** * @@ -66,6 +68,7 @@ public class ContainerNode // This should simplify usage and JSON compatibility. @XmlElement(name = "node") @XmlElementWrapper(name = "nodes", required = true) + @XmlJavaTypeAdapter(RemoveDuplicateTypeAdapter.class) protected List<Node> nodes; public List<Node> getNodes() { diff --git a/src/main/java/net/ivoa/xml/vospace/v2/Node.java b/src/main/java/net/ivoa/xml/vospace/v2/Node.java index e682221..9017944 100644 --- a/src/main/java/net/ivoa/xml/vospace/v2/Node.java +++ b/src/main/java/net/ivoa/xml/vospace/v2/Node.java @@ -59,10 +59,23 @@ public class Node { protected PropertyList properties; // <edit> + // Used for generating missing type attribute for root node. For child nodes it is filled automatically. + @XmlAttribute(name = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance", required = false) + private String type; + + /* This method exists to fix the issue with type attribute. See RemoveDuplicateTypeAdapter class. */ + public void removeType() { + this.type = null; + } + + public Node() { + type = getType(); + } + // Needed for handling inheritance in JSON (in XML, type attribute is automatically generated by JAXB). @JsonProperty @XmlTransient - public String getType() { + public final String getType() { return "vos:" + getClass().getSimpleName(); } // </edit> diff --git a/src/test/java/net/ivoa/xml/vospace/v2/NodeTest.java b/src/test/java/net/ivoa/xml/vospace/v2/NodeTest.java index 09b23f5..3612036 100644 --- a/src/test/java/net/ivoa/xml/vospace/v2/NodeTest.java +++ b/src/test/java/net/ivoa/xml/vospace/v2/NodeTest.java @@ -36,7 +36,7 @@ public class NodeTest { Document doc = loadDocument(xml); assertEquals("vos:node", doc.getDocumentElement().getNodeName()); - //assertEquals("vos:ContainerNode", doc.getDocumentElement().getAttribute("xsi:type")); + assertEquals("vos:ContainerNode", doc.getDocumentElement().getAttribute("xsi:type")); assertTrue(xml.contains("<vos:nodes>")); assertTrue(xml.contains("xsi:type=\"vos:DataNode\"")); @@ -58,7 +58,7 @@ public class NodeTest { String json = MAPPER.writeValueAsString(root); System.out.println(json); - + assertThat(json, hasJsonPath("$.type", is("vos:ContainerNode"))); assertThat(json, hasJsonPath("$.nodes[0].type", is("vos:DataNode"))); -- GitLab