Skip to content

Commit

Permalink
[Java] Support lookup of valueRef to an enum valid value for declared…
Browse files Browse the repository at this point in the history
… basic types and fix composite length calculation when using them. Issue #529.
  • Loading branch information
mjpt777 committed Nov 12, 2017
1 parent 5feb40b commit 84d449f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public Type getType(final String name)
*/
public int encodedLength()
{
int offset = 0;
int length = 0;

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

if (t.offsetAttribute() != -1)
{
offset = t.offsetAttribute();
length = t.offsetAttribute();
}

offset += t.encodedLength();
if (t.presence() != Presence.CONSTANT)
{
length += t.encodedLength();
}
}

return offset;
return length;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

import org.w3c.dom.Node;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathException;
import javax.xml.xpath.XPathFactory;

import static uk.co.real_logic.sbe.xml.Presence.CONSTANT;
import static uk.co.real_logic.sbe.xml.XmlSchemaParser.handleError;
import static uk.co.real_logic.sbe.xml.XmlSchemaParser.handleWarning;
Expand All @@ -41,6 +46,7 @@ public class EncodedDataType extends Type
private final PrimitiveValue maxValue;
private final PrimitiveValue nullValue;
private final String characterEncoding;
private final String valueRef;
private boolean varLen;

/**
Expand Down Expand Up @@ -68,6 +74,20 @@ public EncodedDataType(final Node node, final String givenName, final String ref
final String lengthAttr = getAttributeValueOrNull(node, "length");
length = Integer.parseInt(null == lengthAttr ? "1" : lengthAttr);
varLen = Boolean.parseBoolean(getAttributeValue(node, "variableLength", "false"));
valueRef = getAttributeValueOrNull(node, "valueRef");

if (null != valueRef)
{
if (valueRef.indexOf('.') == -1)
{
handleError(node, "valueRef format not valid (enum-name.valid-value-name): " + valueRef);
}

if (presence() != CONSTANT)
{
handleError(node, "present must be constant when valueRef is set: " + valueRef);
}
}

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

if (presence() == CONSTANT)
{
if (node.getFirstChild() == null)
{
handleError(node, "type has declared presence as \"constant\" but XML node has no data");
constValue = null;
}
else
if (null == valueRef)
{
final String nodeValue = node.getFirstChild().getNodeValue();
if (PrimitiveType.CHAR == primitiveType)
if (node.getFirstChild() == null)
{
constValue = processConstantChar(node, lengthAttr, nodeValue);
handleError(node, "type has declared presence as \"constant\" but XML node has no data");
constValue = null;
}
else
{
constValue = PrimitiveValue.parse(nodeValue, primitiveType);
final String nodeValue = node.getFirstChild().getNodeValue();
if (PrimitiveType.CHAR == primitiveType)
{
constValue = processConstantChar(node, lengthAttr, nodeValue);
}
else
{
constValue = PrimitiveValue.parse(nodeValue, primitiveType);
}
}
}
else
{
constValue = lookupValueRef(node);
}
}
else
{
Expand Down Expand Up @@ -126,6 +153,47 @@ public EncodedDataType(final Node node, final String givenName, final String ref
}
}

private PrimitiveValue lookupValueRef(final Node node)
{
try
{
final int periodIndex = valueRef.indexOf('.');
final String valueRefType = valueRef.substring(0, periodIndex);

final XPath xPath = XPathFactory.newInstance().newXPath();
final Node valueRefNode = (Node)xPath.compile("/messageSchema/types/enum[@name='" + valueRefType + "']")
.evaluate(node.getOwnerDocument(), XPathConstants.NODE);

if (valueRefNode == null)
{
XmlSchemaParser.handleError(node, "valueRef not found: " + valueRefType);
return null;
}

final EnumType enumType = new EnumType(valueRefNode);
if (enumType.encodingType() != primitiveType)
{
handleError(node, "valueRef does not match this type: " + valueRef);
return null;
}

final String validValueName = valueRef.substring(periodIndex + 1);
final EnumType.ValidValue validValue = enumType.getValidValue(validValueName);

if (null == validValue)
{
handleError(node, "valueRef for validValue name not found: " + validValueName);
return null;
}

return validValue.primitiveValue();
}
catch (final XPathException ex)
{
throw new RuntimeException(ex);
}
}

/**
* Construct a new EncodedDataType with direct values. Does not handle constant values.
*
Expand Down Expand Up @@ -156,6 +224,7 @@ public EncodedDataType(
this.maxValue = null;
this.nullValue = null;
characterEncoding = null;
valueRef = null;
}

/**
Expand Down Expand Up @@ -269,6 +338,16 @@ public String characterEncoding()
return characterEncoding;
}

/**
* Get the value of the valueRef attribute.
*
* @return the value of the valueRef attribute.
*/
public String valueRef()
{
return valueRef;
}

private PrimitiveValue processConstantChar(final Node node, final String lengthAttr, final String nodeValue)
{
final int valueLength = nodeValue.length();
Expand Down
3 changes: 1 addition & 2 deletions sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,7 @@ private void validateValueRef(final Node node, final Map<String, Type> typeByNam
final int periodIndex = valueRef.indexOf('.');
if (periodIndex < 1 || periodIndex == (valueRef.length() - 1))
{
handleError(
node, "valueRef format not valid for constant (enum-name.valid-value-name): " + valueRef);
handleError(node, "valueRef format not valid (enum-name.valid-value-name): " + valueRef);
}

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

0 comments on commit 84d449f

Please sign in to comment.