Skip to content

Commit 84d449f

Browse files
committed
[Java] Support lookup of valueRef to an enum valid value for declared basic types and fix composite length calculation when using them. Issue #529.
1 parent 5feb40b commit 84d449f

File tree

3 files changed

+97
-16
lines changed

3 files changed

+97
-16
lines changed

sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/CompositeType.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public Type getType(final String name)
101101
*/
102102
public int encodedLength()
103103
{
104-
int offset = 0;
104+
int length = 0;
105105

106106
for (final Type t : containedTypeByNameMap.values())
107107
{
@@ -112,13 +112,16 @@ public int encodedLength()
112112

113113
if (t.offsetAttribute() != -1)
114114
{
115-
offset = t.offsetAttribute();
115+
length = t.offsetAttribute();
116116
}
117117

118-
offset += t.encodedLength();
118+
if (t.presence() != Presence.CONSTANT)
119+
{
120+
length += t.encodedLength();
121+
}
119122
}
120123

121-
return offset;
124+
return length;
122125
}
123126

124127
/**

sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/EncodedDataType.java

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121

2222
import org.w3c.dom.Node;
2323

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+
2429
import static uk.co.real_logic.sbe.xml.Presence.CONSTANT;
2530
import static uk.co.real_logic.sbe.xml.XmlSchemaParser.handleError;
2631
import static uk.co.real_logic.sbe.xml.XmlSchemaParser.handleWarning;
@@ -41,6 +46,7 @@ public class EncodedDataType extends Type
4146
private final PrimitiveValue maxValue;
4247
private final PrimitiveValue nullValue;
4348
private final String characterEncoding;
49+
private final String valueRef;
4450
private boolean varLen;
4551

4652
/**
@@ -68,6 +74,20 @@ public EncodedDataType(final Node node, final String givenName, final String ref
6874
final String lengthAttr = getAttributeValueOrNull(node, "length");
6975
length = Integer.parseInt(null == lengthAttr ? "1" : lengthAttr);
7076
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+
}
7191

7292
if (PrimitiveType.CHAR == primitiveType)
7393
{
@@ -81,23 +101,30 @@ public EncodedDataType(final Node node, final String givenName, final String ref
81101

82102
if (presence() == CONSTANT)
83103
{
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)
90105
{
91-
final String nodeValue = node.getFirstChild().getNodeValue();
92-
if (PrimitiveType.CHAR == primitiveType)
106+
if (node.getFirstChild() == null)
93107
{
94-
constValue = processConstantChar(node, lengthAttr, nodeValue);
108+
handleError(node, "type has declared presence as \"constant\" but XML node has no data");
109+
constValue = null;
95110
}
96111
else
97112
{
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+
}
99122
}
100123
}
124+
else
125+
{
126+
constValue = lookupValueRef(node);
127+
}
101128
}
102129
else
103130
{
@@ -126,6 +153,47 @@ public EncodedDataType(final Node node, final String givenName, final String ref
126153
}
127154
}
128155

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+
129197
/**
130198
* Construct a new EncodedDataType with direct values. Does not handle constant values.
131199
*
@@ -156,6 +224,7 @@ public EncodedDataType(
156224
this.maxValue = null;
157225
this.nullValue = null;
158226
characterEncoding = null;
227+
valueRef = null;
159228
}
160229

161230
/**
@@ -269,6 +338,16 @@ public String characterEncoding()
269338
return characterEncoding;
270339
}
271340

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+
272351
private PrimitiveValue processConstantChar(final Node node, final String lengthAttr, final String nodeValue)
273352
{
274353
final int valueLength = nodeValue.length();

sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,7 @@ private void validateValueRef(final Node node, final Map<String, Type> typeByNam
270270
final int periodIndex = valueRef.indexOf('.');
271271
if (periodIndex < 1 || periodIndex == (valueRef.length() - 1))
272272
{
273-
handleError(
274-
node, "valueRef format not valid for constant (enum-name.valid-value-name): " + valueRef);
273+
handleError(node, "valueRef format not valid (enum-name.valid-value-name): " + valueRef);
275274
}
276275

277276
final String valueRefType = valueRef.substring(0, periodIndex);

0 commit comments

Comments
 (0)