|  | 
| 15 | 15 |  */ | 
| 16 | 16 | package uk.co.real_logic.sbe.xml; | 
| 17 | 17 | 
 | 
|  | 18 | +import org.agrona.collections.IntHashSet; | 
| 18 | 19 | import org.agrona.collections.ObjectHashSet; | 
| 19 | 20 | import uk.co.real_logic.sbe.ir.Token; | 
| 20 | 21 | 
 | 
| @@ -75,7 +76,7 @@ public Message(final Node messageNode, final Map<String, Type> typeByNameMap) th | 
| 75 | 76 |  semanticType = getAttributeValueOrNull(messageNode, "semanticType"); // optional | 
| 76 | 77 |  this.typeByNameMap = typeByNameMap; | 
| 77 | 78 | 
 | 
| 78 |  | - fieldList = parseFieldsAndGroups(messageNode); | 
|  | 79 | + fieldList = parseMembers(messageNode); | 
| 79 | 80 |  computeAndValidateOffsets(messageNode, fieldList, blockLength); | 
| 80 | 81 | 
 | 
| 81 | 82 |  computedBlockLength = computeMessageRootBlockLength(fieldList); | 
| @@ -162,14 +163,15 @@ public int blockLength() | 
| 162 | 163 |  return blockLength > computedBlockLength ? blockLength : computedBlockLength; | 
| 163 | 164 |  } | 
| 164 | 165 | 
 | 
| 165 |  | - private List<Field> parseFieldsAndGroups(final Node node) throws XPathExpressionException | 
|  | 166 | + private List<Field> parseMembers(final Node node) throws XPathExpressionException | 
| 166 | 167 |  { | 
| 167 | 168 |  final XPath xPath = XPathFactory.newInstance().newXPath(); | 
| 168 | 169 |  final NodeList list = (NodeList)xPath.compile(FIELD_OR_GROUP_OR_DATA_EXPR).evaluate(node, NODESET); | 
| 169 | 170 |  boolean groupEncountered = false, dataEncountered = false; | 
| 170 | 171 | 
 | 
| 171 | 172 |  final ObjectHashSet<String> distinctNames = new ObjectHashSet<>(); | 
| 172 |  | - final List<Field> fieldList = new ArrayList<>(); | 
|  | 173 | + final IntHashSet distinctIds = new IntHashSet(); | 
|  | 174 | + final ArrayList<Field> fieldList = new ArrayList<>(); | 
| 173 | 175 | 
 | 
| 174 | 176 |  for (int i = 0, size = list.getLength(); i < size; i++) | 
| 175 | 177 |  { | 
| @@ -206,6 +208,11 @@ private List<Field> parseFieldsAndGroups(final Node node) throws XPathExpression | 
| 206 | 208 |  throw new IllegalStateException("Unknown node name: " + nodeName); | 
| 207 | 209 |  } | 
| 208 | 210 | 
 | 
|  | 211 | + if (!distinctIds.add(field.id())) | 
|  | 212 | + { | 
|  | 213 | + handleError(node, "duplicate id found: " + field.id()); | 
|  | 214 | + } | 
|  | 215 | + | 
| 209 | 216 |  if (!distinctNames.add(field.name())) | 
| 210 | 217 |  { | 
| 211 | 218 |  handleError(node, "duplicate name found: " + field.name()); | 
| @@ -248,7 +255,7 @@ else if (!(dimensionType instanceof CompositeType)) | 
| 248 | 255 | 
 | 
| 249 | 256 |  XmlSchemaParser.checkForValidName(node, field.name()); | 
| 250 | 257 | 
 | 
| 251 |  | - field.groupFields(parseFieldsAndGroups(node)); // recursive call | 
|  | 258 | + field.groupFields(parseMembers(node)); // recursive call | 
| 252 | 259 | 
 | 
| 253 | 260 |  return field; | 
| 254 | 261 |  } | 
|  | 
0 commit comments