6
6
import org .lfenergy .compas .scl .data .exception .CompasSclDataServiceException ;
7
7
import org .w3c .dom .Element ;
8
8
import org .w3c .dom .Node ;
9
+ import org .w3c .dom .NodeList ;
9
10
10
- import java .util .ArrayList ;
11
- import java .util .List ;
12
- import java .util .Optional ;
11
+ import java .util .*;
13
12
14
13
import static org .lfenergy .compas .scl .data .Constants .*;
15
14
import static org .lfenergy .compas .scl .data .exception .CompasSclDataServiceErrorCode .HEADER_NOT_FOUND_ERROR_CODE ;
15
+ import static org .w3c .dom .Node .ELEMENT_NODE ;
16
16
17
+ /**
18
+ * Support class to work with the SCL XML in a generic way as W3C Element/Node class.
19
+ * This way multiple versions of the SCL XSD can easily be supported.
20
+ */
17
21
public class SclElementProcessor {
22
+ /**
23
+ * Make sure that the SCL XSD Namespace will be the default namespace used on the passed
24
+ * Node and all it's child nodes. Attributes aren't fixed, because these use the "null" namespace
25
+ * as they are marked as "unqualified" in the XSD (attributeFormDefault="unqualified").
26
+ *
27
+ * @param root The root node from which to start, will mostly be the SCL XML Element.
28
+ */
29
+ public void fixDefaultPrefix (Node root ) {
30
+ var oldNamespacePrefixes = new HashSet <String >();
31
+ // Use a stack to walk through all child nodes.
32
+ var nodes = new Stack <Node >();
33
+ // Start with the root node.
34
+ nodes .push (root );
35
+
36
+ while (!nodes .isEmpty ()) {
37
+ var node = nodes .pop ();
38
+ if (SCL_NS_URI .equals (node .getNamespaceURI ())
39
+ && node .getPrefix () != null && !node .getPrefix ().isBlank ()) {
40
+ // The namespace is the SCL XSD Namespace, but with a prefix, so we will fix that.
41
+ oldNamespacePrefixes .add (node .getPrefix ());
42
+ node .setPrefix ("" );
43
+ }
44
+
45
+ // Push all the Child Nodes (Type Element) on the Stack and continue with these.
46
+ NodeList childNodes = node .getChildNodes ();
47
+ if (childNodes != null ) {
48
+ for (int i = 0 , count = childNodes .getLength (); i < count ; ++i ) {
49
+ var childNode = childNodes .item (i );
50
+ if (childNode .getNodeType () == ELEMENT_NODE ) {
51
+ nodes .push (childNode );
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ oldNamespacePrefixes .forEach (
58
+ prefix -> root .getAttributes ().removeNamedItem ("xmlns:" + prefix )
59
+ );
60
+ }
61
+
62
+ /**
63
+ * Search for the SCL Header in the SCL Root Element and return that.
64
+ *
65
+ * @param scl The SCL Root Element
66
+ * @return The Header Element if found or empty() if not.
67
+ */
18
68
public Optional <Element > getSclHeader (Element scl ) {
19
69
return getChildNodesByName (scl , SCL_HEADER_ELEMENT_NAME ).stream ()
20
70
.findFirst ();
21
71
}
22
72
73
+ /**
74
+ * Add the SCL Header ot the SCL Root Element, because that element is important for the SCL Data Service
75
+ * we want to make sure it's there.
76
+ *
77
+ * @param scl The SCL Root Element
78
+ * @return The new created Header Element.
79
+ */
23
80
public Element addSclHeader (Element scl ) {
24
81
var header = scl .getOwnerDocument ().createElementNS (SCL_NS_URI , SCL_HEADER_ELEMENT_NAME );
25
82
header .setPrefix (SCL_NS_PREFIX );
26
83
scl .insertBefore (header , scl .getFirstChild ());
27
84
return header ;
28
85
}
29
86
87
+ /**
88
+ * Search for the private element with type "#Constants.COMPAS_SCL_EXTENSION_TYPE" on the SCL Root Element.
89
+ *
90
+ * @param scl The SCL Root Element
91
+ * @return The Private Element with the correct type if found or empty() if not.
92
+ */
30
93
public Optional <Element > getCompasPrivate (Element scl ) {
31
94
return getChildNodesByName (scl , SCL_PRIVATE_ELEMENT_NAME ).stream ()
32
95
.filter (element -> element .hasAttribute (SCL_PRIVATE_TYPE_ATTR ))
33
96
.filter (element -> element .getAttribute (SCL_PRIVATE_TYPE_ATTR ).equals (COMPAS_SCL_EXTENSION_TYPE ))
34
97
.findFirst ();
35
98
}
36
99
100
+ /**
101
+ * Create a Private Element with type "#COMPAS_SCL_EXTENSION_TYPE" on the SCL Root Element.
102
+ *
103
+ * @param scl The SCL Root Element
104
+ * @return The new created Private Element with the correct type.
105
+ */
37
106
public Element addCompasPrivate (Element scl ) {
38
107
scl .setAttribute ("xmlns:" + COMPAS_EXTENSION_NS_PREFIX , COMPAS_EXTENSION_NS_URI );
39
108
@@ -47,7 +116,14 @@ public Element addCompasPrivate(Element scl) {
47
116
return tPrivate ;
48
117
}
49
118
50
-
119
+ /**
120
+ * Add a new element with namespace "#COMPAS_EXTENSION_NS_URI" to the Private element of CoMPAS.
121
+ *
122
+ * @param compasPrivate The Private Element on which to add the new Element.
123
+ * @param localName The name of the Element to create.
124
+ * @param value The value set on the new Element.
125
+ * @return The new created Element.
126
+ */
51
127
public Element addCompasElement (Element compasPrivate , String localName , String value ) {
52
128
Element element = compasPrivate .getOwnerDocument ().createElementNS (COMPAS_EXTENSION_NS_URI , localName );
53
129
element .setPrefix (COMPAS_EXTENSION_NS_PREFIX );
@@ -56,17 +132,38 @@ public Element addCompasElement(Element compasPrivate, String localName, String
56
132
return element ;
57
133
}
58
134
135
+ /**
136
+ * Returns the value of a specific attribute from the passed Element.
137
+ *
138
+ * @param element The Element to search for the attribute.
139
+ * @param attributeName The name of the Attribute to search for.
140
+ * @return The value if found or empty() if not.
141
+ */
59
142
public Optional <String > getAttributeValue (Element element , String attributeName ) {
60
143
var value = element .getAttribute (attributeName );
61
144
return (value != null && !value .isBlank ()) ? Optional .of (value ) : Optional .empty ();
62
145
}
63
146
147
+ /**
148
+ * Search for a Child Node on the passed Element.
149
+ *
150
+ * @param root The element on which to search for a child Node.
151
+ * @param localName The name of the Child Node.
152
+ * @return The Child Node if found or empty() if not.
153
+ */
64
154
public Optional <Element > getChildNodeByName (Element root , String localName ) {
65
155
return getChildNodesByName (root , localName )
66
156
.stream ()
67
157
.findFirst ();
68
158
}
69
159
160
+ /**
161
+ * Search for all Child Node on the passed Element.
162
+ *
163
+ * @param root The element on which to search for all child Node.
164
+ * @param localName The name of the Child Node.
165
+ * @return The list of Child Nodes found.
166
+ */
70
167
public List <Element > getChildNodesByName (Element root , String localName ) {
71
168
var foundElements = new ArrayList <Element >();
72
169
var childNodes = root .getChildNodes ();
0 commit comments