• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vidal-community / atom-jaxb / #317

28 May 2024 06:34PM UTC coverage: 76.35% (+0.1%) from 76.208%
#317

push

github

jcgay
Merge remote-tracking branch 'origin/release/1.0.2'

* origin/release/1.0.2:
  [maven-release-plugin] prepare for next development iteration
  [maven-release-plugin] prepare release v1.1.0
  Make JAXBContext static to improve performance
  Introduce benchmark run with JMH
  Add @XmlRootElement on entry class

8 of 10 new or added lines in 1 file covered. (80.0%)

1 existing line in 1 file now uncovered.

410 of 537 relevant lines covered (76.35%)

0.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.69
/src/main/java/fr/vidal/oss/jaxb/atom/core/ExtensionElementAdapter.java
1
package fr.vidal.oss.jaxb.atom.core;
2

3
import static java.lang.String.format;
4

5
import java.util.Arrays;
6
import java.util.Collection;
7
import java.util.stream.Collectors;
8
import java.util.stream.IntStream;
9
import jakarta.xml.bind.JAXBContext;
10
import jakarta.xml.bind.JAXBElement;
11
import jakarta.xml.bind.JAXBException;
12
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
13
import javax.xml.parsers.DocumentBuilder;
14
import javax.xml.parsers.DocumentBuilderFactory;
15
import javax.xml.parsers.ParserConfigurationException;
16
import org.w3c.dom.Attr;
17
import org.w3c.dom.Document;
18
import org.w3c.dom.Element;
19
import org.w3c.dom.NamedNodeMap;
20
import org.w3c.dom.Node;
21
import org.w3c.dom.NodeList;
22
import org.w3c.dom.Text;
23

24
public class ExtensionElementAdapter extends XmlAdapter<Element, ExtensionElement> {
25

26
    private static final Class[] ADAPTED_TYPES = {StructuredElement.class, SimpleElement.class};
1✔
27
    private static final JAXBContext context;
28

29
    private final DocumentBuilderFactory dbf;
30

31
    static {
32
       try {
33
          context = JAXBContext.newInstance(ADAPTED_TYPES);
1✔
NEW
34
       } catch (JAXBException e) {
×
NEW
35
           throw new AtomExtensionException("Cannot instantiate JAXBContext for classes : " + Arrays.toString(ADAPTED_TYPES), e);
×
36
       }
1✔
37
    }
1✔
38

39
    public ExtensionElementAdapter() {
1✔
40
        this.dbf = DocumentBuilderFactory.newInstance();
1✔
41
    }
1✔
42

43
    @Override
44
    public Element marshal(ExtensionElement extensionElement) throws Exception {
45
        if (extensionElement == null) {
1✔
46
            return null;
×
47
        }
48

49
        JAXBElement jaxbElement = extensionElement.toJAXBElement();
1✔
50

51
        Document document = builder().newDocument();
1✔
52
        context.createMarshaller().marshal(jaxbElement, document);
1✔
53
        Element element = document.getDocumentElement();
1✔
54

55
        addAttributes(element, extensionElement);
1✔
56
        return element;
1✔
57
    }
58

59
    private DocumentBuilder builder() throws AtomExtensionException {
60
        try {
61
            return dbf.newDocumentBuilder();
1✔
UNCOV
62
        } catch (ParserConfigurationException e) {
×
63
            throw new AtomExtensionException("Cannot instantiate DocumentBuilder.", e);
×
64
        }
65
    }
66

67
    private void addAttributes(Element element, ExtensionElement extensionElement) {
68
        for (Attribute attribute : extensionElement.attributes()) {
1✔
69
            addAttribute(element, attribute);
1✔
70
        }
1✔
71
    }
1✔
72

73
    private void addAttribute(Element element, Attribute attribute) {
74
        Namespace namespace = attribute.getNamespace();
1✔
75
        String attributeName = attribute.getName();
1✔
76
        String attributeValue = attribute.getValue();
1✔
77

78
        if (namespace == null) {
1✔
79
            element.setAttribute(attributeName, attributeValue);
×
80
            return;
×
81
        }
82

83
        element.setAttributeNS(
1✔
84
            namespace.uri(),
1✔
85
            format("%s:%s", namespace.prefix(), attributeName),
1✔
86
            attributeValue
87
        );
88
    }
1✔
89

90
    @Override
91
    public ExtensionElement unmarshal(Element element) {
92
        if (element == null) {
1✔
93
            return null;
×
94
        }
95
        return extensionElement(element);
1✔
96
    }
97

98
    private ExtensionElement extensionElement(Node node) {
99

100
        ExtensionElement.Builder elementBuilder;
101
        if (isSimpleElementNode(node)) {
1✔
102
            elementBuilder = ExtensionElements.simpleElement(node.getLocalName(), node.getTextContent());
1✔
103
        } else {
104
            elementBuilder = ExtensionElements.structuredElement(node.getLocalName(), children(node));
1✔
105
        }
106

107
        return elementBuilder
1✔
108
            .withNamespace(namespace(node))
1✔
109
            .addAttributes(attributes(node))
1✔
110
            .build();
1✔
111
    }
112

113
    private boolean isSimpleElementNode(Node node) {
114
        return node.getChildNodes().getLength() == 1
1✔
115
            && isTextualNode(node.getFirstChild());
1✔
116
    }
117

118
    private boolean isTextualNode(Node node) {
119
        return Text.class.isAssignableFrom(node.getClass());
1✔
120
    }
121

122
    private Collection<ExtensionElement> children(Node node) {
123
        return toElements(node.getChildNodes());
1✔
124
    }
125

126
    private Collection<ExtensionElement> toElements(NodeList nodes) {
127
        return IntStream.range(0, nodes.getLength())
1✔
128
            .mapToObj(nodes::item)
1✔
129
            .filter(n -> !isTextualNode(n))
1✔
130
            .map(this::extensionElement)
1✔
131
            .collect(Collectors.toList());
1✔
132
    }
133

134
    private Collection<Attribute> attributes(Node node) {
135
        NamedNodeMap attributes = node.getAttributes();
1✔
136

137
        return IntStream.range(0, attributes.getLength())
1✔
138
            .mapToObj(attributes::item)
1✔
139
            .map(Attr.class::cast)
1✔
140
            .map(ExtensionElementAdapter::attribute)
1✔
141
            .collect(Collectors.toList());
1✔
142
    }
143

144
    private static Attribute attribute(Attr attribute) {
145
        Attribute.Builder builder = Attribute.builder(attribute.getLocalName(), attribute.getTextContent());
1✔
146
        if (hasProperNamespace(attribute)) {
1✔
147
            builder.withNamespace(namespace(attribute));
1✔
148
        }
149
        return builder.build();
1✔
150
    }
151

152
    private static boolean hasProperNamespace(Attr attribute) {
153
        return attribute.getNamespaceURI() != null;
1✔
154
    }
155

156
    private static Namespace namespace(Node item) {
157
        return Namespace.builder(item.getNamespaceURI()).withPrefix(item.getPrefix()).build();
1✔
158
    }
159
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc