Skip to content

Commit 6ba561e

Browse files
Generate EncodingMask encoding and decoding according to the current SDK release (#212)
* Improve C# data type templates to deal with optional fields Removed currently unsupported EncodingMask calls. * Add auto-generated attribute to suppress warnings * Switched encoding mask type back to fields enum This allows for a simpler and more failsafe usage. --------- Co-authored-by: opcfoundation-org <[email protected]>
1 parent 526c3e4 commit 6ba561e

File tree

9 files changed

+226
-94
lines changed

9 files changed

+226
-94
lines changed

Opc.Ua.ModelCompiler/ModelGenerator2.cs

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3815,6 +3815,14 @@ private bool WriteTemplate_ListOfTypes(Template template, Context context)
38153815
new LoadTemplateEventHandler(LoadTemplate_ListOfEncodingMaskFields),
38163816
null);
38173817

3818+
AddTemplate(
3819+
template,
3820+
"// EncodingMaskProperty",
3821+
TemplatePath + "Version2.EncodingMaskProperty.cs",
3822+
new DataTypeDesign[] { dataType },
3823+
new LoadTemplateEventHandler(LoadTemplate_EncodingMaskProperty),
3824+
new WriteTemplateEventHandler(WriteTemplate_EncodingMaskProperty));
3825+
38183826
AddTemplate(
38193827
template,
38203828
"// ListOfEncodedFields",
@@ -4596,7 +4604,7 @@ private string LoadTemplate_ListOfEncodedFields(Template template, Context conte
45964604

45974605
if (field.IsOptional)
45984606
{
4599-
template.Write($"if ((EncodingMask & (uint){dataType.ClassName}Fields.{field.Name}) != 0) ");
4607+
template.Write($"if ((EncodingMask & {dataType.ClassName}Fields.{field.Name}) != 0) ");
46004608
}
46014609

46024610
string functionName = field.DataTypeNode.BasicDataType.ToString();
@@ -4767,7 +4775,7 @@ private string LoadTemplate_ListOfDecodedFields(Template template, Context conte
47674775

47684776
if (field.IsOptional)
47694777
{
4770-
template.Write($"if ((EncodingMask & (uint){dataType.ClassName}Fields.{field.Name}) != 0) ");
4778+
template.Write($"if ((EncodingMask & {dataType.ClassName}Fields.{field.Name}) != 0) ");
47714779
}
47724780

47734781
string functionName = field.DataTypeNode.BasicDataType.ToString();
@@ -4925,7 +4933,7 @@ private string LoadTemplate_ListOfComparedFields(Template template, Context cont
49254933

49264934
if (field.IsOptional)
49274935
{
4928-
template.Write($"if ((EncodingMask & (uint){dataType.ClassName}Fields.{field.Name}) != 0) ");
4936+
template.Write($"if ((EncodingMask & {dataType.ClassName}Fields.{field.Name}) != 0) ");
49294937
}
49304938

49314939
template.Write("if (!Utils.IsEqual({0}, value.{0})) return false;", GetChildFieldName(field));
@@ -4960,7 +4968,7 @@ private string LoadTemplate_ListOfClonedFields(Template template, Context contex
49604968

49614969
if (field.IsOptional)
49624970
{
4963-
template.Write($"if ((EncodingMask & (uint){dataType.ClassName}Fields.{field.Name}) != 0) ");
4971+
template.Write($"if ((EncodingMask & {dataType.ClassName}Fields.{field.Name}) != 0) ");
49644972
}
49654973

49664974
template.Write("clone.{0} = ({1})Utils.Clone(this.{0});", GetChildFieldName(field), GetSystemTypeName(field.DataTypeNode, field.ValueRank));
@@ -5376,6 +5384,54 @@ private bool WriteTemplate_InitializeOptionalChildren(Template template, Context
53765384
}
53775385
#endregion
53785386

5387+
#region "// EncodingMaskProperty"
5388+
5389+
private string LoadTemplate_EncodingMaskProperty(Template template, Context context)
5390+
{
5391+
if (context.Target is not DataTypeDesign _)
5392+
{
5393+
return null;
5394+
}
5395+
5396+
return TemplatePath + "Version2.DataTypes.EncodingMaskProperty.cs";
5397+
}
5398+
5399+
private bool WriteTemplate_EncodingMaskProperty(Template template, Context context)
5400+
{
5401+
if (context.Target is not DataTypeDesign dataType)
5402+
{
5403+
return false;
5404+
}
5405+
5406+
template.AddReplacement("_hide_by_new_", IsFirstDataTypeWithOptionalFields(dataType) ? string.Empty : "new ");
5407+
template.AddReplacement("_ClassName_", dataType.ClassName);
5408+
5409+
var result = template.WriteTemplate(context);
5410+
template.WriteLine(string.Empty);
5411+
5412+
return result;
5413+
}
5414+
5415+
private static bool HasOptionalFields(DataTypeDesign dataType)
5416+
{
5417+
return dataType.Fields?.Any(field => field.IsOptional) ?? false;
5418+
}
5419+
5420+
private static bool HasOptionalFieldsInherited(DataTypeDesign dataType)
5421+
{
5422+
return dataType.BaseTypeNode is DataTypeDesign baseDataType
5423+
&& (HasOptionalFields(baseDataType) || HasOptionalFieldsInherited(baseDataType));
5424+
}
5425+
5426+
private static bool IsFirstDataTypeWithOptionalFields(DataTypeDesign dataType)
5427+
{
5428+
return dataType.IsStructure
5429+
&& HasOptionalFields(dataType)
5430+
&& !HasOptionalFieldsInherited(dataType);
5431+
}
5432+
5433+
#endregion
5434+
53795435
#region "// ListOfPropertiesForType and // ListOfProperties"
53805436
private string LoadTemplate_ListOfPropertiesForType(Template template, Context context)
53815437
{

Opc.Ua.ModelCompiler/Opc.Ua.ModelCompiler.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@
471471
<EmbeddedResource Include="Templates\Version2\DataTypes\DerivedClass.cs" />
472472
<EmbeddedResource Include="Templates\Version2\DataTypes\Enumeration.cs" />
473473
<EmbeddedResource Include="Templates\Version2\DataTypes\EnumerationValue.cs" />
474+
<EmbeddedResource Include="Templates\Version2\DataTypes\EncodingMaskProperty.cs" />
474475
<EmbeddedResource Include="Templates\Version2\DataTypes\Property.cs" />
475476
<EmbeddedResource Include="Templates\Version2\File.cs" />
476477
<EmbeddedResource Include="Templates\Version2\FindChildCase.cs" />

Opc.Ua.ModelCompiler/Templates/Version2/ConstantsFile.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*
2727
* The complete license agreement can be found here:
2828
* http://opcfoundation.org/License/MIT/1.00/
29+
* <auto-generated/>
2930
* ======================================================================*/
3031

3132
using System;

Opc.Ua.ModelCompiler/Templates/Version2/DataTypes/Class.cs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,33 @@ namespace X {
88
[DataContract(Namespace = _XmlNamespaceUri_)]
99
public _IsAbstract_partial class _BrowseName_ : IEncodeable, IJsonEncodeable
1010
{
11+
#region Fields
12+
13+
private readonly ExpandedNodeId _typeId;
14+
private readonly ExpandedNodeId _binaryEncodingId;
15+
private readonly ExpandedNodeId _xmlEncodingId;
16+
private readonly ExpandedNodeId _jsonEncodingId;
17+
18+
#endregion
19+
1120
#region Constructors
12-
public _BrowseName_()
21+
/// <remarks />
22+
public _BrowseName_() : this(
23+
DataTypeIds._BrowseName_,
24+
ObjectIds._BrowseName__Encoding_DefaultBinary,
25+
ObjectIds._BrowseName__Encoding_DefaultXml,
26+
ObjectIds._BrowseName__Encoding_DefaultJson)
27+
{
28+
}
29+
30+
/// <remarks />
31+
protected _BrowseName_(ExpandedNodeId typeId, ExpandedNodeId binaryEncodingId, ExpandedNodeId xmlEncodingId, ExpandedNodeId jsonEncodingId)
1332
{
33+
_typeId = typeId;
34+
_binaryEncodingId = binaryEncodingId;
35+
_xmlEncodingId = xmlEncodingId;
36+
_jsonEncodingId = jsonEncodingId;
37+
1438
Initialize();
1539
}
1640

@@ -32,37 +56,53 @@ private void Initialize()
3256

3357
#region IEncodeable Members
3458
/// <summary cref="IEncodeable.TypeId" />
35-
public virtual ExpandedNodeId TypeId => DataTypeIds._BrowseName_;
59+
ExpandedNodeId IEncodeable.TypeId => _typeId;
3660

3761
/// <summary cref="IEncodeable.BinaryEncodingId" />
38-
public virtual ExpandedNodeId BinaryEncodingId => ObjectIds._BrowseName__Encoding_DefaultBinary;
62+
ExpandedNodeId IEncodeable.BinaryEncodingId => _binaryEncodingId;
3963

4064
/// <summary cref="IEncodeable.XmlEncodingId" />
41-
public virtual ExpandedNodeId XmlEncodingId => ObjectIds._BrowseName__Encoding_DefaultXml;
42-
65+
ExpandedNodeId IEncodeable.XmlEncodingId => _xmlEncodingId;
66+
4367
/// <summary cref="IJsonEncodeable.JsonEncodingId" />
44-
public virtual ExpandedNodeId JsonEncodingId => ObjectIds._BrowseName__Encoding_DefaultJson;
68+
ExpandedNodeId IJsonEncodeable.JsonEncodingId => _jsonEncodingId;
4569

4670
/// <summary cref="IEncodeable.Encode(IEncoder)" />
47-
public virtual void Encode(IEncoder encoder)
71+
void IEncodeable.Encode(IEncoder encoder)
4872
{
4973
encoder.PushNamespace(_XmlNamespaceUri_);
5074

51-
// ListOfEncodedFields
75+
OnWriteEncodingMask(encoder);
76+
OnEncodeFields(encoder);
5277

5378
encoder.PopNamespace();
5479
}
5580

81+
protected virtual void OnWriteEncodingMask(IEncoder encoder) { }
82+
83+
protected virtual void OnEncodeFields(IEncoder encoder)
84+
{
85+
// ListOfEncodedFields
86+
}
87+
5688
/// <summary cref="IEncodeable.Decode(IDecoder)" />
57-
public virtual void Decode(IDecoder decoder)
89+
void IEncodeable.Decode(IDecoder decoder)
5890
{
5991
decoder.PushNamespace(_XmlNamespaceUri_);
6092

61-
// ListOfDecodedFields
93+
OnReadEncodingMask(decoder);
94+
OnDecodeFields(decoder);
6295

6396
decoder.PopNamespace();
6497
}
6598

99+
protected virtual void OnReadEncodingMask(IDecoder decoder) { }
100+
101+
protected virtual void OnDecodeFields(IDecoder decoder)
102+
{
103+
// ListOfDecodedFields
104+
}
105+
66106
/// <summary cref="IEncodeable.IsEqual(IEncodeable)" />
67107
public virtual bool IsEqual(IEncodeable encodeable)
68108
{

Opc.Ua.ModelCompiler/Templates/Version2/DataTypes/ClassWithOptionalFields.cs

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,33 @@ public enum _ClassName_Fields : uint
1919
[DataContract(Namespace = _XmlNamespaceUri_)]
2020
public partial class _BrowseName_ : IEncodeable, IJsonEncodeable
2121
{
22+
#region Fields
23+
24+
private readonly ExpandedNodeId _typeId;
25+
private readonly ExpandedNodeId _binaryEncodingId;
26+
private readonly ExpandedNodeId _xmlEncodingId;
27+
private readonly ExpandedNodeId _jsonEncodingId;
28+
29+
#endregion
30+
2231
#region Constructors
23-
public _BrowseName_()
32+
/// <remarks />
33+
public _BrowseName_() : this(
34+
DataTypeIds._BrowseName_,
35+
ObjectIds._BrowseName__Encoding_DefaultBinary,
36+
ObjectIds._BrowseName__Encoding_DefaultXml,
37+
ObjectIds._BrowseName__Encoding_DefaultJson)
2438
{
39+
}
40+
41+
/// <remarks />
42+
protected _BrowseName_(ExpandedNodeId typeId, ExpandedNodeId binaryEncodingId, ExpandedNodeId xmlEncodingId, ExpandedNodeId jsonEncodingId)
43+
{
44+
_typeId = typeId;
45+
_binaryEncodingId = binaryEncodingId;
46+
_xmlEncodingId = xmlEncodingId;
47+
_jsonEncodingId = jsonEncodingId;
48+
2549
Initialize();
2650
}
2751

@@ -33,54 +57,74 @@ private void Initialize(StreamingContext context)
3357

3458
private void Initialize()
3559
{
36-
EncodingMask = (uint)_ClassName_Fields.None;
60+
EncodingMask = _ClassName_Fields.None;
3761
// ListOfFieldInitializers
3862
}
3963
#endregion
4064

4165
#region Public Properties
4266
[DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)]
43-
public virtual uint EncodingMask { get; set; }
67+
public _ClassName_Fields EncodingMask { get; set; }
4468

4569
// ListOfProperties
4670
#endregion
4771

4872
#region IEncodeable Members
4973
/// <summary cref="IEncodeable.TypeId" />
50-
public virtual ExpandedNodeId TypeId => DataTypeIds._BrowseName_;
74+
ExpandedNodeId IEncodeable.TypeId => _typeId;
5175

5276
/// <summary cref="IEncodeable.BinaryEncodingId" />
53-
public virtual ExpandedNodeId BinaryEncodingId => ObjectIds._BrowseName__Encoding_DefaultBinary;
77+
ExpandedNodeId IEncodeable.BinaryEncodingId => _binaryEncodingId;
5478

5579
/// <summary cref="IEncodeable.XmlEncodingId" />
56-
public virtual ExpandedNodeId XmlEncodingId => ObjectIds._BrowseName__Encoding_DefaultXml;
57-
80+
ExpandedNodeId IEncodeable.XmlEncodingId => _xmlEncodingId;
81+
5882
/// <summary cref="IJsonEncodeable.JsonEncodingId" />
59-
public virtual ExpandedNodeId JsonEncodingId => ObjectIds._BrowseName__Encoding_DefaultJson;
83+
ExpandedNodeId IJsonEncodeable.JsonEncodingId => _jsonEncodingId;
6084

6185
/// <summary cref="IEncodeable.Encode(IEncoder)" />
62-
public virtual void Encode(IEncoder encoder)
86+
void IEncodeable.Encode(IEncoder encoder)
6387
{
6488
encoder.PushNamespace(_XmlNamespaceUri_);
65-
encoder.WriteEncodingMask((uint)EncodingMask);
6689

67-
// ListOfEncodedFields
90+
OnWriteEncodingMask(encoder);
91+
OnEncodeFields(encoder);
6892

6993
encoder.PopNamespace();
7094
}
7195

96+
protected virtual void OnWriteEncodingMask(IEncoder encoder)
97+
{
98+
encoder.WriteEncodingMask((uint)EncodingMask);
99+
}
100+
101+
protected virtual void OnEncodeFields(IEncoder encoder)
102+
{
103+
// ListOfEncodedFields
104+
}
105+
106+
72107
/// <summary cref="IEncodeable.Decode(IDecoder)" />
73-
public virtual void Decode(IDecoder decoder)
108+
void IEncodeable.Decode(IDecoder decoder)
74109
{
75110
decoder.PushNamespace(_XmlNamespaceUri_);
76111

77-
EncodingMask = decoder.ReadEncodingMask(m_FieldNames);
78-
79-
// ListOfDecodedFields
112+
OnReadEncodingMask(decoder);
113+
OnDecodeFields(decoder);
80114

81115
decoder.PopNamespace();
82116
}
83117

118+
protected virtual void OnReadEncodingMask(IDecoder decoder)
119+
{
120+
EncodingMask = (_ClassName_Fields)decoder.ReadEncodingMask(m_FieldNames);
121+
}
122+
123+
protected virtual void OnDecodeFields(IDecoder decoder)
124+
{
125+
// ListOfDecodedFields
126+
}
127+
84128
/// <summary cref="IEncodeable.IsEqual(IEncodeable)" />
85129
public virtual bool IsEqual(IEncodeable encodeable)
86130
{

0 commit comments

Comments
 (0)