use of org.opcfoundation.opcua.binaryschema.FieldType in project milo by eclipse.
the class DataTypeDictionaryGenerator method createStructuredType.
private StructuredType createStructuredType(StructureDescription description) {
QualifiedName name = description.getName();
StructureDefinition definition = description.getStructureDefinition();
StructureType structureType = definition.getStructureType();
StructuredType structuredType = new StructuredType();
structuredType.setName(name.getName());
// Create a combined list of StructuredFields from all parent types
LinkedList<StructureDefinition> definitions = new LinkedList<>();
definitions.addFirst(definition);
NodeId baseDataTypeId = definition.getBaseDataType();
while (baseDataTypeId != null && baseDataTypeId.isNotNull() && !Identifiers.Structure.equals(baseDataTypeId) && !Identifiers.Union.equals(baseDataTypeId)) {
StructureDescription baseDescription = structureDescriptions.get(baseDataTypeId);
StructureDefinition baseDefinition = baseDescription.getStructureDefinition();
definitions.addFirst(baseDefinition);
baseDataTypeId = baseDefinition.getBaseDataType();
}
LinkedHashMap<String, StructureField> allFields = new LinkedHashMap<>();
for (StructureDefinition d : definitions) {
for (StructureField f : d.getFields()) {
allFields.put(f.getName(), f);
}
}
List<StructureField> fields = new ArrayList<>(allFields.values());
if (structureType == StructureType.StructureWithOptionalFields) {
int optionalFieldCount = 0;
for (StructureField field : fields) {
if (field.getIsOptional()) {
optionalFieldCount++;
FieldType fieldType = new FieldType();
fieldType.setName(field.getName() + "Present");
fieldType.setTypeName(new QName(Namespaces.OPC_UA_BSD, "Bit"));
structuredType.getField().add(fieldType);
}
}
if (optionalFieldCount > 0) {
int reservedFieldCount = (optionalFieldCount + 31) / 32;
for (int i = 0; i < reservedFieldCount; i++) {
long reservedBits = 32 - optionalFieldCount;
optionalFieldCount -= 32;
FieldType fieldType = new FieldType();
fieldType.setLength(reservedBits);
fieldType.setName("Reserved" + i);
fieldType.setTypeName(new QName(Namespaces.OPC_UA_BSD, "Bit"));
structuredType.getField().add(fieldType);
}
}
} else if (structureType == StructureType.Union) {
FieldType fieldType = new FieldType();
fieldType.setName("SwitchField");
fieldType.setTypeName(new QName(Namespaces.OPC_UA_BSD, "UInt32"));
structuredType.getField().add(fieldType);
}
long switchValue = 0L;
for (StructureField field : fields) {
String fieldName = field.getName();
NodeId fieldDataTypeId = field.getDataType();
DataTypeLocation dataTypeLocation = dataTypeLookup.apply(fieldDataTypeId);
String dataTypeName = dataTypeLocation.dataTypeName;
String dictionaryNamespaceUri = dataTypeLocation.dictionaryNamespaceUri;
namespaces.add(dictionaryNamespaceUri);
FieldType fieldType = new FieldType();
fieldType.setName(fieldName);
fieldType.setTypeName(new QName(dictionaryNamespaceUri, dataTypeName));
if (structureType == StructureType.StructureWithOptionalFields) {
if (field.getIsOptional()) {
fieldType.setSwitchField(fieldName + "Present");
}
} else if (structureType == StructureType.Union) {
fieldType.setSwitchField("SwitchField");
fieldType.setSwitchValue(++switchValue);
}
if (field.getValueRank() >= 1) {
// Fixed-dimension array... specify a LengthField
FieldType lengthFieldType = new FieldType();
lengthFieldType.setName(fieldName + "Length");
lengthFieldType.setTypeName(new QName(Namespaces.OPC_UA_BSD, "Int32"));
if (structureType == StructureType.StructureWithOptionalFields) {
if (field.getIsOptional()) {
lengthFieldType.setSwitchField(fieldName + "Present");
}
} else if (structureType == StructureType.Union) {
fieldType.setSwitchField("SwitchField");
fieldType.setSwitchValue(switchValue);
}
structuredType.getField().add(lengthFieldType);
fieldType.setLengthField(fieldName + "Length");
} else if (field.getValueRank() != -1) {
// Not scalar, not fixed-dimension, not supported
throw new IllegalArgumentException("cannot encode field \"" + fieldName + "\" " + "with ValueRank: %s" + field.getValueRank());
}
structuredType.getField().add(fieldType);
}
return structuredType;
}
use of org.opcfoundation.opcua.binaryschema.FieldType in project milo by eclipse.
the class AbstractCodec method fieldIsAbsent.
private boolean fieldIsAbsent(FieldType field, Map<String, MemberT> members) {
if (field.getSwitchField() == null) {
return false;
} else {
MemberT controlField = members.get(field.getSwitchField());
String controlTypeName = structuredType.getField().stream().filter(f -> f.getName().equals(field.getSwitchField())).findFirst().map(f -> f.getTypeName().getLocalPart()).orElse("Int32");
long controlValue = ((Number) memberTypeToOpcUaScalar(controlField, controlTypeName)).longValue();
long switchValue = field.getSwitchValue() != null ? field.getSwitchValue() : 1L;
SwitchOperand switchOperand = field.getSwitchOperand() != null ? field.getSwitchOperand() : SwitchOperand.EQUALS;
return !compareToSwitchValue(controlValue, switchOperand, switchValue);
}
}
use of org.opcfoundation.opcua.binaryschema.FieldType in project milo by eclipse.
the class AbstractCodec method encodeField.
private void encodeField(SerializationContext context, OpcUaBinaryStreamEncoder encoder, LinkedHashMap<String, MemberT> members, FieldType field) {
String typeName = field.getTypeName().getLocalPart();
String typeNamespace = field.getTypeName().getNamespaceURI();
MemberT member = members.get(field.getName());
boolean typeNamespaceIsUa = Namespaces.OPC_UA.equals(typeNamespace) || Namespaces.OPC_UA_BSD.equals(typeNamespace);
if (fieldIsScalar(field)) {
Object scalarValue = memberTypeToOpcUaScalar(member, typeName);
if (typeNamespaceIsUa && WRITERS.containsKey(typeName)) {
WRITERS.get(typeName).accept(encoder, scalarValue);
} else {
context.encode(typeNamespace, typeName, scalarValue, encoder);
}
} else {
if (field.isIsLengthInBytes()) {
throw new UaSerializationException(StatusCodes.Bad_EncodingError, "IsLengthInBytes=true not supported");
}
if ("Bit".equals(typeName) && typeNamespaceIsUa) {
int length = fieldLength(field, members);
Number number = (Number) memberTypeToOpcUaArray(member, typeName);
BigInteger bi = BigInteger.valueOf(number.longValue());
for (int i = 0; i < length; i++) {
encoder.writeBit(bi.shiftRight(i).and(BigInteger.ONE).intValue());
}
} else {
Object[] valueArray = (Object[]) memberTypeToOpcUaArray(member, typeName);
FieldType lengthField = fields.get(field.getLengthField());
if (lengthField != null) {
int length = valueArray.length;
members.put(lengthField.getName(), opcUaToMemberTypeScalar(lengthField.getName(), length, lengthField.getTypeName().getLocalPart()));
encodeField(context, encoder, members, lengthField);
}
if (valueArray != null) {
if (typeNamespaceIsUa && WRITERS.containsKey(typeName)) {
for (Object value : valueArray) {
WRITERS.get(typeName).accept(encoder, value);
}
} else {
for (Object value : valueArray) {
context.encode(typeNamespace, typeName, value, encoder);
}
}
}
}
}
}
use of org.opcfoundation.opcua.binaryschema.FieldType in project milo by eclipse.
the class AbstractCodec method decode.
@Override
public StructureT decode(SerializationContext context, OpcUaBinaryStreamDecoder decoder) throws UaSerializationException {
LinkedHashMap<String, MemberT> members = new LinkedHashMap<>();
PeekingIterator<FieldType> fieldIterator = Iterators.peekingIterator(structuredType.getField().iterator());
while (fieldIterator.hasNext()) {
FieldType field = fieldIterator.next();
String fieldName = field.getName();
String typeName = field.getTypeName().getLocalPart();
String typeNamespace = field.getTypeName().getNamespaceURI();
if (fieldIsAbsent(field, members)) {
continue;
}
boolean typeNamespaceIsUa = Namespaces.OPC_UA.equals(typeNamespace) || Namespaces.OPC_UA_BSD.equals(typeNamespace);
if (fieldIsScalar(field)) {
if (typeNamespaceIsUa && READERS.containsKey(typeName)) {
Object value = READERS.get(typeName).apply(decoder);
members.put(fieldName, opcUaToMemberTypeScalar(fieldName, value, typeName));
} else {
Object value = context.decode(typeNamespace, typeName, decoder);
members.put(fieldName, opcUaToMemberTypeScalar(fieldName, value, typeName));
}
} else {
if (field.isIsLengthInBytes()) {
throw new UaSerializationException(StatusCodes.Bad_DecodingError, "IsLengthInBytes=true not supported");
}
int length = fieldLength(field, members);
if ("Bit".equals(typeName) && typeNamespaceIsUa) {
BigInteger bitAccumulation = BigInteger.valueOf(0L);
for (int i = 0; i < length; i++) {
BigInteger bitValue = BigInteger.valueOf(decoder.readBit());
bitAccumulation = bitAccumulation.or(bitValue.shiftLeft(i));
}
members.put(fieldName, opcUaToMemberTypeArray(fieldName, bitAccumulation.intValue(), typeName));
} else {
Object[] values = null;
if (length >= 0) {
values = new Object[length];
if (typeNamespaceIsUa && READERS.containsKey(typeName)) {
for (int i = 0; i < length; i++) {
Object value = READERS.get(typeName).apply(decoder);
values[i] = value;
}
} else {
for (int i = 0; i < length; i++) {
Object value = context.decode(typeNamespace, typeName, decoder);
values[i] = value;
}
}
}
members.put(fieldName, opcUaToMemberTypeArray(fieldName, values, typeName));
}
}
}
for (String lengthField : lengthFields.keySet()) {
members.remove(lengthField);
}
return createStructure(structuredType.getName(), members);
}
use of org.opcfoundation.opcua.binaryschema.FieldType in project milo by eclipse.
the class AbstractCodec method encode.
@Override
public void encode(SerializationContext context, OpcUaBinaryStreamEncoder encoder, StructureT structure) throws UaSerializationException {
LinkedHashMap<String, MemberT> members = new LinkedHashMap<>(getMembers(structure));
PeekingIterator<FieldType> fieldIterator = Iterators.peekingIterator(structuredType.getField().iterator());
while (fieldIterator.hasNext()) {
FieldType field = fieldIterator.next();
if (fieldIsAbsent(field, members)) {
continue;
}
if (lengthFields.containsKey(field.getName())) {
// structure representation isn't required to include it
continue;
}
encodeField(context, encoder, members, field);
}
}
Aggregations