|
22 | 22 | import org.eclipse.milo.opcua.sdk.core.typetree.DataType; |
23 | 23 | import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree; |
24 | 24 | import org.eclipse.milo.opcua.stack.core.BuiltinDataType; |
| 25 | +import org.eclipse.milo.opcua.stack.core.NodeIds; |
25 | 26 | import org.eclipse.milo.opcua.stack.core.StatusCodes; |
26 | 27 | import org.eclipse.milo.opcua.stack.core.UaSerializationException; |
27 | 28 | import org.eclipse.milo.opcua.stack.core.encoding.EncodingContext; |
@@ -263,7 +264,12 @@ private Object decodeFieldValue(UaDecoder decoder, StructureField field) { |
263 | 264 | break; |
264 | 265 | } |
265 | 266 | case STRUCT: |
266 | | - value = decoder.decodeStruct(fieldName, dataTypeId); |
| 267 | + if (dataTypeId.equals(NodeIds.Structure) || fieldAllowsSubtyping(field)) { |
| 268 | + ExtensionObject xo = decoder.decodeExtensionObject(fieldName); |
| 269 | + value = xo.decode(decoder.getEncodingContext()); |
| 270 | + } else { |
| 271 | + value = decoder.decodeStruct(fieldName, dataTypeId); |
| 272 | + } |
267 | 273 | break; |
268 | 274 | default: |
269 | 275 | throw new RuntimeException("codecType: " + typeHint); |
@@ -356,7 +362,14 @@ private void encodeFieldValue(UaEncoder encoder, StructureField field, Object va |
356 | 362 | encoder.encodeEnum(fieldName, (UaEnumeratedType) value); |
357 | 363 | break; |
358 | 364 | case STRUCT: |
359 | | - encoder.encodeStruct(fieldName, value, dataTypeId); |
| 365 | + if (dataTypeId.equals(NodeIds.Structure) || fieldAllowsSubtyping(field)) { |
| 366 | + DynamicStruct structValue = (DynamicStruct) value; |
| 367 | + ExtensionObject xo = |
| 368 | + ExtensionObject.encode(encoder.getEncodingContext(), structValue); |
| 369 | + encoder.encodeExtensionObject(fieldName, xo); |
| 370 | + } else { |
| 371 | + encoder.encodeStruct(fieldName, value, dataTypeId); |
| 372 | + } |
360 | 373 | break; |
361 | 374 | default: |
362 | 375 | throw new RuntimeException("codecType: " + typeHint); |
@@ -406,6 +419,20 @@ private void encodeFieldValue(UaEncoder encoder, StructureField field, Object va |
406 | 419 | } |
407 | 420 | } |
408 | 421 |
|
| 422 | + /** |
| 423 | + * Check if the field allows subtyping. |
| 424 | + * |
| 425 | + * <p>In Structures and Unions this means the field is encoded as an ExtensionObject. |
| 426 | + * |
| 427 | + * @param field the {@link StructureField} to check. |
| 428 | + * @return {@code true} if the field allows subtyping. |
| 429 | + */ |
| 430 | + private boolean fieldAllowsSubtyping(StructureField field) { |
| 431 | + return field.getIsOptional() |
| 432 | + && (definition.getStructureType() == StructureType.StructureWithSubtypedValues |
| 433 | + || definition.getStructureType() == StructureType.UnionWithSubtypedValues); |
| 434 | + } |
| 435 | + |
409 | 436 | private static Object decodeBuiltinDataType( |
410 | 437 | UaDecoder decoder, String fieldName, BuiltinDataType builtinDataType) { |
411 | 438 |
|
|
0 commit comments