21
21
22
22
import org .w3c .dom .Node ;
23
23
24
+ import javax .xml .xpath .XPath ;
25
+ import javax .xml .xpath .XPathConstants ;
26
+ import javax .xml .xpath .XPathException ;
27
+ import javax .xml .xpath .XPathFactory ;
28
+
24
29
import static uk .co .real_logic .sbe .xml .Presence .CONSTANT ;
25
30
import static uk .co .real_logic .sbe .xml .XmlSchemaParser .handleError ;
26
31
import static uk .co .real_logic .sbe .xml .XmlSchemaParser .handleWarning ;
@@ -41,6 +46,7 @@ public class EncodedDataType extends Type
41
46
private final PrimitiveValue maxValue ;
42
47
private final PrimitiveValue nullValue ;
43
48
private final String characterEncoding ;
49
+ private final String valueRef ;
44
50
private boolean varLen ;
45
51
46
52
/**
@@ -68,6 +74,20 @@ public EncodedDataType(final Node node, final String givenName, final String ref
68
74
final String lengthAttr = getAttributeValueOrNull (node , "length" );
69
75
length = Integer .parseInt (null == lengthAttr ? "1" : lengthAttr );
70
76
varLen = Boolean .parseBoolean (getAttributeValue (node , "variableLength" , "false" ));
77
+ valueRef = getAttributeValueOrNull (node , "valueRef" );
78
+
79
+ if (null != valueRef )
80
+ {
81
+ if (valueRef .indexOf ('.' ) == -1 )
82
+ {
83
+ handleError (node , "valueRef format not valid (enum-name.valid-value-name): " + valueRef );
84
+ }
85
+
86
+ if (presence () != CONSTANT )
87
+ {
88
+ handleError (node , "present must be constant when valueRef is set: " + valueRef );
89
+ }
90
+ }
71
91
72
92
if (PrimitiveType .CHAR == primitiveType )
73
93
{
@@ -81,23 +101,30 @@ public EncodedDataType(final Node node, final String givenName, final String ref
81
101
82
102
if (presence () == CONSTANT )
83
103
{
84
- if (node .getFirstChild () == null )
85
- {
86
- handleError (node , "type has declared presence as \" constant\" but XML node has no data" );
87
- constValue = null ;
88
- }
89
- else
104
+ if (null == valueRef )
90
105
{
91
- final String nodeValue = node .getFirstChild ().getNodeValue ();
92
- if (PrimitiveType .CHAR == primitiveType )
106
+ if (node .getFirstChild () == null )
93
107
{
94
- constValue = processConstantChar (node , lengthAttr , nodeValue );
108
+ handleError (node , "type has declared presence as \" constant\" but XML node has no data" );
109
+ constValue = null ;
95
110
}
96
111
else
97
112
{
98
- constValue = PrimitiveValue .parse (nodeValue , primitiveType );
113
+ final String nodeValue = node .getFirstChild ().getNodeValue ();
114
+ if (PrimitiveType .CHAR == primitiveType )
115
+ {
116
+ constValue = processConstantChar (node , lengthAttr , nodeValue );
117
+ }
118
+ else
119
+ {
120
+ constValue = PrimitiveValue .parse (nodeValue , primitiveType );
121
+ }
99
122
}
100
123
}
124
+ else
125
+ {
126
+ constValue = lookupValueRef (node );
127
+ }
101
128
}
102
129
else
103
130
{
@@ -126,6 +153,47 @@ public EncodedDataType(final Node node, final String givenName, final String ref
126
153
}
127
154
}
128
155
156
+ private PrimitiveValue lookupValueRef (final Node node )
157
+ {
158
+ try
159
+ {
160
+ final int periodIndex = valueRef .indexOf ('.' );
161
+ final String valueRefType = valueRef .substring (0 , periodIndex );
162
+
163
+ final XPath xPath = XPathFactory .newInstance ().newXPath ();
164
+ final Node valueRefNode = (Node )xPath .compile ("/messageSchema/types/enum[@name='" + valueRefType + "']" )
165
+ .evaluate (node .getOwnerDocument (), XPathConstants .NODE );
166
+
167
+ if (valueRefNode == null )
168
+ {
169
+ XmlSchemaParser .handleError (node , "valueRef not found: " + valueRefType );
170
+ return null ;
171
+ }
172
+
173
+ final EnumType enumType = new EnumType (valueRefNode );
174
+ if (enumType .encodingType () != primitiveType )
175
+ {
176
+ handleError (node , "valueRef does not match this type: " + valueRef );
177
+ return null ;
178
+ }
179
+
180
+ final String validValueName = valueRef .substring (periodIndex + 1 );
181
+ final EnumType .ValidValue validValue = enumType .getValidValue (validValueName );
182
+
183
+ if (null == validValue )
184
+ {
185
+ handleError (node , "valueRef for validValue name not found: " + validValueName );
186
+ return null ;
187
+ }
188
+
189
+ return validValue .primitiveValue ();
190
+ }
191
+ catch (final XPathException ex )
192
+ {
193
+ throw new RuntimeException (ex );
194
+ }
195
+ }
196
+
129
197
/**
130
198
* Construct a new EncodedDataType with direct values. Does not handle constant values.
131
199
*
@@ -156,6 +224,7 @@ public EncodedDataType(
156
224
this .maxValue = null ;
157
225
this .nullValue = null ;
158
226
characterEncoding = null ;
227
+ valueRef = null ;
159
228
}
160
229
161
230
/**
@@ -269,6 +338,16 @@ public String characterEncoding()
269
338
return characterEncoding ;
270
339
}
271
340
341
+ /**
342
+ * Get the value of the valueRef attribute.
343
+ *
344
+ * @return the value of the valueRef attribute.
345
+ */
346
+ public String valueRef ()
347
+ {
348
+ return valueRef ;
349
+ }
350
+
272
351
private PrimitiveValue processConstantChar (final Node node , final String lengthAttr , final String nodeValue )
273
352
{
274
353
final int valueLength = nodeValue .length ();
0 commit comments